package com.twilight.h264.util; import java.io.IOException; import java.io.InputStream; public class BufferedInputStream extends FilterInputStream{ protected volatile byte[] buf; protected int count; protected int markLimit; protected int markPos = -1; protected int pos; public BufferedInputStream(InputStream is) { super(is); buf = new byte[8912]; } public BufferedInputStream(InputStream is, int size) { super(is); buf = new byte[size]; } public synchronized int available() throws IOException { InputStream local = inputStream; return count - pos + local.available(); } public void close() throws IOException { InputStream local = inputStream; buf = null; inputStream = null; if(local != null) local.close(); } private int fillBuf(InputStream localIn, byte[] localBuf) throws IOException { if(markPos == -1 || (pos - markPos >= markLimit)) { int result = localIn.read(localBuf); if(result > 0) { markPos = -1; pos = 0; count = result == -1?0:result; } // if return result; } // if if(markPos == 0 && markLimit > localBuf.length) { int newLength = localBuf.length * 2; if(newLength > markLimit) newLength = markLimit; byte[] newBuf = new byte[newLength]; System.arraycopy(localBuf, 0, newBuf, 0, localBuf.length); localBuf = buf = newBuf; } else if(markPos > 0) { System.arraycopy(localBuf, markPos, localBuf, 0, localBuf.length - markPos); } // if pos -= markPos; count = markPos = 0; int bytesRead = localIn.read(localBuf,pos,localBuf.length - pos); count = bytesRead <= 0? pos: pos + bytesRead; return bytesRead; } public synchronized void mark(int readLimit) { markLimit = readLimit; markPos = pos; } public boolean markSupported() { return true; } public synchronized int read() throws IOException { byte[] localBuf = buf; InputStream localIn = inputStream; if(pos >= count && fillBuf(localIn, localBuf) == -1) { return -1; } // if if(localBuf != buf) { localBuf = buf; if(localBuf == null) throw new IOException(); } if(count - pos > 0) return localBuf[pos++] & 0xff; return -1; } public synchronized int read(byte[] buffer,int offset,int length) throws IOException { byte[] localBuf = buf; if(localBuf==null) throw new IOException(); if(length == 0) return 0; InputStream localIn = inputStream; if(localIn==null) throw new IOException(); int required; if(pos < count) { int copyLength = count - pos >= length?length: count - pos; System.arraycopy(localBuf, pos, buffer, offset, copyLength); pos += copyLength; if(copyLength == length || localIn.available() == 0) return copyLength; offset += copyLength; required = length - copyLength; } else { required = length; } // if while(true) { int read; if(markPos == -1 && required > localBuf.length) { read = localIn.read(buffer, offset, required); if(read == -1) return required == length?-1:length - required; } else { if(fillBuf(localIn, localBuf) == -1) return required == length?-1:length - required; if(localBuf != buf) { localBuf = buf; if(localBuf == null) throw new IOException(); } // if read = count - pos >= required? required: count - pos; System.arraycopy(localBuf, pos, buffer, offset, read); pos += read; } // if required -= read; if(required == 0) return length; if(localIn.available() == 0) return length - required; offset += read; } // while } public synchronized void reset() throws IOException { if(buf == null) throw new IOException(); if(-1 == markPos) throw new IOException(); pos = markPos; } public synchronized long skip(long amount) throws IOException { byte[] localBuf = buf; InputStream localIn = inputStream; if(localBuf == null) throw new IOException(); if(amount < 1) return 0; if(localIn == null) throw new IOException(); if(count - pos >= amount) { pos += amount; return amount; } // if long read = count - pos; pos = count; if(markPos != -1) { if(amount <= markLimit) { if(fillBuf(localIn, localBuf) == -1) return read; if(count - pos >= amount - read) { pos += amount - read; return amount; } // if read += (count - pos); pos = count; return read; } // if } // if return read + localIn.skip(amount - read); } }