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 /** Constructs a new NutDataInputStream wrapping the given input stream. */ 024 public NutDataInputStream(InputStream in) { 025 checkNotNull(in); 026 this.count = new CountingInputStream(in); 027 this.crc = new CRC32InputStream(count); 028 this.in = new DataInputStream(crc); 029 } 030 031 /** Resets the CRC32 checksum for a new calculation range. */ 032 public void resetCRC() { 033 startCrcRange = count.getCount(); 034 crc.resetCrc(); 035 } 036 037 /** Returns the current CRC32 checksum value. */ 038 public long getCRC() { 039 endCrcRange = count.getCount(); 040 return crc.getValue(); 041 } 042 043 /** Reads a variable-length encoded integer up to 32 bits. */ 044 public int readVarInt() throws IOException { 045 boolean more; 046 int result = 0; 047 do { 048 int b = in.readUnsignedByte(); 049 more = (b & 0x80) == 0x80; 050 result = 128 * result + (b & 0x7F); 051 052 // TODO Check for int overflow 053 } while (more); 054 055 return result; 056 } 057 058 /** Reads a variable-length encoded integer up to 64 bits. */ 059 public long readVarLong() throws IOException { 060 boolean more; 061 long result = 0; 062 do { 063 int b = in.readUnsignedByte(); 064 more = (b & 0x80) == 0x80; 065 result = 128 * result + (b & 0x7F); 066 067 // TODO Check for long overflow 068 } while (more); 069 070 return result; 071 } 072 073 /** Reads a signed variable-length encoded integer. */ 074 public long readSignedVarInt() throws IOException { 075 long temp = readVarLong() + 1; 076 if ((temp & 1) == 1) { 077 return -(temp >> 1); 078 } 079 return temp >> 1; 080 } 081 082 /** Reads a byte array prefixed with a variable-length encoded length. */ 083 public byte[] readVarArray() throws IOException { 084 int len = (int) readVarLong(); 085 byte[] result = new byte[len]; 086 in.read(result); 087 return result; 088 } 089 090 /** Returns the start code, or the frame code if it does not start with 'N'. */ 091 public long readStartCode() throws IOException { 092 byte frameCode = in.readByte(); 093 if (frameCode != 'N') { 094 return (long) (frameCode & 0xff); 095 } 096 097 // Otherwise read the remaining 64bit startCode 098 byte[] buffer = new byte[8]; 099 buffer[0] = frameCode; 100 readFully(buffer, 1, 7); 101 return (((long) buffer[0] << 56) 102 + ((long) (buffer[1] & 255) << 48) 103 + ((long) (buffer[2] & 255) << 40) 104 + ((long) (buffer[3] & 255) << 32) 105 + ((long) (buffer[4] & 255) << 24) 106 + ((buffer[5] & 255) << 16) 107 + ((buffer[6] & 255) << 8) 108 + ((buffer[7] & 255) << 0)); 109 } 110 111 /** Returns the current byte offset in the input stream. */ 112 public long offset() { 113 return count.getCount(); 114 } 115 116 @Override 117 public void readFully(byte[] b) throws IOException { 118 in.readFully(b); 119 } 120 121 @Override 122 public void readFully(byte[] b, int off, int len) throws IOException { 123 in.readFully(b, off, len); 124 } 125 126 @Override 127 public int skipBytes(int n) throws IOException { 128 return in.skipBytes(n); 129 } 130 131 @Override 132 public boolean readBoolean() throws IOException { 133 return in.readBoolean(); 134 } 135 136 @Override 137 public byte readByte() throws IOException { 138 return in.readByte(); 139 } 140 141 @Override 142 public int readUnsignedByte() throws IOException { 143 return in.readUnsignedByte(); 144 } 145 146 @Override 147 public short readShort() throws IOException { 148 return in.readShort(); 149 } 150 151 @Override 152 public int readUnsignedShort() throws IOException { 153 return in.readUnsignedShort(); 154 } 155 156 @Override 157 public char readChar() throws IOException { 158 return in.readChar(); 159 } 160 161 @Override 162 public int readInt() throws IOException { 163 return in.readInt(); 164 } 165 166 @Override 167 public long readLong() throws IOException { 168 return in.readLong(); 169 } 170 171 @Override 172 public float readFloat() throws IOException { 173 return in.readFloat(); 174 } 175 176 @Override 177 public double readDouble() throws IOException { 178 return in.readDouble(); 179 } 180 181 @Override 182 @Deprecated 183 public String readLine() throws IOException { 184 return in.readLine(); 185 } 186 187 @Override 188 public String readUTF() throws IOException { 189 return in.readUTF(); 190 } 191}