package org.jcodec.movtool; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; import org.jcodec.common.io.IOUtils; import org.jcodec.common.io.NIOUtils; import org.jcodec.common.io.SeekableByteChannel; import org.jcodec.containers.mp4.BoxFactory; import org.jcodec.containers.mp4.BoxUtil; import org.jcodec.containers.mp4.MP4Util; import org.jcodec.containers.mp4.boxes.Box; import org.jcodec.containers.mp4.boxes.Header; import org.jcodec.containers.mp4.boxes.NodeBox; public class Undo { public static void main1(String[] args) throws IOException { if (args.length < 1) { System.err.println("Syntax: qt-undo [-l] "); System.err.println("\t-l\t\tList all the previous versions of this movie."); System.exit(-1); } Undo undo = new Undo(); if ("-l".equals(args[0])) { List list = undo.list(args[1]); System.out.println("" + list.size() - 1 + " versions."); } else { undo.undo(args[0]); } } private void undo(String fineName) throws IOException { List versions = list(fineName); if (versions.size() < 2) { System.err.println("Nowhere to rollback."); return; } RandomAccessFile raf = null; try { raf = new RandomAccessFile(new File(fineName), "rw"); raf.seek(versions.get(versions.size() - 2).getOffset() + 4L); raf.write(new byte[] { (byte)109, (byte)111, (byte)111, (byte)118 }); raf.seek(versions.get(versions.size() - 1).getOffset() + 4L); raf.write(new byte[] { (byte)102, (byte)114, (byte)101, (byte)101 }); } finally { IOUtils.closeQuietly(raf); } } private List list(String fileName) throws IOException { ArrayList result = new ArrayList<>(); SeekableByteChannel is = null; try { is = NIOUtils.readableChannel(new File(fileName)); int version = 0; for (MP4Util.Atom atom : MP4Util.getRootAtoms(is)) { if ("free".equals(atom.getHeader().getFourcc()) && isMoov(is, atom)) result.add(atom); if ("moov".equals(atom.getHeader().getFourcc())) { result.add(atom); break; } } } finally { IOUtils.closeQuietly(is); } return result; } private boolean isMoov(SeekableByteChannel is, MP4Util.Atom atom) throws IOException { is.setPosition(atom.getOffset() + atom.getHeader().headerSize()); try { Box mov = BoxUtil.parseBox(NIOUtils.fetchFromChannel(is, (int)atom.getHeader().getSize()), Header.createHeader("moov", atom.getHeader().getSize()), BoxFactory.getDefault()); return (mov instanceof org.jcodec.containers.mp4.boxes.MovieBox && BoxUtil.containsBox((NodeBox)mov, "mvhd")); } catch (Throwable t) { return false; } } }