/Play/bits.js
JavaScript | 218 lines | 146 code | 23 blank | 49 comment | 21 complexity | e1fd83f495cf2ea6006f298160542546 MD5 | raw file
1'use strict'; 2 3var trace = false; 4 5/** 6 * Represents a bit stream view over a RBSP buffer. 7 */ 8var Bitstream = (function () { 9 /** 10 * @param {Uint8Array} ptr A pointer to a buffer underlying this bitstream. 11 */ 12 function constructor(ptr) { 13 this.incnt = 0; 14 this.incnt_next = 0; 15 this.bitcnt = 0; 16 this.curr_word = this.next_word = 0; 17 this.read_pos = 0; 18 this.buffer = ptr; 19 if (trace) printArray(ptr); 20 } 21 22 constructor.prototype.flush = function (n) { 23 this.bitcnt += n; 24 this.incnt -= n; 25 this.curr_word <<= n; 26 }; 27 28 /** 29 * Reads up to 32 bits. 30 */ 31 constructor.prototype.fill = function () { 32 if (trace) println("Before Fill: " + this.toString()); 33 var buffer = this.buffer; 34 var num_bits; 35 36 this.curr_word |= (this.next_word >>> this.incnt); // this.incnt cannot be 32 37 this.next_word <<= (31 - this.incnt); 38 this.next_word <<= 1; 39 num_bits = this.incnt_next + this.incnt; 40 if (num_bits >= 32) { 41 this.incnt_next -= (32 - this.incnt); 42 this.incnt = 32; 43 } 44 45 var pos = this.read_pos; 46 47 if (this.read_pos > buffer.length - 4) { 48 if (buffer.length <= this.read_pos) { 49 this.incnt = num_bits; 50 this.incnt_next = 0; 51 } 52 this.next_word = 0; 53 for (var i = 0; i < buffer.length - this.read_pos; i++) { 54 this.next_word |= (buffer[pos + i] << ((3 - i) << 3)); 55 } 56 this.read_pos = buffer.length; 57 this.curr_word |= (this.next_word >> num_bits); 58 this.next_word <<= (31 - num_bits); 59 this.next_word <<= 1; 60 num_bits = i << 3; 61 this.incnt += this.incnt_next; 62 this.incnt_next = num_bits - (32 - this.incnt); 63 if (this.incnt_next < 0) { 64 this.incnt += num_bits; 65 this.incnt_next = 0; 66 } else { 67 this.incnt = 32; 68 } 69 if (trace) println("After Fill: " + this.toString()); 70 return; 71 } 72 73 this.next_word = (buffer[pos] << 24 | (buffer[pos + 1] << 16) | (buffer[pos + 2] << 8) | buffer[pos + 3]); 74 this.read_pos += 4; 75 76 this.curr_word |= (this.next_word >>> num_bits); // this is safe 77 this.next_word <<= (31 - num_bits); 78 this.next_word <<= 1; 79 this.incnt_next += this.incnt; 80 this.incnt = 32; 81 if (trace) println("After Fill: " + this.toString()); 82 }; 83 84 /* 85 * Reads up to one machine word. 86 */ 87 constructor.prototype.readBits = function (n) { 88 if (this.incnt < n) { 89 this.fill(); 90 } 91 var bits = this.curr_word >>> (32 - n); 92 this.flush(n); 93 return bits; 94 }; 95 96 /* 97 * Reads up to one machine word but does not advance. 98 */ 99 constructor.prototype.peekBits = function (n) { 100 if (this.incnt < n) { 101 this.fill(); 102 } 103 return this.curr_word >>> (32 - n); 104 }; 105 106 /* 107 * Reads a single bit. 108 */ 109 constructor.prototype.readBit = function () { 110 if (this.incnt < 1) { 111 this.fill(); 112 } 113 var bit = this.curr_word >>> 31; 114 this.flush(1); 115 return bit; 116 }; 117 118 /* 119 * Exponential-Golomb Coding: 120 * See algorithm in Section 9.1, Table 9-1, Table 9-2. 121 * 122 * Pattern Code 123 * 124 * 1 0 125 * 01X 1,2 126 * 001XX 3,6 127 * 0001XXX 7,14 128 * 00001XXXX 15,30 129 * ......... ..... 130 * 131 * Code = 2 ^ (z) - 1 + readBits(z), where n is the number of leading zeros up until the first 1 bit, and 132 * readBits(z) are the z bits following the first bit 1. 133 * 134 */ 135 136 137 /** 138 * Unsigned Exponential-Golomb Coding for 16 bit values. 139 */ 140 constructor.prototype.uev = function () { 141 var temp = this.peekBits(16); 142 // if (trace) println("uev bits: " + getNumberInfo(temp)); 143 var leading_zeros = countLeadingZeros16(temp | 0x1); 144 // if (trace) println("uev lzs: " + leading_zeros); 145 if (leading_zeros < 8) { 146 var code = (temp >>> (15 - (leading_zeros << 1))) - 1; 147 this.flush((leading_zeros << 1) + 1); 148 return code; 149 } 150 return this.readBits((leading_zeros << 1) + 1) - 1; 151 }; 152 153 /** 154 * Signed Exponential-Golomb Coding for 16 bit values. 155 */ 156 constructor.prototype.sev = function () { 157 var temp = this.peekBits(16); 158 var leading_zeros = countLeadingZeros16(temp | 0x1); 159 if (leading_zeros < 8) { 160 temp >>>= (15 - (leading_zeros << 1)); 161 this.flush((leading_zeros << 1) + 1); 162 } else { 163 temp = this.readBits((leading_zeros << 1) + 1); 164 } 165 var ret = temp >>> 1; 166 if (temp & 0x01) { 167 ret = -ret; 168 } 169 return ret; 170 }; 171 172 /** 173 * Read Exponential-Golomb 32 bit values with range from -2^31 to 2^31-1. 174 */ 175 constructor.prototype.readEBBits32 = function () { 176 var bit = this.readBit(); 177 var leading_zeros = 0; 178 while(!bit) { 179 leading_zeros += 1; 180 bit = this.readBit(); 181 } 182 183 if (leading_zeros > 0) { 184 return this.readBits(leading_zeros); 185 } 186 return 0; 187 }; 188 189 /* 190 * Signed Exponential-Golomb Coding for 32 bit values. 191 */ 192 constructor.prototype.sev32 = function () { 193 var bit = this.readBit(); 194 var leading_zeros = 0; 195 while(!bit) { 196 leading_zeros += 1; 197 bit = this.readBit(); 198 } 199 200 var bits = 0; 201 if (leading_zeros > 0) { 202 bits = this.readBits(leading_zeros); 203 } 204 205 var code = (1 << leading_zeros) - 1 + bits; 206 var value = (code + 1) / 2; 207 208 if ((code & 0x01) == 0) { 209 value = -value; 210 } 211 return value; 212 }; 213 214 constructor.prototype.toString = function () { 215 return getProperties(this, true); 216 }; 217 return constructor; 218})();