| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- JSMpeg.BitBuffer = (function(){ "use strict";
-
- var BitBuffer = function(bufferOrLength, mode) {
- if (typeof(bufferOrLength) === 'object') {
- this.bytes = (bufferOrLength instanceof Uint8Array)
- ? bufferOrLength
- : new Uint8Array(bufferOrLength);
-
- this.byteLength = this.bytes.length;
- }
- else {
- this.bytes = new Uint8Array(bufferOrLength || 1024*1024);
- this.byteLength = 0;
- }
-
- this.mode = mode || BitBuffer.MODE.EXPAND;
- this.index = 0;
- };
-
- BitBuffer.prototype.resize = function(size) {
- var newBytes = new Uint8Array(size);
- if (this.byteLength !== 0) {
- this.byteLength = Math.min(this.byteLength, size);
- newBytes.set(this.bytes, 0, this.byteLength);
- }
- this.bytes = newBytes;
- this.index = Math.min(this.index, this.byteLength << 3);
- };
-
- BitBuffer.prototype.evict = function(sizeNeeded) {
- var bytePos = this.index >> 3,
- available = this.bytes.length - this.byteLength;
-
- // If the current index is the write position, we can simply reset both
- // to 0. Also reset (and throw away yet unread data) if we won't be able
- // to fit the new data in even after a normal eviction.
- if (
- this.index === this.byteLength << 3 ||
- sizeNeeded > available + bytePos // emergency evac
- ) {
- this.byteLength = 0;
- this.index = 0;
- return;
- }
- else if (bytePos === 0) {
- // Nothing read yet - we can't evict anything
- return;
- }
-
- // Some browsers don't support copyWithin() yet - we may have to do
- // it manually using set and a subarray
- if (this.bytes.copyWithin) {
- this.bytes.copyWithin(0, bytePos, this.byteLength);
- }
- else {
- this.bytes.set(this.bytes.subarray(bytePos, this.byteLength));
- }
-
- this.byteLength = this.byteLength - bytePos;
- this.index -= bytePos << 3;
- return;
- };
-
- BitBuffer.prototype.write = function(buffers) {
- var isArrayOfBuffers = (typeof(buffers[0]) === 'object'),
- totalLength = 0,
- available = this.bytes.length - this.byteLength;
-
- // Calculate total byte length
- if (isArrayOfBuffers) {
- var totalLength = 0;
- for (var i = 0; i < buffers.length; i++) {
- totalLength += buffers[i].byteLength;
- }
- }
- else {
- totalLength = buffers.byteLength;
- }
-
- // Do we need to resize or evict?
- if (totalLength > available) {
- if (this.mode === BitBuffer.MODE.EXPAND) {
- var newSize = Math.max(
- this.bytes.length * 2,
- totalLength - available
- );
- this.resize(newSize)
- }
- else {
- this.evict(totalLength);
- }
- }
-
- if (isArrayOfBuffers) {
- for (var i = 0; i < buffers.length; i++) {
- this.appendSingleBuffer(buffers[i]);
- }
- }
- else {
- this.appendSingleBuffer(buffers);
- }
- };
-
- BitBuffer.prototype.appendSingleBuffer = function(buffer) {
- buffer = buffer instanceof Uint8Array
- ? buffer
- : new Uint8Array(buffer);
-
- this.bytes.set(buffer, this.byteLength);
- this.byteLength += buffer.length;
- };
-
- BitBuffer.prototype.findNextStartCode = function() {
- for (var i = (this.index+7 >> 3); i < this.byteLength; i++) {
- if(
- this.bytes[i] == 0x00 &&
- this.bytes[i+1] == 0x00 &&
- this.bytes[i+2] == 0x01
- ) {
- this.index = (i+4) << 3;
- return this.bytes[i+3];
- }
- }
- this.index = (this.byteLength << 3);
- return -1;
- };
-
- BitBuffer.prototype.findStartCode = function(code) {
- var current = 0;
- while (true) {
- current = this.findNextStartCode();
- if (current === code || current === -1) {
- return current;
- }
- }
- return -1;
- };
-
- BitBuffer.prototype.nextBytesAreStartCode = function() {
- var i = (this.index+7 >> 3);
- return (
- i >= this.byteLength || (
- this.bytes[i] == 0x00 &&
- this.bytes[i+1] == 0x00 &&
- this.bytes[i+2] == 0x01
- )
- );
- };
-
- BitBuffer.prototype.peek = function(count) {
- var offset = this.index;
- var value = 0;
- while (count) {
- var currentByte = this.bytes[offset >> 3],
- remaining = 8 - (offset & 7), // remaining bits in byte
- read = remaining < count ? remaining : count, // bits in this run
- shift = remaining - read,
- mask = (0xff >> (8-read));
-
- value = (value << read) | ((currentByte & (mask << shift)) >> shift);
-
- offset += read;
- count -= read;
- }
-
- return value;
- }
-
- BitBuffer.prototype.read = function(count) {
- var value = this.peek(count);
- this.index += count;
- return value;
- };
-
- BitBuffer.prototype.skip = function(count) {
- return (this.index += count);
- };
-
- BitBuffer.prototype.rewind = function(count) {
- this.index = Math.max(this.index - count, 0);
- };
-
- BitBuffer.prototype.has = function(count) {
- return ((this.byteLength << 3) - this.index) >= count;
- };
-
- BitBuffer.MODE = {
- EVICT: 1,
- EXPAND: 2
- };
-
- return BitBuffer;
-
- })();
-
-
|