Methods Summary |
---|
protected abstract void | _parseDetails(java.nio.ByteBuffer content)Parse the box's fields and child boxes if any.
|
public void | getBox(java.nio.channels.WritableByteChannel os)
ByteBuffer bb = ByteBuffer.allocate(l2i(getSize()));
getHeader(bb);
if (content == null) {
getContent(bb);
if (deadBytes != null) {
deadBytes.rewind();
while (deadBytes.remaining() > 0) {
bb.put(deadBytes);
}
}
} else {
content.rewind();
bb.put(content);
}
bb.rewind();
os.write(bb);
|
protected abstract void | getContent(java.nio.ByteBuffer byteBuffer)Write the box's content into the given ByteBuffer . This must include flags
and version in case of a full box. byteBuffer has been initialized with
getSize() bytes.
|
protected abstract long | getContentSize()Get the box's content size without its header. This must be the exact number of bytes
that getContent(ByteBuffer) writes.
|
private void | getHeader(java.nio.ByteBuffer byteBuffer)
if (isSmallBox()) {
IsoTypeWriter.writeUInt32(byteBuffer, this.getSize());
byteBuffer.put(IsoFile.fourCCtoBytes(getType()));
} else {
IsoTypeWriter.writeUInt32(byteBuffer, 1);
byteBuffer.put(IsoFile.fourCCtoBytes(getType()));
IsoTypeWriter.writeUInt64(byteBuffer, getSize());
}
if (UserBox.TYPE.equals(getType())) {
byteBuffer.put(getUserType());
}
|
public com.coremedia.iso.IsoFile | getIsoFile()
return parent.getIsoFile();
|
public com.coremedia.iso.boxes.ContainerBox | getParent()
return parent;
|
public long | getSize()Gets the full size of the box including header and content.
long size = (content == null ? getContentSize() : content.limit());
size += (8 + // size|type
(size >= ((1L << 32) - 8) ? 8 : 0) + // 32bit - 8 byte size and type
(UserBox.TYPE.equals(getType()) ? 16 : 0));
size += (deadBytes == null ? 0 : deadBytes.limit());
return size;
|
public java.lang.String | getType()
return type;
|
public byte[] | getUserType()
return userType;
|
public boolean | isParsed()Check if details are parsed.
return content == null;
|
private boolean | isSmallBox()
return (content == null ? (getContentSize() + (deadBytes != null ? deadBytes.limit() : 0) + 8) : content.limit()) < 1L << 32;
|
public void | parse(java.nio.channels.ReadableByteChannel readableByteChannel, java.nio.ByteBuffer header, long contentSize, com.coremedia.iso.BoxParser boxParser)Read the box's content from a byte channel without parsing it. Parsing is done on-demand.
if (readableByteChannel instanceof FileChannel && contentSize > MEM_MAP_THRESHOLD) {
// todo: if I map this here delayed I could use transferFrom/transferTo in the getBox method
// todo: potentially this could speed up writing.
//
// It's quite expensive to map a file into the memory. Just do it when the box is larger than a MB.
content = ((FileChannel) readableByteChannel).map(FileChannel.MapMode.READ_ONLY, ((FileChannel) readableByteChannel).position(), contentSize);
((FileChannel) readableByteChannel).position(((FileChannel) readableByteChannel).position() + contentSize);
} else {
assert contentSize < Integer.MAX_VALUE;
content = ChannelHelper.readFully(readableByteChannel, contentSize);
}
|
final synchronized void | parseDetails()Parses the raw content of the box. It surrounds the actual parsing
which is done
if (content != null) {
ByteBuffer content = this.content;
this.content = null;
content.rewind();
_parseDetails(content);
if (content.remaining() > 0) {
deadBytes = content.slice();
}
assert verify(content);
}
|
protected void | setDeadBytes(java.nio.ByteBuffer newDeadBytes)Sets the 'dead' bytes. These bytes are left if the content of the box
has been parsed but not all bytes have been used up.
deadBytes = newDeadBytes;
|
public void | setParent(com.coremedia.iso.boxes.ContainerBox parent)
this.parent = parent;
|
private boolean | verify(java.nio.ByteBuffer content)Verifies that a box can be reconstructed byte-exact after parsing.
ByteBuffer bb = ByteBuffer.allocate(l2i(getContentSize() + (deadBytes != null ? deadBytes.limit() : 0)));
getContent(bb);
if (deadBytes != null) {
deadBytes.rewind();
while (deadBytes.remaining() > 0) {
bb.put(deadBytes);
}
}
content.rewind();
bb.rewind();
if (content.remaining() != bb.remaining()) {
LOG.severe(this.getType() + ": remaining differs " + content.remaining() + " vs. " + bb.remaining());
return false;
}
int p = content.position();
for (int i = content.limit() - 1, j = bb.limit() - 1; i >= p; i--, j--) {
byte v1 = content.get(i);
byte v2 = bb.get(j);
if (v1 != v2) {
LOG.severe(String.format("%s: buffers differ at %d: %2X/%2X", this.getType(), i, v1, v2));
byte[] b1 = new byte[content.remaining()];
byte[] b2 = new byte[bb.remaining()];
content.get(b1);
bb.get(b2);
System.err.println("original : " + Hex.encodeHex(b1, 4));
System.err.println("reconstructed : " + Hex.encodeHex(b2, 4));
return false;
}
}
return true;
|