package org.jcodec.movtool;
import java.lang.IllegalStateException;
import java.lang.System;
import static org.jcodec.common.io.NIOUtils.readableChannel;
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.MP4Util.Atom;
import org.jcodec.containers.mp4.boxes.Box;
import org.jcodec.containers.mp4.boxes.Header;
import org.jcodec.containers.mp4.boxes.MovieBox;
import org.jcodec.containers.mp4.boxes.NodeBox;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Uses QuickTime feature to undo the recent changes
*
* @author The JCodec project
*
*/
public class Undo {
public static void main1(String[] args) throws IOException {
if (args.length < 1) {
System.err.println("Syntax: qt-undo [-l] <movie>");
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<Atom> 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<Atom> 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() + 4);
raf.write(new byte[] { 'm', 'o', 'o', 'v' });
raf.seek(versions.get(versions.size() - 1).getOffset() + 4);
raf.write(new byte[] { 'f', 'r', 'e', 'e' });
} finally {
raf.close();
}
}
private List<Atom> list(String fileName) throws IOException {
ArrayList<Atom> result = new ArrayList<Atom>();
SeekableByteChannel is = null;
try {
is = readableChannel(new File(fileName));
int version = 0;
for (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 {
is.close();
}
return result;
}
private boolean isMoov(SeekableByteChannel is, 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 MovieBox) && BoxUtil.containsBox((NodeBox) mov, "mvhd");
} catch (Throwable t) {
return false;
}
}
}