GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/dirac_arith.h Lines: 50 54 92.6 %
Date: 2021-04-20 15:25:36 Branches: 14 16 87.5 %

Line Branch Exec Source
1
/*
2
 * Copyright (C) 2007 Marco Gerards <marco@gnu.org>
3
 * Copyright (C) 2009 David Conrad
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
/**
23
 * @file
24
 * Arithmetic decoder for Dirac
25
 * @author Marco Gerards <marco@gnu.org>
26
 */
27
28
#ifndef AVCODEC_DIRAC_ARITH_H
29
#define AVCODEC_DIRAC_ARITH_H
30
31
#include "libavutil/x86/asm.h"
32
#include "bytestream.h"
33
#include "get_bits.h"
34
35
enum dirac_arith_contexts {
36
    CTX_ZPZN_F1,
37
    CTX_ZPNN_F1,
38
    CTX_NPZN_F1,
39
    CTX_NPNN_F1,
40
    CTX_ZP_F2,
41
    CTX_ZP_F3,
42
    CTX_ZP_F4,
43
    CTX_ZP_F5,
44
    CTX_ZP_F6,
45
    CTX_NP_F2,
46
    CTX_NP_F3,
47
    CTX_NP_F4,
48
    CTX_NP_F5,
49
    CTX_NP_F6,
50
    CTX_COEFF_DATA,
51
    CTX_SIGN_NEG,
52
    CTX_SIGN_ZERO,
53
    CTX_SIGN_POS,
54
    CTX_ZERO_BLOCK,
55
    CTX_DELTA_Q_F,
56
    CTX_DELTA_Q_DATA,
57
    CTX_DELTA_Q_SIGN,
58
59
    DIRAC_CTX_COUNT
60
};
61
62
// Dirac resets the arith decoder between decoding various types of data,
63
// so many contexts are never used simultaneously. Thus, we can reduce
64
// the number of contexts needed by reusing them.
65
#define CTX_SB_F1        CTX_ZP_F5
66
#define CTX_SB_DATA      0
67
#define CTX_PMODE_REF1   0
68
#define CTX_PMODE_REF2   1
69
#define CTX_GLOBAL_BLOCK 2
70
#define CTX_MV_F1        CTX_ZP_F2
71
#define CTX_MV_DATA      0
72
#define CTX_DC_F1        CTX_ZP_F5
73
#define CTX_DC_DATA      0
74
75
typedef struct {
76
    unsigned low;
77
    uint16_t range;
78
    int16_t  counter;
79
80
    const uint8_t *bytestream;
81
    const uint8_t *bytestream_end;
82
83
    uint16_t contexts[DIRAC_CTX_COUNT];
84
    int error;
85
    int overread;
86
} DiracArith;
87
88
extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
89
extern int16_t ff_dirac_prob_branchless[256][2];
90
91
1024041
static inline void renorm(DiracArith *c)
92
{
93
#if HAVE_FAST_CLZ
94
1024041
    int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
95
96
1024041
    c->low    <<= shift;
97
1024041
    c->range  <<= shift;
98
1024041
    c->counter += shift;
99
#else
100
    while (c->range <= 0x4000) {
101
        c->low   <<= 1;
102
        c->range <<= 1;
103
        c->counter++;
104
    }
105
#endif
106
1024041
}
107
108
1024041
static inline void refill(DiracArith *c)
109
{
110
1024041
    int counter = c->counter;
111
112
1024041
    if (counter >= 0) {
113
46510
        int new = bytestream_get_be16(&c->bytestream);
114
115
        // the spec defines overread bits to be 1, and streams rely on this
116
46510
        if (c->bytestream > c->bytestream_end) {
117
495
            new |= 0xff;
118
495
            if (c->bytestream > c->bytestream_end+1)
119
91
                new |= 0xff00;
120
121
495
            c->bytestream = c->bytestream_end;
122
495
            c->overread ++;
123
495
            if (c->overread > 4)
124
                c->error = AVERROR_INVALIDDATA;
125
        }
126
127
46510
        c->low += new << counter;
128
46510
        counter -= 16;
129
    }
130
1024041
    c->counter = counter;
131
1024041
}
132
133
1024041
static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
134
{
135
1024041
    int prob_zero = c->contexts[ctx];
136
    int range_times_prob, bit;
137
1024041
    unsigned low = c->low;
138
1024041
    int    range = c->range;
139
140
1024041
    range_times_prob = (c->range * prob_zero) >> 16;
141
142
#if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
143
1024041
    low   -= range_times_prob << 16;
144
1024041
    range -= range_times_prob;
145
1024041
    bit = 0;
146
1024041
    __asm__(
147
        "cmpl   %5, %4 \n\t"
148
        "setae  %b0    \n\t"
149
        "cmovb  %3, %2 \n\t"
150
        "cmovb  %5, %1 \n\t"
151
        : "+q"(bit), "+r"(range), "+r"(low)
152
1024041
        : "r"(c->low), "r"(c->low>>16),
153
          "r"(range_times_prob)
154
    );
155
#else
156
    bit = (low >> 16) >= range_times_prob;
157
    if (bit) {
158
        low   -= range_times_prob << 16;
159
        range -= range_times_prob;
160
    } else {
161
        range  = range_times_prob;
162
    }
163
#endif
164
165
1024041
    c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
166
1024041
    c->low   = low;
167
1024041
    c->range = range;
168
169
1024041
    renorm(c);
170
1024041
    refill(c);
171
1024041
    return bit;
172
}
173
174
353584
static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
175
{
176
353584
    int ret = 1;
177
573506
    while (!dirac_get_arith_bit(c, follow_ctx)) {
178
219922
        if (ret >= 0x40000000) {
179
            av_log(NULL, AV_LOG_ERROR, "dirac_get_arith_uint overflow\n");
180
            c->error = AVERROR_INVALIDDATA;
181
            return -1;
182
        }
183
219922
        ret <<= 1;
184
219922
        ret += dirac_get_arith_bit(c, data_ctx);
185
219922
        follow_ctx = ff_dirac_next_ctx[follow_ctx];
186
    }
187
353584
    return ret-1;
188
}
189
190
14164
static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
191
{
192
14164
    int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
193

14164
    if (ret && dirac_get_arith_bit(c, data_ctx+1))
194
1346
        ret = -ret;
195
14164
    return ret;
196
}
197
198
void ff_dirac_init_arith_tables(void);
199
void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
200
201
#endif /* AVCODEC_DIRAC_ARITH_H */