]> git.sesse.net Git - ffmpeg/blob - libavcodec/dirac_arith.h
avformat/argo_asf: initialise file header inline
[ffmpeg] / libavcodec / dirac_arith.h
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 static inline void renorm(DiracArith *c)
93 {
94 #if HAVE_FAST_CLZ
95     int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15);
96
97     c->low    <<= shift;
98     c->range  <<= shift;
99     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 }
108
109 static inline void refill(DiracArith *c)
110 {
111     int counter = c->counter;
112
113     if (counter >= 0) {
114         int new = bytestream_get_be16(&c->bytestream);
115
116         // the spec defines overread bits to be 1, and streams rely on this
117         if (c->bytestream > c->bytestream_end) {
118             new |= 0xff;
119             if (c->bytestream > c->bytestream_end+1)
120                 new |= 0xff00;
121
122             c->bytestream = c->bytestream_end;
123             c->overread ++;
124             if (c->overread > 4)
125                 c->error = AVERROR_INVALIDDATA;
126         }
127
128         c->low += new << counter;
129         counter -= 16;
130     }
131     c->counter = counter;
132 }
133
134 static inline int dirac_get_arith_bit(DiracArith *c, int ctx)
135 {
136     int prob_zero = c->contexts[ctx];
137     int range_times_prob, bit;
138     unsigned low = c->low;
139     int    range = c->range;
140
141     range_times_prob = (c->range * prob_zero) >> 16;
142
143 #if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
144     low   -= range_times_prob << 16;
145     range -= range_times_prob;
146     bit = 0;
147     __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         : "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     c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit];
167     c->low   = low;
168     c->range = range;
169
170     renorm(c);
171     refill(c);
172     return bit;
173 }
174
175 static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx)
176 {
177     int ret = 1;
178     while (!dirac_get_arith_bit(c, follow_ctx)) {
179         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         ret <<= 1;
185         ret += dirac_get_arith_bit(c, data_ctx);
186         follow_ctx = ff_dirac_next_ctx[follow_ctx];
187     }
188     return ret-1;
189 }
190
191 static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx)
192 {
193     int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx);
194     if (ret && dirac_get_arith_bit(c, data_ctx+1))
195         ret = -ret;
196     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 */