/**
*
*/
package edu.washington.cs.oneswarm.ui.gwt.server.ffmpeg;
import java.util.concurrent.ArrayBlockingQueue;
class ByteStreamBuffer {
private ArrayBlockingQueue<byte[]> buffer;
private final int maxElementSize;
// private volatile int currentBufferSize = 0;
private Object writeLock = new Object();
private Object readLock = new Object();
public ByteStreamBuffer(int bufferSize, int chunkSize) {
this.maxElementSize = chunkSize;
int queueLength = bufferSize / maxElementSize + 1;
buffer = new ArrayBlockingQueue<byte[]>(queueLength);
}
public int read(byte[] buf) throws InterruptedException {
synchronized (readLock) {
if (buffer.peek() != null) {
if (buf.length < buffer.peek().length) {
throw new RuntimeException("reading less than allowed");
}
}
// this will block if the buffer is empty
byte[] read = buffer.take();
// currentBufferSize -= read.length;
System.arraycopy(read, 0, buf, 0, read.length);
// System.out.println("read from buffer (" + read.length + "/"
// + (maxElementSize * buffer.size()) + ")");
return read.length;
}
}
public void write(byte[] buf, int len) throws InterruptedException {
this.write(buf, len, true);
}
private void write(byte[] buf, int len, boolean copy) throws InterruptedException {
if (buf == null) {
throw new NullPointerException();
}
if (len < 0 || len > buf.length) {
throw new ArrayIndexOutOfBoundsException();
}
synchronized (writeLock) {
// check if we are writing more than maxEmementSize
if (len > maxElementSize) {
int pos = 0;
while (pos < len) {
int bytesLeft = len - pos;
int bytesToCopy = Math.min(bytesLeft, maxElementSize);
// System.out.println("pos=" + pos + " len=" + len
// + " bytesLeft=" + bytesLeft + " bytesToCopy="
// + bytesToCopy);
byte[] tempBuf = new byte[bytesToCopy];
System.arraycopy(buf, pos, tempBuf, 0, tempBuf.length);
this.write(tempBuf, tempBuf.length, false);
pos += bytesToCopy;
}
} else {
// check if we need to copy the byte array
if (copy || buf.length != len) {
// ok, copy the content and put in the queue
byte[] tempBuf = new byte[len];
System.arraycopy(buf, 0, tempBuf, 0, len);
// this will block if the queue is full
buffer.put(tempBuf);
} else {
buffer.put(buf);
}
// currentBufferSize += len;
// System.out.println("wrote to buffer (" + len + "/"
// + (maxElementSize * buffer.size()) + ")");
}
}
}
public boolean isEmpty() {
return buffer.isEmpty();
}
}