www in docker support
This commit is contained in:
parent
539a848e95
commit
c227fce036
2145 changed files with 399596 additions and 58 deletions
|
|
@ -0,0 +1,47 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AutoPool {
|
||||
private final List<AutoResource> resources = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, daemonThreadFactory());
|
||||
|
||||
private AutoPool() {
|
||||
final List<AutoResource> res = this.resources;
|
||||
this.scheduler.scheduleAtFixedRate(new Runnable() {
|
||||
public void run() {
|
||||
long curTime = System.currentTimeMillis();
|
||||
for (AutoResource autoResource : (Iterable<AutoResource>)res)
|
||||
autoResource.setCurTime(curTime);
|
||||
}
|
||||
}, 0L, 100L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private ThreadFactory daemonThreadFactory() {
|
||||
return new ThreadFactory() {
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName(AutoPool.class.getName());
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static AutoPool getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void add(AutoResource res) {
|
||||
this.resources.add(res);
|
||||
}
|
||||
|
||||
private static AutoPool instance = new AutoPool();
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
public interface AutoResource {
|
||||
void setCurTime(long paramLong);
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BitReader {
|
||||
public static BitReader createBitReader(ByteBuffer bb) {
|
||||
BitReader r = new BitReader(bb);
|
||||
r.curInt = r.readInt();
|
||||
r.deficit = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
private int deficit = -1;
|
||||
|
||||
private int curInt = -1;
|
||||
|
||||
private ByteBuffer bb;
|
||||
|
||||
private int initPos;
|
||||
|
||||
private BitReader(ByteBuffer bb) {
|
||||
this.bb = bb;
|
||||
this.initPos = bb.position();
|
||||
}
|
||||
|
||||
public BitReader fork() {
|
||||
BitReader fork = new BitReader(this.bb.duplicate());
|
||||
fork.initPos = 0;
|
||||
fork.curInt = this.curInt;
|
||||
fork.deficit = this.deficit;
|
||||
return fork;
|
||||
}
|
||||
|
||||
public final int readInt() {
|
||||
if (this.bb.remaining() >= 4) {
|
||||
this.deficit -= 32;
|
||||
return (this.bb.get() & 0xFF) << 24 | (this.bb.get() & 0xFF) << 16 | (this.bb.get() & 0xFF) << 8 | this.bb.get() & 0xFF;
|
||||
}
|
||||
return readIntSafe();
|
||||
}
|
||||
|
||||
private int readIntSafe() {
|
||||
this.deficit -= this.bb.remaining() << 3;
|
||||
int res = 0;
|
||||
if (this.bb.hasRemaining())
|
||||
res |= this.bb.get() & 0xFF;
|
||||
res <<= 8;
|
||||
if (this.bb.hasRemaining())
|
||||
res |= this.bb.get() & 0xFF;
|
||||
res <<= 8;
|
||||
if (this.bb.hasRemaining())
|
||||
res |= this.bb.get() & 0xFF;
|
||||
res <<= 8;
|
||||
if (this.bb.hasRemaining())
|
||||
res |= this.bb.get() & 0xFF;
|
||||
return res;
|
||||
}
|
||||
|
||||
public int read1Bit() {
|
||||
int ret = this.curInt >>> 31;
|
||||
this.curInt <<= 1;
|
||||
this.deficit++;
|
||||
if (this.deficit == 32)
|
||||
this.curInt = readInt();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int readNBitSigned(int n) {
|
||||
int v = readNBit(n);
|
||||
return (read1Bit() == 0) ? v : -v;
|
||||
}
|
||||
|
||||
public int readNBit(int n) {
|
||||
if (n > 32)
|
||||
throw new IllegalArgumentException("Can not read more then 32 bit");
|
||||
int nn = n;
|
||||
int ret = 0;
|
||||
if (n + this.deficit > 31) {
|
||||
ret |= this.curInt >>> this.deficit;
|
||||
n -= 32 - this.deficit;
|
||||
ret <<= n;
|
||||
this.deficit = 32;
|
||||
this.curInt = readInt();
|
||||
}
|
||||
if (n != 0) {
|
||||
ret |= this.curInt >>> 32 - n;
|
||||
this.curInt <<= n;
|
||||
this.deficit += n;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean moreData() {
|
||||
int remaining = this.bb.remaining() + 4 - (this.deficit + 7 >> 3);
|
||||
return (remaining > 1 || (remaining == 1 && this.curInt != 0));
|
||||
}
|
||||
|
||||
public int remaining() {
|
||||
return (this.bb.remaining() << 3) + 32 - this.deficit;
|
||||
}
|
||||
|
||||
public final boolean isByteAligned() {
|
||||
return ((this.deficit & 0x7) == 0);
|
||||
}
|
||||
|
||||
public int skip(int bits) {
|
||||
int left = bits;
|
||||
if (left + this.deficit > 31) {
|
||||
left -= 32 - this.deficit;
|
||||
this.deficit = 32;
|
||||
if (left > 31) {
|
||||
int skip = Math.min(left >> 3, this.bb.remaining());
|
||||
this.bb.position(this.bb.position() + skip);
|
||||
left -= skip << 3;
|
||||
}
|
||||
this.curInt = readInt();
|
||||
}
|
||||
this.deficit += left;
|
||||
this.curInt <<= left;
|
||||
return bits;
|
||||
}
|
||||
|
||||
public int skipFast(int bits) {
|
||||
this.deficit += bits;
|
||||
this.curInt <<= bits;
|
||||
return bits;
|
||||
}
|
||||
|
||||
public int bitsToAlign() {
|
||||
return ((this.deficit & 0x7) > 0) ? (8 - (this.deficit & 0x7)) : 0;
|
||||
}
|
||||
|
||||
public int align() {
|
||||
return ((this.deficit & 0x7) > 0) ? skip(8 - (this.deficit & 0x7)) : 0;
|
||||
}
|
||||
|
||||
public int check24Bits() {
|
||||
if (this.deficit > 16) {
|
||||
this.deficit -= 16;
|
||||
this.curInt |= nextIgnore16() << this.deficit;
|
||||
}
|
||||
if (this.deficit > 8) {
|
||||
this.deficit -= 8;
|
||||
this.curInt |= nextIgnore() << this.deficit;
|
||||
}
|
||||
return this.curInt >>> 8;
|
||||
}
|
||||
|
||||
public int check16Bits() {
|
||||
if (this.deficit > 16) {
|
||||
this.deficit -= 16;
|
||||
this.curInt |= nextIgnore16() << this.deficit;
|
||||
}
|
||||
return this.curInt >>> 16;
|
||||
}
|
||||
|
||||
public int readFast16(int n) {
|
||||
if (n == 0)
|
||||
return 0;
|
||||
if (this.deficit > 16) {
|
||||
this.deficit -= 16;
|
||||
this.curInt |= nextIgnore16() << this.deficit;
|
||||
}
|
||||
int ret = this.curInt >>> 32 - n;
|
||||
this.deficit += n;
|
||||
this.curInt <<= n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int checkNBit(int n) {
|
||||
if (n > 24)
|
||||
throw new IllegalArgumentException("Can not check more then 24 bit");
|
||||
return checkNBitDontCare(n);
|
||||
}
|
||||
|
||||
public int checkNBitDontCare(int n) {
|
||||
while (this.deficit + n > 32) {
|
||||
this.deficit -= 8;
|
||||
this.curInt |= nextIgnore() << this.deficit;
|
||||
}
|
||||
int res = this.curInt >>> 32 - n;
|
||||
return res;
|
||||
}
|
||||
|
||||
private int nextIgnore16() {
|
||||
return (this.bb.remaining() > 1) ? (this.bb.getShort() & 0xFFFF) : (this.bb.hasRemaining() ? ((this.bb.get() & 0xFF) << 8) : 0);
|
||||
}
|
||||
|
||||
private int nextIgnore() {
|
||||
return this.bb.hasRemaining() ? (this.bb.get() & 0xFF) : 0;
|
||||
}
|
||||
|
||||
public int curBit() {
|
||||
return this.deficit & 0x7;
|
||||
}
|
||||
|
||||
public boolean lastByte() {
|
||||
return (this.bb.remaining() + 4 - (this.deficit >> 3) <= 1);
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
int putBack = 32 - this.deficit >> 3;
|
||||
this.bb.position(this.bb.position() - putBack);
|
||||
}
|
||||
|
||||
public int position() {
|
||||
return (this.bb.position() - this.initPos - 4 << 3) + this.deficit;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.bb.position(this.bb.position() - (32 - this.deficit >> 3));
|
||||
}
|
||||
|
||||
public int checkAllBits() {
|
||||
return this.curInt;
|
||||
}
|
||||
|
||||
public boolean readBool() {
|
||||
return (read1Bit() == 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BitWriter {
|
||||
private final ByteBuffer buf;
|
||||
|
||||
private int curInt;
|
||||
|
||||
private int _curBit;
|
||||
|
||||
private int initPos;
|
||||
|
||||
public BitWriter(ByteBuffer buf) {
|
||||
this.buf = buf;
|
||||
this.initPos = buf.position();
|
||||
}
|
||||
|
||||
public BitWriter fork() {
|
||||
BitWriter fork = new BitWriter(this.buf.duplicate());
|
||||
fork._curBit = this._curBit;
|
||||
fork.curInt = this.curInt;
|
||||
fork.initPos = this.initPos;
|
||||
return fork;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
int toWrite = this._curBit + 7 >> 3;
|
||||
for (int i = 0; i < toWrite; i++) {
|
||||
this.buf.put((byte)(this.curInt >>> 24));
|
||||
this.curInt <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
private final void putInt(int i) {
|
||||
this.buf.put((byte)(i >>> 24));
|
||||
this.buf.put((byte)(i >> 16));
|
||||
this.buf.put((byte)(i >> 8));
|
||||
this.buf.put((byte)i);
|
||||
}
|
||||
|
||||
public final void writeNBit(int value, int n) {
|
||||
if (n > 32)
|
||||
throw new IllegalArgumentException("Max 32 bit to write");
|
||||
if (n == 0)
|
||||
return;
|
||||
value &= -1 >>> 32 - n;
|
||||
if (32 - this._curBit >= n) {
|
||||
this.curInt |= value << 32 - this._curBit - n;
|
||||
this._curBit += n;
|
||||
if (this._curBit == 32) {
|
||||
putInt(this.curInt);
|
||||
this._curBit = 0;
|
||||
this.curInt = 0;
|
||||
}
|
||||
} else {
|
||||
int secPart = n - (32 - this._curBit);
|
||||
this.curInt |= value >>> secPart;
|
||||
putInt(this.curInt);
|
||||
this.curInt = value << 32 - secPart;
|
||||
this._curBit = secPart;
|
||||
}
|
||||
}
|
||||
|
||||
public void write1Bit(int bit) {
|
||||
this.curInt |= bit << 32 - this._curBit - 1;
|
||||
this._curBit++;
|
||||
if (this._curBit == 32) {
|
||||
putInt(this.curInt);
|
||||
this._curBit = 0;
|
||||
this.curInt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int curBit() {
|
||||
return this._curBit & 0x7;
|
||||
}
|
||||
|
||||
public int position() {
|
||||
return (this.buf.position() - this.initPos << 3) + this._curBit;
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
return this.buf;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ByteBufferSeekableByteChannel implements SeekableByteChannel {
|
||||
private ByteBuffer backing;
|
||||
|
||||
private boolean open;
|
||||
|
||||
private int contentLength;
|
||||
|
||||
public ByteBufferSeekableByteChannel(ByteBuffer backing, int contentLength) {
|
||||
this.backing = backing;
|
||||
this.contentLength = contentLength;
|
||||
this.open = true;
|
||||
}
|
||||
|
||||
public static ByteBufferSeekableByteChannel writeToByteBuffer(ByteBuffer buf) {
|
||||
return new ByteBufferSeekableByteChannel(buf, 0);
|
||||
}
|
||||
|
||||
public static ByteBufferSeekableByteChannel readFromByteBuffer(ByteBuffer buf) {
|
||||
return new ByteBufferSeekableByteChannel(buf, buf.remaining());
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return this.open;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.open = false;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst) throws IOException {
|
||||
if (!this.backing.hasRemaining() || this.contentLength <= 0)
|
||||
return -1;
|
||||
int toRead = Math.min(this.backing.remaining(), dst.remaining());
|
||||
toRead = Math.min(toRead, this.contentLength);
|
||||
dst.put(NIOUtils.read(this.backing, toRead));
|
||||
this.contentLength = Math.max(this.contentLength, this.backing.position());
|
||||
return toRead;
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
int toWrite = Math.min(this.backing.remaining(), src.remaining());
|
||||
this.backing.put(NIOUtils.read(src, toWrite));
|
||||
this.contentLength = Math.max(this.contentLength, this.backing.position());
|
||||
return toWrite;
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
return (long)this.backing.position();
|
||||
}
|
||||
|
||||
public SeekableByteChannel setPosition(long newPosition) throws IOException {
|
||||
this.backing.position((int)newPosition);
|
||||
this.contentLength = Math.max(this.contentLength, this.backing.position());
|
||||
return this;
|
||||
}
|
||||
|
||||
public long size() throws IOException {
|
||||
return (long)this.contentLength;
|
||||
}
|
||||
|
||||
public SeekableByteChannel truncate(long size) throws IOException {
|
||||
this.contentLength = (int)size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ByteBuffer getContents() {
|
||||
ByteBuffer contents = this.backing.duplicate();
|
||||
contents.position(0);
|
||||
contents.limit(this.contentLength);
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class DataReader implements Closeable {
|
||||
private static final int DEFAULT_BUFFER_SIZE = 1048576;
|
||||
|
||||
private SeekableByteChannel channel;
|
||||
|
||||
private ByteBuffer buffer;
|
||||
|
||||
public static DataReader createDataReader(SeekableByteChannel channel, ByteOrder order) {
|
||||
return new DataReader(channel, order, 1048576);
|
||||
}
|
||||
|
||||
public DataReader(SeekableByteChannel channel, ByteOrder order, int bufferSize) {
|
||||
this.channel = channel;
|
||||
this.buffer = ByteBuffer.allocate(bufferSize);
|
||||
this.buffer.limit(0);
|
||||
this.buffer.order(order);
|
||||
}
|
||||
|
||||
public int readFully3(byte[] b, int off, int len) throws IOException {
|
||||
int initOff = off;
|
||||
while (len > 0) {
|
||||
fetchIfNeeded(len);
|
||||
if (this.buffer.remaining() == 0)
|
||||
break;
|
||||
int toRead = Math.min(this.buffer.remaining(), len);
|
||||
this.buffer.get(b, off, toRead);
|
||||
off += toRead;
|
||||
len -= toRead;
|
||||
}
|
||||
return off - initOff;
|
||||
}
|
||||
|
||||
public int skipBytes(int n) throws IOException {
|
||||
long oldPosition = position();
|
||||
if (n < this.buffer.remaining()) {
|
||||
this.buffer.position(this.buffer.position() + n);
|
||||
} else {
|
||||
setPosition(oldPosition + (long)n);
|
||||
}
|
||||
return (int)(position() - oldPosition);
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
fetchIfNeeded(1);
|
||||
return this.buffer.get();
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
fetchIfNeeded(2);
|
||||
return this.buffer.getShort();
|
||||
}
|
||||
|
||||
public char readChar() throws IOException {
|
||||
fetchIfNeeded(2);
|
||||
return this.buffer.getChar();
|
||||
}
|
||||
|
||||
public int readInt() throws IOException {
|
||||
fetchIfNeeded(4);
|
||||
return this.buffer.getInt();
|
||||
}
|
||||
|
||||
public long readLong() throws IOException {
|
||||
fetchIfNeeded(8);
|
||||
return this.buffer.getLong();
|
||||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
fetchIfNeeded(4);
|
||||
return this.buffer.getFloat();
|
||||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
fetchIfNeeded(8);
|
||||
return this.buffer.getDouble();
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
return this.channel.position() - (long)this.buffer.limit() + (long)this.buffer.position();
|
||||
}
|
||||
|
||||
public long setPosition(long newPos) throws IOException {
|
||||
int relative = (int)(newPos - (this.channel.position() - (long)this.buffer.limit()));
|
||||
if (relative >= 0 && relative < this.buffer.limit()) {
|
||||
this.buffer.position(relative);
|
||||
} else {
|
||||
this.buffer.limit(0);
|
||||
this.channel.setPosition(newPos);
|
||||
}
|
||||
return position();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
private void fetchIfNeeded(int length) throws IOException {
|
||||
if (this.buffer.remaining() < length) {
|
||||
moveRemainderToTheStart(this.buffer);
|
||||
this.channel.read(this.buffer);
|
||||
this.buffer.flip();
|
||||
}
|
||||
}
|
||||
|
||||
private static void moveRemainderToTheStart(ByteBuffer readBuf) {
|
||||
int rem = readBuf.remaining();
|
||||
for (int i = 0; i < rem; i++)
|
||||
readBuf.put(i, readBuf.get());
|
||||
readBuf.clear();
|
||||
readBuf.position(rem);
|
||||
}
|
||||
|
||||
public long size() throws IOException {
|
||||
return this.channel.size();
|
||||
}
|
||||
|
||||
public int readFully(byte[] b) throws IOException {
|
||||
return readFully3(b, 0, b.length);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class DummyBitstreamReader {
|
||||
private InputStream is;
|
||||
|
||||
private int curByte;
|
||||
|
||||
private int nextByte;
|
||||
|
||||
private int secondByte;
|
||||
|
||||
int nBit;
|
||||
|
||||
protected static int bitsRead;
|
||||
|
||||
public DummyBitstreamReader(InputStream is) throws IOException {
|
||||
this.is = is;
|
||||
this.curByte = is.read();
|
||||
this.nextByte = is.read();
|
||||
this.secondByte = is.read();
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
|
||||
public int read1Bit() throws IOException {
|
||||
return read1BitInt();
|
||||
}
|
||||
|
||||
public int read1BitInt() throws IOException {
|
||||
if (this.nBit == 8) {
|
||||
advance();
|
||||
if (this.curByte == -1)
|
||||
return -1;
|
||||
}
|
||||
int res = this.curByte >> 7 - this.nBit & 0x1;
|
||||
this.nBit++;
|
||||
bitsRead++;
|
||||
return res;
|
||||
}
|
||||
|
||||
public int readNBit(int n) throws IOException {
|
||||
if (n > 32)
|
||||
throw new IllegalArgumentException("Can not read more then 32 bit");
|
||||
int val = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
val <<= 1;
|
||||
val |= read1BitInt();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
private final void advance1() throws IOException {
|
||||
this.curByte = this.nextByte;
|
||||
this.nextByte = this.secondByte;
|
||||
this.secondByte = this.is.read();
|
||||
}
|
||||
|
||||
private final void advance() throws IOException {
|
||||
advance1();
|
||||
this.nBit = 0;
|
||||
}
|
||||
|
||||
public int readByte() throws IOException {
|
||||
if (this.nBit > 0)
|
||||
advance();
|
||||
int res = this.curByte;
|
||||
advance();
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean moreRBSPData() throws IOException {
|
||||
if (this.nBit == 8)
|
||||
advance();
|
||||
int tail = 1 << 8 - this.nBit - 1;
|
||||
int mask = (tail << 1) - 1;
|
||||
boolean hasTail = ((this.curByte & mask) == tail);
|
||||
return (this.curByte != -1 && (this.nextByte != -1 || !hasTail));
|
||||
}
|
||||
|
||||
public long getBitPosition() {
|
||||
return (long)(bitsRead * 8 + this.nBit % 8);
|
||||
}
|
||||
|
||||
public boolean moreData() throws IOException {
|
||||
if (this.nBit == 8)
|
||||
advance();
|
||||
if (this.curByte == -1)
|
||||
return false;
|
||||
if (this.nextByte == -1 || (this.nextByte == 0 && this.secondByte == -1)) {
|
||||
int mask = (1 << 8 - this.nBit) - 1;
|
||||
return ((this.curByte & mask) != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public long readRemainingByte() throws IOException {
|
||||
return (long)readNBit(8 - this.nBit);
|
||||
}
|
||||
|
||||
public int peakNextBits(int n) throws IOException {
|
||||
if (n > 8)
|
||||
throw new IllegalArgumentException("N should be less then 8");
|
||||
if (this.nBit == 8) {
|
||||
advance();
|
||||
if (this.curByte == -1)
|
||||
return -1;
|
||||
}
|
||||
int[] bits = new int[16 - this.nBit];
|
||||
int cnt = 0;
|
||||
for (int j = this.nBit; j < 8; j++)
|
||||
bits[cnt++] = this.curByte >> 7 - j & 0x1;
|
||||
for (int i = 0; i < 8; i++)
|
||||
bits[cnt++] = this.nextByte >> 7 - i & 0x1;
|
||||
int result = 0;
|
||||
for (int k = 0; k < n; k++) {
|
||||
result <<= 1;
|
||||
result |= bits[k];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isByteAligned() {
|
||||
return (this.nBit % 8 == 0);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.is.close();
|
||||
}
|
||||
|
||||
public int getCurBit() {
|
||||
return this.nBit;
|
||||
}
|
||||
|
||||
public final int skip(int bits) throws IOException {
|
||||
this.nBit += bits;
|
||||
int was = this.nBit;
|
||||
while (this.nBit >= 8 && this.curByte != -1) {
|
||||
advance1();
|
||||
this.nBit -= 8;
|
||||
}
|
||||
return was - this.nBit;
|
||||
}
|
||||
|
||||
public int align() throws IOException {
|
||||
int n = 8 - this.nBit & 0x7;
|
||||
skip(8 - this.nBit & 0x7);
|
||||
return n;
|
||||
}
|
||||
|
||||
public int checkNBit(int n) throws IOException {
|
||||
return peakNextBits(n);
|
||||
}
|
||||
|
||||
public int curBit() {
|
||||
return this.nBit;
|
||||
}
|
||||
|
||||
public boolean lastByte() throws IOException {
|
||||
return (this.nextByte == -1 && this.secondByte == -1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
public class FileChannelWrapper implements SeekableByteChannel {
|
||||
private FileChannel ch;
|
||||
|
||||
public FileChannelWrapper(FileChannel ch) throws FileNotFoundException {
|
||||
this.ch = ch;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer arg0) throws IOException {
|
||||
return this.ch.read(arg0);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.ch.close();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return this.ch.isOpen();
|
||||
}
|
||||
|
||||
public int write(ByteBuffer arg0) throws IOException {
|
||||
return this.ch.write(arg0);
|
||||
}
|
||||
|
||||
public long position() throws IOException {
|
||||
return this.ch.position();
|
||||
}
|
||||
|
||||
public SeekableByteChannel setPosition(long newPosition) throws IOException {
|
||||
this.ch.position(newPosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public long size() throws IOException {
|
||||
return this.ch.size();
|
||||
}
|
||||
|
||||
public SeekableByteChannel truncate(long size) throws IOException {
|
||||
this.ch.truncate(size);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class IOUtils {
|
||||
public static final int DEFAULT_BUFFER_SIZE = 4096;
|
||||
|
||||
public static void closeQuietly(Closeable c) {
|
||||
if (c == null)
|
||||
return;
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(InputStream input) throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
copy(input, output);
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
public static int copy(InputStream input, OutputStream output) throws IOException {
|
||||
byte[] buffer = new byte[4096];
|
||||
int count = 0;
|
||||
int n = 0;
|
||||
while (-1 != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
count += n;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static int copyDumb(InputStream input, OutputStream output) throws IOException {
|
||||
int count = 0;
|
||||
int n = 0;
|
||||
while (-1 != (n = input.read())) {
|
||||
output.write(n);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static byte[] readFileToByteArray(File file) throws IOException {
|
||||
return NIOUtils.toArray(NIOUtils.fetchFromFile(file));
|
||||
}
|
||||
|
||||
public static String readToString(InputStream is) throws IOException {
|
||||
return Platform.stringFromBytes(toByteArray(is));
|
||||
}
|
||||
|
||||
public static void writeStringToFile(File file, String str) throws IOException {
|
||||
NIOUtils.writeTo(ByteBuffer.wrap(str.getBytes()), file);
|
||||
}
|
||||
|
||||
public static void forceMkdir(File directory) throws IOException {
|
||||
if (directory.exists()) {
|
||||
if (!directory.isDirectory()) {
|
||||
String message = "File " + String.valueOf(directory) + " exists and is not a directory. Unable to create directory.";
|
||||
throw new IOException(message);
|
||||
}
|
||||
} else if (!directory.mkdirs()) {
|
||||
if (!directory.isDirectory()) {
|
||||
String message = "Unable to create directory " + String.valueOf(directory);
|
||||
throw new IOException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFile(File src, File dst) throws IOException {
|
||||
FileChannelWrapper _in = null;
|
||||
FileChannelWrapper out = null;
|
||||
try {
|
||||
_in = NIOUtils.readableChannel(src);
|
||||
out = NIOUtils.writableChannel(dst);
|
||||
NIOUtils.copy(_in, out, Long.MAX_VALUE);
|
||||
} finally {
|
||||
NIOUtils.closeQuietly(_in);
|
||||
NIOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,429 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.jcodec.common.ArrayUtil;
|
||||
import org.jcodec.common.AutoFileChannelWrapper;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class NIOUtils {
|
||||
public static ByteBuffer search(ByteBuffer buffer, int n, byte[] param) {
|
||||
ByteBuffer result = buffer.duplicate();
|
||||
int step = 0, rem = buffer.position();
|
||||
while (buffer.hasRemaining()) {
|
||||
int b = buffer.get();
|
||||
if (b == param[step]) {
|
||||
step++;
|
||||
if (step == param.length) {
|
||||
if (n == 0) {
|
||||
buffer.position(rem);
|
||||
result.limit(buffer.position());
|
||||
break;
|
||||
}
|
||||
n--;
|
||||
step = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (step != 0) {
|
||||
step = 0;
|
||||
rem++;
|
||||
buffer.position(rem);
|
||||
continue;
|
||||
}
|
||||
rem = buffer.position();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final ByteBuffer read(ByteBuffer buffer, int count) {
|
||||
ByteBuffer slice = buffer.duplicate();
|
||||
int limit = buffer.position() + count;
|
||||
slice.limit(limit);
|
||||
buffer.position(limit);
|
||||
return slice;
|
||||
}
|
||||
|
||||
public static ByteBuffer fetchFromFile(File file) throws IOException {
|
||||
return fetchFromFileL(file, (int)file.length());
|
||||
}
|
||||
|
||||
public static ByteBuffer fetchFromChannel(ReadableByteChannel ch, int size) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(size);
|
||||
readFromChannel(ch, buf);
|
||||
buf.flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static ByteBuffer fetchAllFromChannel(SeekableByteChannel ch) throws IOException {
|
||||
ByteBuffer buf;
|
||||
List<ByteBuffer> buffers = new ArrayList<>();
|
||||
do {
|
||||
buf = fetchFromChannel(ch, 1048576);
|
||||
buffers.add(buf);
|
||||
} while (buf.hasRemaining());
|
||||
return combineBuffers(buffers);
|
||||
}
|
||||
|
||||
public static ByteBuffer fetchFrom(ByteBuffer buf, ReadableByteChannel ch, int size) throws IOException {
|
||||
ByteBuffer result = buf.duplicate();
|
||||
result.limit(size);
|
||||
readFromChannel(ch, result);
|
||||
result.flip();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ByteBuffer fetchFromFileL(File file, int length) throws IOException {
|
||||
FileChannel is = null;
|
||||
try {
|
||||
is = new FileInputStream(file).getChannel();
|
||||
return fetchFromChannel(is, length);
|
||||
} finally {
|
||||
closeQuietly(is);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeTo(ByteBuffer buffer, File file) throws IOException {
|
||||
FileChannel out = null;
|
||||
try {
|
||||
out = new FileOutputStream(file).getChannel();
|
||||
out.write(buffer);
|
||||
} finally {
|
||||
closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toArray(ByteBuffer buffer) {
|
||||
byte[] result = new byte[buffer.remaining()];
|
||||
buffer.duplicate().get(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] toArrayL(ByteBuffer buffer, int count) {
|
||||
byte[] result = new byte[Math.min(buffer.remaining(), count)];
|
||||
buffer.duplicate().get(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int readL(ReadableByteChannel channel, ByteBuffer buffer, int length) throws IOException {
|
||||
ByteBuffer fork = buffer.duplicate();
|
||||
fork.limit(Math.min(fork.position() + length, fork.limit()));
|
||||
while (channel.read(fork) != -1 && fork.hasRemaining());
|
||||
buffer.position(fork.position());
|
||||
return (buffer.position() == 0) ? -1 : buffer.position();
|
||||
}
|
||||
|
||||
public static int readFromChannel(ReadableByteChannel channel, ByteBuffer buffer) throws IOException {
|
||||
int rem = buffer.position();
|
||||
while (channel.read(buffer) != -1 && buffer.hasRemaining());
|
||||
return buffer.position() - rem;
|
||||
}
|
||||
|
||||
public static void write(ByteBuffer to, ByteBuffer from) {
|
||||
if (from.hasArray()) {
|
||||
to.put(from.array(), from.arrayOffset() + from.position(), Math.min(to.remaining(), from.remaining()));
|
||||
} else {
|
||||
to.put(toArrayL(from, to.remaining()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeL(ByteBuffer to, ByteBuffer from, int count) {
|
||||
if (from.hasArray()) {
|
||||
to.put(from.array(), from.arrayOffset() + from.position(), Math.min(from.remaining(), count));
|
||||
} else {
|
||||
to.put(toArrayL(from, count));
|
||||
}
|
||||
}
|
||||
|
||||
public static void fill(ByteBuffer buffer, byte val) {
|
||||
while (buffer.hasRemaining())
|
||||
buffer.put(val);
|
||||
}
|
||||
|
||||
public static final MappedByteBuffer map(String fileName) throws IOException {
|
||||
return mapFile(new File(fileName));
|
||||
}
|
||||
|
||||
public static final MappedByteBuffer mapFile(File file) throws IOException {
|
||||
FileInputStream is = new FileInputStream(file);
|
||||
MappedByteBuffer map = is.getChannel().map(FileChannel.MapMode.READ_ONLY, 0L, file.length());
|
||||
is.close();
|
||||
return map;
|
||||
}
|
||||
|
||||
public static int skip(ByteBuffer buffer, int count) {
|
||||
int toSkip = Math.min(buffer.remaining(), count);
|
||||
buffer.position(buffer.position() + toSkip);
|
||||
return toSkip;
|
||||
}
|
||||
|
||||
public static ByteBuffer from(ByteBuffer buffer, int offset) {
|
||||
ByteBuffer dup = buffer.duplicate();
|
||||
dup.position(dup.position() + offset);
|
||||
return dup;
|
||||
}
|
||||
|
||||
public static ByteBuffer combineBuffers(Iterable<ByteBuffer> picture) {
|
||||
int size = 0;
|
||||
for (ByteBuffer byteBuffer : picture)
|
||||
size += byteBuffer.remaining();
|
||||
ByteBuffer result = ByteBuffer.allocate(size);
|
||||
for (ByteBuffer byteBuffer : picture)
|
||||
write(result, byteBuffer);
|
||||
result.flip();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean combineBuffersInto(ByteBuffer dup, List<ByteBuffer> buffers) {
|
||||
throw new RuntimeException("Stan");
|
||||
}
|
||||
|
||||
public static String readString(ByteBuffer buffer, int len) {
|
||||
return Platform.stringFromBytes(toArray(read(buffer, len)));
|
||||
}
|
||||
|
||||
public static String readPascalStringL(ByteBuffer buffer, int maxLen) {
|
||||
ByteBuffer sub = read(buffer, maxLen + 1);
|
||||
return Platform.stringFromBytes(toArray(read(sub, Math.min(sub.get() & 0xFF, maxLen))));
|
||||
}
|
||||
|
||||
public static void writePascalStringL(ByteBuffer buffer, String string, int maxLen) {
|
||||
buffer.put((byte)string.length());
|
||||
buffer.put(asciiString(string));
|
||||
skip(buffer, maxLen - string.length());
|
||||
}
|
||||
|
||||
public static byte[] asciiString(String fourcc) {
|
||||
return Platform.getBytes(fourcc);
|
||||
}
|
||||
|
||||
public static void writePascalString(ByteBuffer buffer, String name) {
|
||||
buffer.put((byte)name.length());
|
||||
buffer.put(asciiString(name));
|
||||
}
|
||||
|
||||
public static String readPascalString(ByteBuffer buffer) {
|
||||
return readString(buffer, buffer.get() & 0xFF);
|
||||
}
|
||||
|
||||
public static String readNullTermString(ByteBuffer buffer) {
|
||||
return readNullTermStringCharset(buffer, "UTF-8");
|
||||
}
|
||||
|
||||
public static String readNullTermStringCharset(ByteBuffer buffer, String charset) {
|
||||
ByteBuffer fork = buffer.duplicate();
|
||||
while (buffer.hasRemaining() && buffer.get() != 0);
|
||||
if (buffer.hasRemaining())
|
||||
fork.limit(buffer.position() - 1);
|
||||
return Platform.stringFromCharset(toArray(fork), charset);
|
||||
}
|
||||
|
||||
public static ByteBuffer readBuf(ByteBuffer buffer) {
|
||||
ByteBuffer result = buffer.duplicate();
|
||||
buffer.position(buffer.limit());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void copy(ReadableByteChannel _in, WritableByteChannel out, long amount) throws IOException {
|
||||
int read;
|
||||
ByteBuffer buf = ByteBuffer.allocate(65536);
|
||||
do {
|
||||
buf.position(0);
|
||||
buf.limit((int)Math.min(amount, (long)buf.capacity()));
|
||||
read = _in.read(buf);
|
||||
if (read == -1)
|
||||
continue;
|
||||
buf.flip();
|
||||
out.write(buf);
|
||||
amount -= (long)read;
|
||||
} while (read != -1 && amount > 0L);
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable channel) {
|
||||
if (channel == null)
|
||||
return;
|
||||
try {
|
||||
channel.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
public static byte readByte(ReadableByteChannel channel) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(1);
|
||||
channel.read(buf);
|
||||
buf.flip();
|
||||
return buf.get();
|
||||
}
|
||||
|
||||
public static byte[] readNByte(ReadableByteChannel channel, int n) throws IOException {
|
||||
byte[] result = new byte[n];
|
||||
channel.read(ByteBuffer.wrap(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int readInt(ReadableByteChannel channel) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(4);
|
||||
channel.read(buf);
|
||||
buf.flip();
|
||||
return buf.getInt();
|
||||
}
|
||||
|
||||
public static int readIntOrder(ReadableByteChannel channel, ByteOrder order) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(4).order(order);
|
||||
channel.read(buf);
|
||||
buf.flip();
|
||||
return buf.getInt();
|
||||
}
|
||||
|
||||
public static void writeByte(WritableByteChannel channel, byte value) throws IOException {
|
||||
channel.write(ByteBuffer.allocate(1).put(value).flip());
|
||||
}
|
||||
|
||||
public static void writeIntOrder(WritableByteChannel channel, int value, ByteOrder order) throws IOException {
|
||||
ByteBuffer order2 = ByteBuffer.allocate(4).order(order);
|
||||
channel.write(order2.putInt(value).flip());
|
||||
}
|
||||
|
||||
public static void writeIntLE(WritableByteChannel channel, int value) throws IOException {
|
||||
ByteBuffer allocate = ByteBuffer.allocate(4);
|
||||
allocate.order(ByteOrder.LITTLE_ENDIAN);
|
||||
channel.write(allocate.putInt(value).flip());
|
||||
}
|
||||
|
||||
public static void writeInt(WritableByteChannel channel, int value) throws IOException {
|
||||
channel.write(ByteBuffer.allocate(4).putInt(value).flip());
|
||||
}
|
||||
|
||||
public static void writeLong(WritableByteChannel channel, long value) throws IOException {
|
||||
channel.write(ByteBuffer.allocate(8).putLong(value).flip());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper readableChannel(File file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new FileInputStream(file).getChannel());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper writableChannel(File file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new FileOutputStream(file).getChannel());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper rwChannel(File file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new RandomAccessFile(file, "rw").getChannel());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper readableFileChannel(String file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new FileInputStream(file).getChannel());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper writableFileChannel(String file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new FileOutputStream(file).getChannel());
|
||||
}
|
||||
|
||||
public static FileChannelWrapper rwFileChannel(String file) throws FileNotFoundException {
|
||||
return new FileChannelWrapper(new RandomAccessFile(file, "rw").getChannel());
|
||||
}
|
||||
|
||||
public static AutoFileChannelWrapper autoChannel(File file) throws IOException {
|
||||
return new AutoFileChannelWrapper(file);
|
||||
}
|
||||
|
||||
public static ByteBuffer duplicate(ByteBuffer bb) {
|
||||
ByteBuffer out = ByteBuffer.allocate(bb.remaining());
|
||||
out.put(bb.duplicate());
|
||||
out.flip();
|
||||
return out;
|
||||
}
|
||||
|
||||
public static int find(List<ByteBuffer> catalog, ByteBuffer key) {
|
||||
byte[] keyA = toArray(key);
|
||||
for (int i = 0; i < catalog.size(); i++) {
|
||||
if (Platform.arrayEqualsByte(toArray(catalog.get(i)), keyA))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static abstract class FileReader {
|
||||
private int oldPd;
|
||||
|
||||
protected abstract void data(ByteBuffer param1ByteBuffer, long param1Long);
|
||||
|
||||
protected abstract void done();
|
||||
|
||||
public void readChannel(SeekableByteChannel ch, int bufferSize, NIOUtils.FileReaderListener listener) throws IOException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(bufferSize);
|
||||
long size = ch.size();
|
||||
for (long pos = ch.position(); ch.read(buf) != -1; pos = ch.position()) {
|
||||
buf.flip();
|
||||
data(buf, pos);
|
||||
buf.flip();
|
||||
if (listener != null) {
|
||||
int newPd = (int)(100L * pos / size);
|
||||
if (newPd != this.oldPd)
|
||||
listener.progress(newPd);
|
||||
this.oldPd = newPd;
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
|
||||
public void readFile(File source, int bufferSize, NIOUtils.FileReaderListener listener) throws IOException {
|
||||
SeekableByteChannel ch = null;
|
||||
try {
|
||||
ch = NIOUtils.readableChannel(source);
|
||||
readChannel(ch, bufferSize, listener);
|
||||
} finally {
|
||||
NIOUtils.closeQuietly(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte getRel(ByteBuffer bb, int rel) {
|
||||
return bb.get(bb.position() + rel);
|
||||
}
|
||||
|
||||
public static ByteBuffer cloneBuffer(ByteBuffer pesBuffer) {
|
||||
ByteBuffer res = ByteBuffer.allocate(pesBuffer.remaining());
|
||||
res.put(pesBuffer.duplicate());
|
||||
res.clear();
|
||||
return res;
|
||||
}
|
||||
|
||||
public static ByteBuffer clone(ByteBuffer byteBuffer) {
|
||||
ByteBuffer result = ByteBuffer.allocate(byteBuffer.remaining());
|
||||
result.put(byteBuffer.duplicate());
|
||||
result.flip();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ByteBuffer asByteBuffer(byte[] bytes) {
|
||||
return ByteBuffer.wrap(bytes);
|
||||
}
|
||||
|
||||
public static ByteBuffer asByteBufferInt(int[] ints) {
|
||||
return asByteBuffer(ArrayUtil.toByteArray(ints));
|
||||
}
|
||||
|
||||
public static void relocateLeftover(ByteBuffer bb) {
|
||||
int pos;
|
||||
for (pos = 0; bb.hasRemaining(); pos++)
|
||||
bb.put(pos, bb.get());
|
||||
bb.position(pos);
|
||||
bb.limit(bb.capacity());
|
||||
}
|
||||
|
||||
public static interface FileReaderListener {
|
||||
void progress(int param1Int);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.ByteChannel;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
|
||||
public interface SeekableByteChannel extends ByteChannel, Channel, Closeable, ReadableByteChannel, WritableByteChannel {
|
||||
long position() throws IOException;
|
||||
|
||||
SeekableByteChannel setPosition(long paramLong) throws IOException;
|
||||
|
||||
long size() throws IOException;
|
||||
|
||||
SeekableByteChannel truncate(long paramLong) throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public abstract class StringReader {
|
||||
public static String readString(InputStream input, int len) throws IOException {
|
||||
byte[] bs = _sureRead(input, len);
|
||||
return (bs == null) ? null : Platform.stringFromBytes(bs);
|
||||
}
|
||||
|
||||
public static byte[] _sureRead(InputStream input, int len) throws IOException {
|
||||
byte[] res = new byte[len];
|
||||
if (sureRead(input, res, res.length) == len)
|
||||
return res;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int sureRead(InputStream input, byte[] buf, int len) throws IOException {
|
||||
int read = 0;
|
||||
while (read < len) {
|
||||
int tmp = input.read(buf, read, len - read);
|
||||
if (tmp == -1)
|
||||
break;
|
||||
read += tmp;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
public static void sureSkip(InputStream is, long l) throws IOException {
|
||||
while (l > 0L)
|
||||
l -= is.skip(l);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import org.jcodec.common.IntArrayList;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class VLC {
|
||||
private int[] codes;
|
||||
|
||||
private int[] codeSizes;
|
||||
|
||||
private int[] values;
|
||||
|
||||
private int[] valueSizes;
|
||||
|
||||
public static VLC createVLC(String[] codes) {
|
||||
IntArrayList _codes = IntArrayList.createIntArrayList();
|
||||
IntArrayList _codeSizes = IntArrayList.createIntArrayList();
|
||||
for (int i = 0; i < codes.length; i++) {
|
||||
String string = codes[i];
|
||||
_codes.add(Integer.parseInt(string, 2) << 32 - string.length());
|
||||
_codeSizes.add(string.length());
|
||||
}
|
||||
VLC vlc = new VLC(_codes.toArray(), _codeSizes.toArray());
|
||||
return vlc;
|
||||
}
|
||||
|
||||
public VLC(int[] codes, int[] codeSizes) {
|
||||
this.codes = codes;
|
||||
this.codeSizes = codeSizes;
|
||||
_invert();
|
||||
}
|
||||
|
||||
private void _invert() {
|
||||
IntArrayList values = IntArrayList.createIntArrayList();
|
||||
IntArrayList valueSizes = IntArrayList.createIntArrayList();
|
||||
invert(0, 0, 0, values, valueSizes);
|
||||
this.values = values.toArray();
|
||||
this.valueSizes = valueSizes.toArray();
|
||||
}
|
||||
|
||||
private int invert(int startOff, int level, int prefix, IntArrayList values, IntArrayList valueSizes) {
|
||||
int tableEnd = startOff + 256;
|
||||
values.fill(startOff, tableEnd, -1);
|
||||
valueSizes.fill(startOff, tableEnd, 0);
|
||||
int prefLen = level << 3;
|
||||
for (int i = 0; i < this.codeSizes.length; i++) {
|
||||
if (this.codeSizes[i] > prefLen && (level <= 0 || this.codes[i] >>> 32 - prefLen == prefix)) {
|
||||
int pref = this.codes[i] >>> 32 - prefLen - 8;
|
||||
int code = pref & 0xFF;
|
||||
int len = this.codeSizes[i] - prefLen;
|
||||
if (len <= 8) {
|
||||
for (int k = 0; k < 1 << 8 - len; k++) {
|
||||
values.set(startOff + code + k, i);
|
||||
valueSizes.set(startOff + code + k, len);
|
||||
}
|
||||
} else if (values.get(startOff + code) == -1) {
|
||||
values.set(startOff + code, tableEnd);
|
||||
tableEnd = invert(tableEnd, level + 1, pref, values, valueSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tableEnd;
|
||||
}
|
||||
|
||||
public int readVLC16(BitReader _in) {
|
||||
int string = _in.check16Bits();
|
||||
int b = string >>> 8;
|
||||
int code = this.values[b];
|
||||
int len = this.valueSizes[b];
|
||||
if (len == 0) {
|
||||
b = (string & 0xFF) + code;
|
||||
code = this.values[b];
|
||||
_in.skipFast(8 + this.valueSizes[b]);
|
||||
} else {
|
||||
_in.skipFast(len);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
public int readVLC(BitReader _in) {
|
||||
int code = 0, len = 0, overall = 0, total = 0;
|
||||
for (int i = 0; len == 0; i++) {
|
||||
int string = _in.checkNBit(8);
|
||||
int ind = string + code;
|
||||
code = this.values[ind];
|
||||
len = this.valueSizes[ind];
|
||||
int bits = (len != 0) ? len : 8;
|
||||
total += bits;
|
||||
overall = overall << bits | string >> 8 - bits;
|
||||
_in.skip(bits);
|
||||
if (code == -1)
|
||||
throw new RuntimeException("Invalid code prefix " + binary(overall, (i << 3) + bits));
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private static String binary(int string, int len) {
|
||||
char[] symb = new char[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
symb[i] = ((string & 1 << len - i - 1) != 0) ? '1' : '0';
|
||||
return Platform.stringFromChars(symb);
|
||||
}
|
||||
|
||||
public void writeVLC(BitWriter out, int code) {
|
||||
out.writeNBit(this.codes[code] >>> 32 - this.codeSizes[code], this.codeSizes[code]);
|
||||
}
|
||||
|
||||
public void printTable(PrintStream ps) {
|
||||
for (int i = 0; i < this.values.length; i++)
|
||||
ps.println("" + i + ": " + i + " (" + extracted(i) + ") -> " + this.valueSizes[i]);
|
||||
}
|
||||
|
||||
private static String extracted(int num) {
|
||||
String str = Integer.toString(num & 0xFF, 2);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < 8 - str.length(); i++)
|
||||
builder.append("0");
|
||||
builder.append(str);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public int[] getCodes() {
|
||||
return this.codes;
|
||||
}
|
||||
|
||||
public int[] getCodeSizes() {
|
||||
return this.codeSizes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package org.jcodec.common.io;
|
||||
|
||||
import org.jcodec.common.IntArrayList;
|
||||
import org.jcodec.common.IntIntMap;
|
||||
|
||||
public class VLCBuilder {
|
||||
private IntIntMap forward;
|
||||
|
||||
private IntIntMap inverse;
|
||||
|
||||
private IntArrayList codes;
|
||||
|
||||
private IntArrayList codesSizes;
|
||||
|
||||
public static VLCBuilder createVLCBuilder(int[] codes, int[] lens, int[] vals) {
|
||||
VLCBuilder b = new VLCBuilder();
|
||||
for (int i = 0; i < codes.length; i++)
|
||||
b.setInt(codes[i], lens[i], vals[i]);
|
||||
return b;
|
||||
}
|
||||
|
||||
public VLCBuilder() {
|
||||
this.forward = new IntIntMap();
|
||||
this.inverse = new IntIntMap();
|
||||
this.codes = IntArrayList.createIntArrayList();
|
||||
this.codesSizes = IntArrayList.createIntArrayList();
|
||||
}
|
||||
|
||||
public VLCBuilder set(int val, String code) {
|
||||
setInt(Integer.parseInt(code, 2), code.length(), val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VLCBuilder setInt(int code, int len, int val) {
|
||||
this.codes.add(code << 32 - len);
|
||||
this.codesSizes.add(len);
|
||||
this.forward.put(val, this.codes.size() - 1);
|
||||
this.inverse.put(this.codes.size() - 1, val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VLC getVLC() {
|
||||
final VLCBuilder self = this;
|
||||
return new VLC(this.codes.toArray(), this.codesSizes.toArray()) {
|
||||
public int readVLC(BitReader _in) {
|
||||
return self.inverse.get(super.readVLC(_in));
|
||||
}
|
||||
|
||||
public int readVLC16(BitReader _in) {
|
||||
return self.inverse.get(super.readVLC16(_in));
|
||||
}
|
||||
|
||||
public void writeVLC(BitWriter out, int code) {
|
||||
super.writeVLC(out, self.forward.get(code));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue