summaryrefslogtreecommitdiff
path: root/bitstream.h
blob: 98937e89f2b98f126007d795f8070c0b33508598 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * Extracted 2009 from mplayer 2009-02-10 libavcodec/bitstream.h.
 *
 * copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
 *
 * Licensed under the GNU Lesser General Public License, see file COPYING.LIB.
 */

/** \file bitstream.h Bitstream structures and inline functions. */

/** Structure for bistream I/O. */
struct getbit_context {
	/** Start of the internal buffer. */
	const uint8_t *buffer;
	/** Length of buffer in bits (always a multiple of 8). */
	uint32_t num_bits;
	/** Bit counter. */
	int index;
};

/** A variable length code table. */
struct vlc {
	/** Number of bits of the table. */
	int bits;
	/** The code and the bits table. */
	int16_t (*table)[2];
	/** The size of the table. */
	int table_size;
	/** Amount of memory allocated so far. */
	int table_allocated;
};

static inline uint32_t show_bits(struct getbit_context *gbc, int num)
{
	int idx = gbc->index;
	const char *p;
	uint32_t x;

	assert(idx + num <= gbc->num_bits);
	p = (const char *)gbc->buffer + (idx >> 3);
	x = read_u32_be(p);
	return (x << (idx & 7)) >> (32 - num);
}

static inline int get_bits_count(struct getbit_context *gbc)
{
	return gbc->index;
}

static inline void skip_bits(struct getbit_context *gbc, int n)
{
	assert(gbc->index + n <= gbc->num_bits);
	gbc->index += n;
}

static inline unsigned int get_bits(struct getbit_context *gbc, int n)
{
	unsigned int ret = show_bits(gbc, n); /* checks n */
	skip_bits(gbc, n);
	return ret;
}

/* This is rather hot, we can do better than get_bits(gbc, 1). */
static inline unsigned int get_bit(struct getbit_context *gbc)
{
	int idx;
	uint8_t tmp, mask;

	assert(gbc->index < gbc->num_bits);
	idx = gbc->index++;
	tmp = gbc->buffer[idx >> 3];
	mask = 1 << (7 - (idx & 7));
	return !!(tmp & mask);
}

/**
 * Initialize a getbit_context structure.
 *
 * \param gbc The structure to initialize.
 * \param buffer The bitstream buffer.
 * \param size The size of the buffer in bytes.
 *
 * The bitstream buffer must be 4 bytes larger then the actual read bits
 * because the bitstream reader might read 32 bits at once and could read over
 * the end.
 */
static inline void init_get_bits(struct getbit_context *gbc,
		const uint8_t *buffer, int size)
{
	gbc->buffer = buffer;
	gbc->num_bits = size * 8;
	gbc->index = 0;
}

void init_vlc(struct vlc *vlc, int nb_bits, int nb_codes, const void *bits,
		const void *codes, int codes_size);
void free_vlc(struct vlc *vlc);
int get_vlc(struct getbit_context *gbc, const struct vlc *vlc);