GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/intrax8dsp.c Lines: 233 233 100.0 %
Date: 2019-11-18 18:00:01 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
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
5391
    if (!(edges & 1)) { // (mb_x != 0) // there is previous block on this row
90
5220
        ptr = src - 1; // left column, area 2
91
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
5391
    if (!(edges & 2)) { // (mb_y != 0) // there is row above
106
5160
        ptr = src - stride; // top line
107
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
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
5391
    if (edges & 3) { // mb_x ==0 || mb_y == 0) {
124
402
        int avg = (sum + 4) >> 3;
125
126
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
25146
    for (i = 0; i < 8; i++) {
173
22352
        a = src[area2 + 7 - i] << 4;
174
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
25146
    for (i = 0; i < 8; i++) {
181
22352
        a = src[area4 + i] << 4;
182
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
8382
    for (; i < 10; i++) {
188
5588
        a = src[area4 + i] << 4;
189
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
8382
    for (; i < 12; i++) {
195
5588
        a = src[area4 + i] << 4;
196
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
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
25146
    for (y = 0; y < 8; y++) {
207
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
81
    for (y = 0; y < 8; y++) {
220
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
171
    for (y = 0; y < 8; y++) {
231
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
225
    for (y = 0; y < 8; y++) {
242
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
1908
    for (y = 0; y < 8; y++) {
253
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
198
    for (y = 0; y < 8; y++) {
264
1584
        for (x = 0; x < 8; x++) {
265
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
171
    for (y = 0; y < 8; y++) {
279
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
108
    for (y = 0; y < 8; y++) {
290
864
        for (x = 0; x < 8; x++) {
291
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
5112
    for (y = 0; y < 8; y++) {
305
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
279
    for (y = 0; y < 8; y++) {
316
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
1467
    for (y = 0; y < 8; y++) {
327
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
1449
    for (y = 0; y < 8; y++) {
338
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
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
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
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
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
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
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

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
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
54
av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp)
449
{
450
54
    dsp->h_loop_filter              = x8_h_loop_filter;
451
54
    dsp->v_loop_filter              = x8_v_loop_filter;
452
54
    dsp->setup_spatial_compensation = x8_setup_spatial_compensation;
453
54
    dsp->spatial_compensation[0]    = spatial_compensation_0;
454
54
    dsp->spatial_compensation[1]    = spatial_compensation_1;
455
54
    dsp->spatial_compensation[2]    = spatial_compensation_2;
456
54
    dsp->spatial_compensation[3]    = spatial_compensation_3;
457
54
    dsp->spatial_compensation[4]    = spatial_compensation_4;
458
54
    dsp->spatial_compensation[5]    = spatial_compensation_5;
459
54
    dsp->spatial_compensation[6]    = spatial_compensation_6;
460
54
    dsp->spatial_compensation[7]    = spatial_compensation_7;
461
54
    dsp->spatial_compensation[8]    = spatial_compensation_8;
462
54
    dsp->spatial_compensation[9]    = spatial_compensation_9;
463
54
    dsp->spatial_compensation[10]   = spatial_compensation_10;
464
54
    dsp->spatial_compensation[11]   = spatial_compensation_11;
465
54
}