#ifndef X264_BS_H
#define X264_BS_H
+typedef struct
+{
+ uint8_t i_bits;
+ uint8_t i_size;
+} vlc_t;
+
+typedef struct
+{
+ uint16_t i_bits;
+ uint8_t i_size;
+ /* Next level table to use */
+ uint8_t i_next;
+} vlc_large_t;
+
typedef struct bs_s
{
uint8_t *p_start;
int i_bits_encoded; /* RD only */
} bs_t;
+typedef struct
+{
+ int last;
+ int16_t level[16];
+ uint8_t run[16];
+} x264_run_level_t;
+
+extern const vlc_t x264_coeff0_token[5];
+extern const vlc_t x264_coeff_token[5][16][4];
+extern const vlc_t x264_total_zeros[15][16];
+extern const vlc_t x264_total_zeros_dc[3][4];
+extern const vlc_t x264_run_before[7][16];
+
+/* A larger level table size theoretically could help a bit at extremely
+ * high bitrates, but the cost in cache is usually too high for it to be
+ * useful.
+ * This size appears to be optimal for QP18 encoding on a Nehalem CPU.
+ * FIXME: Do further testing? */
+#define LEVEL_TABLE_SIZE 128
+extern vlc_large_t x264_level_token[7][LEVEL_TABLE_SIZE];
+
static inline void bs_init( bs_t *s, void *p_data, int i_data )
{
- int offset = ((intptr_t)p_data & (WORD_SIZE-1));
+ int offset = ((intptr_t)p_data & 3);
s->p = s->p_start = (uint8_t*)p_data - offset;
s->p_end = (uint8_t*)p_data + i_data;
- s->i_left = offset ? 8*offset : (WORD_SIZE*8);
- s->cur_bits = endian_fix( *(intptr_t*)s->p );
+ s->i_left = (WORD_SIZE - offset)*8;
+ s->cur_bits = endian_fix32( M32(s->p) );
+ s->cur_bits >>= (4-offset)*8;
}
static inline int bs_pos( bs_t *s )
{
return( 8 * (s->p - s->p_start) + (WORD_SIZE*8) - s->i_left );
}
-/* Write the rest of cur_bits to the bitstream; results in a bitstream no longer 32/64-bit aligned. */
+/* Write the rest of cur_bits to the bitstream; results in a bitstream no longer 32-bit aligned. */
static inline void bs_flush( bs_t *s )
{
- *(intptr_t*)s->p = endian_fix( s->cur_bits << s->i_left );
+ M32( s->p ) = endian_fix32( s->cur_bits << (s->i_left&31) );
s->p += WORD_SIZE - s->i_left / 8;
s->i_left = WORD_SIZE*8;
}
+/* The inverse of bs_flush: prepare the bitstream to be written to again. */
+static inline void bs_realign( bs_t *s )
+{
+ int offset = ((intptr_t)s->p & 3);
+ if( offset )
+ {
+ s->p = (uint8_t*)s->p - offset;
+ s->i_left = (WORD_SIZE - offset)*8;
+ s->cur_bits = endian_fix32( M32(s->p) );
+ s->cur_bits >>= (4-offset)*8;
+ }
+}
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
{
s->i_left -= i_count;
if( s->i_left <= 32 )
{
- *(uint32_t*)s->p = endian_fix( s->cur_bits << s->i_left );
+#ifdef WORDS_BIGENDIAN
+ M32( s->p ) = s->cur_bits >> (32 - s->i_left);
+#else
+ M32( s->p ) = endian_fix( s->cur_bits << s->i_left );
+#endif
s->i_left += 32;
s->p += 4;
}
{
i_count -= s->i_left;
s->cur_bits = (s->cur_bits << s->i_left) | (i_bits >> i_count);
- *(uint32_t*)s->p = endian_fix( s->cur_bits );
+ M32( s->p ) = endian_fix( s->cur_bits );
s->p += 4;
s->cur_bits = i_bits;
s->i_left = 32 - i_count;
s->i_left--;
if( s->i_left == WORD_SIZE*8-32 )
{
- *(uint32_t*)s->p = endian_fix32( s->cur_bits );
+ M32( s->p ) = endian_fix32( s->cur_bits );
s->p += 4;
s->i_left = WORD_SIZE*8;
}
static inline void bs_align_0( bs_t *s )
{
- if( s->i_left&7 )
- {
- s->cur_bits <<= s->i_left&7;
- s->i_left &= ~7;
- }
+ bs_write( s, s->i_left&7, 0 );
bs_flush( s );
}
static inline void bs_align_1( bs_t *s )
{
- if( s->i_left&7 )
- {
- s->cur_bits <<= s->i_left&7;
- s->cur_bits |= (1 << (s->i_left&7)) - 1;
- s->i_left &= ~7;
- }
+ bs_write( s, s->i_left&7, (1 << (s->i_left&7)) - 1 );
bs_flush( s );
}
+static inline void bs_align_10( bs_t *s )
+{
+ if( s->i_left&7 )
+ bs_write( s, s->i_left&7, 1 << ( (s->i_left&7) - 1 ) );
+}
/* golomb functions */
-static const uint8_t i_size0_255[256] =
+static const uint8_t x264_ue_size_tab[256] =
{
- 1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+ 1, 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
};
static inline void bs_write_ue_big( bs_t *s, unsigned int val )
{
- int i_size = 0;
-
- if( val == 0 )
- bs_write1( s, 1 );
- else
+ int size = 0;
+ int tmp = ++val;
+ if( tmp >= 0x10000 )
{
- unsigned int tmp = ++val;
-
- if( tmp >= 0x00010000 )
- {
- i_size += 16;
- tmp >>= 16;
- }
- if( tmp >= 0x100 )
- {
- i_size += 8;
- tmp >>= 8;
- }
- i_size += i_size0_255[tmp];
-
- bs_write( s, 2 * i_size - 1, val );
+ size = 32;
+ tmp >>= 16;
}
+ if( tmp >= 0x100 )
+ {
+ size += 16;
+ tmp >>= 8;
+ }
+ size += x264_ue_size_tab[tmp];
+ bs_write( s, size>>1, 0 );
+ bs_write( s, (size>>1)+1, val );
}
/* Only works on values under 255. */
static inline void bs_write_ue( bs_t *s, int val )
{
- if( val == 0 )
- bs_write1( s, 1 );
- else
- bs_write( s, 2 * i_size0_255[val+1] - 1, val+1 );
+ bs_write( s, x264_ue_size_tab[val+1], val+1 );
}
static inline void bs_write_se( bs_t *s, int val )
{
- int i_size = 0;
- val = val <= 0 ? -val * 2 : val * 2 - 1;
+ int size = 0;
+ /* Faster than (val <= 0 ? -val*2+1 : val*2) */
+ /* 4 instructions on x86, 3 on ARM */
+ int tmp = 1 - val*2;
+ if( tmp < 0 ) tmp = val*2;
+ val = tmp;
- if( val == 0 )
- bs_write1( s, 1 );
- else
+ if( tmp >= 0x100 )
{
- unsigned int tmp = ++val;
-
- if( tmp >= 0x100 )
- {
- i_size += 8;
- tmp >>= 8;
- }
- i_size += i_size0_255[tmp];
-
- bs_write( s, 2 * i_size - 1, val );
+ size = 16;
+ tmp >>= 8;
}
+ size += x264_ue_size_tab[tmp];
+ bs_write( s, size, val );
}
static inline void bs_write_te( bs_t *s, int x, int val )
{
if( x == 1 )
bs_write1( s, 1^val );
- else if( x > 1 )
+ else //if( x > 1 )
bs_write_ue( s, val );
}
static inline void bs_rbsp_trailing( bs_t *s )
{
bs_write1( s, 1 );
- bs_flush( s );
+ bs_write( s, s->i_left&7, 0 );
}
-static const uint8_t i_size0_254[255] =
-{
- 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
- 11,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
- 13,13,13,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
- 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
-};
-
-static inline int bs_size_ue( unsigned int val )
+static ALWAYS_INLINE int bs_size_ue( unsigned int val )
{
- return i_size0_254[val];
+ return x264_ue_size_tab[val+1];
}
-static inline int bs_size_ue_big( unsigned int val )
+static ALWAYS_INLINE int bs_size_ue_big( unsigned int val )
{
if( val < 255 )
- return i_size0_254[val];
+ return x264_ue_size_tab[val+1];
else
- {
- val++;
- val = (val >> 8) - 1;
- return i_size0_254[val] + 16;
- }
+ return x264_ue_size_tab[(val+1)>>8] + 16;
}
-static inline int bs_size_se( int val )
+static ALWAYS_INLINE int bs_size_se( int val )
{
- val = val <= 0 ? -val * 2 : val * 2 - 1;
- if( val < 255 )
- return i_size0_254[val];
+ int tmp = 1 - val*2;
+ if( tmp < 0 ) tmp = val*2;
+ if( tmp < 256 )
+ return x264_ue_size_tab[tmp];
else
- {
- val++;
- val = (val >> 8) - 1;
- return i_size0_254[val] + 16;
- }
+ return x264_ue_size_tab[tmp>>8]+16;
}
-static inline int bs_size_te( int x, int val )
+static ALWAYS_INLINE int bs_size_te( int x, int val )
{
if( x == 1 )
return 1;
- else if( x > 1 )
- return i_size0_254[val];
- return 0;
+ else //if( x > 1 )
+ return x264_ue_size_tab[val+1];
}
#endif