public int read(byte[] buffer, int pos, int len) throws IOException { if (transparent) { return (input.read(buffer, pos, len)); } // [header] // file [body-start -> body-end] long start_pos = seek_position; int start_len = len; if (seek_position < header.length) { int rem = (int) (header.length - seek_position); if (rem > len) { rem = len; } System.arraycopy(header, (int) seek_position, buffer, pos, rem); pos += rem; len -= rem; seek_position += rem; } if (len > 0) { long file_position = body_start + seek_position - header.length; long rem = body_end - file_position; if (len < rem) { rem = len; } input.seek(file_position); int temp = input.read(buffer, pos, (int) rem); pos += temp; len -= temp; seek_position += temp; } int read = start_len - len; seek_position = start_pos + read; return (read); }
public void seek(long pos) throws IOException { if (transparent) { input.seek(pos); } else { seek_position = pos; } }
public Atom(FileAccessor input) throws IOException { offset = input.getFilePointer(); // get atom size size = input.readInt(); // get atom type byte[] atomTypeFCC = new byte[4]; input.readFully(atomTypeFCC); type = new String(atomTypeFCC); if (size == 1) { // 64 bit size. Read new size from body and store it size = input.readLong(); } // skip back to atom start input.seek(offset); }
public QTFastStartRAF(FileAccessor accessor, boolean enable) throws IOException { input = accessor; if (enable) { String name = accessor.getName(); boolean log; String fail = null; synchronized (tested) { log = !tested.contains(name); if (log) { tested.add(name); } } try { Atom ah = null; Atom ftypAtom = null; boolean gotFtyp = false; boolean gotMdat = false; boolean justCopy = false; while (input.getFilePointer() < input.length()) { ah = new Atom(input); // System.out.println( "got " + ah.type +", size=" + ah.size ); if (!isValidTopLevelAtom(ah)) { throw new IOException("Non top level QT atom found (" + ah.type + "). File invalid?"); } if (gotFtyp && !gotMdat && ah.type.equalsIgnoreCase(ATOM_MOOV)) { justCopy = true; break; } // store ftyp atom to buffer if (ah.type.equalsIgnoreCase(ATOM_FTYP)) { ftypAtom = ah; ftypAtom.fillBuffer(input); gotFtyp = true; } else if (ah.type.equalsIgnoreCase(ATOM_MDAT)) { gotMdat = true; input.skipBytes((int) ah.size); } else { input.skipBytes((int) ah.size); } } if (justCopy) { transparent = true; return; } if (ftypAtom == null) { throw new IOException("No FTYP atom found"); } if (ah == null || !ah.type.equalsIgnoreCase(ATOM_MOOV)) { throw new IOException("Last QT atom was not the MOOV atom."); } input.seek(ah.offset); Atom moovAtom = ah; moovAtom.fillBuffer(input); if (isCompressedMoovAtom(moovAtom)) { throw new IOException("Compressed MOOV qt atoms are not supported"); } patchMoovAtom(moovAtom); body_start = ftypAtom.offset + ftypAtom.size; body_end = moovAtom.offset; header = new byte[ftypAtom.buffer.length + moovAtom.buffer.length]; System.arraycopy(ftypAtom.buffer, 0, header, 0, ftypAtom.buffer.length); System.arraycopy( moovAtom.buffer, 0, header, ftypAtom.buffer.length, moovAtom.buffer.length); if (accessor.length() != header.length + (body_end - body_start)) { throw (new IOException("Inconsistent: file size has changed")); } } catch (Throwable e) { // e.printStackTrace(); fail = Debug.getNestedExceptionMessage(e); transparent = true; } finally { input.seek(0); if (log) { String message; if (fail == null) { message = transparent ? "Not required" : "Required"; } else { message = "Failed - " + fail; } Debug.outNoStack("MOOV relocation for " + accessor.getName() + ": " + message); } } } else { transparent = true; } }