package org.jcodec.codecs.mpeg12;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import org.jcodec.common.NIOUtils;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Pulls frames from MPEG elementary stream
*
* @author The JCodec project
*
*/
public class SegmentReader {
private ReadableByteChannel channel;
private ByteBuffer buf;
protected int curMarker;
private int fetchSize;
private boolean done;
private long pos;
public SegmentReader(ReadableByteChannel channel) throws IOException {
this(channel, 4096);
}
public SegmentReader(ReadableByteChannel channel, int fetchSize) throws IOException {
this.channel = channel;
this.fetchSize = fetchSize;
buf = NIOUtils.fetchFrom(channel, 4);
pos = buf.remaining();
curMarker = buf.getInt();
}
public final boolean readToNextMarker(ByteBuffer out) throws IOException {
if (done)
return false;
int n = 1;
do {
while (buf.hasRemaining()) {
if (curMarker >= 0x100 && curMarker <= 0x1ff) {
if (n == 0) {
return true;
}
--n;
}
out.put((byte) (curMarker >>> 24));
curMarker = (curMarker << 8) | (buf.get() & 0xff);
}
buf = NIOUtils.fetchFrom(channel, fetchSize);
pos += buf.remaining();
} while (buf.hasRemaining());
out.putInt(curMarker);
done = true;
return false;
}
public final boolean skipToMarker() throws IOException {
if (done)
return false;
do {
while (buf.hasRemaining()) {
curMarker = (curMarker << 8) | (buf.get() & 0xff);
if (curMarker >= 0x100 && curMarker <= 0x1ff) {
return true;
}
}
buf = NIOUtils.fetchFrom(channel, fetchSize);
pos += buf.remaining();
} while (buf.hasRemaining());
done = true;
return false;
}
public final boolean read(ByteBuffer out, int length) throws IOException {
if (done)
return false;
do {
while (buf.hasRemaining()) {
if (length-- == 0)
return true;
out.put((byte) (curMarker >>> 24));
curMarker = (curMarker << 8) | (buf.get() & 0xff);
}
buf = NIOUtils.fetchFrom(channel, fetchSize);
pos += buf.remaining();
} while (buf.hasRemaining());
out.putInt(curMarker);
done = true;
return false;
}
public final long curPos() {
return pos - buf.remaining() - 4;
}
}