]> git.sesse.net Git - x264/blob - common/bs.h
faster ue/se/te write
[x264] / common / bs.h
1 /*****************************************************************************
2  * bs.h :
3  *****************************************************************************
4  * Copyright (C) 2003-2008 x264 project
5  *
6  * Authors: Loren Merritt <lorenm@u.washington.edu>
7  *          Fiona Glaser <fiona@x264.com>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #ifndef X264_BS_H
26 #define X264_BS_H
27
28 typedef struct bs_s
29 {
30     uint8_t *p_start;
31     uint8_t *p;
32     uint8_t *p_end;
33
34     intptr_t cur_bits;
35     int     i_left;    /* i_count number of available bits */
36     int     i_bits_encoded; /* RD only */
37 } bs_t;
38
39 static inline void bs_init( bs_t *s, void *p_data, int i_data )
40 {
41     int offset = ((intptr_t)p_data & (WORD_SIZE-1));
42     s->p       = s->p_start = (uint8_t*)p_data - offset;
43     s->p_end   = (uint8_t*)p_data + i_data;
44     s->i_left  = offset ? 8*offset : (WORD_SIZE*8);
45     s->cur_bits = endian_fix( *(intptr_t*)s->p );
46 }
47 static inline int bs_pos( bs_t *s )
48 {
49     return( 8 * (s->p - s->p_start) + (WORD_SIZE*8) - s->i_left );
50 }
51
52 /* Write the rest of cur_bits to the bitstream; results in a bitstream no longer 32/64-bit aligned. */
53 static inline void bs_flush( bs_t *s )
54 {
55     *(intptr_t*)s->p = endian_fix( s->cur_bits << s->i_left );
56     s->p += WORD_SIZE - s->i_left / 8;
57     s->i_left = WORD_SIZE*8;
58 }
59
60 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
61 {
62     if( WORD_SIZE == 8 )
63     {
64         s->cur_bits = (s->cur_bits << i_count) | i_bits;
65         s->i_left -= i_count;
66         if( s->i_left <= 32 )
67         {
68             *(uint32_t*)s->p = endian_fix( s->cur_bits << s->i_left );
69             s->i_left += 32;
70             s->p += 4;
71         }
72     }
73     else
74     {
75         if( i_count < s->i_left )
76         {
77             s->cur_bits = (s->cur_bits << i_count) | i_bits;
78             s->i_left -= i_count;
79         }
80         else
81         {
82             i_count -= s->i_left;
83             s->cur_bits = (s->cur_bits << s->i_left) | (i_bits >> i_count);
84             *(uint32_t*)s->p = endian_fix( s->cur_bits );
85             s->p += 4;
86             s->cur_bits = i_bits;
87             s->i_left = 32 - i_count;
88         }
89     }
90 }
91
92 /* Special case to eliminate branch in normal bs_write. */
93 /* Golomb never writes an even-size code, so this is only used in slice headers. */
94 static inline void bs_write32( bs_t *s, uint32_t i_bits )
95 {
96     bs_write( s, 16, i_bits >> 16 );
97     bs_write( s, 16, i_bits );
98 }
99
100 static inline void bs_write1( bs_t *s, uint32_t i_bit )
101 {
102     s->cur_bits <<= 1;
103     s->cur_bits |= i_bit;
104     s->i_left--;
105     if( s->i_left == WORD_SIZE*8-32 )
106     {
107         *(uint32_t*)s->p = endian_fix32( s->cur_bits );
108         s->p += 4;
109         s->i_left = WORD_SIZE*8;
110     }
111 }
112
113 static inline void bs_align_0( bs_t *s )
114 {
115     if( s->i_left&7 )
116     {
117         s->cur_bits <<= s->i_left&7;
118         s->i_left &= ~7;
119     }
120     bs_flush( s );
121 }
122 static inline void bs_align_1( bs_t *s )
123 {
124     if( s->i_left&7 )
125     {
126         s->cur_bits <<= s->i_left&7;
127         s->cur_bits |= (1 << (s->i_left&7)) - 1;
128         s->i_left &= ~7;
129     }
130     bs_flush( s );
131 }
132
133 /* golomb functions */
134
135 static const uint8_t x264_ue_size_tab[256] =
136 {
137      1, 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
138      9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
139     11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
140     11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
141     13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
142     13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
143     13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
144     13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
145     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
146     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
147     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
148     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
149     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
150     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
151     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
152     15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
153 };
154
155 static inline void bs_write_ue_big( bs_t *s, unsigned int val )
156 {
157     int size = 0;
158     int tmp = ++val;
159     if( tmp >= 0x10000 )
160     {
161         bs_write32( s, 0 );
162         tmp >>= 16;
163     }
164     if( tmp >= 0x100 )
165     {
166         size = 16;
167         tmp >>= 8;
168     }
169     size += x264_ue_size_tab[tmp];
170     bs_write( s, size, val );
171 }
172
173 /* Only works on values under 255. */
174 static inline void bs_write_ue( bs_t *s, int val )
175 {
176     bs_write( s, x264_ue_size_tab[val+1], val+1 );
177 }
178
179 static inline void bs_write_se( bs_t *s, int val )
180 {
181     int size = 0;
182     int tmp = val = val <= 0 ? -val*2+1 : val*2;
183     if( tmp >= 0x100 )
184     {
185         size = 16;
186         tmp >>= 8;
187     }
188     size += x264_ue_size_tab[tmp];
189     bs_write( s, size, val );
190 }
191
192 static inline void bs_write_te( bs_t *s, int x, int val )
193 {
194     if( x == 1 )
195         bs_write1( s, 1^val );
196     else if( x > 1 )
197         bs_write_ue( s, val );
198 }
199
200 static inline void bs_rbsp_trailing( bs_t *s )
201 {
202     bs_write1( s, 1 );
203     bs_flush( s );
204 }
205
206 static inline int bs_size_ue( unsigned int val )
207 {
208     return x264_ue_size_tab[val+1];
209 }
210
211 static inline int bs_size_ue_big( unsigned int val )
212 {
213     if( val < 255 )
214         return x264_ue_size_tab[val+1];
215     else
216         return x264_ue_size_tab[(val+1)>>8] + 16;
217 }
218
219 static inline int bs_size_se( int val )
220 {
221     return bs_size_ue_big( val <= 0 ? -val*2 : val*2-1 );
222 }
223
224 static inline int bs_size_te( int x, int val )
225 {
226     if( x == 1 )
227         return 1;
228     else if( x > 1 )
229         return x264_ue_size_tab[val+1];
230     else
231         return 0;
232 }
233
234 #endif