com.coremedia.iso.AbstractIsoBufferWrapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of isoparser Show documentation
Show all versions of isoparser Show documentation
A generic parser and writer for all ISO 14496 based files (MP4, Quicktime, DCF, PDCF, ...)
package com.coremedia.iso;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public abstract class AbstractIsoBufferWrapper implements IsoBufferWrapper {
public int readBitsRemaining;
private byte readBitsBuffer;
public long readUInt64() throws IOException {
long result = 0;
// thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed
result += readUInt32() << 32;
if (result < 0) {
throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt");
}
result += readUInt32();
return result;
}
public long readUInt32() throws IOException {
long result = 0;
result += ((long) readUInt16()) << 16;
result += readUInt16();
return result;
}
public int readInt32() throws IOException {
int ch1 = readUInt8();
int ch2 = readUInt8();
int ch3 = readUInt8();
int ch4 = readUInt8();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
public int readUInt24() throws IOException {
int result = 0;
result += readUInt16() << 8;
result += readUInt8();
return result;
}
public int readUInt16() throws IOException {
int result = 0;
result += readUInt8() << 8;
result += readUInt8();
return result;
}
public int readUInt8() throws IOException {
byte b = readByte();
return b < 0 ? b + 256 : b;
}
public byte readByte() throws IOException {
if (readBitsRemaining != 0) {
// throw new IllegalStateException("Not byte aligned! Use up all bits until you aligned again.");
}
int b = read();
if (b == -1) {
throw new RuntimeException("Read beyond buffer's end");
} else {
return (byte) (b >= 128 ? b - 256 : b);
}
}
public String readIso639() throws IOException {
int bits = readUInt16();
StringBuilder result = new StringBuilder();
for (int i = 0; i < 3; i++) {
int c = (bits >> (2 - i) * 5) & 0x1f;
result.append((char) (c + 0x60));
}
return result.toString();
}
/**
* Reads a zero terminated string.
*
* @return the string readByte
* @throws Error in case of an error in the underlying stream
*/
public String readString() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int read;
while ((read = readByte()) != 0) {
out.write(read);
}
try {
return out.toString("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error("JVM doesn't support UTF-8");
}
}
public long readUInt32BE() throws IOException {
long result = 0;
result += readUInt16BE();
result += ((long) readUInt16BE()) << 16;
return result;
}
public int readUInt16BE() throws IOException {
int result = 0;
result += readUInt8();
result += readUInt8() << 8;
return result;
}
/**
* Reads i bits from the underlying buffers.
* Caveat: this method always consumes full bytes even if just a bit is readByte!
*
* @param i number of bits to readByte, 31 max
* @return bitstring value as unsigned int
*/
public int readBits(int i) throws IOException {
if (i > 31) {
//> signed int
throw new IllegalArgumentException("cannot readByte more than 31 bits");
}
int ret = 0;
while (i > 8) {
final int moved = parse8(8) << i - 8;
ret = ret | moved;
i -= 8;
}
return ret | parse8(i);
}
private int parse8(int i) throws IOException {
if (readBitsRemaining == 0) {
readBitsBuffer = readByte();
readBitsRemaining = 8;
}
if (i > readBitsRemaining) {
final int resultRemaining = i - readBitsRemaining;
int buffer = (readBitsBuffer & (int) (Math.pow(2, readBitsRemaining) - 1)) << resultRemaining;
readBitsBuffer = readByte();
readBitsRemaining = 8 - resultRemaining;
final int movedAndMasked = (readBitsBuffer >>> readBitsRemaining) & (int) (Math.pow(2, resultRemaining) - 1);
return buffer | movedAndMasked;
} else {
readBitsRemaining -= i;
return (readBitsBuffer >>> readBitsRemaining) & (int) (Math.pow(2, i) - 1);
}
}
public int getReadBitsRemaining() {
return readBitsRemaining;
}
public double readFixedPoint1616() throws IOException {
byte[] bytes = read(4);
int result = 0;
result |= ((bytes[0] << 24) & 0xFF000000);
result |= ((bytes[1] << 16) & 0xFF0000);
result |= ((bytes[2] << 8) & 0xFF00);
result |= ((bytes[3]) & 0xFF);
return ((double) result) / 65536;
}
public float readFixedPoint88() throws IOException {
byte[] bytes = read(2);
short result = 0;
result |= ((bytes[0] << 8) & 0xFF00);
result |= ((bytes[1]) & 0xFF);
return ((float) result) / 256;
}
public String readString(int length) throws IOException {
byte[] buffer = new byte[length];
this.read(buffer);
try {
return new String(buffer, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error("JVM doesn't support UTF-8");
}
}
public byte[] read(int byteCount) throws IOException {
byte[] result = new byte[byteCount];
this.read(result);
return result;
}
public long skip(long n) throws IOException {
this.position(this.position() + n);
return n;
}
}