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 }