2 * Copyright (C) 2007 Marco Gerards <marco@gnu.org>
3 * Copyright (C) 2009 David Conrad
5 * This file is part of FFmpeg.
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.
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.
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
24 * Arithmetic decoder for Dirac
25 * @author Marco Gerards <marco@gnu.org>
28 #ifndef AVCODEC_DIRAC_ARITH_H
29 #define AVCODEC_DIRAC_ARITH_H
31 #include "libavutil/x86/asm.h"
32 #include "bytestream.h"
35 enum dirac_arith_contexts
{
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
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
72 #define CTX_DC_F1 CTX_ZP_F5
80 const uint8_t *bytestream
;
81 const uint8_t *bytestream_end
;
83 uint16_t contexts
[DIRAC_CTX_COUNT
];
86 extern const uint8_t ff_dirac_next_ctx
[DIRAC_CTX_COUNT
];
87 extern const uint16_t ff_dirac_prob
[256];
88 extern int16_t ff_dirac_prob_branchless
[256][2];
90 static inline void renorm(DiracArith
*c
)
93 int shift
= 14 - av_log2_16bit(c
->range
-1) + ((c
->range
-1)>>15);
99 while (c
->range
<= 0x4000) {
107 static inline void refill(DiracArith
*c
)
109 int counter
= c
->counter
;
112 int new = bytestream_get_be16(&c
->bytestream
);
114 // the spec defines overread bits to be 1, and streams rely on this
115 if (c
->bytestream
> c
->bytestream_end
) {
117 if (c
->bytestream
> c
->bytestream_end
+1)
120 c
->bytestream
= c
->bytestream_end
;
123 c
->low
+= new << counter
;
126 c
->counter
= counter
;
129 static inline int dirac_get_arith_bit(DiracArith
*c
, int ctx
)
131 int prob_zero
= c
->contexts
[ctx
];
132 int range_times_prob
, bit
;
133 unsigned low
= c
->low
;
134 int range
= c
->range
;
136 range_times_prob
= (c
->range
* prob_zero
) >> 16;
138 #if ARCH_X86 && HAVE_FAST_CMOV && HAVE_INLINE_ASM && HAVE_6REGS
139 low
-= range_times_prob
<< 16;
140 range
-= range_times_prob
;
147 : "+q"(bit
), "+r"(range
), "+r"(low
)
148 : "r"(c
->low
), "r"(c
->low
>>16),
149 "r"(range_times_prob
)
152 bit
= (low
>> 16) >= range_times_prob
;
154 low
-= range_times_prob
<< 16;
155 range
-= range_times_prob
;
157 range
= range_times_prob
;
161 c
->contexts
[ctx
] += ff_dirac_prob_branchless
[prob_zero
>>8][bit
];
170 static inline int dirac_get_arith_uint(DiracArith
*c
, int follow_ctx
, int data_ctx
)
173 while (!dirac_get_arith_bit(c
, follow_ctx
)) {
174 if (ret
>= 0x40000000) {
175 av_log(NULL
, AV_LOG_ERROR
, "dirac_get_arith_uint overflow\n");
179 ret
+= dirac_get_arith_bit(c
, data_ctx
);
180 follow_ctx
= ff_dirac_next_ctx
[follow_ctx
];
185 static inline int dirac_get_arith_int(DiracArith
*c
, int follow_ctx
, int data_ctx
)
187 int ret
= dirac_get_arith_uint(c
, follow_ctx
, data_ctx
);
188 if (ret
&& dirac_get_arith_bit(c
, data_ctx
+1))
193 void ff_dirac_init_arith_decoder(DiracArith
*c
, GetBitContext
*gb
, int length
);
195 #endif /* AVCODEC_DIRAC_ARITH_H */