GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/dirac_arith.h Lines: 50 54 92.6 %
Date: 2019-11-22 03:34: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 const uint16_t ff_dirac_prob[256];
90
extern int16_t ff_dirac_prob_branchless[256][2];
91
92
1024041
static inline void renorm(DiracArith *c)
93
{
94
#if HAVE_FAST_CLZ
95
1024041
    int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
96
97
1024041
    c->low    <<= shift;
98
1024041
    c->range  <<= shift;
99
1024041
    c->counter += shift;
100
#else
101
    while (c->range <= 0x4000) {
102
        c->low   <<= 1;
103
        c->range <<= 1;
104
        c->counter++;
105
    }
106
#endif
107
1024041
}
108
109
1024041
static inline void refill(DiracArith *c)
110
{
111
1024041
    int counter = c->counter;
112
113
1024041
    if (counter >= 0) {
114
46510
        int new = bytestream_get_be16(&c->bytestream);
115
116
        // the spec defines overread bits to be 1, and streams rely on this
117
46510
        if (c->bytestream > c->bytestream_end) {
118
495
            new |= 0xff;
119
495
            if (c->bytestream > c->bytestream_end+1)
120
91
                new |= 0xff00;
121
122
495
            c->bytestream = c->bytestream_end;
123
495
            c->overread ++;
124
495
            if (c->overread > 4)
125
                c->error = AVERROR_INVALIDDATA;
126
        }
127
128
46510
        c->low += new << counter;
129
46510
        counter -= 16;
130
    }
131
1024041
    c->counter = counter;
132
1024041
}
133
134
1024041
static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
135
{
136
1024041
    int prob_zero = c->contexts[ctx];
137
    int range_times_prob, bit;
138
1024041
    unsigned low = c->low;
139
1024041
    int    range = c->range;
140
141
1024041
    range_times_prob = (c->range * prob_zero) >> 16;
142
143
#if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
144
1024041
    low   -= range_times_prob << 16;
145
1024041
    range -= range_times_prob;
146
1024041
    bit = 0;
147
1024041
    __asm__(
148
        "cmpl   %5, %4 \n\t"
149
        "setae  %b0    \n\t"
150
        "cmovb  %3, %2 \n\t"
151
        "cmovb  %5, %1 \n\t"
152
        : "+q"(bit), "+r"(range), "+r"(low)
153
1024041
        : "r"(c->low), "r"(c->low>>16),
154
          "r"(range_times_prob)
155
    );
156
#else
157
    bit = (low >> 16) >= range_times_prob;
158
    if (bit) {
159
        low   -= range_times_prob << 16;
160
        range -= range_times_prob;
161
    } else {
162
        range  = range_times_prob;
163
    }
164
#endif
165
166
1024041
    c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
167
1024041
    c->low   = low;
168
1024041
    c->range = range;
169
170
1024041
    renorm(c);
171
1024041
    refill(c);
172
1024041
    return bit;
173
}
174
175
353584
static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
176
{
177
353584
    int ret = 1;
178
573506
    while (!dirac_get_arith_bit(c, follow_ctx)) {
179
219922
        if (ret >= 0x40000000) {
180
            av_log(NULL, AV_LOG_ERROR, "dirac_get_arith_uint overflow\n");
181
            c->error = AVERROR_INVALIDDATA;
182
            return -1;
183
        }
184
219922
        ret <<= 1;
185
219922
        ret += dirac_get_arith_bit(c, data_ctx);
186
219922
        follow_ctx = ff_dirac_next_ctx[follow_ctx];
187
    }
188
353584
    return ret-1;
189
}
190
191
14164
static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
192
{
193
14164
    int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
194

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