/*
* Flazr <http://flazr.com> Copyright (C) 2009 Peter Thomas.
*
* This file is part of Flazr.
*
* Flazr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Flazr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Flazr. If not, see <http://www.gnu.org/licenses/>.
*/
package com.flazr.io.f4vutil;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.util.Log;
import com.flazr.rtmp.reader.FileChannelReader;
public class Box {
private final BoxType type;
private final long fileOffset;
private List<Box> children;
private Payload payload;
public Box(final FileChannelReader in, final long endPos) {
final long boxSize = (in.readInt()& 0xFFFFFFFFL);
final byte[] typeBytes = in.readBytes(4);
type = BoxType.parse(new String(typeBytes));
final long payloadSize;
if (boxSize == 1) { // extended
final byte[] extBytes = in.readBytes(8);
final BigInteger bigLen = new BigInteger(1, extBytes);
payloadSize = bigLen.longValue() - 16;
} else if (boxSize == 0) { // decided by parent bound
payloadSize = endPos - in.position();
} else {
payloadSize = boxSize - 8;
}
fileOffset = in.position();
final long childEndPos = fileOffset + payloadSize;
Log.d(">> type: {}, payloadSize: {}",""+ type +" "+ payloadSize);
final BoxType[] childBoxes = type.getChildren();
if(childBoxes == null) {
if(type == BoxType.MDAT) {
Log.d("skipping MDAT","");
in.position(childEndPos);
return;
}
payload = type.read(in.wrappedReadBytes((int) payloadSize));
Log.d("<< {} payload: {}",""+ type+" "+ payload);
return;
}
while(in.position() < childEndPos) {
if(children == null) {
children = new ArrayList<Box>();
}
children.add(new Box(in, childEndPos));
}
Log.d("<< {} children: {}", ""+type+" "+ children);
}
public BoxType getType() {
return type;
}
public long getFileOffset() {
return fileOffset;
}
public List<Box> getChildren() {
return children;
}
public Payload getPayload() {
return payload;
}
public static void recurse(final Box box, final List<Box> collect, final int level) {
final char[] chars = new char[level * 2];
Arrays.fill(chars, ' ');
Log.d("{} recursing {}, payload: {}",
""+new Object[]{String.valueOf(chars), box.type, box.payload});
if(collect != null && box.getPayload() != null) {
collect.add(box);
}
if(box.getChildren() != null) {
for(final Box child : box.getChildren()) {
recurse(child, collect, level + 1);
}
}
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append('[').append(type);
sb.append(" fileOffset: ").append(fileOffset);
if(children != null) {
sb.append(" children: [");
for(Box box : children) {
sb.append(box.getType()).append(' ');
}
sb.append(']');
}
sb.append(" payload: ").append(payload);
sb.append(']');
return sb.toString();
}
}