Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6148 serge 1
/*
2
 * Copyright (C) 2007 Marco Gerards 
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 
26
 */
27
 
28
#ifndef AVCODEC_DIRAC_ARITH_H
29
#define AVCODEC_DIRAC_ARITH_H
30
 
31
#include "bytestream.h"
32
#include "get_bits.h"
33
 
34
enum dirac_arith_contexts {
35
    CTX_ZPZN_F1,
36
    CTX_ZPNN_F1,
37
    CTX_NPZN_F1,
38
    CTX_NPNN_F1,
39
    CTX_ZP_F2,
40
    CTX_ZP_F3,
41
    CTX_ZP_F4,
42
    CTX_ZP_F5,
43
    CTX_ZP_F6,
44
    CTX_NP_F2,
45
    CTX_NP_F3,
46
    CTX_NP_F4,
47
    CTX_NP_F5,
48
    CTX_NP_F6,
49
    CTX_COEFF_DATA,
50
    CTX_SIGN_NEG,
51
    CTX_SIGN_ZERO,
52
    CTX_SIGN_POS,
53
    CTX_ZERO_BLOCK,
54
    CTX_DELTA_Q_F,
55
    CTX_DELTA_Q_DATA,
56
    CTX_DELTA_Q_SIGN,
57
 
58
    DIRAC_CTX_COUNT
59
};
60
 
61
// Dirac resets the arith decoder between decoding various types of data,
62
// so many contexts are never used simultaneously. Thus, we can reduce
63
// the number of contexts needed by reusing them.
64
#define CTX_SB_F1        CTX_ZP_F5
65
#define CTX_SB_DATA      0
66
#define CTX_PMODE_REF1   0
67
#define CTX_PMODE_REF2   1
68
#define CTX_GLOBAL_BLOCK 2
69
#define CTX_MV_F1        CTX_ZP_F2
70
#define CTX_MV_DATA      0
71
#define CTX_DC_F1        CTX_ZP_F5
72
#define CTX_DC_DATA      0
73
 
74
typedef struct {
75
    unsigned low;
76
    uint16_t range;
77
    int16_t  counter;
78
 
79
    const uint8_t *bytestream;
80
    const uint8_t *bytestream_end;
81
 
82
    uint16_t contexts[DIRAC_CTX_COUNT];
83
} DiracArith;
84
 
85
extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
86
extern const uint16_t ff_dirac_prob[256];
87
extern int16_t ff_dirac_prob_branchless[256][2];
88
 
89
static inline void renorm(DiracArith *c)
90
{
91
#if HAVE_FAST_CLZ
92
    int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
93
 
94
    c->low    <<= shift;
95
    c->range  <<= shift;
96
    c->counter += shift;
97
#else
98
    while (c->range <= 0x4000) {
99
        c->low   <<= 1;
100
        c->range <<= 1;
101
        c->counter++;
102
    }
103
#endif
104
}
105
 
106
static inline void refill(DiracArith *c)
107
{
108
    int counter = c->counter;
109
 
110
    if (counter >= 0) {
111
        int new = bytestream_get_be16(&c->bytestream);
112
 
113
        // the spec defines overread bits to be 1, and streams rely on this
114
        if (c->bytestream > c->bytestream_end) {
115
            new |= 0xff;
116
            if (c->bytestream > c->bytestream_end+1)
117
                new |= 0xff00;
118
 
119
            c->bytestream = c->bytestream_end;
120
        }
121
 
122
        c->low += new << counter;
123
        counter -= 16;
124
    }
125
    c->counter = counter;
126
}
127
 
128
static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
129
{
130
    int prob_zero = c->contexts[ctx];
131
    int range_times_prob, bit;
132
    unsigned low = c->low;
133
    int    range = c->range;
134
 
135
    range_times_prob = (c->range * prob_zero) >> 16;
136
 
137
#if HAVE_FAST_CMOV && HAVE_INLINE_ASM
138
    low   -= range_times_prob << 16;
139
    range -= range_times_prob;
140
    bit = 0;
141
    __asm__(
142
        "cmpl   %5, %4 \n\t"
143
        "setae  %b0    \n\t"
144
        "cmovb  %3, %2 \n\t"
145
        "cmovb  %5, %1 \n\t"
146
        : "+q"(bit), "+r"(range), "+r"(low)
147
        : "r"(c->low), "r"(c->low>>16),
148
          "r"(range_times_prob)
149
    );
150
#else
151
    bit = (low >> 16) >= range_times_prob;
152
    if (bit) {
153
        low   -= range_times_prob << 16;
154
        range -= range_times_prob;
155
    } else {
156
        range  = range_times_prob;
157
    }
158
#endif
159
 
160
    c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
161
    c->low   = low;
162
    c->range = range;
163
 
164
    renorm(c);
165
    refill(c);
166
    return bit;
167
}
168
 
169
static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
170
{
171
    int ret = 1;
172
    while (!dirac_get_arith_bit(c, follow_ctx)) {
173
        ret <<= 1;
174
        ret += dirac_get_arith_bit(c, data_ctx);
175
        follow_ctx = ff_dirac_next_ctx[follow_ctx];
176
    }
177
    return ret-1;
178
}
179
 
180
static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
181
{
182
    int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
183
    if (ret && dirac_get_arith_bit(c, data_ctx+1))
184
        ret = -ret;
185
    return ret;
186
}
187
 
188
void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
189
 
190
#endif /* AVCODEC_DIRAC_ARITH_H */