#ifdef BS_H #warning FIXME Multiple inclusion of bs.h #else #define BS_H typedef struct bs_s { uint8 * p_start; uint8 * p; uint8 * p_end; int i_left; /* i_count number of available bits */ } bs_t; static inline void bs_init(bs_t *s, void *p_data, int i_data) { s->p_start = (uint8 *)p_data; s->p = (uint8 *)p_data; s->p_end = s->p + i_data; s->i_left = 8; } static inline int bs_pos(bs_t *s) { return (int)(8 * (s->p - s->p_start) + 8 - s->i_left); } static inline int bs_left(bs_t *s) { return (int)(8 * (s->p_end - s->p) + 8 - s->i_left); } static inline int bs_eof(bs_t *s) { return (s->p >= s->p_end ? 1: 0); } static inline uint32 bs_read(bs_t *s, int i_count) { static uint32 i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; int i_shr; uint32 i_result = 0; while (i_count > 0) { if (s->p >= s->p_end) { break; } if ((i_shr = s->i_left - i_count) >= 0) { /* more in the buffer than requested */ i_result |= (*s->p >> i_shr)&i_mask[i_count]; s->i_left -= i_count; if (s->i_left == 0) { s->p++; s->i_left = 8; } return i_result; } else { /* less in the buffer than requested */ i_result |= (*s->p&i_mask[s->i_left]) << -i_shr; i_count -= s->i_left; s->p++; s->i_left = 8; } } return i_result; } static inline uint32 bs_read1(bs_t *s) { if (s->p < s->p_end) { uint32 i_result; s->i_left--; i_result = (*s->p >> s->i_left)&0x01; if (s->i_left == 0) { s->p++; s->i_left = 8; } return i_result; } return 0; } static inline uint32 bs_show(bs_t *s, int i_count) { if (s->p < s->p_end && i_count > 0) { uint32 i_cache = ((s->p[0] << 24)+(s->p[1] << 16)+(s->p[2] << 8)+s->p[3]) << (8-s->i_left); return (i_cache >> (32 - i_count)); } return 0; } /* TODO optimize */ static inline void bs_skip(bs_t *s, int i_count) { s->i_left -= i_count; while (s->i_left <= 0) { s->p++; s->i_left += 8; } } static inline int bs_read_ue(bs_t *s) { int i = 0; while (bs_read1(s) == 0 && s->p < s->p_end && i < 32) { i++; } return ((1 << i) - 1 + bs_read(s, i)); } static inline int bs_read_se(bs_t *s) { int val = bs_read_ue(s); return val&0x01 ? (val+1)/2 : -(val/2); } static inline int bs_read_te(bs_t *s, int x) { if (x == 1) { return 1 - bs_read1(s); } else if (x > 1) { return bs_read_ue(s); } return 0; } /* TODO optimize (write x bits at once) */ static inline void bs_write(bs_t *s, int i_count, uint32 i_bits) { while (i_count > 0) { if (s->p >= s->p_end) { break; } i_count--; if ((i_bits >> i_count) & 0x01) { *s->p |= 1 << (s->i_left - 1); } else { *s->p &= ~(1 << (s->i_left - 1)); } s->i_left--; if (s->i_left == 0) { s->p++; s->i_left = 8; } } } static inline void bs_write1(bs_t *s, uint32 i_bits) { if (s->p < s->p_end) { s->i_left--; if (i_bits & 0x01) { *s->p |= 1 << s->i_left; } else { *s->p &= ~(1 << s->i_left); } if (s->i_left == 0) { s->p++; s->i_left = 8; } } } static inline void bs_align(bs_t *s) { if (s->i_left != 8) { s->i_left = 8; s->p++; } } static inline void bs_align_0(bs_t *s) { if (s->i_left != 8) { bs_write(s, s->i_left, 0); } } static inline void bs_align_1(bs_t *s) { if (s->i_left != 8) { bs_write(s, s->i_left, ~0); } } /* golomb functions */ static inline void bs_write_ue(bs_t *s, uint32 val) { int i_size = 0; static const int i_size0_255[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 }; if (val == 0) { bs_write(s, 1, 1); } else { uint32 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); } } static inline void bs_write_se(bs_t *s, int val) { bs_write_ue(s, val <= 0 ? -val * 2 : val * 2 - 1); } static inline void bs_write_te(bs_t *s, int x, int val) { if (x == 1) { bs_write(s, 1, ~val); } else if (x > 1) { bs_write_ue(s, val); } } static inline void bs_rbsp_trailing(bs_t *s) { bs_write(s, 1, 1); if (s->i_left != 8) { bs_write(s, s->i_left, 0x00); } } static inline int bs_size_ue(uint32 val) { static const int 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 }; if (val < 255) { return i_size0_254[val]; } else { int i_size = 0; val++; if (val >= 0x10000) { i_size += 32; val = (val >> 16) - 1; } if (val >= 0x100) { i_size += 16; val = (val >> 8) - 1; } return i_size0_254[val] + i_size; } } static inline int bs_size_se(int val) { return bs_size_ue(val <= 0 ? -val * 2 : val * 2 - 1); } static inline int bs_size_te(int x, int val) { if (x == 1) { return 1; } else if (x > 1) { return bs_size_ue(val); } return 0; } static inline uint8 * bs_data(bs_t *s) { return s->p - (8 - s->i_left) / 8; } #endif