Package com.bfo.box

Class Box

java.lang.Object
com.bfo.box.Box
Direct Known Subclasses:
DataBox, ExtensionBox, JUMBox, TrackHeaderBox

public class Box extends Object

A general class for ISO base media boxes, eg M4V, M4A, quicktime, as defined in ISO14496, and also JUMBox as defined in ISO19566. This is the format of many modern media types (video/mp4, audio/aac, image/jp2) and is also used for C2PA.

Each box is encoded like so:

  • bytes 0-3 - length of this box, including the length field and type, 0 for "to the end of the stream", or 1 for "extended length".
  • bytes 4-7 - four-byte tag, interpreted as a 4-character ASCII string
  • bytes 7-15 (optional) - if length == 1, this 8 bytes is the "extended length". These are supported for reading but not writing by this API
  • remaining - ths box data, which may be a list of other boxes (for "container" boxes), or other types of data

Most types of boxes are loaded but not stored; you can traverse the tree, but attempting to write them out again will fail (this is intentional; we don't want to store a multi-GB movie in memory when all you want is the metadata). Some particular types of boxes can also be created from scratch; currently this only applies to C2PA related boxes. Some simple examples.

 BoxFactory factory = new BoxFactory();
 Box box;
 while ((box=factory.load(inpustream)) != null) {
   traverse(box, "");
 }
 
 void traverse(Box box, String prefix) {
   System.out.println(box.type()); // a 4-character string
   if (box instanceof XMPBox) {
     byte[] xmpdata = ((XMPBox)box).data(); // box subclasses are more interesting
   }
   for (Box child=box.first();box!=null;box=box.next()) {
     assert child.parent() == box;
     traverse(child, prefix + " ");
   }
 }
 
Since:
5
See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    add(Box box)
    Add this box to the end of the list of children
    dump(String prefix, Appendable out)
    A convenience method to dump the box trree
    Return a deep duplicate of this box, duplicating all its children too if necessary.
    Return the first child of this box, or null if this box has no children
    Return the full hierarchy of types from the root box to this box, separated by dots.
    final byte[]
    Return a byte[] array containing the encoded box structure.
    void
    Insert this box before the specified box.
    boolean
    Return true if this box was not completely read during the BoxFactory.load(java.nio.ByteBuffer) method.
    long
    Return the length of this box in bytes, or 0 for "until end of file".
    Return the next box in the list, or null if this is the last.
    Return the parent of this box, or null if this is the root
    void
    Remove this box from its parent
    Return a String representation of this Box, which will be parseable as JSON
    Return the type of this box, a four-character string

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
  • Method Details

    • add

      public void add(Box box)
      Add this box to the end of the list of children
      Parameters:
      box - the box, which must not be already part of a tree
      Throws:
      IllegalStateException - if box is already part of a tree
    • remove

      public void remove()
      Remove this box from its parent
    • insertBefore

      public void insertBefore(Box other)
      Insert this box before the specified box. If this box already exists
      Parameters:
      other - the Box to insert this box before. The box must have a parent.
      Throws:
      IllegalStateException - if this box is already part of a tree, or other has no parent
    • getEncoded

      public final byte[] getEncoded()
      Return a byte[] array containing the encoded box structure. All descendents that are not container boxes must override write(java.io.OutputStream)
      Returns:
      the encoded box
      Throws:
      UnsupportedOperationException - if any descendent of this box is not a container box and write(java.io.OutputStream) hasn't been overridden
    • isSparse

      public boolean isSparse()
      Return true if this box was not completely read during the BoxFactory.load(java.nio.ByteBuffer) method. Sparse boxes cannot be written, so getEncoded() will fail.
      Returns:
      whether box is sparse
    • type

      public String type()
      Return the type of this box, a four-character string
      Returns:
      the Box type
    • fullType

      public String fullType()
      Return the full hierarchy of types from the root box to this box, separated by dots. For example if this box has type "udat" and the parent box has type "moov", this method returns "moov.udat"
      Returns:
      the Box type hierarchy
    • length

      public long length()
      Return the length of this box in bytes, or 0 for "until end of file". Boxes that have not been read from disk will always have zero length
      Returns:
      the Box length
    • parent

      public Box parent()
      Return the parent of this box, or null if this is the root
      Returns:
      the parent
    • next

      public Box next()
      Return the next box in the list, or null if this is the last.
      Returns:
      the next sibling
    • first

      public Box first()
      Return the first child of this box, or null if this box has no children
      Returns:
      the first child
    • duplicate

      public Box duplicate()
      Return a deep duplicate of this box, duplicating all its children too if necessary.
      Returns:
      the duplicated box
    • toString

      public String toString()
      Return a String representation of this Box, which will be parseable as JSON
      Overrides:
      toString in class Object
    • dump

      public Appendable dump(String prefix, Appendable out)
      A convenience method to dump the box trree
      Parameters:
      prefix - the prefix to add to each line, or null for none
      out - the Appendable to write to, or null to create a new StringBuilder
      Returns:
      the appendable
      Throws:
      RuntimeException - wrapping an IOException if encountered while writing to the Appendable.