Files

383 lines
7.8 KiB
C

#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