Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libdav1d/8bd_filmgrain_tmpl.c
Warning:line 163, column 5
Assigned value is uninitialized

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name 8bd_filmgrain_tmpl.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libdav1d -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libdav1d -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D DAV1D_API= -D STACK_ALIGNMENT=16 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/media/libdav1d -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libdav1d -I /root/firefox-clang/third_party/dav1d -I /root/firefox-clang/third_party/dav1d/include -I /root/firefox-clang/third_party/dav1d/include/dav1d -I /root/firefox-clang/third_party/dav1d/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c 8bd_filmgrain_tmpl.c
1#define BITDEPTH8 8
2/*
3 * Copyright © 2018, Niklas Haas
4 * Copyright © 2018, VideoLAN and dav1d authors
5 * Copyright © 2018, Two Orioles, LLC
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "common/attributes.h"
31#include "common/intops.h"
32
33#include "src/filmgrain.h"
34#include "src/tables.h"
35
36#define SUB_GRAIN_WIDTH44 44
37#define SUB_GRAIN_HEIGHT38 38
38
39static inline int get_random_number(const int bits, unsigned *const state) {
40 const int r = *state;
41 unsigned bit = ((r >> 0) ^ (r >> 1) ^ (r >> 3) ^ (r >> 12)) & 1;
42 *state = (r >> 1) | (bit << 15);
43
44 return (*state >> (16 - bits)) & ((1 << bits) - 1);
45}
46
47static inline int round2(const int x, const uint64_t shift) {
48 return (x + ((1 << shift) >> 1)) >> shift;
49}
50
51static void generate_grain_y_c(entry buf[][GRAIN_WIDTH82],
52 const Dav1dFilmGrainData *const data
53 HIGHBD_DECL_SUFFIX)
54{
55 const int bitdepth_min_8 = bitdepth_from_max(bitdepth_max)8 - 8;
56 unsigned seed = data->seed;
57 const int shift = 4 - bitdepth_min_8 + data->grain_scale_shift;
58 const int grain_ctr = 128 << bitdepth_min_8;
59 const int grain_min = -grain_ctr, grain_max = grain_ctr - 1;
60
61 for (int y = 0; y < GRAIN_HEIGHT73; y++) {
62 for (int x = 0; x < GRAIN_WIDTH82; x++) {
63 const int value = get_random_number(11, &seed);
64 buf[y][x] = round2(dav1d_gaussian_sequence[ value ], shift);
65 }
66 }
67
68 const int ar_pad = 3;
69 const int ar_lag = data->ar_coeff_lag;
70
71 for (int y = ar_pad; y < GRAIN_HEIGHT73; y++) {
72 for (int x = ar_pad; x < GRAIN_WIDTH82 - ar_pad; x++) {
73 const int8_t *coeff = data->ar_coeffs_y;
74 int sum = 0;
75 for (int dy = -ar_lag; dy <= 0; dy++) {
76 for (int dx = -ar_lag; dx <= ar_lag; dx++) {
77 if (!dx && !dy)
78 break;
79 sum += *(coeff++) * buf[y + dy][x + dx];
80 }
81 }
82
83 const int grain = buf[y][x] + round2(sum, data->ar_coeff_shift);
84 buf[y][x] = iclip(grain, grain_min, grain_max);
85 }
86 }
87}
88
89static NOINLINE__attribute__((noinline)) void
90generate_grain_uv_c(entry buf[][GRAIN_WIDTH82],
91 const entry buf_y[][GRAIN_WIDTH82],
92 const Dav1dFilmGrainData *const data, const intptr_t uv,
93 const int subx, const int suby HIGHBD_DECL_SUFFIX)
94{
95 const int bitdepth_min_8 = bitdepth_from_max(bitdepth_max)8 - 8;
96 unsigned seed = data->seed ^ (uv ? 0x49d8 : 0xb524);
97 const int shift = 4 - bitdepth_min_8 + data->grain_scale_shift;
98 const int grain_ctr = 128 << bitdepth_min_8;
99 const int grain_min = -grain_ctr, grain_max = grain_ctr - 1;
100
101 const int chromaW = subx ? SUB_GRAIN_WIDTH44 : GRAIN_WIDTH82;
102 const int chromaH = suby ? SUB_GRAIN_HEIGHT38 : GRAIN_HEIGHT73;
103
104 for (int y = 0; y < chromaH; y++) {
105 for (int x = 0; x < chromaW; x++) {
106 const int value = get_random_number(11, &seed);
107 buf[y][x] = round2(dav1d_gaussian_sequence[ value ], shift);
108 }
109 }
110
111 const int ar_pad = 3;
112 const int ar_lag = data->ar_coeff_lag;
113
114 for (int y = ar_pad; y < chromaH; y++) {
115 for (int x = ar_pad; x < chromaW - ar_pad; x++) {
116 const int8_t *coeff = data->ar_coeffs_uv[uv];
117 int sum = 0;
118 for (int dy = -ar_lag; dy <= 0; dy++) {
119 for (int dx = -ar_lag; dx <= ar_lag; dx++) {
120 // For the final (current) pixel, we need to add in the
121 // contribution from the luma grain texture
122 if (!dx && !dy) {
123 if (!data->num_y_points)
124 break;
125 int luma = 0;
126 const int lumaX = ((x - ar_pad) << subx) + ar_pad;
127 const int lumaY = ((y - ar_pad) << suby) + ar_pad;
128 for (int i = 0; i <= suby; i++) {
129 for (int j = 0; j <= subx; j++) {
130 luma += buf_y[lumaY + i][lumaX + j];
131 }
132 }
133 luma = round2(luma, subx + suby);
134 sum += luma * (*coeff);
135 break;
136 }
137
138 sum += *(coeff++) * buf[y + dy][x + dx];
139 }
140 }
141
142 const int grain = buf[y][x] + round2(sum, data->ar_coeff_shift);
143 buf[y][x] = iclip(grain, grain_min, grain_max);
144 }
145 }
146}
147
148#define gnuv_ss_fn(nm, ss_x, ss_y)static void (generate_grain_uv_nm_c)(entry buf[][82], const entry
buf_y[][82], const Dav1dFilmGrainData *const data, const intptr_t
uv ) { generate_grain_uv_c(buf, buf_y, data, uv, ss_x, ss_y )
; }
\
149static decl_generate_grain_uv_fn(generate_grain_uv_##nm##_c)void (generate_grain_uv_##nm##_c)(entry buf[][82], const entry
buf_y[][82], const Dav1dFilmGrainData *const data, const intptr_t
uv )
{ \
150 generate_grain_uv_c(buf, buf_y, data, uv, ss_x, ss_y HIGHBD_TAIL_SUFFIX); \
151}
152
153gnuv_ss_fn(420, 1, 1)static void (generate_grain_uv_420_c)(entry buf[][82], const entry
buf_y[][82], const Dav1dFilmGrainData *const data, const intptr_t
uv ) { generate_grain_uv_c(buf, buf_y, data, uv, 1, 1 ); }
;
154gnuv_ss_fn(422, 1, 0)static void (generate_grain_uv_422_c)(entry buf[][82], const entry
buf_y[][82], const Dav1dFilmGrainData *const data, const intptr_t
uv ) { generate_grain_uv_c(buf, buf_y, data, uv, 1, 0 ); }
;
155gnuv_ss_fn(444, 0, 0)static void (generate_grain_uv_444_c)(entry buf[][82], const entry
buf_y[][82], const Dav1dFilmGrainData *const data, const intptr_t
uv ) { generate_grain_uv_c(buf, buf_y, data, uv, 0, 0 ); }
;
156
157// samples from the correct block of a grain LUT, while taking into account the
158// offsets provided by the offsets cache
159static inline entry sample_lut(const entry grain_lut[][GRAIN_WIDTH82],
160 const int offsets[2][2], const int subx, const int suby,
161 const int bx, const int by, const int x, const int y)
162{
163 const int randval = offsets[bx][by];
22
Assigned value is uninitialized
164 const int offx = 3 + (2 >> subx) * (3 + (randval >> 4));
165 const int offy = 3 + (2 >> suby) * (3 + (randval & 0xF));
166 return grain_lut[offy + y + (FG_BLOCK_SIZE32 >> suby) * by]
167 [offx + x + (FG_BLOCK_SIZE32 >> subx) * bx];
168}
169
170static void fgy_32x32xn_c(pixel *const dst_row, const pixel *const src_row,
171 const ptrdiff_t stride,
172 const Dav1dFilmGrainData *const data, const size_t pw,
173 const uint8_t scaling[SCALING_SIZE256],
174 const entry grain_lut[][GRAIN_WIDTH82],
175 const int bh, const int row_num HIGHBD_DECL_SUFFIX)
176{
177 const int rows = 1 + (data->overlap_flag && row_num > 0);
1
Assuming field 'overlap_flag' is not equal to 0
2
Assuming 'row_num' is <= 0
178 const int bitdepth_min_8 = bitdepth_from_max(bitdepth_max)8 - 8;
179 const int grain_ctr = 128 << bitdepth_min_8;
180 const int grain_min = -grain_ctr, grain_max = grain_ctr - 1;
181
182 int min_value, max_value;
183 if (data->clip_to_restricted_range) {
3
Assuming field 'clip_to_restricted_range' is 0
4
Taking false branch
184 min_value = 16 << bitdepth_min_8;
185 max_value = 235 << bitdepth_min_8;
186 } else {
187 min_value = 0;
188 max_value = BITDEPTH_MAX0xff;
189 }
190
191 // seed[0] contains the current row, seed[1] contains the previous
192 unsigned seed[2];
193 for (int i = 0; i < rows; i++) {
5
Loop condition is true. Entering loop body
6
Loop condition is false. Execution continues on line 199
194 seed[i] = data->seed;
195 seed[i] ^= (((row_num - i) * 37 + 178) & 0xFF) << 8;
196 seed[i] ^= (((row_num - i) * 173 + 105) & 0xFF);
197 }
198
199 assert(stride % (FG_BLOCK_SIZE * sizeof(pixel)) == 0)((void) sizeof ((stride % (32 * sizeof(pixel)) == 0) ? 1 : 0)
, __extension__ ({ if (stride % (32 * sizeof(pixel)) == 0) ; else
__assert_fail ("stride % (FG_BLOCK_SIZE * sizeof(pixel)) == 0"
, "8bd_filmgrain_tmpl.c", 199, __extension__ __PRETTY_FUNCTION__
); }))
;
7
Assuming the condition is true
8
Taking true branch
200
201 int offsets[2 /* col offset */][2 /* row offset */];
202
203 // process this row in FG_BLOCK_SIZE^2 blocks
204 for (unsigned bx = 0; bx < pw; bx += FG_BLOCK_SIZE32) {
9
Assuming 'bx' is < 'pw'
10
Loop condition is true. Entering loop body
205 const int bw = imin(FG_BLOCK_SIZE32, (int) pw - bx);
206
207 if (data->overlap_flag
10.1
Field 'overlap_flag' is not equal to 0
&& bx
10.2
'bx' is 0
) {
11
Taking false branch
208 // shift previous offsets left
209 for (int i = 0; i < rows; i++)
210 offsets[1][i] = offsets[0][i];
211 }
212
213 // update current offsets
214 for (int i = 0; i < rows; i++)
12
Loop condition is true. Entering loop body
215 offsets[0][i] = get_random_number(8, &seed[i]);
216
217 // x/y block offsets to compensate for overlapped regions
218 const int ystart = data->overlap_flag
12.1
Field 'overlap_flag' is not equal to 0
&& row_num ? imin(2, bh) : 0;
13
Assuming 'row_num' is not equal to 0
14
'?' condition is true
219 const int xstart = data->overlap_flag
14.1
Field 'overlap_flag' is not equal to 0
&& bx
14.2
'bx' is 0
? imin(2, bw) : 0;
15
'?' condition is false
220
221 static const int w[2][2] = { { 27, 17 }, { 17, 27 } };
222
223#define add_noise_y(x, y, grain)const pixel *const src = src_row + (y) * (stride) + (x) + bx;
pixel *const dst = dst_row + (y) * (stride) + (x) + bx; const
int noise = round2(scaling[ *src ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
\
224 const pixel *const src = src_row + (y) * PXSTRIDE(stride)(stride) + (x) + bx; \
225 pixel *const dst = dst_row + (y) * PXSTRIDE(stride)(stride) + (x) + bx; \
226 const int noise = round2(scaling[ *src ] * (grain), data->scaling_shift); \
227 *dst = iclip(*src + noise, min_value, max_value);
228
229 for (int y = ystart; y < bh; y++) {
16
Loop condition is false. Execution continues on line 246
230 // Non-overlapped image region (straightforward)
231 for (int x = xstart; x < bw; x++) {
232 int grain = sample_lut(grain_lut, offsets, 0, 0, 0, 0, x, y);
233 add_noise_y(x, y, grain)const pixel *const src = src_row + (y) * (stride) + (x) + bx;
pixel *const dst = dst_row + (y) * (stride) + (x) + bx; const
int noise = round2(scaling[ *src ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
234 }
235
236 // Special case for overlapped column
237 for (int x = 0; x < xstart; x++) {
238 int grain = sample_lut(grain_lut, offsets, 0, 0, 0, 0, x, y);
239 int old = sample_lut(grain_lut, offsets, 0, 0, 1, 0, x, y);
240 grain = round2(old * w[x][0] + grain * w[x][1], 5);
241 grain = iclip(grain, grain_min, grain_max);
242 add_noise_y(x, y, grain)const pixel *const src = src_row + (y) * (stride) + (x) + bx;
pixel *const dst = dst_row + (y) * (stride) + (x) + bx; const
int noise = round2(scaling[ *src ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
243 }
244 }
245
246 for (int y = 0; y < ystart; y++) {
17
Assuming 'y' is < 'ystart'
18
Loop condition is true. Entering loop body
247 // Special case for overlapped row (sans corner)
248 for (int x = xstart; x < bw; x++) {
19
Loop condition is true. Entering loop body
249 int grain = sample_lut(grain_lut, offsets, 0, 0, 0, 0, x, y);
250 int old = sample_lut(grain_lut, offsets, 0, 0, 0, 1, x, y);
20
Passing the value 1 via 6th parameter 'by'
21
Calling 'sample_lut'
251 grain = round2(old * w[y][0] + grain * w[y][1], 5);
252 grain = iclip(grain, grain_min, grain_max);
253 add_noise_y(x, y, grain)const pixel *const src = src_row + (y) * (stride) + (x) + bx;
pixel *const dst = dst_row + (y) * (stride) + (x) + bx; const
int noise = round2(scaling[ *src ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
254 }
255
256 // Special case for doubly-overlapped corner
257 for (int x = 0; x < xstart; x++) {
258 // Blend the top pixel with the top left block
259 int top = sample_lut(grain_lut, offsets, 0, 0, 0, 1, x, y);
260 int old = sample_lut(grain_lut, offsets, 0, 0, 1, 1, x, y);
261 top = round2(old * w[x][0] + top * w[x][1], 5);
262 top = iclip(top, grain_min, grain_max);
263
264 // Blend the current pixel with the left block
265 int grain = sample_lut(grain_lut, offsets, 0, 0, 0, 0, x, y);
266 old = sample_lut(grain_lut, offsets, 0, 0, 1, 0, x, y);
267 grain = round2(old * w[x][0] + grain * w[x][1], 5);
268 grain = iclip(grain, grain_min, grain_max);
269
270 // Mix the row rows together and apply grain
271 grain = round2(top * w[y][0] + grain * w[y][1], 5);
272 grain = iclip(grain, grain_min, grain_max);
273 add_noise_y(x, y, grain)const pixel *const src = src_row + (y) * (stride) + (x) + bx;
pixel *const dst = dst_row + (y) * (stride) + (x) + bx; const
int noise = round2(scaling[ *src ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
274 }
275 }
276 }
277}
278
279static NOINLINE__attribute__((noinline)) void
280fguv_32x32xn_c(pixel *const dst_row, const pixel *const src_row,
281 const ptrdiff_t stride, const Dav1dFilmGrainData *const data,
282 const size_t pw, const uint8_t scaling[SCALING_SIZE256],
283 const entry grain_lut[][GRAIN_WIDTH82], const int bh,
284 const int row_num, const pixel *const luma_row,
285 const ptrdiff_t luma_stride, const int uv, const int is_id,
286 const int sx, const int sy HIGHBD_DECL_SUFFIX)
287{
288 const int rows = 1 + (data->overlap_flag && row_num > 0);
289 const int bitdepth_min_8 = bitdepth_from_max(bitdepth_max)8 - 8;
290 const int grain_ctr = 128 << bitdepth_min_8;
291 const int grain_min = -grain_ctr, grain_max = grain_ctr - 1;
292
293 int min_value, max_value;
294 if (data->clip_to_restricted_range) {
295 min_value = 16 << bitdepth_min_8;
296 max_value = (is_id ? 235 : 240) << bitdepth_min_8;
297 } else {
298 min_value = 0;
299 max_value = BITDEPTH_MAX0xff;
300 }
301
302 // seed[0] contains the current row, seed[1] contains the previous
303 unsigned seed[2];
304 for (int i = 0; i < rows; i++) {
305 seed[i] = data->seed;
306 seed[i] ^= (((row_num - i) * 37 + 178) & 0xFF) << 8;
307 seed[i] ^= (((row_num - i) * 173 + 105) & 0xFF);
308 }
309
310 assert(stride % (FG_BLOCK_SIZE * sizeof(pixel)) == 0)((void) sizeof ((stride % (32 * sizeof(pixel)) == 0) ? 1 : 0)
, __extension__ ({ if (stride % (32 * sizeof(pixel)) == 0) ; else
__assert_fail ("stride % (FG_BLOCK_SIZE * sizeof(pixel)) == 0"
, "8bd_filmgrain_tmpl.c", 310, __extension__ __PRETTY_FUNCTION__
); }))
;
311
312 int offsets[2 /* col offset */][2 /* row offset */];
313
314 // process this row in FG_BLOCK_SIZE^2 blocks (subsampled)
315 for (unsigned bx = 0; bx < pw; bx += FG_BLOCK_SIZE32 >> sx) {
316 const int bw = imin(FG_BLOCK_SIZE32 >> sx, (int)(pw - bx));
317 if (data->overlap_flag && bx) {
318 // shift previous offsets left
319 for (int i = 0; i < rows; i++)
320 offsets[1][i] = offsets[0][i];
321 }
322
323 // update current offsets
324 for (int i = 0; i < rows; i++)
325 offsets[0][i] = get_random_number(8, &seed[i]);
326
327 // x/y block offsets to compensate for overlapped regions
328 const int ystart = data->overlap_flag && row_num ? imin(2 >> sy, bh) : 0;
329 const int xstart = data->overlap_flag && bx ? imin(2 >> sx, bw) : 0;
330
331 static const int w[2 /* sub */][2 /* off */][2] = {
332 { { 27, 17 }, { 17, 27 } },
333 { { 23, 22 } },
334 };
335
336#define add_noise_uv(x, y, grain)const int lx = (bx + x) << sx; const int ly = y <<
sy; const pixel *const luma = luma_row + ly * (luma_stride) +
lx; pixel avg = luma[0]; if (sx) avg = (avg + luma[1] + 1) >>
1; const pixel *const src = src_row + (y) * (stride) + (bx +
(x)); pixel *const dst = dst_row + (y) * (stride) + (bx + (x
)); int val = avg; if (!data->chroma_scaling_from_luma) { const
int combined = avg * data->uv_luma_mult[uv] + *src * data
->uv_mult[uv]; val = iclip_u8( (combined >> 6) + (data
->uv_offset[uv] * (1 << bitdepth_min_8)) ); } const int
noise = round2(scaling[ val ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
\
337 const int lx = (bx + x) << sx; \
338 const int ly = y << sy; \
339 const pixel *const luma = luma_row + ly * PXSTRIDE(luma_stride)(luma_stride) + lx; \
340 pixel avg = luma[0]; \
341 if (sx) \
342 avg = (avg + luma[1] + 1) >> 1; \
343 const pixel *const src = src_row + (y) * PXSTRIDE(stride)(stride) + (bx + (x)); \
344 pixel *const dst = dst_row + (y) * PXSTRIDE(stride)(stride) + (bx + (x)); \
345 int val = avg; \
346 if (!data->chroma_scaling_from_luma) { \
347 const int combined = avg * data->uv_luma_mult[uv] + \
348 *src * data->uv_mult[uv]; \
349 val = iclip_pixeliclip_u8( (combined >> 6) + \
350 (data->uv_offset[uv] * (1 << bitdepth_min_8)) ); \
351 } \
352 const int noise = round2(scaling[ val ] * (grain), data->scaling_shift); \
353 *dst = iclip(*src + noise, min_value, max_value);
354
355 for (int y = ystart; y < bh; y++) {
356 // Non-overlapped image region (straightforward)
357 for (int x = xstart; x < bw; x++) {
358 int grain = sample_lut(grain_lut, offsets, sx, sy, 0, 0, x, y);
359 add_noise_uv(x, y, grain)const int lx = (bx + x) << sx; const int ly = y <<
sy; const pixel *const luma = luma_row + ly * (luma_stride) +
lx; pixel avg = luma[0]; if (sx) avg = (avg + luma[1] + 1) >>
1; const pixel *const src = src_row + (y) * (stride) + (bx +
(x)); pixel *const dst = dst_row + (y) * (stride) + (bx + (x
)); int val = avg; if (!data->chroma_scaling_from_luma) { const
int combined = avg * data->uv_luma_mult[uv] + *src * data
->uv_mult[uv]; val = iclip_u8( (combined >> 6) + (data
->uv_offset[uv] * (1 << bitdepth_min_8)) ); } const int
noise = round2(scaling[ val ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
360 }
361
362 // Special case for overlapped column
363 for (int x = 0; x < xstart; x++) {
364 int grain = sample_lut(grain_lut, offsets, sx, sy, 0, 0, x, y);
365 int old = sample_lut(grain_lut, offsets, sx, sy, 1, 0, x, y);
366 grain = round2(old * w[sx][x][0] + grain * w[sx][x][1], 5);
367 grain = iclip(grain, grain_min, grain_max);
368 add_noise_uv(x, y, grain)const int lx = (bx + x) << sx; const int ly = y <<
sy; const pixel *const luma = luma_row + ly * (luma_stride) +
lx; pixel avg = luma[0]; if (sx) avg = (avg + luma[1] + 1) >>
1; const pixel *const src = src_row + (y) * (stride) + (bx +
(x)); pixel *const dst = dst_row + (y) * (stride) + (bx + (x
)); int val = avg; if (!data->chroma_scaling_from_luma) { const
int combined = avg * data->uv_luma_mult[uv] + *src * data
->uv_mult[uv]; val = iclip_u8( (combined >> 6) + (data
->uv_offset[uv] * (1 << bitdepth_min_8)) ); } const int
noise = round2(scaling[ val ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
369 }
370 }
371
372 for (int y = 0; y < ystart; y++) {
373 // Special case for overlapped row (sans corner)
374 for (int x = xstart; x < bw; x++) {
375 int grain = sample_lut(grain_lut, offsets, sx, sy, 0, 0, x, y);
376 int old = sample_lut(grain_lut, offsets, sx, sy, 0, 1, x, y);
377 grain = round2(old * w[sy][y][0] + grain * w[sy][y][1], 5);
378 grain = iclip(grain, grain_min, grain_max);
379 add_noise_uv(x, y, grain)const int lx = (bx + x) << sx; const int ly = y <<
sy; const pixel *const luma = luma_row + ly * (luma_stride) +
lx; pixel avg = luma[0]; if (sx) avg = (avg + luma[1] + 1) >>
1; const pixel *const src = src_row + (y) * (stride) + (bx +
(x)); pixel *const dst = dst_row + (y) * (stride) + (bx + (x
)); int val = avg; if (!data->chroma_scaling_from_luma) { const
int combined = avg * data->uv_luma_mult[uv] + *src * data
->uv_mult[uv]; val = iclip_u8( (combined >> 6) + (data
->uv_offset[uv] * (1 << bitdepth_min_8)) ); } const int
noise = round2(scaling[ val ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
380 }
381
382 // Special case for doubly-overlapped corner
383 for (int x = 0; x < xstart; x++) {
384 // Blend the top pixel with the top left block
385 int top = sample_lut(grain_lut, offsets, sx, sy, 0, 1, x, y);
386 int old = sample_lut(grain_lut, offsets, sx, sy, 1, 1, x, y);
387 top = round2(old * w[sx][x][0] + top * w[sx][x][1], 5);
388 top = iclip(top, grain_min, grain_max);
389
390 // Blend the current pixel with the left block
391 int grain = sample_lut(grain_lut, offsets, sx, sy, 0, 0, x, y);
392 old = sample_lut(grain_lut, offsets, sx, sy, 1, 0, x, y);
393 grain = round2(old * w[sx][x][0] + grain * w[sx][x][1], 5);
394 grain = iclip(grain, grain_min, grain_max);
395
396 // Mix the row rows together and apply to image
397 grain = round2(top * w[sy][y][0] + grain * w[sy][y][1], 5);
398 grain = iclip(grain, grain_min, grain_max);
399 add_noise_uv(x, y, grain)const int lx = (bx + x) << sx; const int ly = y <<
sy; const pixel *const luma = luma_row + ly * (luma_stride) +
lx; pixel avg = luma[0]; if (sx) avg = (avg + luma[1] + 1) >>
1; const pixel *const src = src_row + (y) * (stride) + (bx +
(x)); pixel *const dst = dst_row + (y) * (stride) + (bx + (x
)); int val = avg; if (!data->chroma_scaling_from_luma) { const
int combined = avg * data->uv_luma_mult[uv] + *src * data
->uv_mult[uv]; val = iclip_u8( (combined >> 6) + (data
->uv_offset[uv] * (1 << bitdepth_min_8)) ); } const int
noise = round2(scaling[ val ] * (grain), data->scaling_shift
); *dst = iclip(*src + noise, min_value, max_value);
;
400 }
401 }
402 }
403}
404
405#define fguv_ss_fn(nm, ss_x, ss_y)static void (fguv_32x32xn_nm_c)(pixel *dst_row, const pixel *
src_row, ptrdiff_t stride, const Dav1dFilmGrainData *data, size_t
pw, const uint8_t scaling[256], const entry grain_lut[][82],
int bh, int row_num, const pixel *luma_row, ptrdiff_t luma_stride
, int uv_pl, int is_id ) { fguv_32x32xn_c(dst_row, src_row, stride
, data, pw, scaling, grain_lut, bh, row_num, luma_row, luma_stride
, uv_pl, is_id, ss_x, ss_y ); }
\
406static decl_fguv_32x32xn_fn(fguv_32x32xn_##nm##_c)void (fguv_32x32xn_##nm##_c)(pixel *dst_row, const pixel *src_row
, ptrdiff_t stride, const Dav1dFilmGrainData *data, size_t pw
, const uint8_t scaling[256], const entry grain_lut[][82], int
bh, int row_num, const pixel *luma_row, ptrdiff_t luma_stride
, int uv_pl, int is_id )
{ \
407 fguv_32x32xn_c(dst_row, src_row, stride, data, pw, scaling, grain_lut, bh, \
408 row_num, luma_row, luma_stride, uv_pl, is_id, ss_x, ss_y \
409 HIGHBD_TAIL_SUFFIX); \
410}
411
412fguv_ss_fn(420, 1, 1)static void (fguv_32x32xn_420_c)(pixel *dst_row, const pixel *
src_row, ptrdiff_t stride, const Dav1dFilmGrainData *data, size_t
pw, const uint8_t scaling[256], const entry grain_lut[][82],
int bh, int row_num, const pixel *luma_row, ptrdiff_t luma_stride
, int uv_pl, int is_id ) { fguv_32x32xn_c(dst_row, src_row, stride
, data, pw, scaling, grain_lut, bh, row_num, luma_row, luma_stride
, uv_pl, is_id, 1, 1 ); }
;
413fguv_ss_fn(422, 1, 0)static void (fguv_32x32xn_422_c)(pixel *dst_row, const pixel *
src_row, ptrdiff_t stride, const Dav1dFilmGrainData *data, size_t
pw, const uint8_t scaling[256], const entry grain_lut[][82],
int bh, int row_num, const pixel *luma_row, ptrdiff_t luma_stride
, int uv_pl, int is_id ) { fguv_32x32xn_c(dst_row, src_row, stride
, data, pw, scaling, grain_lut, bh, row_num, luma_row, luma_stride
, uv_pl, is_id, 1, 0 ); }
;
414fguv_ss_fn(444, 0, 0)static void (fguv_32x32xn_444_c)(pixel *dst_row, const pixel *
src_row, ptrdiff_t stride, const Dav1dFilmGrainData *data, size_t
pw, const uint8_t scaling[256], const entry grain_lut[][82],
int bh, int row_num, const pixel *luma_row, ptrdiff_t luma_stride
, int uv_pl, int is_id ) { fguv_32x32xn_c(dst_row, src_row, stride
, data, pw, scaling, grain_lut, bh, row_num, luma_row, luma_stride
, uv_pl, is_id, 0, 0 ); }
;
415
416#if HAVE_ASM1
417#if ARCH_AARCH640 || ARCH_ARM0
418#include "src/arm/filmgrain.h"
419#elif ARCH_X861
420#include "src/x86/filmgrain.h"
421#elif ARCH_RISCV
422#include "src/riscv/filmgrain.h"
423#endif
424#endif
425
426COLD__attribute__((cold)) void bitfn(dav1d_film_grain_dsp_init)dav1d_film_grain_dsp_init_8bpc(Dav1dFilmGrainDSPContext *const c) {
427 c->generate_grain_y = generate_grain_y_c;
428 c->generate_grain_uv[DAV1D_PIXEL_LAYOUT_I420 - 1] = generate_grain_uv_420_c;
429 c->generate_grain_uv[DAV1D_PIXEL_LAYOUT_I422 - 1] = generate_grain_uv_422_c;
430 c->generate_grain_uv[DAV1D_PIXEL_LAYOUT_I444 - 1] = generate_grain_uv_444_c;
431
432 c->fgy_32x32xn = fgy_32x32xn_c;
433 c->fguv_32x32xn[DAV1D_PIXEL_LAYOUT_I420 - 1] = fguv_32x32xn_420_c;
434 c->fguv_32x32xn[DAV1D_PIXEL_LAYOUT_I422 - 1] = fguv_32x32xn_422_c;
435 c->fguv_32x32xn[DAV1D_PIXEL_LAYOUT_I444 - 1] = fguv_32x32xn_444_c;
436
437#if HAVE_ASM1
438#if ARCH_AARCH640 || ARCH_ARM0
439 film_grain_dsp_init_arm(c);
440#elif ARCH_X861
441 film_grain_dsp_init_x86(c);
442#elif ARCH_RISCV
443 film_grain_dsp_init_riscv(c);
444#endif
445#endif
446}