1 
2 module bitstream;
3 
4 public import stdint;
5 
6 import std.exception;
7 import std.algorithm;
8 
9 /**
10 * @brief Bitstream reader and parser
11 *
12 * @copyright The code is borrowed from h264bitstream library and translated to D
13 */
14 
15 public class BitstreamReader
16 {
17 	public this(const ubyte[] data)
18 	{
19 		_data = data;
20 		start = _data.ptr;
21 		p = start;
22 		end = _data.ptr + _data.length;
23 		bits_left = 8;
24 	}
25 
26 	public bool eof() const @property
27 	{
28 		return _eof;
29 	}
30 
31 	public size_t bits_read() const @property
32 	{
33 		return _bits_read;
34 	}
35 
36 	public bool is_byte_aligned() const
37 	{
38 		return bits_left == 8;
39 	}
40 
41 	public void align_to_next_byte()
42 	{
43 		if(bits_left != 8)
44 		{
45 			p++;
46 			bits_left = 8;
47 		}
48 	}
49 
50 	public bool read_bool()
51 	{
52 		return cast(bool) read_u1;
53 	}
54 
55 	public uint nextbits(int n) const
56 	{
57 		static immutable int[] mask = [
58 			~0xFF,
59 			~0x7F,
60 			~0x3F,
61 			~0x1F,
62 			~0x0F,
63 			~0x07,
64 			~0x03,
65 			~0x01,
66 			~0x00,
67 		];
68 
69 		uint r = 0;
70 		int i = 0;
71 		int bits_to_put = min(min(n, 8), bits_left);
72 		int bits_left_shift = 8 - bits_left;
73 
74 		while(n > 0)
75 		{
76 			r <<= bits_to_put;
77 
78 			ubyte b = cast(ubyte) (p[i] << bits_left_shift);
79 			int tail = ( b & mask[bits_to_put]) >> (8 - bits_to_put);
80 			r |= tail;
81 
82 			n -= bits_to_put;
83 			i+= 1;
84 			bits_to_put = min(n, 8);
85 			bits_left_shift = 0;
86 		}
87 
88 		return r;
89 	}
90 
91 	public ubyte read_u1()
92 	{
93 		ubyte r = 0;
94 
95 		bits_left--;
96 		_bits_read += 1;
97 
98 		if( ! _eof )
99 		{
100 			r = ((*(p)) >> bits_left) & 0x01;
101 		}
102 
103 		if (bits_left == 0) { p ++; bits_left = 8; }
104 
105 		return r;
106 	}
107 
108 	public void skip_u1()
109 	{
110 		bits_left--;
111 		_bits_read += 1;
112 
113 		if(bits_left == 0)
114 		{
115 			p++;
116 			bits_left = 8;
117 		}
118 	}
119 
120 	alias skip = skip_u;
121 
122 	public uint32 peek_u1()
123 	{
124 		uint32 r = 0;
125 
126 		if( ! _eof )
127 		{
128 			r = ((*(p)) >> ( bits_left - 1 )) & 0x01;
129 		}
130 		return r;
131 	}
132 
133 
134 	public T read_u(T = uint32)(int n)
135 	{
136 		uint32 r = 0;
137 		int i;
138 		for (i = 0; i < n; i++)
139 		{
140 			r |= ( read_u1() << ( n - i - 1 ) );
141 		}
142 		return cast(T) r;
143 	}
144 
145 	public ubyte read_b(int n)
146 	{
147 		return cast(ubyte) read_u(n);
148 	}
149 
150 	public void skip_u(int n)
151 	{
152 		int i;
153 		for ( i = 0; i < n; i++ )
154 		{
155 			skip_u1();
156 		}
157 	}
158 
159 	public uint32 read_f(int n)
160 	{
161 		return read_u(n);
162 	}
163 
164 	public ubyte read_u8()
165 	{
166 		if (bits_left == 8 && ! eof()) // can do fast read
167 		{
168 			ubyte r = p[0];
169 			p++;
170 			_bits_read += 8;
171 			return r;
172 		}
173 
174 		return cast(ubyte) read_u(8);
175 	}
176 
177 	public uint32 read_ue()
178 	{
179 		int32 r = 0;
180 		int i = 0;
181 
182 		while( (read_u1() == 0) && (i < 32) && (!eof()) )
183 		{
184 			i++;
185 		}
186 		r = read_u(i);
187 		r += (1 << i) - 1;
188 		return r;
189 	}
190 
191 	public int32 read_se()
192 	{
193 		int32 r = read_ue();
194 		if (r & 0x01)
195 		{
196 			r = (r+1)/2;
197 		}
198 		else
199 		{
200 			r = -(r/2);
201 		}
202 		return r;
203 	}
204 
205 	public const(ubyte)[] read_bytes(long len)
206 	{
207 		enforce(is_byte_aligned());
208 
209 		auto actual_len = len;
210 		if (end - p < actual_len) { actual_len = end - p; }
211 		if (actual_len < 0) { actual_len = 0; }
212 		auto buf = p[0..actual_len];
213 		p += actual_len;
214 		_bits_read += actual_len * 8;
215 
216 		return buf;
217 	}
218 
219 	public long read_bytes(ubyte[] b)
220 	{
221 		auto r = read_bytes(b.length);
222 
223 		b[0..r.length] = r[0..$];
224 
225 		return r.length;
226 	}
227 
228 	public long skip_bytes(long len)
229 	{
230 		enforce(is_byte_aligned());
231 
232 		auto actual_len = len;
233 		if (end - p < actual_len) { actual_len = end - p; }
234 		if (actual_len < 0) { actual_len = 0; }
235 		if (len < 0) { len = 0; }
236 		p += actual_len;
237 		_bits_read += actual_len * 8;
238 
239 		return actual_len;
240 	}
241 
242 	//public uint32 next_bits(int nbits);
243 
244 	public uint64 next_bytes(int nbytes)
245 	{
246 		int i = 0;
247 		uint64 val = 0;
248 
249 		if ( (nbytes > 8) || (nbytes < 1) ) { return 0; }
250 		if (p + nbytes > end) { return 0; }
251 
252 		for ( i = 0; i < nbytes; i++ ) { val = ( val << 8 ) | p[i]; }
253 		return val;
254 	}
255 
256 	private const ubyte[] _data;
257 	private const uint8* start;
258 	private const uint8* end;
259 	private const(uint8)* p;
260 	private int bits_left;
261 	private size_t _bits_read = 0;
262 
263 	invariant()
264 	{
265 		assert(bits_left > 0);
266 		assert(bits_left <= 8);
267 		assert(start < end);
268 		assert(start<=p);
269 		assert(p<=end);
270 	}
271 
272 	private bool _eof() const @property
273 	{
274 		return p >= end;
275 	}
276 }
277 
278 unittest
279 {
280 	auto bs = new BitstreamReader([0x12, 0x25, 0xf1]);
281 	auto vals = [0,0,0,1, 0,0,1,0, 0,0,1,0, 0,1,0,1, 1,1,1,1, 0,0,0,1];
282 
283 	foreach(v; vals)
284 	{
285 		assert(bs.read_u1() == v);
286 	}
287 
288 	assert(bs.eof);
289 	assert(bs.bits_read == 24);
290 }
291 
292 unittest
293 {
294 	auto bs = new BitstreamReader([0x12, 0x25, 0xf1, 0x25, 0xf1]);
295 	auto vals = [0,0,0,1, 0,0,1,0, 0,0,1,0, 0,1,0,1, 1,1,1,1, 0,0,0,1, 0,0,1,0, 0,1,0,1, 1,1,1,1, 0,0,0,1];
296 
297 	uint preapre_uint(int[] v)
298 	{
299 		uint r = 0;
300 		for(size_t i=0; i<v.length; ++i)
301 		{
302 			r = r << 1;
303 			r |= v[i] & 0x01;
304 		}
305 
306 		return r;
307 	}
308 
309 	assert(preapre_uint(vals[0..8]) == 0x12);
310 	assert(preapre_uint(vals[0..16]) == 0x1225);
311 	assert(preapre_uint(vals[4..16]) == 0x225);
312 
313 	for(uint i=0; i<vals.length; ++i)
314 	{
315 		for(uint j=0; j<vals.length - i; ++j)
316 		{
317 			auto nb = bs.nextbits(j);
318 			assert(nb == preapre_uint(vals[i..i+j]));
319 		}
320 
321 		bs.skip_u1;
322 	}
323 
324 	assert(bs.eof);
325 	assert(bs.bits_read == 40);
326 }
327 
328 unittest
329 {
330 	auto bs = new BitstreamReader([0x12, 0x25, 0xf1]);
331 	auto bitstring = [0,0,0,1, 0,0,1,0, 0,0,1,0, 0,1,0,1, 1,1,1,1, 0,0,0,1];
332 	auto steps = [5,3,9,2,1,4];
333 
334 	size_t pos = 0;
335 	foreach(i,s; steps)
336 	{
337 		uint32 r = 0;
338 		auto r_bits = bitstring[pos..pos + s];
339 		foreach(v; r_bits)
340 		{
341 			r <<= 1;
342 			r |= v;
343 		}
344 
345 		assert(r == bs.read_u(s));
346 
347 		pos += s;
348 		if(bs.eof)
349 		{
350 			break;
351 		}
352 	}
353 
354 	assert(bs.eof);
355 	assert(pos == bitstring.length);
356 	assert(bs.bits_read == 24);
357 }