blob: fdb7ac9a9c2db04076ccfc3b062cc526dc82b3c8 [file] [log] [blame]
package com.coremedia.iso.boxes.apple;
import com.coremedia.iso.IsoTypeReader;
import com.coremedia.iso.IsoTypeWriter;
import com.coremedia.iso.Utf8;
import com.googlecode.mp4parser.AbstractBox;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.ContainerBox;
import com.googlecode.mp4parser.util.ByteBufferByteChannel;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
/**
*
*/
public abstract class AbstractAppleMetaDataBox extends AbstractBox implements ContainerBox {
private static Logger LOG = Logger.getLogger(AbstractAppleMetaDataBox.class.getName());
AppleDataBox appleDataBox = new AppleDataBox();
public List<Box> getBoxes() {
return Collections.singletonList((Box) appleDataBox);
}
public void setBoxes(List<Box> boxes) {
if (boxes.size() == 1 && boxes.get(0) instanceof AppleDataBox) {
appleDataBox = (AppleDataBox) boxes.get(0);
} else {
throw new IllegalArgumentException("This box only accepts one AppleDataBox child");
}
}
public <T extends Box> List<T> getBoxes(Class<T> clazz) {
return getBoxes(clazz, false);
}
public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) {
//todo recursive?
if (clazz.isAssignableFrom(appleDataBox.getClass())) {
return (List<T>) Collections.singletonList(appleDataBox);
}
return null;
}
public AbstractAppleMetaDataBox(String type) {
super(type);
}
@Override
public void _parseDetails(ByteBuffer content) {
long dataBoxSize = IsoTypeReader.readUInt32(content);
String thisShouldBeData = IsoTypeReader.read4cc(content);
assert "data".equals(thisShouldBeData);
appleDataBox = new AppleDataBox();
try {
appleDataBox.parse(new ByteBufferByteChannel(content), null, content.remaining(), null);
} catch (IOException e) {
throw new RuntimeException(e);
}
appleDataBox.setParent(this);
}
protected long getContentSize() {
return appleDataBox.getSize();
}
protected void getContent(ByteBuffer byteBuffer) {
try {
appleDataBox.getBox(new ByteBufferByteChannel(byteBuffer));
} catch (IOException e) {
throw new RuntimeException("The Channel is based on a ByteBuffer and therefore it shouldn't throw any exception");
}
}
public long getNumOfBytesToFirstChild() {
return getSize() - appleDataBox.getSize();
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" +
"appleDataBox=" + getValue() +
'}';
}
static long toLong(byte b) {
return b < 0 ? b + 256 : b;
}
public void setValue(String value) {
if (appleDataBox.getFlags() == 1) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(1);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(Utf8.convert(value));
} else if (appleDataBox.getFlags() == 21) {
byte[] content = appleDataBox.getData();
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(21);
appleDataBox.setFourBytes(new byte[4]);
ByteBuffer bb = ByteBuffer.allocate(content.length);
if (content.length == 1) {
IsoTypeWriter.writeUInt8(bb, (Byte.parseByte(value) & 0xFF));
} else if (content.length == 2) {
IsoTypeWriter.writeUInt16(bb, Integer.parseInt(value));
} else if (content.length == 4) {
IsoTypeWriter.writeUInt32(bb, Long.parseLong(value));
} else if (content.length == 8) {
IsoTypeWriter.writeUInt64(bb, Long.parseLong(value));
} else {
throw new Error("The content length within the appleDataBox is neither 1, 2, 4 or 8. I can't handle that!");
}
appleDataBox.setData(bb.array());
} else if (appleDataBox.getFlags() == 0) {
appleDataBox = new AppleDataBox();
appleDataBox.setVersion(0);
appleDataBox.setFlags(0);
appleDataBox.setFourBytes(new byte[4]);
appleDataBox.setData(hexStringToByteArray(value));
} else {
LOG.warning("Don't know how to handle appleDataBox with flag=" + appleDataBox.getFlags());
}
}
public String getValue() {
if (appleDataBox.getFlags() == 1) {
return Utf8.convert(appleDataBox.getData());
} else if (appleDataBox.getFlags() == 21) {
byte[] content = appleDataBox.getData();
long l = 0;
int current = 1;
int length = content.length;
for (byte b : content) {
l += toLong(b) << (8 * (length - current++));
}
return "" + l;
} else if (appleDataBox.getFlags() == 0) {
return String.format("%x", new BigInteger(appleDataBox.getData()));
} else {
return "unknown";
}
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}