Coverage Report

Created: 2026-08-13 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/dav1d/src/msac.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 <limits.h>
31
32
#include "common/intops.h"
33
34
#include "src/msac.h"
35
36
132M
#define EC_PROB_SHIFT 6
37
76.0M
#define EC_MIN_PROB 4  // must be <= (1<<EC_PROB_SHIFT)/16
38
39
71.9M
#define EC_WIN_SIZE (sizeof(ec_win) << 3)
40
41
852k
static inline void ctx_refill(MsacContext *const s) {
42
852k
    const uint8_t *buf_pos = s->buf_pos;
43
852k
    const uint8_t *buf_end = s->buf_end;
44
852k
    int c = EC_WIN_SIZE - s->cnt - 24;
45
852k
    ec_win dif = s->dif;
46
5.16M
    do {
47
5.16M
        if (buf_pos >= buf_end) {
48
            // set remaining bits to 1;
49
8.09k
            dif |= ~(~(ec_win)0xff << c);
50
8.09k
            break;
51
8.09k
        }
52
5.16M
        dif |= (ec_win)(*buf_pos++ ^ 0xff) << c;
53
5.16M
        c -= 8;
54
5.16M
    } while (c >= 0);
55
852k
    s->dif = dif;
56
852k
    s->cnt = EC_WIN_SIZE - c - 24;
57
852k
    s->buf_pos = buf_pos;
58
852k
}
59
60
int dav1d_msac_decode_subexp(MsacContext *const s, const int ref,
61
                             const int n, unsigned k)
62
208k
{
63
208k
    assert(n >> k == 8);
64
65
208k
    unsigned a = 0;
66
208k
    if (dav1d_msac_decode_bool_equi(s)) {
67
98.5k
        if (dav1d_msac_decode_bool_equi(s))
68
53.0k
            k += dav1d_msac_decode_bool_equi(s) + 1;
69
98.5k
        a = 1 << k;
70
98.5k
    }
71
208k
    const unsigned v = dav1d_msac_decode_bools(s, k) + a;
72
208k
    return ref * 2 <= n ? inv_recenter(ref, v) :
73
208k
                          n - 1 - inv_recenter(n - 1 - ref, v);
74
208k
}
75
76
#if !(HAVE_ASM && TRIM_DSP_FUNCTIONS && ( \
77
  ARCH_AARCH64 || \
78
  (ARCH_ARM && (defined(__ARM_NEON) || defined(__APPLE__) || defined(_WIN32))) \
79
))
80
/* Takes updated dif and range values, renormalizes them so that
81
 * 32768 <= rng < 65536 (reading more bytes from the stream into dif if
82
 * necessary), and stores them back in the decoder context.
83
 * dif: The new value of dif.
84
 * rng: The new value of the range. */
85
static inline void ctx_norm(MsacContext *const s, const ec_win dif,
86
                            const unsigned rng)
87
42.8M
{
88
42.8M
    const int d = 15 ^ (31 ^ clz(rng));
89
42.8M
    const int cnt = s->cnt;
90
42.8M
    assert(rng <= 65535U);
91
42.8M
    s->dif = dif << d;
92
42.8M
    s->rng = rng << d;
93
42.8M
    s->cnt = cnt - d;
94
    // unsigned compare avoids redundant refills at eob
95
42.8M
    if ((unsigned)cnt < (unsigned)d)
96
780k
        ctx_refill(s);
97
42.8M
}
98
99
9.63M
unsigned dav1d_msac_decode_bool_equi_c(MsacContext *const s) {
100
9.63M
    const unsigned r = s->rng;
101
9.63M
    ec_win dif = s->dif;
102
9.63M
    assert((dif >> (EC_WIN_SIZE - 16)) < r);
103
    // When the probability is 1/2, f = 16384 >> EC_PROB_SHIFT = 256 and we can
104
    // replace the multiply with a simple shift.
105
9.63M
    unsigned v = ((r >> 8) << 7) + EC_MIN_PROB;
106
9.63M
    const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16);
107
9.63M
    const unsigned ret = dif >= vw;
108
9.63M
    dif -= ret * vw;
109
9.63M
    v += ret * (r - 2 * v);
110
9.63M
    ctx_norm(s, dif, v);
111
9.63M
    return !ret;
112
9.63M
}
113
114
/* Decode a single binary value.
115
 * f: The probability that the bit is one
116
 * Return: The value decoded (0 or 1). */
117
6.13M
unsigned dav1d_msac_decode_bool_c(MsacContext *const s, const unsigned f) {
118
6.13M
    const unsigned r = s->rng;
119
6.13M
    ec_win dif = s->dif;
120
6.13M
    assert((dif >> (EC_WIN_SIZE - 16)) < r);
121
6.13M
    unsigned v = ((r >> 8) * (f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) + EC_MIN_PROB;
122
6.13M
    const ec_win vw = (ec_win)v << (EC_WIN_SIZE - 16);
123
6.13M
    const unsigned ret = dif >= vw;
124
6.13M
    dif -= ret * vw;
125
6.13M
    v += ret * (r - 2 * v);
126
6.13M
    ctx_norm(s, dif, v);
127
6.13M
    return !ret;
128
6.13M
}
129
130
/* Decodes a symbol given an inverse cumulative distribution function (CDF)
131
 * table in Q15. */
132
unsigned dav1d_msac_decode_symbol_adapt_c(MsacContext *const s,
133
                                          uint16_t *const cdf,
134
                                          const size_t n_symbols)
135
27.2M
{
136
27.2M
    const unsigned c = s->dif >> (EC_WIN_SIZE - 16), r = s->rng >> 8;
137
27.2M
    unsigned u, v = s->rng, val = -1;
138
139
27.2M
    assert(n_symbols <= 15);
140
27.2M
    assert(cdf[n_symbols] <= 32);
141
142
60.3M
    do {
143
60.3M
        val++;
144
60.3M
        u = v;
145
60.3M
        v = r * (cdf[val] >> EC_PROB_SHIFT);
146
60.3M
        v >>= 7 - EC_PROB_SHIFT;
147
60.3M
        v += EC_MIN_PROB * ((unsigned)n_symbols - val);
148
60.3M
    } while (c < v);
149
150
27.2M
    assert(u <= s->rng);
151
152
27.2M
    ctx_norm(s, s->dif - ((ec_win)v << (EC_WIN_SIZE - 16)), u - v);
153
154
27.2M
    if (s->allow_update_cdf) {
155
26.4M
        const unsigned count = cdf[n_symbols];
156
26.4M
        const unsigned rate = 4 + (count >> 4) + (n_symbols > 2);
157
26.4M
        unsigned i;
158
58.6M
        for (i = 0; i < val; i++)
159
32.1M
            cdf[i] += (32768 - cdf[i]) >> rate;
160
99.8M
        for (; i < n_symbols; i++)
161
73.3M
            cdf[i] -= cdf[i] >> rate;
162
26.4M
        cdf[n_symbols] = count + (count < 32);
163
26.4M
    }
164
165
27.2M
    return val;
166
27.2M
}
167
168
unsigned dav1d_msac_decode_bool_adapt_c(MsacContext *const s,
169
                                        uint16_t *const cdf)
170
6.05M
{
171
6.05M
    const unsigned bit = dav1d_msac_decode_bool(s, *cdf);
172
173
6.05M
    if (s->allow_update_cdf) {
174
        // update_cdf() specialized for boolean CDFs
175
5.63M
        const unsigned count = cdf[1];
176
5.63M
        const int rate = 4 + (count >> 4);
177
5.63M
        if (bit)
178
2.62M
            cdf[0] += (32768 - cdf[0]) >> rate;
179
3.01M
        else
180
3.01M
            cdf[0] -= cdf[0] >> rate;
181
5.63M
        cdf[1] = count + (count < 32);
182
5.63M
    }
183
184
6.05M
    return bit;
185
6.05M
}
186
187
1.52M
unsigned dav1d_msac_decode_hi_tok_c(MsacContext *const s, uint16_t *const cdf) {
188
1.52M
    unsigned tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
189
1.52M
    unsigned tok = 3 + tok_br;
190
1.52M
    if (tok_br == 3) {
191
685k
        tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
192
685k
        tok = 6 + tok_br;
193
685k
        if (tok_br == 3) {
194
465k
            tok_br = dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
195
465k
            tok = 9 + tok_br;
196
465k
            if (tok_br == 3)
197
375k
                tok = 12 + dav1d_msac_decode_symbol_adapt4(s, cdf, 3);
198
465k
        }
199
685k
    }
200
1.52M
    return tok;
201
1.52M
}
202
#endif
203
204
void dav1d_msac_init(MsacContext *const s, const uint8_t *const data,
205
                     const size_t sz, const int disable_cdf_update_flag)
206
72.4k
{
207
72.4k
    s->buf_pos = data;
208
72.4k
    s->buf_end = data + sz;
209
72.4k
    s->dif = 0;
210
72.4k
    s->rng = 0x8000;
211
72.4k
    s->cnt = -15;
212
72.4k
    s->allow_update_cdf = !disable_cdf_update_flag;
213
72.4k
    ctx_refill(s);
214
215
#if ARCH_X86_64 && HAVE_ASM
216
    s->symbol_adapt16 = dav1d_msac_decode_symbol_adapt_c;
217
218
    msac_init_x86(s);
219
#endif
220
72.4k
}