FFmpeg coverage


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