FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/intrax8dsp.c
Date: 2025-03-08 20:38:41
Exec Total Coverage
Lines: 230 230 100.0%
Functions: 17 17 100.0%
Branches: 98 98 100.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 *@brief IntraX8 frame subdecoder image manipulation routines
22 */
23
24 #include "intrax8dsp.h"
25 #include "libavutil/common.h"
26 #include "libavutil/intreadwrite.h"
27
28 /*
29 * area positions, #3 is 1 pixel only, other are 8 pixels
30 * |66666666|
31 * 3|44444444|55555555|
32 * - -+--------+--------+
33 * 1 2|XXXXXXXX|
34 * 1 2|XXXXXXXX|
35 * 1 2|XXXXXXXX|
36 * 1 2|XXXXXXXX|
37 * 1 2|XXXXXXXX|
38 * 1 2|XXXXXXXX|
39 * 1 2|XXXXXXXX|
40 * 1 2|XXXXXXXX|
41 * ^-start
42 */
43
44 #define area1 (0)
45 #define area2 (8)
46 #define area3 (8 + 8)
47 #define area4 (8 + 8 + 1)
48 #define area5 (8 + 8 + 1 + 8)
49 #define area6 (8 + 8 + 1 + 16)
50
51 /**
52 Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
53
54 * @param src pointer to the beginning of the processed block
55 * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.
56 * @param linesize byte offset between 2 vertical pixels in the source image
57 * @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
58 * @param psum pointer to the variable where the edge pixel sum is to be stored
59 * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels.
60 and some of the edge pixels should be interpolated, the flag has the following meaning:
61 1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3;
62 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
63 note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
64 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
65 -*/
66 5400 static void x8_setup_spatial_compensation(const uint8_t *restrict src,
67 uint8_t *restrict dst,
68 ptrdiff_t stride, int *range,
69 int *psum, int edges)
70 {
71 const uint8_t *ptr;
72 int sum;
73 int i;
74 int min_pix, max_pix;
75 uint8_t c;
76
77
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5391 times.
5400 if ((edges & 3) == 3) {
78 9 *psum = 0x80 * (8 + 1 + 8 + 2);
79 9 *range = 0;
80 9 memset(dst, 0x80, 16 + 1 + 16 + 8);
81 /* this triggers flat_dc for sure. flat_dc avoids all (other)
82 * prediction modes, but requires dc_level decoding. */
83 9 return;
84 }
85
86 5391 min_pix = 256;
87 5391 max_pix = -1;
88
89 5391 sum = 0;
90
91
2/2
✓ Branch 0 taken 5220 times.
✓ Branch 1 taken 171 times.
5391 if (!(edges & 1)) { // (mb_x != 0) // there is previous block on this row
92 5220 ptr = src - 1; // left column, area 2
93
2/2
✓ Branch 0 taken 41760 times.
✓ Branch 1 taken 5220 times.
46980 for (i = 7; i >= 0; i--) {
94 41760 c = *(ptr - 1); // area1, same mb as area2, no need to check
95 41760 dst[area1 + i] = c;
96 41760 c = *ptr;
97
98 41760 sum += c;
99 41760 min_pix = FFMIN(min_pix, c);
100 41760 max_pix = FFMAX(max_pix, c);
101 41760 dst[area2 + i] = c;
102
103 41760 ptr += stride;
104 }
105 }
106
107
2/2
✓ Branch 0 taken 5160 times.
✓ Branch 1 taken 231 times.
5391 if (!(edges & 2)) { // (mb_y != 0) // there is row above
108 5160 ptr = src - stride; // top line
109
2/2
✓ Branch 0 taken 41280 times.
✓ Branch 1 taken 5160 times.
46440 for (i = 0; i < 8; i++) {
110 41280 c = *(ptr + i);
111 41280 sum += c;
112 41280 min_pix = FFMIN(min_pix, c);
113 41280 max_pix = FFMAX(max_pix, c);
114 }
115
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 4989 times.
5160 if (edges & 4) { // last block on the row?
116 171 memset(dst + area5, c, 8); // set with last pixel fr
117 171 memcpy(dst + area4, ptr, 8);
118 } else {
119 4989 memcpy(dst + area4, ptr, 16); // both area4 and 5
120 }
121 // area6 always present in the above block
122 5160 memcpy(dst + area6, ptr - stride, 8);
123 }
124 // now calculate the stuff we need
125
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 4989 times.
5391 if (edges & 3) { // mb_x ==0 || mb_y == 0) {
126 402 int avg = (sum + 4) >> 3;
127
128
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 231 times.
402 if (edges & 1) // (mb_x == 0) { // implies mb_y !=0
129 171 memset(dst + area1, avg, 8 + 8 + 1); // areas 1, 2, 3 are averaged
130 else // implies y == 0 x != 0
131 231 memset(dst + area3, avg, 1 + 16 + 8); // areas 3, 4, 5, 6
132
133 402 sum += avg * 9;
134 } else {
135 // the edge pixel, in the top line and left column
136 4989 uint8_t c = *(src - 1 - stride);
137 4989 dst[area3] = c;
138 4989 sum += c;
139 // edge pixel is not part of min/max
140 }
141 5391 *range = max_pix - min_pix;
142 5391 sum += *(dst + area5) + *(dst + area5 + 1);
143 5391 *psum = sum;
144 }
145
146 static const uint16_t zero_prediction_weights[64 * 2] = {
147 640, 640, 669, 480, 708, 354, 748, 257,
148 792, 198, 760, 143, 808, 101, 772, 72,
149 480, 669, 537, 537, 598, 416, 661, 316,
150 719, 250, 707, 185, 768, 134, 745, 97,
151 354, 708, 416, 598, 488, 488, 564, 388,
152 634, 317, 642, 241, 716, 179, 706, 132,
153 257, 748, 316, 661, 388, 564, 469, 469,
154 543, 395, 571, 311, 655, 238, 660, 180,
155 198, 792, 250, 719, 317, 634, 395, 543,
156 469, 469, 507, 380, 597, 299, 616, 231,
157 161, 855, 206, 788, 266, 710, 340, 623,
158 411, 548, 455, 455, 548, 366, 576, 288,
159 122, 972, 159, 914, 211, 842, 276, 758,
160 341, 682, 389, 584, 483, 483, 520, 390,
161 110, 1172, 144, 1107, 193, 1028, 254, 932,
162 317, 846, 366, 731, 458, 611, 499, 499,
163 };
164
165 2794 static void spatial_compensation_0(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
166 {
167 int i, j;
168 int x, y;
169 unsigned int p; // power divided by 2
170 int a;
171 2794 uint16_t left_sum[2][8] = { { 0 } };
172 2794 uint16_t top_sum[2][8] = { { 0 } };
173
174
2/2
✓ Branch 0 taken 22352 times.
✓ Branch 1 taken 2794 times.
25146 for (i = 0; i < 8; i++) {
175 22352 a = src[area2 + 7 - i] << 4;
176
2/2
✓ Branch 0 taken 178816 times.
✓ Branch 1 taken 22352 times.
201168 for (j = 0; j < 8; j++) {
177 178816 p = abs(i - j);
178 178816 left_sum[p & 1][j] += a >> (p >> 1);
179 }
180 }
181
182
2/2
✓ Branch 0 taken 22352 times.
✓ Branch 1 taken 2794 times.
25146 for (i = 0; i < 8; i++) {
183 22352 a = src[area4 + i] << 4;
184
2/2
✓ Branch 0 taken 178816 times.
✓ Branch 1 taken 22352 times.
201168 for (j = 0; j < 8; j++) {
185 178816 p = abs(i - j);
186 178816 top_sum[p & 1][j] += a >> (p >> 1);
187 }
188 }
189
2/2
✓ Branch 0 taken 5588 times.
✓ Branch 1 taken 2794 times.
8382 for (; i < 10; i++) {
190 5588 a = src[area4 + i] << 4;
191
2/2
✓ Branch 0 taken 16764 times.
✓ Branch 1 taken 5588 times.
22352 for (j = 5; j < 8; j++) {
192 16764 p = abs(i - j);
193 16764 top_sum[p & 1][j] += a >> (p >> 1);
194 }
195 }
196
2/2
✓ Branch 0 taken 5588 times.
✓ Branch 1 taken 2794 times.
8382 for (; i < 12; i++) {
197 5588 a = src[area4 + i] << 4;
198
2/2
✓ Branch 0 taken 5588 times.
✓ Branch 1 taken 5588 times.
11176 for (j = 7; j < 8; j++) {
199 5588 p = abs(i - j);
200 5588 top_sum[p & 1][j] += a >> (p >> 1);
201 }
202 }
203
204
2/2
✓ Branch 0 taken 22352 times.
✓ Branch 1 taken 2794 times.
25146 for (i = 0; i < 8; i++) {
205 22352 top_sum[0][i] += (top_sum[1][i] * 181 + 128) >> 8; // 181 is sqrt(2)/2
206 22352 left_sum[0][i] += (left_sum[1][i] * 181 + 128) >> 8;
207 }
208
2/2
✓ Branch 0 taken 22352 times.
✓ Branch 1 taken 2794 times.
25146 for (y = 0; y < 8; y++) {
209
2/2
✓ Branch 0 taken 178816 times.
✓ Branch 1 taken 22352 times.
201168 for (x = 0; x < 8; x++)
210 178816 dst[x] = ((uint32_t) top_sum[0][x] * zero_prediction_weights[y * 16 + x * 2 + 0] +
211 178816 (uint32_t) left_sum[0][y] * zero_prediction_weights[y * 16 + x * 2 + 1] +
212 178816 0x8000) >> 16;
213 22352 dst += stride;
214 }
215 2794 }
216
217 9 static void spatial_compensation_1(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
218 {
219 int x, y;
220
221
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 9 times.
81 for (y = 0; y < 8; y++) {
222
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 72 times.
648 for (x = 0; x < 8; x++)
223 576 dst[x] = src[area4 + FFMIN(2 * y + x + 2, 15)];
224 72 dst += stride;
225 }
226 9 }
227
228 19 static void spatial_compensation_2(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
229 {
230
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 19 times.
171 for (int y = 0; y < 8; y++) {
231 152 AV_COPY64U(dst, src + area4 + 1 + y);
232 152 dst += stride;
233 }
234 19 }
235
236 25 static void spatial_compensation_3(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
237 {
238
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 25 times.
225 for (int y = 0; y < 8; y++) {
239 200 AV_COPY64U(dst, src + area4 + ((y + 1) >> 1));
240 200 dst += stride;
241 }
242 25 }
243
244 212 static void spatial_compensation_4(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
245 {
246 int x, y;
247
248
2/2
✓ Branch 0 taken 1696 times.
✓ Branch 1 taken 212 times.
1908 for (y = 0; y < 8; y++) {
249
2/2
✓ Branch 0 taken 13568 times.
✓ Branch 1 taken 1696 times.
15264 for (x = 0; x < 8; x++)
250 13568 dst[x] = (src[area4 + x] + src[area6 + x] + 1) >> 1;
251 1696 dst += stride;
252 }
253 212 }
254
255 22 static void spatial_compensation_5(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
256 {
257 int x, y;
258
259
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 22 times.
198 for (y = 0; y < 8; y++) {
260
2/2
✓ Branch 0 taken 1408 times.
✓ Branch 1 taken 176 times.
1584 for (x = 0; x < 8; x++) {
261
2/2
✓ Branch 0 taken 352 times.
✓ Branch 1 taken 1056 times.
1408 if (2 * x - y < 0)
262 352 dst[x] = src[area2 + 9 + 2 * x - y];
263 else
264 1056 dst[x] = src[area4 + x - ((y + 1) >> 1)];
265 }
266 176 dst += stride;
267 }
268 22 }
269
270 19 static void spatial_compensation_6(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
271 {
272
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 19 times.
171 for (int y = 0; y < 8; y++) {
273 152 AV_COPY64U(dst, src + area3 - y);
274 152 dst += stride;
275 }
276 19 }
277
278 12 static void spatial_compensation_7(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
279 {
280 int x, y;
281
282
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 12 times.
108 for (y = 0; y < 8; y++) {
283
2/2
✓ Branch 0 taken 768 times.
✓ Branch 1 taken 96 times.
864 for (x = 0; x < 8; x++) {
284
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 576 times.
768 if (x - 2 * y > 0)
285 192 dst[x] = (src[area3 - 1 + x - 2 * y] + src[area3 + x - 2 * y] + 1) >> 1;
286 else
287 576 dst[x] = src[area2 + 8 - y + (x >> 1)];
288 }
289 96 dst += stride;
290 }
291 12 }
292
293 568 static void spatial_compensation_8(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
294 {
295 int x, y;
296
297
2/2
✓ Branch 0 taken 4544 times.
✓ Branch 1 taken 568 times.
5112 for (y = 0; y < 8; y++) {
298
2/2
✓ Branch 0 taken 36352 times.
✓ Branch 1 taken 4544 times.
40896 for (x = 0; x < 8; x++)
299 36352 dst[x] = (src[area1 + 7 - y] + src[area2 + 7 - y] + 1) >> 1;
300 4544 dst += stride;
301 }
302 568 }
303
304 31 static void spatial_compensation_9(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
305 {
306 int x, y;
307
308
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 31 times.
279 for (y = 0; y < 8; y++) {
309
2/2
✓ Branch 0 taken 1984 times.
✓ Branch 1 taken 248 times.
2232 for (x = 0; x < 8; x++)
310 1984 dst[x] = src[area2 + 6 - FFMIN(x + y, 6)];
311 248 dst += stride;
312 }
313 31 }
314
315 163 static void spatial_compensation_10(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
316 {
317 int x, y;
318
319
2/2
✓ Branch 0 taken 1304 times.
✓ Branch 1 taken 163 times.
1467 for (y = 0; y < 8; y++) {
320
2/2
✓ Branch 0 taken 10432 times.
✓ Branch 1 taken 1304 times.
11736 for (x = 0; x < 8; x++)
321 10432 dst[x] = (src[area2 + 7 - y] * (8 - x) + src[area4 + x] * x + 4) >> 3;
322 1304 dst += stride;
323 }
324 163 }
325
326 161 static void spatial_compensation_11(const uint8_t *restrict src, uint8_t *restrict dst, ptrdiff_t stride)
327 {
328 int x, y;
329
330
2/2
✓ Branch 0 taken 1288 times.
✓ Branch 1 taken 161 times.
1449 for (y = 0; y < 8; y++) {
331
2/2
✓ Branch 0 taken 10304 times.
✓ Branch 1 taken 1288 times.
11592 for (x = 0; x < 8; x++)
332 10304 dst[x] = (src[area2 + 7 - y] * y + src[area4 + x] * (8 - y) + 4) >> 3;
333 1288 dst += stride;
334 }
335 161 }
336
337 9685 static void x8_loop_filter(uint8_t *ptr, const ptrdiff_t a_stride,
338 const ptrdiff_t b_stride, int quant)
339 {
340 int i, t;
341 int p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
342 9685 int ql = (quant + 10) >> 3;
343
344
2/2
✓ Branch 0 taken 77480 times.
✓ Branch 1 taken 9685 times.
87165 for (i = 0; i < 8; i++, ptr += b_stride) {
345 77480 p0 = ptr[-5 * a_stride];
346 77480 p1 = ptr[-4 * a_stride];
347 77480 p2 = ptr[-3 * a_stride];
348 77480 p3 = ptr[-2 * a_stride];
349 77480 p4 = ptr[-1 * a_stride];
350 77480 p5 = ptr[0];
351 77480 p6 = ptr[1 * a_stride];
352 77480 p7 = ptr[2 * a_stride];
353 77480 p8 = ptr[3 * a_stride];
354 77480 p9 = ptr[4 * a_stride];
355
356 77480 t = (FFABS(p1 - p2) <= ql) +
357 77480 (FFABS(p2 - p3) <= ql) +
358 77480 (FFABS(p3 - p4) <= ql) +
359 77480 (FFABS(p4 - p5) <= ql);
360
361 // You need at least 1 to be able to reach a total score of 6.
362
2/2
✓ Branch 0 taken 70608 times.
✓ Branch 1 taken 6872 times.
77480 if (t > 0) {
363 70608 t += (FFABS(p5 - p6) <= ql) +
364 70608 (FFABS(p6 - p7) <= ql) +
365 70608 (FFABS(p7 - p8) <= ql) +
366 70608 (FFABS(p8 - p9) <= ql) +
367 70608 (FFABS(p0 - p1) <= ql);
368
2/2
✓ Branch 0 taken 58950 times.
✓ Branch 1 taken 11658 times.
70608 if (t >= 6) {
369 int min, max;
370
371 58950 min = max = p1;
372 58950 min = FFMIN(min, p3);
373 58950 max = FFMAX(max, p3);
374 58950 min = FFMIN(min, p5);
375 58950 max = FFMAX(max, p5);
376 58950 min = FFMIN(min, p8);
377 58950 max = FFMAX(max, p8);
378
2/2
✓ Branch 0 taken 57738 times.
✓ Branch 1 taken 1212 times.
58950 if (max - min < 2 * quant) { // early stop
379 57738 min = FFMIN(min, p2);
380 57738 max = FFMAX(max, p2);
381 57738 min = FFMIN(min, p4);
382 57738 max = FFMAX(max, p4);
383 57738 min = FFMIN(min, p6);
384 57738 max = FFMAX(max, p6);
385 57738 min = FFMIN(min, p7);
386 57738 max = FFMAX(max, p7);
387
2/2
✓ Branch 0 taken 57642 times.
✓ Branch 1 taken 96 times.
57738 if (max - min < 2 * quant) {
388 57642 ptr[-2 * a_stride] = (4 * p2 + 3 * p3 + 1 * p7 + 4) >> 3;
389 57642 ptr[-1 * a_stride] = (3 * p2 + 3 * p4 + 2 * p7 + 4) >> 3;
390 57642 ptr[0] = (2 * p2 + 3 * p5 + 3 * p7 + 4) >> 3;
391 57642 ptr[1 * a_stride] = (1 * p2 + 3 * p6 + 4 * p7 + 4) >> 3;
392 57642 continue;
393 }
394 }
395 }
396 }
397 {
398 int x, x0, x1, x2;
399 int m;
400
401 19838 x0 = (2 * p3 - 5 * p4 + 5 * p5 - 2 * p6 + 4) >> 3;
402
2/2
✓ Branch 0 taken 16362 times.
✓ Branch 1 taken 3476 times.
19838 if (FFABS(x0) < quant) {
403 16362 x1 = (2 * p1 - 5 * p2 + 5 * p3 - 2 * p4 + 4) >> 3;
404 16362 x2 = (2 * p5 - 5 * p6 + 5 * p7 - 2 * p8 + 4) >> 3;
405
406 16362 x = FFABS(x0) - FFMIN(FFABS(x1), FFABS(x2));
407 16362 m = p4 - p5;
408
409
4/4
✓ Branch 0 taken 13366 times.
✓ Branch 1 taken 2996 times.
✓ Branch 2 taken 11380 times.
✓ Branch 3 taken 1986 times.
16362 if (x > 0 && (m ^ x0) < 0) {
410 int32_t sign;
411
412 11380 sign = m >> 31;
413 11380 m = (m ^ sign) - sign; // abs(m)
414 11380 m >>= 1;
415
416 11380 x = 5 * x >> 3;
417
418
2/2
✓ Branch 0 taken 871 times.
✓ Branch 1 taken 10509 times.
11380 if (x > m)
419 871 x = m;
420
421 11380 x = (x ^ sign) - sign;
422
423 11380 ptr[-1 * a_stride] -= x;
424 11380 ptr[0] += x;
425 }
426 }
427 }
428 }
429 9685 }
430
431 4836 static void x8_h_loop_filter(uint8_t *src, ptrdiff_t stride, int qscale)
432 {
433 4836 x8_loop_filter(src, stride, 1, qscale);
434 4836 }
435
436 4849 static void x8_v_loop_filter(uint8_t *src, ptrdiff_t stride, int qscale)
437 {
438 4849 x8_loop_filter(src, 1, stride, qscale);
439 4849 }
440
441 46 av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp)
442 {
443 46 dsp->h_loop_filter = x8_h_loop_filter;
444 46 dsp->v_loop_filter = x8_v_loop_filter;
445 46 dsp->setup_spatial_compensation = x8_setup_spatial_compensation;
446 46 dsp->spatial_compensation[0] = spatial_compensation_0;
447 46 dsp->spatial_compensation[1] = spatial_compensation_1;
448 46 dsp->spatial_compensation[2] = spatial_compensation_2;
449 46 dsp->spatial_compensation[3] = spatial_compensation_3;
450 46 dsp->spatial_compensation[4] = spatial_compensation_4;
451 46 dsp->spatial_compensation[5] = spatial_compensation_5;
452 46 dsp->spatial_compensation[6] = spatial_compensation_6;
453 46 dsp->spatial_compensation[7] = spatial_compensation_7;
454 46 dsp->spatial_compensation[8] = spatial_compensation_8;
455 46 dsp->spatial_compensation[9] = spatial_compensation_9;
456 46 dsp->spatial_compensation[10] = spatial_compensation_10;
457 46 dsp->spatial_compensation[11] = spatial_compensation_11;
458 46 }
459