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
35enum 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
75typedef 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
88extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT];
89extern int16_t ff_dirac_prob_branchless[256][2];
90
91static inline void renorm(DiracArith *c)
92{
93#if HAVE_FAST_CLZ
94    int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
95
96    c->low    <<= shift;
97    c->range  <<= shift;
98    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}
107
108static inline void refill(DiracArith *c)
109{
110    int counter = c->counter;
111
112    if (counter >= 0) {
113        int new = bytestream_get_be16(&c->bytestream);
114
115        // the spec defines overread bits to be 1, and streams rely on this
116        if (c->bytestream > c->bytestream_end) {
117            new |= 0xff;
118            if (c->bytestream > c->bytestream_end+1)
119                new |= 0xff00;
120
121            c->bytestream = c->bytestream_end;
122            c->overread ++;
123            if (c->overread > 4)
124                c->error = AVERROR_INVALIDDATA;
125        }
126
127        c->low += new << counter;
128        counter -= 16;
129    }
130    c->counter = counter;
131}
132
133static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
134{
135    int prob_zero = c->contexts[ctx];
136    int range_times_prob, bit;
137    unsigned low = c->low;
138    int    range = c->range;
139
140    range_times_prob = (c->range * prob_zero) >> 16;
141
142#if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
143    low   -= range_times_prob << 16;
144    range -= range_times_prob;
145    bit = 0;
146    __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        : "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    c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
166    c->low   = low;
167    c->range = range;
168
169    renorm(c);
170    refill(c);
171    return bit;
172}
173
174static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
175{
176    int ret = 1;
177    while (!dirac_get_arith_bit(c, follow_ctx)) {
178        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        ret <<= 1;
184        ret += dirac_get_arith_bit(c, data_ctx);
185        follow_ctx = ff_dirac_next_ctx[follow_ctx];
186    }
187    return ret-1;
188}
189
190static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
191{
192    int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
193    if (ret && dirac_get_arith_bit(c, data_ctx+1))
194        ret = -ret;
195    return ret;
196}
197
198void ff_dirac_init_arith_tables(void);
199void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length);
200
201#endif /* AVCODEC_DIRAC_ARITH_H */
202