001package net.bramp.ffmpeg.nut;
002
003import static com.google.common.base.Preconditions.checkNotNull;
004
005import com.google.common.io.CountingInputStream;
006import java.io.DataInput;
007import java.io.DataInputStream;
008import java.io.IOException;
009import java.io.InputStream;
010import net.bramp.ffmpeg.io.CRC32InputStream;
011
012/** A DataInputStream that implements a couple of custom FFmpeg Nut datatypes. */
013public class NutDataInputStream implements DataInput {
014
015  final DataInputStream in;
016  final CRC32InputStream crc;
017  final CountingInputStream count;
018
019  // These are for debugging, remove later
020  long startCrcRange;
021  long endCrcRange;
022
023  public NutDataInputStream(InputStream in) {
024    checkNotNull(in);
025    this.count = new CountingInputStream(in);
026    this.crc = new CRC32InputStream(count);
027    this.in = new DataInputStream(crc);
028  }
029
030  public void resetCRC() {
031    startCrcRange = count.getCount();
032    crc.resetCrc();
033  }
034
035  public long getCRC() {
036    endCrcRange = count.getCount();
037    return crc.getValue();
038  }
039
040  // Read a simple var int up to 32 bits
041  public int readVarInt() throws IOException {
042    boolean more;
043    int result = 0;
044    do {
045      int b = in.readUnsignedByte();
046      more = (b & 0x80) == 0x80;
047      result = 128 * result + (b & 0x7F);
048
049      // TODO Check for int overflow
050    } while (more);
051
052    return result;
053  }
054
055  // Read a simple var int up to 64 bits
056  public long readVarLong() throws IOException {
057    boolean more;
058    long result = 0;
059    do {
060      int b = in.readUnsignedByte();
061      more = (b & 0x80) == 0x80;
062      result = 128 * result + (b & 0x7F);
063
064      // TODO Check for long overflow
065    } while (more);
066
067    return result;
068  }
069
070  // Read a signed var int
071  public long readSignedVarInt() throws IOException {
072    long temp = readVarLong() + 1;
073    if ((temp & 1) == 1) {
074      return -(temp >> 1);
075    }
076    return temp >> 1;
077  }
078
079  // Read a array with a varint prefixed length
080  public byte[] readVarArray() throws IOException {
081    int len = (int) readVarLong();
082    byte[] result = new byte[len];
083    in.read(result);
084    return result;
085  }
086
087  // Returns the start code, OR frame_code if the code doesn't start with 'N'
088  public long readStartCode() throws IOException {
089    byte frameCode = in.readByte();
090    if (frameCode != 'N') {
091      return (long) (frameCode & 0xff);
092    }
093
094    // Otherwise read the remaining 64bit startCode
095    byte[] buffer = new byte[8];
096    buffer[0] = frameCode;
097    readFully(buffer, 1, 7);
098    return (((long) buffer[0] << 56)
099        + ((long) (buffer[1] & 255) << 48)
100        + ((long) (buffer[2] & 255) << 40)
101        + ((long) (buffer[3] & 255) << 32)
102        + ((long) (buffer[4] & 255) << 24)
103        + ((buffer[5] & 255) << 16)
104        + ((buffer[6] & 255) << 8)
105        + ((buffer[7] & 255) << 0));
106  }
107
108  public long offset() {
109    return count.getCount();
110  }
111
112  @Override
113  public void readFully(byte[] b) throws IOException {
114    in.readFully(b);
115  }
116
117  @Override
118  public void readFully(byte[] b, int off, int len) throws IOException {
119    in.readFully(b, off, len);
120  }
121
122  @Override
123  public int skipBytes(int n) throws IOException {
124    return in.skipBytes(n);
125  }
126
127  @Override
128  public boolean readBoolean() throws IOException {
129    return in.readBoolean();
130  }
131
132  @Override
133  public byte readByte() throws IOException {
134    return in.readByte();
135  }
136
137  @Override
138  public int readUnsignedByte() throws IOException {
139    return in.readUnsignedByte();
140  }
141
142  @Override
143  public short readShort() throws IOException {
144    return in.readShort();
145  }
146
147  @Override
148  public int readUnsignedShort() throws IOException {
149    return in.readUnsignedShort();
150  }
151
152  @Override
153  public char readChar() throws IOException {
154    return in.readChar();
155  }
156
157  @Override
158  public int readInt() throws IOException {
159    return in.readInt();
160  }
161
162  @Override
163  public long readLong() throws IOException {
164    return in.readLong();
165  }
166
167  @Override
168  public float readFloat() throws IOException {
169    return in.readFloat();
170  }
171
172  @Override
173  public double readDouble() throws IOException {
174    return in.readDouble();
175  }
176
177  @Override
178  @Deprecated
179  public String readLine() throws IOException {
180    return in.readLine();
181  }
182
183  @Override
184  public String readUTF() throws IOException {
185    return in.readUTF();
186  }
187}