Coverage Report

Created: 2026-09-06 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dav1d/src/ipred_prepare_tmpl.c
Line
Count
Source
1
/*
2
 * Copyright © 2018, VideoLAN and dav1d authors
3
 * Copyright © 2018, Two Orioles, LLC
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice, this
10
 *    list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *    this list of conditions and the following disclaimer in the documentation
14
 *    and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
#include "config.h"
29
30
#include <stdint.h>
31
#include <string.h>
32
33
#include "common/intops.h"
34
35
#include "src/ipred_prepare.h"
36
37
static const uint8_t av1_mode_conv[N_INTRA_PRED_MODES]
38
                                  [2 /* have_left */][2 /* have_top */] =
39
{
40
    [DC_PRED]    = { { DC_128_PRED,  TOP_DC_PRED },
41
                     { LEFT_DC_PRED, DC_PRED     } },
42
    [PAETH_PRED] = { { DC_128_PRED,  VERT_PRED   },
43
                     { HOR_PRED,     PAETH_PRED  } },
44
};
45
46
static const uint8_t av1_mode_to_angle_map[8] = {
47
    90, 180, 45, 135, 113, 157, 203, 67
48
};
49
50
static const struct {
51
    uint8_t needs_left:1;
52
    uint8_t needs_top:1;
53
    uint8_t needs_topleft:1;
54
    uint8_t needs_topright:1;
55
    uint8_t needs_bottomleft:1;
56
} av1_intra_prediction_edges[N_IMPL_INTRA_PRED_MODES] = {
57
    [DC_PRED]       = { .needs_top  = 1, .needs_left = 1 },
58
    [VERT_PRED]     = { .needs_top  = 1 },
59
    [HOR_PRED]      = { .needs_left = 1 },
60
    [LEFT_DC_PRED]  = { .needs_left = 1 },
61
    [TOP_DC_PRED]   = { .needs_top  = 1 },
62
    [DC_128_PRED]   = { 0 },
63
    [Z1_PRED]       = { .needs_top = 1, .needs_topright = 1,
64
                        .needs_topleft = 1 },
65
    [Z2_PRED]       = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 },
66
    [Z3_PRED]       = { .needs_left = 1, .needs_bottomleft = 1,
67
                        .needs_topleft = 1 },
68
    [SMOOTH_PRED]   = { .needs_left = 1, .needs_top = 1 },
69
    [SMOOTH_V_PRED] = { .needs_left = 1, .needs_top = 1 },
70
    [SMOOTH_H_PRED] = { .needs_left = 1, .needs_top = 1 },
71
    [PAETH_PRED]    = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 },
72
    [FILTER_PRED]   = { .needs_left = 1, .needs_top = 1, .needs_topleft = 1 },
73
};
74
75
enum IntraPredMode
76
bytefn(dav1d_prepare_intra_edges)(const int x, const int have_left,
77
                                  const int y, const int have_top,
78
                                  const int w, const int h,
79
                                  const enum EdgeFlags edge_flags,
80
                                  const pixel *const dst,
81
                                  const ptrdiff_t stride,
82
                                  const pixel *prefilter_toplevel_sb_edge,
83
                                  enum IntraPredMode mode, int *const angle,
84
                                  const int tw, const int th, const int filter_edge,
85
                                  pixel *const topleft_out HIGHBD_DECL_SUFFIX)
86
29.4M
{
87
29.4M
    const int bitdepth = bitdepth_from_max(bitdepth_max);
88
29.4M
    assert(y < h && x < w);
89
90
29.4M
    switch (mode) {
91
1.43M
    case VERT_PRED:
92
3.93M
    case HOR_PRED:
93
4.53M
    case DIAG_DOWN_LEFT_PRED:
94
5.03M
    case DIAG_DOWN_RIGHT_PRED:
95
5.52M
    case VERT_RIGHT_PRED:
96
6.16M
    case HOR_DOWN_PRED:
97
7.20M
    case HOR_UP_PRED:
98
7.82M
    case VERT_LEFT_PRED: {
99
7.82M
        *angle = av1_mode_to_angle_map[mode - VERT_PRED] + 3 * *angle;
100
101
7.82M
        if (*angle <= 90)
102
2.27M
            mode = *angle < 90 && have_top ? Z1_PRED : VERT_PRED;
103
5.55M
        else if (*angle < 180)
104
2.62M
            mode = Z2_PRED;
105
2.92M
        else
106
2.92M
            mode = *angle > 180 && have_left ? Z3_PRED : HOR_PRED;
107
7.82M
        break;
108
7.20M
    }
109
11.8M
    case DC_PRED:
110
15.7M
    case PAETH_PRED:
111
15.7M
        mode = av1_mode_conv[mode][have_left][have_top];
112
15.7M
        break;
113
5.89M
    default:
114
5.89M
        break;
115
29.4M
    }
116
117
29.4M
    const pixel *dst_top;
118
29.4M
    if (have_top &&
119
28.0M
        (av1_intra_prediction_edges[mode].needs_top ||
120
2.77M
         av1_intra_prediction_edges[mode].needs_topleft ||
121
1.27M
         (av1_intra_prediction_edges[mode].needs_left && !have_left)))
122
26.9M
    {
123
26.9M
        if (prefilter_toplevel_sb_edge) {
124
3.59M
            dst_top = &prefilter_toplevel_sb_edge[x * 4];
125
23.3M
        } else {
126
23.3M
            dst_top = &dst[-PXSTRIDE(stride)];
127
23.3M
        }
128
26.9M
    }
129
130
29.4M
    if (av1_intra_prediction_edges[mode].needs_left) {
131
26.0M
        const int sz = th << 2;
132
26.0M
        pixel *const left = &topleft_out[-sz];
133
134
26.0M
        if (have_left) {
135
25.3M
            const int px_have = imin(sz, (h - y) << 2);
136
137
273M
            for (int i = 0; i < px_have; i++)
138
247M
                left[sz - 1 - i] = dst[PXSTRIDE(stride) * i - 1];
139
25.3M
            if (px_have < sz)
140
323k
                pixel_set(left, left[sz - px_have], sz - px_have);
141
25.3M
        } else {
142
671k
            pixel_set(left, have_top ? *dst_top : ((1 << bitdepth) >> 1) + 1, sz);
143
671k
        }
144
145
26.0M
        if (av1_intra_prediction_edges[mode].needs_bottomleft) {
146
1.58M
            const int have_bottomleft = (!have_left || y + th >= h) ? 0 :
147
1.58M
                                        (edge_flags & EDGE_I444_LEFT_HAS_BOTTOM);
148
149
1.58M
            if (have_bottomleft) {
150
495k
                const int px_have = imin(sz, (h - y - th) << 2);
151
152
4.97M
                for (int i = 0; i < px_have; i++)
153
4.48M
                    left[-(i + 1)] = dst[(sz + i) * PXSTRIDE(stride) - 1];
154
495k
                if (px_have < sz)
155
3.53k
                    pixel_set(left - sz, left[-px_have], sz - px_have);
156
1.08M
            } else {
157
1.08M
                pixel_set(left - sz, left[0], sz);
158
1.08M
            }
159
1.58M
        }
160
26.0M
    }
161
162
29.4M
    if (av1_intra_prediction_edges[mode].needs_top) {
163
25.7M
        const int sz = tw << 2;
164
25.7M
        pixel *const top = &topleft_out[1];
165
166
25.7M
        if (have_top) {
167
25.2M
            const int px_have = imin(sz, (w - x) << 2);
168
25.2M
            pixel_copy(top, dst_top, px_have);
169
25.2M
            if (px_have < sz)
170
557k
                pixel_set(top + px_have, top[px_have - 1], sz - px_have);
171
25.2M
        } else {
172
507k
            pixel_set(top, have_left ? dst[-1] : ((1 << bitdepth) >> 1) - 1, sz);
173
507k
        }
174
175
25.7M
        if (av1_intra_prediction_edges[mode].needs_topright) {
176
1.43M
            const int have_topright = (!have_top || x + tw >= w) ? 0 :
177
1.43M
                                      (edge_flags & EDGE_I444_TOP_HAS_RIGHT);
178
179
1.43M
            if (have_topright) {
180
913k
                const int px_have = imin(sz, (w - x - tw) << 2);
181
182
913k
                pixel_copy(top + sz, &dst_top[sz], px_have);
183
913k
                if (px_have < sz)
184
3.34k
                    pixel_set(top + sz + px_have, top[sz + px_have - 1],
185
2.23k
                              sz - px_have);
186
913k
            } else {
187
521k
                pixel_set(top + sz, top[sz - 1], sz);
188
521k
            }
189
1.43M
        }
190
25.7M
    }
191
192
29.4M
    if (av1_intra_prediction_edges[mode].needs_topleft) {
193
10.9M
        if (have_left)
194
10.6M
            *topleft_out = have_top ? dst_top[-1] : dst[-1];
195
330k
        else
196
330k
            *topleft_out = have_top ? *dst_top : (1 << bitdepth) >> 1;
197
198
10.9M
        if (mode == Z2_PRED && tw + th >= 6 && filter_edge)
199
639k
            *topleft_out = ((topleft_out[-1] + topleft_out[1]) * 5 +
200
639k
                            topleft_out[0] * 6 + 8) >> 4;
201
10.9M
    }
202
203
29.4M
    return mode;
204
29.4M
}
dav1d_prepare_intra_edges_8bpc
Line
Count
Source
86
16.9M
{
87
16.9M
    const int bitdepth = bitdepth_from_max(bitdepth_max);
88
16.9M
    assert(y < h && x < w);
89
90
16.9M
    switch (mode) {
91
893k
    case VERT_PRED:
92
2.38M
    case HOR_PRED:
93
2.74M
    case DIAG_DOWN_LEFT_PRED:
94
3.05M
    case DIAG_DOWN_RIGHT_PRED:
95
3.36M
    case VERT_RIGHT_PRED:
96
3.75M
    case HOR_DOWN_PRED:
97
4.38M
    case HOR_UP_PRED:
98
4.76M
    case VERT_LEFT_PRED: {
99
4.76M
        *angle = av1_mode_to_angle_map[mode - VERT_PRED] + 3 * *angle;
100
101
4.76M
        if (*angle <= 90)
102
1.38M
            mode = *angle < 90 && have_top ? Z1_PRED : VERT_PRED;
103
3.38M
        else if (*angle < 180)
104
1.62M
            mode = Z2_PRED;
105
1.75M
        else
106
1.75M
            mode = *angle > 180 && have_left ? Z3_PRED : HOR_PRED;
107
4.76M
        break;
108
4.38M
    }
109
6.39M
    case DC_PRED:
110
8.38M
    case PAETH_PRED:
111
8.38M
        mode = av1_mode_conv[mode][have_left][have_top];
112
8.38M
        break;
113
3.76M
    default:
114
3.76M
        break;
115
16.9M
    }
116
117
16.9M
    const pixel *dst_top;
118
16.9M
    if (have_top &&
119
16.2M
        (av1_intra_prediction_edges[mode].needs_top ||
120
1.69M
         av1_intra_prediction_edges[mode].needs_topleft ||
121
769k
         (av1_intra_prediction_edges[mode].needs_left && !have_left)))
122
15.5M
    {
123
15.5M
        if (prefilter_toplevel_sb_edge) {
124
2.06M
            dst_top = &prefilter_toplevel_sb_edge[x * 4];
125
13.4M
        } else {
126
13.4M
            dst_top = &dst[-PXSTRIDE(stride)];
127
13.4M
        }
128
15.5M
    }
129
130
16.9M
    if (av1_intra_prediction_edges[mode].needs_left) {
131
14.9M
        const int sz = th << 2;
132
14.9M
        pixel *const left = &topleft_out[-sz];
133
134
14.9M
        if (have_left) {
135
14.6M
            const int px_have = imin(sz, (h - y) << 2);
136
137
161M
            for (int i = 0; i < px_have; i++)
138
147M
                left[sz - 1 - i] = dst[PXSTRIDE(stride) * i - 1];
139
14.6M
            if (px_have < sz)
140
139k
                pixel_set(left, left[sz - px_have], sz - px_have);
141
14.6M
        } else {
142
292k
            pixel_set(left, have_top ? *dst_top : ((1 << bitdepth) >> 1) + 1, sz);
143
292k
        }
144
145
14.9M
        if (av1_intra_prediction_edges[mode].needs_bottomleft) {
146
956k
            const int have_bottomleft = (!have_left || y + th >= h) ? 0 :
147
956k
                                        (edge_flags & EDGE_I444_LEFT_HAS_BOTTOM);
148
149
956k
            if (have_bottomleft) {
150
329k
                const int px_have = imin(sz, (h - y - th) << 2);
151
152
3.17M
                for (int i = 0; i < px_have; i++)
153
2.84M
                    left[-(i + 1)] = dst[(sz + i) * PXSTRIDE(stride) - 1];
154
329k
                if (px_have < sz)
155
2.04k
                    pixel_set(left - sz, left[-px_have], sz - px_have);
156
626k
            } else {
157
626k
                pixel_set(left - sz, left[0], sz);
158
626k
            }
159
956k
        }
160
14.9M
    }
161
162
16.9M
    if (av1_intra_prediction_edges[mode].needs_top) {
163
14.7M
        const int sz = tw << 2;
164
14.7M
        pixel *const top = &topleft_out[1];
165
166
14.7M
        if (have_top) {
167
14.5M
            const int px_have = imin(sz, (w - x) << 2);
168
14.5M
            pixel_copy(top, dst_top, px_have);
169
14.5M
            if (px_have < sz)
170
267k
                pixel_set(top + px_have, top[px_have - 1], sz - px_have);
171
14.5M
        } else {
172
231k
            pixel_set(top, have_left ? dst[-1] : ((1 << bitdepth) >> 1) - 1, sz);
173
231k
        }
174
175
14.7M
        if (av1_intra_prediction_edges[mode].needs_topright) {
176
881k
            const int have_topright = (!have_top || x + tw >= w) ? 0 :
177
881k
                                      (edge_flags & EDGE_I444_TOP_HAS_RIGHT);
178
179
881k
            if (have_topright) {
180
545k
                const int px_have = imin(sz, (w - x - tw) << 2);
181
182
545k
                pixel_copy(top + sz, &dst_top[sz], px_have);
183
545k
                if (px_have < sz)
184
2.23k
                    pixel_set(top + sz + px_have, top[sz + px_have - 1],
185
2.23k
                              sz - px_have);
186
545k
            } else {
187
336k
                pixel_set(top + sz, top[sz - 1], sz);
188
336k
            }
189
881k
        }
190
14.7M
    }
191
192
16.9M
    if (av1_intra_prediction_edges[mode].needs_topleft) {
193
6.51M
        if (have_left)
194
6.37M
            *topleft_out = have_top ? dst_top[-1] : dst[-1];
195
142k
        else
196
142k
            *topleft_out = have_top ? *dst_top : (1 << bitdepth) >> 1;
197
198
6.51M
        if (mode == Z2_PRED && tw + th >= 6 && filter_edge)
199
445k
            *topleft_out = ((topleft_out[-1] + topleft_out[1]) * 5 +
200
445k
                            topleft_out[0] * 6 + 8) >> 4;
201
6.51M
    }
202
203
16.9M
    return mode;
204
16.9M
}
dav1d_prepare_intra_edges_16bpc
Line
Count
Source
86
12.5M
{
87
12.5M
    const int bitdepth = bitdepth_from_max(bitdepth_max);
88
12.5M
    assert(y < h && x < w);
89
90
12.5M
    switch (mode) {
91
542k
    case VERT_PRED:
92
1.54M
    case HOR_PRED:
93
1.79M
    case DIAG_DOWN_LEFT_PRED:
94
1.97M
    case DIAG_DOWN_RIGHT_PRED:
95
2.15M
    case VERT_RIGHT_PRED:
96
2.40M
    case HOR_DOWN_PRED:
97
2.81M
    case HOR_UP_PRED:
98
3.06M
    case VERT_LEFT_PRED: {
99
3.06M
        *angle = av1_mode_to_angle_map[mode - VERT_PRED] + 3 * *angle;
100
101
3.06M
        if (*angle <= 90)
102
895k
            mode = *angle < 90 && have_top ? Z1_PRED : VERT_PRED;
103
2.16M
        else if (*angle < 180)
104
994k
            mode = Z2_PRED;
105
1.17M
        else
106
1.17M
            mode = *angle > 180 && have_left ? Z3_PRED : HOR_PRED;
107
3.06M
        break;
108
2.81M
    }
109
5.49M
    case DC_PRED:
110
7.39M
    case PAETH_PRED:
111
7.39M
        mode = av1_mode_conv[mode][have_left][have_top];
112
7.39M
        break;
113
2.13M
    default:
114
2.13M
        break;
115
12.5M
    }
116
117
12.5M
    const pixel *dst_top;
118
12.5M
    if (have_top &&
119
11.7M
        (av1_intra_prediction_edges[mode].needs_top ||
120
1.08M
         av1_intra_prediction_edges[mode].needs_topleft ||
121
508k
         (av1_intra_prediction_edges[mode].needs_left && !have_left)))
122
11.3M
    {
123
11.3M
        if (prefilter_toplevel_sb_edge) {
124
1.52M
            dst_top = &prefilter_toplevel_sb_edge[x * 4];
125
9.85M
        } else {
126
9.85M
            dst_top = &dst[-PXSTRIDE(stride)];
127
9.85M
        }
128
11.3M
    }
129
130
12.5M
    if (av1_intra_prediction_edges[mode].needs_left) {
131
11.0M
        const int sz = th << 2;
132
11.0M
        pixel *const left = &topleft_out[-sz];
133
134
11.0M
        if (have_left) {
135
10.6M
            const int px_have = imin(sz, (h - y) << 2);
136
137
111M
            for (int i = 0; i < px_have; i++)
138
100M
                left[sz - 1 - i] = dst[PXSTRIDE(stride) * i - 1];
139
10.6M
            if (px_have < sz)
140
183k
                pixel_set(left, left[sz - px_have], sz - px_have);
141
10.6M
        } else {
142
378k
            pixel_set(left, have_top ? *dst_top : ((1 << bitdepth) >> 1) + 1, sz);
143
378k
        }
144
145
11.0M
        if (av1_intra_prediction_edges[mode].needs_bottomleft) {
146
627k
            const int have_bottomleft = (!have_left || y + th >= h) ? 0 :
147
627k
                                        (edge_flags & EDGE_I444_LEFT_HAS_BOTTOM);
148
149
627k
            if (have_bottomleft) {
150
165k
                const int px_have = imin(sz, (h - y - th) << 2);
151
152
1.80M
                for (int i = 0; i < px_have; i++)
153
1.63M
                    left[-(i + 1)] = dst[(sz + i) * PXSTRIDE(stride) - 1];
154
165k
                if (px_have < sz)
155
1.49k
                    pixel_set(left - sz, left[-px_have], sz - px_have);
156
461k
            } else {
157
461k
                pixel_set(left - sz, left[0], sz);
158
461k
            }
159
627k
        }
160
11.0M
    }
161
162
12.5M
    if (av1_intra_prediction_edges[mode].needs_top) {
163
10.9M
        const int sz = tw << 2;
164
10.9M
        pixel *const top = &topleft_out[1];
165
166
10.9M
        if (have_top) {
167
10.7M
            const int px_have = imin(sz, (w - x) << 2);
168
10.7M
            pixel_copy(top, dst_top, px_have);
169
10.7M
            if (px_have < sz)
170
289k
                pixel_set(top + px_have, top[px_have - 1], sz - px_have);
171
10.7M
        } else {
172
275k
            pixel_set(top, have_left ? dst[-1] : ((1 << bitdepth) >> 1) - 1, sz);
173
275k
        }
174
175
10.9M
        if (av1_intra_prediction_edges[mode].needs_topright) {
176
554k
            const int have_topright = (!have_top || x + tw >= w) ? 0 :
177
554k
                                      (edge_flags & EDGE_I444_TOP_HAS_RIGHT);
178
179
554k
            if (have_topright) {
180
368k
                const int px_have = imin(sz, (w - x - tw) << 2);
181
182
368k
                pixel_copy(top + sz, &dst_top[sz], px_have);
183
368k
                if (px_have < sz)
184
1.11k
                    pixel_set(top + sz + px_have, top[sz + px_have - 1],
185
1.11k
                              sz - px_have);
186
368k
            } else {
187
185k
                pixel_set(top + sz, top[sz - 1], sz);
188
185k
            }
189
554k
        }
190
10.9M
    }
191
192
12.5M
    if (av1_intra_prediction_edges[mode].needs_topleft) {
193
4.42M
        if (have_left)
194
4.23M
            *topleft_out = have_top ? dst_top[-1] : dst[-1];
195
188k
        else
196
188k
            *topleft_out = have_top ? *dst_top : (1 << bitdepth) >> 1;
197
198
4.42M
        if (mode == Z2_PRED && tw + th >= 6 && filter_edge)
199
193k
            *topleft_out = ((topleft_out[-1] + topleft_out[1]) * 5 +
200
193k
                            topleft_out[0] * 6 + 8) >> 4;
201
4.42M
    }
202
203
12.5M
    return mode;
204
12.5M
}