(due to the long time, forget the original link, only to write their own current implementation of the way out for reference:)
public class Qtfaststart {public static Boolean sdebug = false; private static void Safeclose (Closeable closeable) {if (closeable! = null) {try {cl
Oseable.close ();
} catch (IOException e) {printe (E, "Failed to close file:"); }}}/* Package */static long Uint32tolong (int int32) {return Int32 & 0x00000000ffffff
FfL;
}/** * ensures passed UInt32 value in long can be represented as Java Int.
*/* Package */static int uint32toint (int uint32) throws Unsupportedfileexception {if (UInt32 < 0) {
throw new Unsupportedfileexception ("UInt32 value is too large");
} return UInt32;
}/** * ensures passed UInt32 value in long can be represented as Java Int. */* Package */static int uint32toint (long UInt32) throws Unsupportedfileexception {if (UInt32 > int Eger. Max_valUE | |
UInt32 < 0) {throw new Unsupportedfileexception ("UInt32 value is too large");
} return (int) UInt32;
}/** * ensures passed UInt64 value can be represented as Java long. */* Package */static long Uint64tolong (long UInt64) throws Unsupportedfileexception {if (UInt64 < 0
) throw new Unsupportedfileexception ("UInt64 value is too large");
return UInt64; } private static int fourcctoint (byte[] byteArray) {return bytebuffer.wrap (ByteArray). Order (Byteorder.big_en
DIAN). GetInt (); } private static void printf (String format, Object ... args) {if (sdebug) System.err.println ("Qtfaststart:"
+ string.format (format, args));
} private static void Printe (Throwable e, String format, Object ... args) {printf (format, args);
if (sdebug) e.printstacktrace ();
} private static Boolean Readandfill (FileChannel infile, Bytebuffer buffer) throws IOException { Buffer.clear ();
int size = infile.read (buffer);
Buffer.flip ();
return size = = Buffer.capacity ();
} private static Boolean Readandfill (FileChannel infile, bytebuffer buffer, long position) throws IOException {
Buffer.clear ();
int size = Infile.read (buffer, position);
Buffer.flip ();
return size = = Buffer.capacity ();
}/* Top level atoms */private static final int free_atom = fourcctoint (new byte[]{' F ', ' r ', ' E ', ' e '});
private static final int junk_atom = fourcctoint (new byte[]{' J ', ' U ', ' n ', ' K '});
private static final int mdat_atom = fourcctoint (new byte[]{' m ', ' d ', ' a ', ' t '});
private static final int moov_atom = fourcctoint (new byte[]{' m ', ' o ', ' o ', ' V '});
private static final int pnot_atom = fourcctoint (new byte[]{' P ', ' n ', ' o ', ' t '});
private static final int skip_atom = fourcctoint (new byte[]{' s ', ' k ', ' I ', ' P '}); private static final int wide_atom = fourcctoint (New byte[]{' W ', ' I ', ' d ', ' e '});
private static final int pict_atom = fourcctoint (new byte[]{' P ', ' I ', ' C ', ' T '});
private static final int ftyp_atom = fourcctoint (new byte[]{' F ', ' t ', ' y ', ' P '});
private static final int uuid_atom = fourcctoint (New byte[]{' u ', ' u ', ' I ', ' d '});
private static final int cmov_atom = fourcctoint (new byte[]{' C ', ' m ', ' o ', ' V '});
private static final int stco_atom = fourcctoint (new byte[]{' s ', ' t ', ' C ', ' O '});
private static final int co64_atom = fourcctoint (new byte[]{' C ', ' O ', ' 6 ', ' 4 '});
private static final int atom_preamble_size = 8; /**
*@paramIn Input file. *@paramOut Output file. *@returnFalse if input file is already fast start. *@throwsIOException */public static Boolean FastStart (String-in, string-out) throws IOException, Malformedfileexception,
unsupportedfileexception {Boolean ret = false;
FileInputStream instream = null;
FileOutputStream outstream = null;
FileChannel infile = null;
FileChannel outfile= null;
try {instream = new FileInputStream (in);
infile = Instream.getchannel ();
OutStream = new FileOutputStream (out);
outfile = Outstream.getchannel ();
return ret = Faststartimpl (infile, outfile); } finally {if (!ret) {infile.transferto (0, Infile.size (), outfile);//When the conversion is unsuccessful (normally due to file size), copy directly
.
Out.delete ();
}else{//In.delete ();
} safeclose (instream);
Safeclose (OutStream); }} private static Boolean Faststartimpl (FileChannel infile, FileChannel outfile) throws IoexcePtion, Malformedfileexception, unsupportedfileexception {bytebuffer atombytes = bytebuffer.allocate (ATOM_PREAMBLE
_size). order (Byteorder.big_endian);
int atomtype = 0; Long atomsize = 0;
uint64_t long LastOffset;
Bytebuffer Moovatom;
Bytebuffer ftypatom = null; uint64_t, but assuming it was in int32 range. It is reasonable as int Max is around 2GB.
Such large Moov is unlikely, yet unallocatable:).
int moovatomsize;
Long startoffset = 0;
SYSTEM.OUT.PRINTLN ("qtfaststart------" + "start"); Traverse through the atoms in the "file to make" sure that ' Moov ' are at the end while (Readandfill (infile, Atomby TES)) {atomsize = Uint32tolong (Atombytes.getint ());//UInt32 Atomtype = Atombytes.getint ();//R
Epresenting uint32_t in signed int//Keep Ftyp atom if (atomtype = = Ftyp_atom) { int ftypatomsize = Uint32toint (atomsize); Xxx:asSume in range of int32_t Ftypatom = Bytebuffer.allocate (ftypatomsize). order (Byteorder.big_endian);
Atombytes.rewind ();
Ftypatom.put (atombytes);
if (Infile.read (Ftypatom) < ftypatomsize-atom_preamble_size) break;
Ftypatom.flip (); Startoffset = Infile.position ();
After Ftyp Atom System.out.println ("Qtfaststart---ftyp_atom---atomtype:" +atomtype);
System.out.println ("Qtfaststart---ftyp_atom---atomtype:" +string.valueof (Infile.position ()));
} else {//SYSTEM.OUT.PRINTLN ("Qtfaststart------atomtype:" +atomtype);
if (atomsize = = 1) {/* 64-bit special Case */atombytes.clear ();
if (!readandfill (infile, atombytes)) break; Atomsize = Uint64tolong (Atombytes.getlong ()); Xxx:assume in range of int64_t infile.position (infiLe.position () + atomsize-atom_preamble_size * 2);
Seek System.out.println ("qtfaststart--atomsize = = 1----atomtype:" +atomtype);
} else {infile.position (infile.position () + atomsize-atom_preamble_size);//Seek
System.out.println ("qtfaststart--else----atomtype:" +atomtype); System.out.println ("qtfaststart--else----Atomtype:" +string.valueof (infile.position () + Atomsize-atom_preamble_
SIZE));
}} if (Sdebug) printf ("%c%c%c%c%10d%d", (Atomtype >>) & 255,
(Atomtype >>) & 255, (Atomtype >> 8) & 255,
(atomtype >> 0) & 255, Infile.position ()-atomsize, atomsize); if (atomtype! = free_atom) && (atomtype! = junk_atom) &&(Atomtype! = mdat_atom) && (atomtype! = moov_atom) && (atomtype! =
Pnot_atom) && (atomtype! = skip_atom) && (atomtype! = wide_atom)
&& (Atomtype! = pict_atom) && (atomtype! = uuid_atom) && (Atomtype! = Ftyp_atom)) {printf ("encountered non-qt top-level ATOM (is this a quickti
Me file?) ");
Break }/* The Atom header is 8 (or bytes), if the atom size (which * includes these 8 or bytes) are less than that, we won ' t is * able to continue scanning sensibly after this atom, so break.
*/if (Atomsize < 8) break;
} System.out.println ("qtfaststart------" + "First Loop end Atomtype:" +atomtype);
if (atomtype! = moov_atom) {printf ("Last atom in file is not a MOOV atom"); return false; }//Moov atom is, in fact, the last atom in the chunk;
Load the whole Moov atom//Atomsize is UInt64, but for Moov UInt32 should was stored.
Xxx:assuming moov atomsize <= Max Vaue of Int32 moovatomsize = Uint32toint (atomsize); LastOffset = Infile.size ()-moovatomsize; Note:assuming no extra data after Moov, as qt-faststart.c Moovatom = Bytebuffer.allocate (moovatomsize). Order (B
Yteorder.big_endian); if (!readandfill (infile, Moovatom, LastOffset)) {throw new Malformedfileexception ("Failed to read Moov atom")
; }//This utility does not the compressed atoms yet, so disqualify files with compressed QT atoms if (Moovatom.getint () = = Cmov_atom)
{throw new Unsupportedfileexception ("This utility does not the support compressed moov atoms yet"); }//Crawl through the Moov chunk in search for Stco or co64 atoms while (Moovatom.remaining () >= 8) {int atomhead = moovatom.position ();