package org.jcodec.containers.mp4.boxes;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.jcodec.common.Assert;
import org.jcodec.common.NIOUtils;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* An MP4 file struncture (box).
*
* @author The JCodec project
*
*/
public abstract class Box {
protected Header header;
public Box(Header header) {
this.header = header;
}
public Box(Box other) {
this.header = other.header;
}
public Header getHeader() {
return header;
}
public abstract void parse(ByteBuffer buf);
public static Box findFirst(NodeBox box, String... path) {
return findFirst(box, Box.class, path);
}
public static <T> T findFirst(NodeBox box, Class<T> clazz, String... path) {
T[] result = (T[]) findAll(box, clazz, path);
return result.length > 0 ? result[0] : null;
}
public static Box[] findAll(Box box, String... path) {
return findAll(box, Box.class, path);
}
private static void findSub(Box box, List<String> path, Collection<Box> result) {
if (path.size() > 0) {
String head = path.remove(0);
if (box instanceof NodeBox) {
NodeBox nb = (NodeBox) box;
for (Box candidate : nb.getBoxes()) {
if (head == null || head.equals(candidate.header.getFourcc())) {
findSub(candidate, path, result);
}
}
}
path.add(0, head);
} else {
result.add(box);
}
}
public static <T> T[] findAll(Box box, Class<T> class1, String... path) {
List<Box> result = new LinkedList<Box>();
List<String> tlist = new LinkedList<String>();
for (String type : path) {
tlist.add(type);
}
findSub(box, tlist, result);
return result.toArray((T[]) Array.newInstance(class1, 0));
}
public void write(ByteBuffer buf) {
ByteBuffer dup = buf.duplicate();
NIOUtils.skip(buf, 8);
doWrite(buf);
header.setBodySize(buf.position() - dup.position() - 8);
Assert.assertEquals(header.headerSize(), 8);
header.write(dup);
}
protected abstract void doWrite(ByteBuffer out);
public String getFourcc() {
return header.getFourcc();
}
public String toString() {
StringBuilder sb = new StringBuilder();
dump(sb);
return sb.toString();
}
public void dump(StringBuilder sb) {
sb.append("'" + header.getFourcc() + "'");
}
public static <T extends Box> T as(Class<T> class1, LeafBox box) {
try {
T res = class1.getConstructor(Header.class).newInstance(box.getHeader());
res.parse(box.getData());
return res;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}