diff --git a/src/Zend/Media/Iso14496.php b/src/Zend/Media/Iso14496.php
new file mode 100644
index 0000000..141e731
--- /dev/null
+++ b/src/Zend/Media/Iso14496.php
@@ -0,0 +1,405 @@
+
+ *
ftyp -- {@link Zend_Media_Iso14496_Box_Ftyp File Type Box};
+ * file type and compatibility
+ * pdin -- {@link Zend_Media_Iso14496_Box_Pdin Progressive Download
+ * Information Box}
+ * moov -- {@link Zend_Media_Iso14496_Box_Moov Movie Box};
+ * container for all the metadata
+ *
+ * - mvhd -- {@link Zend_Media_Iso14496_Box_Mvhd Movie Header
+ * Box}; overall declarations
+ *
- trak -- {@link Zend_Media_Iso14496_Box_Trak Track Box};
+ * container for an individual track or stream
+ *
+ * - tkhd -- {@link Zend_Media_Iso14496_Box_Tkhd Track Header
+ * Box}; overall information about the track
+ *
- tref -- {@link Zend_Media_Iso14496_Box_Tref Track Reference
+ * Box}
+ *
- edts -- {@link Zend_Media_Iso14496_Box_Edts Edit Box}
+ *
+ * - elst -- {@link Zend_Media_Iso14496_Box_Elst Edit List Box}
+ *
+ * - mdia -- {@link Zend_Media_Iso14496_Box_Mdia Media Box}
+ *
+ * - mdhd -- {@link Zend_Media_Iso14496_Box_Mdhd Media Header
+ * Box}; overall information about the media
+ *
- hdlr -- {@link Zend_Media_Iso14496_Box_Hdlr Handler
+ * Reference Box}; declares the media type
+ *
- minf -- {@link Zend_Media_Iso14496_Box_Minf Media
+ * Information Box}
+ *
+ * - vmhd -- {@link Zend_Media_Iso14496_Box_Vmhd Video Media Header
+ * Box}; overall information (video track only)
+ *
- smhd -- {@link Zend_Media_Iso14496_Box_Smhd Sound Media Header
+ * Box}; overall information (sound track only)
+ *
- hmhd -- {@link Zend_Media_Iso14496_Box_Hmhd Hint Media Header
+ * Box}; overall information (hint track only)
+ *
- nmhd -- {@link Zend_Media_Iso14496_Box_Nmhd Null Media Header
+ * Box}; overall information (some tracks only)
+ *
- dinf -- {@link Zend_Media_Iso14496_Box_Dinf Data
+ * Information Box}
+ *
+ * - dref -- {@link Zend_Media_Iso14496_Box_Dref Data
+ * Reference Box}
+ *
+ * - stbl -- {@link Zend_Media_Iso14496_Box_Stbl Sample
+ * Table Box}
+ *
+ * - stsd -- {@link Zend_Media_Iso14496_Box_Stsd Sample
+ * Descriptions Box}
+ *
- stts -- {@link Zend_Media_Iso14496_Box_Stts Decoding
+ * Time To Sample Box}
+ *
- ctts -- {@link Zend_Media_Iso14496_Box_Ctts Composition Time
+ * To Sample Box}
+ *
- stsc -- {@link Zend_Media_Iso14496_Box_Stsc Sample To
+ * Chunk Box}
+ *
- stsz -- {@link Zend_Media_Iso14496_Box_Stsz Sample Size
+ * Box}
+ *
- stz2 -- {@link Zend_Media_Iso14496_Box_Stz2 Compact Sample
+ * Size Box}
+ *
- stco -- {@link Zend_Media_Iso14496_Box_Stco Chunk
+ * Offset Box}; 32-bit
+ *
- co64 -- {@link Zend_Media_Iso14496_Box_Co64 Chunk Ooffset
+ * Box}; 64-bit
+ *
- stss -- {@link Zend_Media_Iso14496_Box_Stss Sync Sample
+ * Table Box}
+ *
- stsh -- {@link Zend_Media_Iso14496_Box_Stsh Shadow Sync
+ * Sample Table Box}
+ *
- padb -- {@link Zend_Media_Iso14496_Box_Padb Padding Bits
+ * Box}
+ *
- stdp -- {@link Zend_Media_Iso14496_Box_Stdp Sample
+ * Degradation Priority Box}
+ *
- sdtp -- {@link Zend_Media_Iso14496_Box_Sdtp Independent and
+ * Disposable Samples Box}
+ *
- sbgp -- {@link Zend_Media_Iso14496_Box_Sbgp Sample To Group
+ * Box}
+ *
- sgpd -- {@link Zend_Media_Iso14496_Box_Sgpd Sample Group
+ * Description}
+ *
- subs -- {@link Zend_Media_Iso14496_Box_Subs Sub-Sample
+ * Information Box}
+ *
+ *
+ *
+ *
+ * - mvex -- {@link Zend_Media_Iso14496_Box_Mvex Movie Extends Box}
+ *
+ * - mehd -- {@link Zend_Media_Iso14496_Box_Mehd Movie Extends Header
+ * Box}
+ *
- trex -- {@link Zend_Media_Iso14496_Box_Trex Track Extends
+ * Box}
+ *
+ * - ipmc -- {@link Zend_Media_Iso14496_Box_Ipmc IPMP Control Box}
+ *
+ * moof -- {@link Zend_Media_Iso14496_Box_Moof Movie Fragment Box}
+ *
+ * - mfhd -- {@link Zend_Media_Iso14496_Box_Mfhd Movie Fragment
+ * Header Box}
+ *
- traf -- {@link Zend_Media_Iso14496_Box_Traf Track Fragment Box}
+ *
+ * - tfhd -- {@link Zend_Media_Iso14496_Box_Tfhd Track Fragment
+ * Header Box}
+ *
- trun -- {@link Zend_Media_Iso14496_Box_Trun Track Fragment
+ * Run}
+ *
- sdtp -- {@link Zend_Media_Iso14496_Box_Sdtp Independent and
+ * Disposable Samples}
+ *
- sbgp -- {@link Zend_Media_Iso14496_Box_Sbgp !SampleToGroup
+ * Box}
+ *
- subs -- {@link Zend_Media_Iso14496_Box_Subs Sub-Sample Information
+ * Box}
+ *
+ *
+ * mfra -- {@link Zend_Media_Iso14496_Box_Mfra Movie Fragment Random
+ * Access Box}
+ *
+ * - tfra -- {@link Zend_Media_Iso14496_Box_Tfra Track Fragment Random
+ * Access Box}
+ *
- mfro -- {@link Zend_Media_Iso14496_Box_Mfro Movie Fragment
+ * Random Access Offset Box}
+ *
+ * mdat -- {@link Zend_Media_Iso14496_Box_Mdat Media Data Box}
+ * free -- {@link Zend_Media_Iso14496_Box_Free Free Space Box}
+ * skip -- {@link Zend_Media_Iso14496_Box_Skip Free Space Box}
+ *
+ * - udta -- {@link Zend_Media_Iso14496_Box_Udta User Data Box}
+ *
+ * - cprt -- {@link Zend_Media_Iso14496_Box_Cprt Copyright Box}
+ *
+ *
+ * meta -- {@link Zend_Media_Iso14496_Box_Meta The Meta Box}
+ *
+ * - hdlr -- {@link Zend_Media_Iso14496_Box_Hdlr Handler Reference
+ * Box}; declares the metadata type
+ *
- dinf -- {@link Zend_Media_Iso14496_Box_Dinf Data Information
+ * Box}
+ *
+ * - dref -- {@link Zend_Media_Iso14496_Box_Dref Data Reference
+ * Box}; declares source(s) of metadata items
+ *
+ * - ipmc -- {@link Zend_Media_Iso14496_Box_Ipmc IPMP Control Box}
+ *
- iloc -- {@link Zend_Media_Iso14496_Box_Iloc Item Location Box}
+ *
- ipro -- {@link Zend_Media_Iso14496_Box_Ipro Item Protection Box}
+ *
+ * - sinf -- {@link Zend_Media_Iso14496_Box_Sinf Protection Scheme
+ * Information Box}
+ *
+ * - frma -- {@link Zend_Media_Iso14496_Box_Frma Original Format
+ * Box}
+ *
- imif -- {@link Zend_Media_Iso14496_Box_Imif IPMP Information
+ * Box}
+ *
- schm -- {@link Zend_Media_Iso14496_Box_Schm Scheme Type Box}
+ *
- schi -- {@link Zend_Media_Iso14496_Box_Schi Scheme Information
+ * Box}
+ *
+ *
+ * - iinf -- {@link Zend_Media_Iso14496_Box_Iinf Item Information
+ * Box}
+ *
+ * - infe -- {@link Zend_Media_Iso14496_Box_Infe Item Information Entry
+ * Box}
+ *
+ * - xml -- {@link Zend_Media_Iso14496_Box_Xml XML Box}
+ *
- bxml -- {@link Zend_Media_Iso14496_Box_Bxml Binary XML Box}
+ *
- pitm -- {@link Zend_Media_Iso14496_Box_Pitm Primary Item Reference
+ * Box}
+ *
+ *
+ *
+ * There are two non-standard extensions to the ISO 14496 standard that add the
+ * ability to include file meta information. Both the boxes reside under
+ * moov.udta.meta.
+ *
+ *
+ * - moov -- {@link Zend_Media_Iso14496_Box_Moov Movie Box};
+ * container for all the metadata
+ *
- udta -- {@link Zend_Media_Iso14496_Box_Udta User Data Box}
+ *
- meta -- {@link Zend_Media_Iso14496_Box_Meta The Meta Box}
+ *
+ * - ilst -- {@link Zend_Media_Iso14496_Box_Ilst The iTunes/iPod Tag
+ * Container Box}
+ *
- id32 -- {@link Zend_Media_Iso14496_Box_Id32 The ID3v2 Box}
+ *
+ *
+ *
+ * @category Zend
+ * @package Zend_Media
+ * @subpackage ISO 14496
+ * @author Sven Vollbehr
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+final class Zend_Media_Iso14496 extends Zend_Media_Iso14496_Box
+{
+ /** @var string */
+ private $_filename;
+
+ /**
+ * Constructs the Zend_Media_Iso14496 class with given file and options.
+ *
+ * The following options are currently recognized:
+ * o base -- Indicates that only boxes with the given base path are parsed
+ * from the ISO base media file. Parsing all boxes can possibly have a
+ * significant impact on running time. Base path is a list of nested
+ * boxes separated by a dot. The use of base option implies readonly
+ * option.
+ * o readonly -- Indicates that the file is read from a temporary location
+ * or another source it cannot be written back to.
+ *
+ * @param string|resource|Zend_Io_Reader $filename The path to the file,
+ * file descriptor of an opened file, or a {@link Zend_Io_Reader} instance.
+ * @param Array $options The options array.
+ */
+ public function __construct($filename, $options = array())
+ {
+ if (isset($options['base'])) {
+ $options['readonly'] = true;
+ }
+ if ($filename instanceof Zend_Io_Reader) {
+ $this->_reader = &$filename;
+ } else {
+ require_once 'Zend/Io/FileReader.php';
+ try {
+ $this->_reader = new Zend_Io_FileReader($filename);
+ } catch (Zend_Io_Exception $e) {
+ $this->_reader = null;
+ require_once 'Zend/Media/Id3/Exception.php';
+ throw new Zend_Media_Iso14496_Exception($e->getMessage());
+ }
+ if (is_string($filename) && !isset($options['readonly'])) {
+ $this->_filename = $filename;
+ }
+ }
+ $this->setOptions($options);
+ $this->setOffset(0);
+ $this->setSize($this->_reader->getSize());
+ $this->setType('file');
+ $this->setContainer(true);
+ $this->constructBoxes();
+ }
+
+ /**
+ * Writes the changes back to the original media file. If the class was
+ * constructed without a file name, one can be provided here as an argument.
+ *
+ * The write operation commits only changes made to the Movie Box. It
+ * further changes the order of the Movie Box and Media Data Box in a way
+ * compatible for progressive download from a web page.
+ *
+ * All file offsets must be assumed to be invalid after the write operation.
+ *
+ * @param string $filename The optional path to the file, use null to save
+ * to the same file.
+ */
+ public function write($filename)
+ {
+ if ($filename === null && ($filename = $this->_filename) === null) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception
+ ('No file given to write the tag to');
+ } else if ($filename !== null && $this->_filename !== null &&
+ realpath($filename) != realpath($this->_filename) &&
+ !copy($this->_filename, $filename)) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception
+ ('Unable to copy source to destination: ' .
+ realpath($this->_filename) . '->' . realpath($filename));
+ }
+
+ if (($fd = fopen
+ ($filename, file_exists($filename) ? 'r+b' : 'wb')) === false) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception
+ ('Unable to open file for writing: ' . $filename);
+ }
+
+ /* Calculate file size */
+ fseek($fd, 0, SEEK_END);
+ $oldFileSize = ftell($fd);
+ $oldMoovSize = $this->moov->getSize();
+ $this->moov->udta->meta->free->setSize(8);
+ $this->moov->udta->meta->hdlr->setHandlerType('mdir');
+ $newFileSize = $oldFileSize - $oldMoovSize + $this->moov->getHeapSize();
+
+ /* Calculate free space size */
+ if ($oldFileSize < $newFileSize ||
+ $this->mdat->getOffset() < $this->moov->getOffset()) {
+ // Add constant 4096 bytes for free space to be used later
+ $this->moov->udta->meta->free->setSize(8 /* header */ + 4096);
+ ftruncate($fd, $newFileSize += 4096);
+ } else {
+ // Adjust free space to fill up the rest of the space
+ $this->moov->udta->meta->free->setSize
+ (8 + $oldFileSize - $newFileSize);
+ $newFileSize = $oldFileSize;
+ }
+
+ /* Calculate positions */
+ if ($this->mdat->getOffset() < $this->moov->getOffset()) {
+ $start = $this->mdat->getOffset();
+ $until = $this->moov->getOffset();
+ $where = $newFileSize;
+ $delta = $this->moov->getHeapSize();
+ } else {
+ $start = $this->moov->getOffset();
+ $until = $oldFileSize;
+ $where = $newFileSize;
+ $delta = $newFileSize - $oldFileSize;
+ }
+
+ /* Move data to the end of the file */
+ if ($newFileSize != $oldFileSize) {
+ for ($i = 1, $cur = $until; $cur > $start; $cur -= 1024, $i++) {
+ fseek
+ ($fd, $until - (($i * 1024) +
+ ($excess = $cur - 1024 > $start ?
+ 0 : $cur - $start - 1024)));
+ $buffer = fread($fd, 1024);
+ fseek($fd, $where - (($i * 1024) + $excess));
+ fwrite($fd, $buffer, 1024);
+ }
+ }
+
+
+ /* Update stco/co64 to correspond the data move */
+ foreach ($this->moov->getBoxesByIdentifier('trak') as $trak) {
+ $chunkOffsetBox =
+ (isset($trak->mdia->minf->stbl->stco) ?
+ $trak->mdia->minf->stbl->stco :
+ $trak->mdia->minf->stbl->co64);
+ $chunkOffsetTable = $chunkOffsetBox->getChunkOffsetTable();
+ $chunkOffsetTableCount = count($chunkOffsetTable);
+ for ($i = 1; $i <= $chunkOffsetTableCount; $i++) {
+ $chunkOffsetTable[$i] += $delta;
+ }
+ $chunkOffsetBox->setChunkOffsetTable($chunkOffsetTable);
+ }
+
+ /* Write moov box */
+ fseek($fd, $start);
+ $this->moov->write(new Zend_Io_Writer($fd));
+ fclose($fd);
+ }
+}
diff --git a/src/Zend/Media/Iso14496/Box.php b/src/Zend/Media/Iso14496/Box.php
new file mode 100644
index 0000000..8582465
--- /dev/null
+++ b/src/Zend/Media/Iso14496/Box.php
@@ -0,0 +1,663 @@
+
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+class Zend_Media_Iso14496_Box
+{
+ /**
+ * The reader object.
+ *
+ * @var Reader
+ */
+ protected $_reader;
+
+ /** @var Array */
+ private $_options;
+
+ /** @var integer */
+ private $_offset = -1;
+
+ /** @var integer */
+ private $_size = -1;
+
+ /** @var string */
+ private $_type;
+
+ /** @var Zend_Media_Iso14496_Box */
+ private $_parent = null;
+
+ /** @var boolean */
+ private $_container = false;
+
+ /** @var Array */
+ private $_boxes = array();
+
+ /** @var Array */
+ private static $_path = array();
+
+ /**
+ * Constructs the class with given parameters and options.
+ *
+ * @param Zend_Io_Reader $reader The reader object.
+ * @param Array $options The options array.
+ */
+ public function __construct($reader, &$options = array())
+ {
+ if (($this->_reader = $reader) === null) {
+ $this->_type = strtolower(substr(get_class($this), -4));
+ } else {
+ $this->_offset = $this->_reader->getOffset();
+ $this->_size = $this->_reader->readUInt32BE();
+ $this->_type = $this->_reader->read(4);
+
+ if ($this->_size == 1) {
+ $this->_size = $this->_reader->readInt64BE();
+ }
+ if ($this->_size == 0) {
+ $this->_size = $this->_reader->getSize() - $this->_offset;
+ }
+ if ($this->_type == 'uuid') {
+ $this->_type = $this->_reader->readGUID();
+ }
+ }
+ $this->_options = &$options;
+ }
+
+ public function __destruct()
+ {
+ unset($this->_boxes);
+ unset($this->_parent);
+ }
+
+ /**
+ * Returns the options array.
+ *
+ * @return Array
+ */
+ public final function &getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Returns the given option value, or the default value if the option is not
+ * defined.
+ *
+ * @param string $option The name of the option.
+ * @param mixed $defaultValue The default value to be returned.
+ */
+ public final function getOption($option, $defaultValue = null)
+ {
+ if (isset($this->_options[$option])) {
+ return $this->_options[$option];
+ }
+ return $defaultValue;
+ }
+
+ /**
+ * Sets the options array. See {@link Zend_Media_Id3v2} class for available
+ * options.
+ *
+ * @param Array $options The options array.
+ */
+ public final function setOptions(&$options)
+ {
+ $this->_options = &$options;
+ }
+
+ /**
+ * Sets the given option the given value.
+ *
+ * @param string $option The name of the option.
+ * @param mixed $value The value to set for the option.
+ */
+ public final function setOption($option, $value)
+ {
+ $this->_options[$option] = $value;
+ }
+
+ /**
+ * Clears the given option value.
+ *
+ * @param string $option The name of the option.
+ */
+ public final function clearOption($option)
+ {
+ unset($this->_options[$option]);
+ }
+
+ /**
+ * Returns the file offset to box start, or -1 if the box was created on heap.
+ *
+ * @return integer
+ */
+ public final function getOffset()
+ {
+ return $this->_offset;
+ }
+
+ /**
+ * Sets the file offset where the box starts.
+ *
+ * @param integer $offset The file offset to box start.
+ */
+ public final function setOffset($offset)
+ {
+ $this->_offset = $offset;
+ }
+
+ /**
+ * Returns the box size in bytes read from the file, including the size and
+ * type header, fields, and all contained boxes, or -1 if the box was
+ * created on heap.
+ *
+ * @return integer
+ */
+ public final function getSize()
+ {
+ return $this->_size;
+ }
+
+ /**
+ * Sets the box size. The size must include the size and type header,
+ * fields, and all contained boxes.
+ *
+ * The method will propagate size change to box parents.
+ *
+ * @param integer $size The box size.
+ */
+ protected final function setSize($size)
+ {
+ if ($this->_parent !== null) {
+ $this->_parent->setSize
+ (($this->_parent->getSize() > 0 ?
+ $this->_parent->getSize() : 0) +
+ $size - ($this->_size > 0 ? $this->_size : 0));
+ }
+ $this->_size = $size;
+ }
+
+ /**
+ * Returns the box type.
+ *
+ * @return string
+ */
+ public final function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Sets the box type.
+ *
+ * @param string $type The box type.
+ */
+ public final function setType($type)
+ {
+ $this->_type = $type;
+ }
+
+ /**
+ * Returns the parent box containing this box.
+ *
+ * @return Zend_Media_Iso14496_Box
+ */
+ public final function getParent()
+ {
+ return $this->_parent;
+ }
+
+ /**
+ * Sets the parent containing box.
+ *
+ * @param Zend_Media_Iso14496_Box $parent The parent box.
+ */
+ public function setParent(&$parent)
+ {
+ $this->_parent = $parent;
+ }
+
+ /**
+ * Returns a boolean value corresponding to whether the box is a container.
+ *
+ * @return boolean
+ */
+ public final function isContainer()
+ {
+ return $this->_container;
+ }
+
+ /**
+ * Returns a boolean value corresponding to whether the box is a container.
+ *
+ * @return boolean
+ */
+ public final function getContainer()
+ {
+ return $this->_container;
+ }
+
+ /**
+ * Sets whether the box is a container.
+ *
+ * @param boolean $container Whether the box is a container.
+ */
+ protected final function setContainer($container)
+ {
+ $this->_container = $container;
+ }
+
+ /**
+ * Reads and constructs the boxes found within this box.
+ *
+ * @todo Does not parse iTunes internal ---- boxes.
+ */
+ protected final function constructBoxes
+ ($defaultclassname = 'Zend_Media_Iso14496_Box')
+ {
+ $base = $this->getOption('base', '');
+ if ($this->getType() != 'file') {
+ self::$_path[] = $this->getType();
+ }
+ $path = implode(self::$_path, '.');
+
+ while (true) {
+ $offset = $this->_reader->getOffset();
+ if ($offset >= $this->_offset + $this->_size) {
+ break;
+ }
+ $size = $this->_reader->readUInt32BE();
+ $type = rtrim($this->_reader->read(4), ' ');
+ if ($size == 1) {
+ $size = $this->_reader->readInt64BE();
+ }
+ if ($size == 0) {
+ $size = $this->_reader->getSize() - $offset;
+ }
+
+ if (preg_match("/^\xa9?[a-z0-9]{3,4}$/i", $type) &&
+ substr($base, 0, min(strlen($base), strlen
+ ($tmp = $path . ($path ? '.' : '') . $type))) ==
+ substr($tmp, 0, min(strlen($base), strlen($tmp))))
+ {
+ $this->_reader->setOffset($offset);
+ if (@fopen($filename = 'Zend/Media/Iso14496/Box/' .
+ ucfirst($type) . '.php', 'r', true) !== false) {
+ require_once($filename);
+ }
+ if (class_exists
+ ($classname = 'Zend_Media_Iso14496_Box_' .
+ ucfirst($type))) {
+ $box = new $classname($this->_reader, $this->_options);
+ } else {
+ $box =
+ new $defaultclassname($this->_reader, $this->_options);
+ }
+ $box->setParent($this);
+ if (!isset($this->_boxes[$box->getType()])) {
+ $this->_boxes[$box->getType()] = array();
+ }
+ $this->_boxes[$box->getType()][] = $box;
+ }
+ $this->_reader->setOffset($offset + $size);
+ }
+
+ array_pop(self::$_path);
+ }
+
+ /**
+ * Checks whether the box given as an argument is present in the file. Returns
+ * true if one or more boxes are present, false
+ * otherwise.
+ *
+ * @param string $identifier The box identifier.
+ * @return boolean
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function hasBox($identifier)
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Box not a container');
+ }
+ return isset($this->_boxes[$identifier]);
+ }
+
+ /**
+ * Returns all the boxes the file contains as an associate array. The box
+ * identifiers work as keys having an array of boxes as associated value.
+ *
+ * @return Array
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function getBoxes()
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Box not a container');
+ }
+ return $this->_boxes;
+ }
+
+ /**
+ * Returns an array of boxes matching the given identifier or an empty array
+ * if no boxes matched the identifier.
+ *
+ * The identifier may contain wildcard characters '*' and '?'. The asterisk
+ * matches against zero or more characters, and the question mark matches
+ * any single character.
+ *
+ * Please note that one may also use the shorthand $obj->identifier to
+ * access the first box with the identifier given. Wildcards cannot be used
+ * with the shorthand and they will not work with user defined uuid types.
+ *
+ * @param string $identifier The box identifier.
+ * @return Array
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function getBoxesByIdentifier($identifier)
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Box not a container');
+ }
+ $matches = array();
+ $searchPattern = "/^" .
+ str_replace(array("*", "?"), array(".*", "."), $identifier) . "$/i";
+ foreach ($this->_boxes as $identifier => $boxes) {
+ if (preg_match($searchPattern, $identifier)) {
+ foreach ($boxes as $box) {
+ $matches[] = $box;
+ }
+ }
+ }
+ return $matches;
+ }
+
+ /**
+ * Removes any boxes matching the given box identifier.
+ *
+ * The identifier may contain wildcard characters '*' and '?'. The asterisk
+ * matches against zero or more characters, and the question mark matches any
+ * single character.
+ *
+ * One may also use the shorthand unset($obj->identifier) to achieve the same
+ * result. Wildcards cannot be used with the shorthand method.
+ *
+ * @param string $identifier The box identifier.
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function removeBoxesByIdentifier($identifier)
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception("Box not a container");
+ }
+ $searchPattern = "/^" .
+ str_replace(array("*", "?"), array(".*", "."), $identifier) . "$/i";
+ foreach ($this->_objects as $identifier => $objects) {
+ if (preg_match($searchPattern, $identifier)) {
+ unset($this->_objects[$identifier]);
+ }
+ }
+ }
+
+ /**
+ * Adds a new box into the current box and returns it.
+ *
+ * @param Zend_Media_Iso14496_Box $box The box to add
+ * @return Zend_Media_Iso14496_Box
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function addBox(&$box)
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Box not a container');
+ }
+ $box->setParent($this);
+ $box->setOptions($this->_options);
+ if (!$this->hasBox($box->getType())) {
+ $this->_boxes[$box->getType()] = array();
+ }
+ return $this->_boxes[$box->getType()][] = $box;
+ }
+
+ /**
+ * Removes the given box.
+ *
+ * @param Zend_Media_Iso14496_Box $box The box to remove
+ * @throws Zend_Media_Iso14496_Exception if called on a non-container box
+ */
+ public final function removeBox($box)
+ {
+ if (!$this->isContainer()) {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Box not a container');
+ }
+ if ($this->hasBox($box->getType())) {
+ foreach ($this->_boxes[$box->getType()] as $key => $value) {
+ if ($box === $value) {
+ unset($this->_boxes[$box->getType()][$key]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the number of boxes this box contains.
+ *
+ * @return integer
+ */
+ public final function getBoxCount()
+ {
+ if (!$this->isContainer()) {
+ return 0;
+ }
+ return count($this->_boxes);
+ }
+
+ /**
+ * Magic function so that $obj->value will work. If called on a container box,
+ * the method will first attempt to return the first contained box that
+ * matches the identifier, and if not found, invoke a getter method.
+ *
+ * If there are no boxes or getter methods with given name, the method
+ * attempts to create a frame with given identifier.
+ *
+ * If none of these work, an exception is thrown.
+ *
+ * @param string $name The box or field name.
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ if ($this->isContainer() &&
+ isset($this->_boxes[str_pad($name, 4, ' ')])) {
+ return $this->_boxes[str_pad($name, 4, ' ')][0];
+ }
+ if (method_exists($this, 'get' . ucfirst($name))) {
+ return call_user_func(array($this, 'get' . ucfirst($name)));
+ }
+ if (@fopen($filename = 'Zend/Media/Iso14496/Box/' .
+ ucfirst($name) . '.php', 'r', true) !== false) {
+ require_once($filename);
+ }
+ if (class_exists
+ ($classname = 'Zend_Media_Iso14496_Box_' . ucfirst($name))) {
+ return $this->addBox(new $classname());
+ }
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Unknown box/field: ' . $name);
+ }
+
+ /**
+ * Magic function so that assignments with $obj->value will work.
+ *
+ * @param string $name The field name.
+ * @param string $value The field value.
+ * @return mixed
+ */
+ public function __set($name, $value)
+ {
+ if (method_exists($this, 'set' . ucfirst($name))) {
+ call_user_func(array($this, 'set' . ucfirst($name)), $value);
+ } else {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception('Unknown field: ' . $name);
+ }
+ }
+
+ /**
+ * Magic function so that isset($obj->value) will work. This method checks
+ * whether the box is a container and contains a box that matches the
+ * identifier.
+ *
+ * @param string $name The box name.
+ * @return boolean
+ */
+ public function __isset($name)
+ {
+ return ($this->isContainer() && isset($this->_boxes[$name]));
+ }
+
+ /**
+ * Magic function so that unset($obj->value) will work. This method removes
+ * all the boxes from this container that match the identifier.
+ *
+ * @param string $name The box name.
+ */
+ public function __unset($name)
+ {
+ if ($this->isContainer()) {
+ unset($this->_boxes[$name]);
+ }
+ }
+
+ /**
+ * Returns the box heap size in bytes, including the size and
+ * type header, fields, and all contained boxes. The box size is updated to
+ * reflect that of the heap size upon write. Subclasses should overwrite
+ * this method and call the parent method to get the calculated header and
+ * subbox sizes and then add their own bytes to that.
+ *
+ * @return integer
+ */
+ public function getHeapSize()
+ {
+ $size = 8;
+ if ($this->isContainer()) {
+ foreach ($this->getBoxes() as $name => $boxes) {
+ foreach ($boxes as $box) {
+ $size += $box->getHeapSize();
+ }
+ }
+ }
+ if ($size > 0xffffffff) {
+ $size += 8;
+ }
+ if (strlen($this->_type) > 4) {
+ $size += 16;
+ }
+ return $size;
+ }
+
+ /**
+ * Writes the box header. Subclasses should overwrite this method and call
+ * the parent method first and then write the box related data.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ protected function _writeData($writer)
+ {
+ if (get_class($this) == "Zend_Media_Iso14496_Box") {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception
+ ('Unknown box \'' . $this->getType() . '\' cannot be written.');
+ }
+
+ $this->_size = $this->getHeapSize();
+ if ($this->_size > 0xffffffff) {
+ $writer->writeUInt32BE(1);
+ } else {
+ $writer->writeUInt32BE($this->_size);
+ }
+ if (strlen($this->_type) > 4) {
+ $writer->write('uuid');
+ } else {
+ $writer->write($this->_type);
+ }
+ if ($this->_size > 0xffffffff) {
+ $writer->writeInt64BE($this->_size);
+ }
+ if (strlen($this->_type) > 4) {
+ $writer->writeGuid($this->_type);
+ }
+ }
+
+ /**
+ * Writes the frame data with the header.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ public function write($writer)
+ {
+ if (get_class($this) == "Zend_Media_Iso14496_Box") {
+ require_once 'Zend/Media/Iso14496/Exception.php';
+ throw new Zend_Media_Iso14496_Exception
+ ('Unknown box \'' . $this->getType() . '\' cannot be written.');
+ }
+
+ $this->_writeData($writer);
+ if ($this->isContainer()) {
+ foreach ($this->getBoxes() as $name => $boxes) {
+ foreach ($boxes as $box) {
+ $box->write($writer);
+ }
+ }
+ }
+ }
+}
diff --git a/src/Zend/Media/Iso14496/Box/Elst.php b/src/Zend/Media/Iso14496/Box/Elst.php
index 2d0aff1..fa4324b 100644
--- a/src/Zend/Media/Iso14496/Box/Elst.php
+++ b/src/Zend/Media/Iso14496/Box/Elst.php
@@ -67,7 +67,7 @@ final class Zend_Media_Iso14496_Box_Elst extends Zend_Media_Iso14496_FullBox
parent::__construct($reader, $options);
$entryCount = $this->_reader->readUInt32BE();
- for ($i = 1; $i <= $entryCount; $i++) {
+ for ($i = 0; $i < $entryCount; $i++) {
$entry = array();
if ($this->getVersion() == 1) {
$entry['segmentDuration'] = $this->_reader->readInt64BE();
@@ -77,8 +77,8 @@ final class Zend_Media_Iso14496_Box_Elst extends Zend_Media_Iso14496_FullBox
$entry['mediaTime'] = $this->_reader->readInt32BE();
}
$entry['mediaRate'] =
- ((($tmp = $this->_reader->readUInt32BE()) >> 16) & 0xffff) +
- (float)("0." . ((string)($tmp & 0xffff)));
+ (float)($this->_reader->readInt16BE() . "." .
+ $this->_reader->readInt16BE());
$this->_entries[] = $entry;
}
}
@@ -152,19 +152,18 @@ final class Zend_Media_Iso14496_Box_Elst extends Zend_Media_Iso14496_FullBox
{
parent::_writeData($writer);
$writer->writeUInt32BE($entryCount = count($this->_entries));
- for ($i = 1; $i <= $entryCount; $i++) {
+ for ($i = 0; $i < $entryCount; $i++) {
if ($this->getVersion() == 1) {
$writer->writeInt64BE($this->_entries[$i]['segmentDuration'])
->writeInt64BE($this->_entries[$i]['mediaTime']);
} else {
$writer->writeUInt32BE($this->_entries[$i]['segmentDuration'])
- ->writeUInt32BE($this->_entries[$i]['mediaTime']);
+ ->writeInt32BE($this->_entries[$i]['mediaTime']);
}
- @list(, $mediaRateDecimals) = explode
+ @list($mediaRateInteger, $mediaRateFraction) = explode
('.', (float)$this->_entries[$i]['mediaRate']);
- $writer->writeUInt32BE
- (floor($this->_entries[$i]['mediaRate']) << 16 |
- $mediaRateDecimals);
+ $writer->writeInt16BE($mediaRateInteger)
+ ->writeInt16BE($mediaRateFraction);
}
}
}
diff --git a/src/Zend/Media/Iso14496/Box/Free.php b/src/Zend/Media/Iso14496/Box/Free.php
index 83cc148..927f0a9 100644
--- a/src/Zend/Media/Iso14496/Box/Free.php
+++ b/src/Zend/Media/Iso14496/Box/Free.php
@@ -70,7 +70,7 @@ final class Zend_Media_Iso14496_Box_Free extends Zend_Media_Iso14496_Box
*/
public function getHeapSize()
{
- return parent::getHeapSize() + $this->getSize();
+ return ($this->getSize() >= 8 ? $this->getSize() : 0);
}
/**
@@ -81,7 +81,9 @@ final class Zend_Media_Iso14496_Box_Free extends Zend_Media_Iso14496_Box
*/
protected function _writeData($writer)
{
- parent::_writeData($writer);
- $writer->write(str_repeat("\0", $this->getSize()));
+ if ($this->getSize() >= 8) {
+ parent::_writeData($writer);
+ $writer->write(str_repeat("\0", $this->getSize() - 8));
+ }
}
}
diff --git a/src/Zend/Media/Iso14496/Box/Sbgp.php b/src/Zend/Media/Iso14496/Box/Sbgp.php
new file mode 100644
index 0000000..9cd4efe
--- /dev/null
+++ b/src/Zend/Media/Iso14496/Box/Sbgp.php
@@ -0,0 +1,197 @@
+Sample To Group Box table can be used to find the group that a
+ * sample belongs to and the associated description of that sample group. The
+ * table is compactly coded with each entry giving the index of the first sample
+ * of a run of samples with the same sample group descriptor. The sample group
+ * description ID is an index that refers to a
+ * {@link Zend_Media_Iso14496_Box_Sgpd Sample Group Description Box}, which
+ * contains entries describing the characteristics of each sample group.
+ *
+ * There may be multiple instances of this box if there is more than one sample
+ * grouping for the samples in a track. Each instance of the Sample To Group Box
+ * has a type code that distinguishes different sample groupings. Within a
+ * track, there shall be at most one instance of this box with a particular
+ * grouping type. The associated Sample Group Description shall indicate the
+ * same value for the grouping type.
+ *
+ * @category Zend
+ * @package Zend_Media
+ * @subpackage ISO 14496
+ * @author Sven Vollbehr
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+final class Zend_Media_Iso14496_Box_Sbgp extends Zend_Media_Iso14496_FullBox
+{
+ /** @var integer */
+ private $_groupingType;
+
+ /** @var Array */
+ private $_sampleToGroupTable = array();
+
+ /**
+ * Constructs the class with given parameters and reads box related data
+ * from the ISO Base Media file.
+ *
+ * @param Zend_Io_Reader $reader The reader object.
+ * @param Array $options The options array.
+ */
+ public function __construct($reader, &$options = array())
+ {
+ parent::__construct($reader, $options);
+
+ $groupingType = $this->_reader->readUInt32BE();
+ $entryCount = $this->_reader->readUInt32BE();
+ for ($i = 1; $i <= $entryCount; $i++) {
+ $this->_sampleToGroupTable[$i] = array
+ ('sampleCount' => $this->_reader->readUInt32BE(),
+ 'groupDescriptionIndex' => $this->_reader->readUInt32BE());
+ }
+ }
+
+ /**
+ * Returns the grouping type that identifies the type (i.e. criterion used
+ * to form the sample groups) of the sample grouping and links it to its
+ * sample group description table with the same value for grouping type. At
+ * most one occurrence of this box with the same value for groupingType
+ * shall exist for a track.
+ *
+ * @return integer
+ */
+ public function getGroupingType()
+ {
+ return $this->_groupingType;
+ }
+
+ /**
+ * Sets the grouping type that identifies the type (i.e. criterion used
+ * to form the sample groups) of the sample grouping and links it to its
+ * sample group description table with the same value for grouping type. At
+ * most one occurrence of this box with the same value for groupingType
+ * shall exist for a track.
+ *
+ * @param integer $groupingType The grouping type.
+ */
+ public function setGroupingType($groupingType)
+ {
+ $this->_groupingType = $groupingType;
+ }
+
+ /**
+ * Returns an array of values. Each entry is an array containing the
+ * following keys.
+ * o sampleCount -- an integer that gives the number of consecutive
+ * samples with the same sample group descriptor. If the sum of the
+ * sample count in this box is less than the total sample count, then
+ * the reader should effectively extend it with an entry that associates
+ * the remaining samples with no group. It is an error for the total in
+ * this box to be greater than the sample_count documented elsewhere,
+ * and the reader behavior would then be undefined.
+ * o groupDescriptionIndex -- an integer that gives the index of the
+ * sample group entry which describes the samples in this group. The
+ * index ranges from 1 to the number of sample group entries in the
+ * {@link Zend_Media_Iso14496_Box_Sgpd Sample Group Description Box},
+ * or takes the value 0 to indicate that this sample is a member of no
+ * group of this type.
+ *
+ * @return Array
+ */
+ public function getSampleToGroupTable()
+ {
+ return $this->_sampleToGroupTable;
+ }
+
+ /**
+ * Sets the array of values. Each entry must be an array containing the
+ * following keys.
+ * o sampleCount -- an integer that gives the number of consecutive
+ * samples with the same sample group descriptor. If the sum of the
+ * sample count in this box is less than the total sample count, then
+ * the reader should effectively extend it with an entry that associates
+ * the remaining samples with no group. It is an error for the total in
+ * this box to be greater than the sample_count documented elsewhere,
+ * and the reader behavior would then be undefined.
+ * o groupDescriptionIndex -- an integer that gives the index of the
+ * sample group entry which describes the samples in this group. The
+ * index ranges from 1 to the number of sample group entries in the
+ * {@link Zend_Media_Iso14496_Box_Sgpd Sample Group Description Box},
+ * or takes the value 0 to indicate that this sample is a member of no
+ * group of this type.
+ *
+ * @param Array $sampleToGroupTable The array of entries
+ */
+ public function setSampleToGroupTable($sampleToGroupTable)
+ {
+ $this->_sampleToGroupTable = $sampleToGroupTable;
+ }
+
+ /**
+ * Returns the box heap size in bytes.
+ *
+ * @return integer
+ */
+ public function getHeapSize()
+ {
+ return parent::getHeapSize() + 8 +
+ count($this->_sampleToGroupTable) * 8;
+ }
+
+ /**
+ * Writes the box data.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ protected function _writeData($writer)
+ {
+ parent::_writeData($writer);
+ $writer->writeUInt32BE($this->_groupingType);
+ $writer->writeUInt32BE($entryCount = count($this->_sampleToGroupTable));
+ for ($i = 1; $i <= $entryCount; $i++) {
+ $writer->writeUInt32BE
+ ($this->_sampleToGroupTable[$i]['sampleCount'])
+ ->writeUInt32BE
+ ($this->_sampleToGroupTable[$i]
+ ['groupDescriptionIndex']);
+ }
+ }
+}
diff --git a/src/Zend/Media/Iso14496/Box/Schm.php b/src/Zend/Media/Iso14496/Box/Schm.php
new file mode 100644
index 0000000..dd8c1a4
--- /dev/null
+++ b/src/Zend/Media/Iso14496/Box/Schm.php
@@ -0,0 +1,177 @@
+Scheme Type Box identifies the protection scheme.
+ *
+ * @category Zend
+ * @package Zend_Media
+ * @subpackage ISO 14496
+ * @author Sven Vollbehr
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+final class Zend_Media_Iso14496_Box_Schm extends Zend_Media_Iso14496_FullBox
+{
+ /** @var string */
+ private $_schemeType;
+
+ /** @var integer */
+ private $_schemeVersion;
+
+ /** @var string */
+ private $_schemeUri;
+
+ /**
+ * Constructs the class with given parameters and reads box related data
+ * from the ISO Base Media file.
+ *
+ * @param Zend_Io_Reader $reader The reader object.
+ * @param Array $options The options array.
+ */
+ public function __construct($reader, &$options = array())
+ {
+ parent::__construct($reader, $options);
+
+ $this->_schemeType = $this->_reader->read(4);
+ $this->_schemeVersion = $this->_reader->readUInt32BE();
+ if ($this->hasFlag(1)) {
+ $this->_schemeUri = preg_split
+ ("/\\x00/", $this->_reader->read
+ ($this->getOffset() + $this->getSize() -
+ $this->_reader->getOffset()));
+ }
+ }
+
+ /**
+ * Returns the code defining the protection scheme.
+ *
+ * @return string
+ */
+ public function getSchemeType()
+ {
+ return $this->_schemeType;
+ }
+
+ /**
+ * Sets the code defining the protection scheme.
+ *
+ * @param string $schemeType The scheme type.
+ */
+ public function setSchemeType($schemeType)
+ {
+ $this->_schemeType = $schemeType;
+ }
+
+ /**
+ * Returns the version of the scheme used to create the content.
+ *
+ * @return integer
+ */
+ public function getSchemeVersion()
+ {
+ return $this->_schemeVersion;
+ }
+
+ /**
+ * Sets the version of the scheme used to create the content.
+ *
+ * @param integer $schemeVersion The scheme version.
+ */
+ public function setSchemeVersion($schemeVersion)
+ {
+ $this->_schemeVersion = $schemeVersion;
+ }
+
+ /**
+ * Returns the optional scheme address to allow for the option of directing
+ * the user to a web-page if they do not have the scheme installed on their
+ * system. It is an absolute URI.
+ *
+ * @return string
+ */
+ public function getSchemeUri()
+ {
+ return $this->_schemeUri;
+ }
+
+ /**
+ * Sets the optional scheme address to allow for the option of directing
+ * the user to a web-page if they do not have the scheme installed on their
+ * system. It is an absolute URI.
+ *
+ * @param string $schemeUri The scheme URI.
+ */
+ public function setSchemeUri($schemeUri)
+ {
+ $this->_schemeUri = $schemeUri;
+ if ($schemeUri === null) {
+ $this->setFlags(0);
+ } else {
+ $this->setFlags(1);
+ }
+ }
+
+ /**
+ * Returns the box heap size in bytes.
+ *
+ * @return integer
+ */
+ public function getHeapSize()
+ {
+ return parent::getHeapSize() + 8 +
+ ($this->hasFlag(1) ? strlen($this->_schemeUri) + 1 : 0);
+ }
+
+ /**
+ * Writes the box data.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ protected function _writeData($writer)
+ {
+ parent::_writeData($writer);
+ $writer->write($this->_schemeType);
+ $writer->writeUInt32BE($this->_schemeVersion);
+ if ($this->hasFlag(1)) {
+ $writer->writeString8($this->_schemeUri, 1);
+ }
+ }
+}
diff --git a/src/Zend/Media/Iso14496/Box/Sdtp.php b/src/Zend/Media/Iso14496/Box/Sdtp.php
new file mode 100644
index 0000000..307ba19
--- /dev/null
+++ b/src/Zend/Media/Iso14496/Box/Sdtp.php
@@ -0,0 +1,187 @@
+Independent and Disposable Samples Box optional table answers
+ * three questions about sample dependency:
+ * 1) does this sample depend on others (is it an I-picture)?
+ * 2) do no other samples depend on this one?
+ * 3) does this sample contain multiple (redundant) encodings of the data at
+ * this time-instant (possibly with different dependencies)?
+ *
+ * In the absence of this table:
+ * 1) the sync sample table answers the first question; in most video codecs,
+ * I-pictures are also sync points,
+ * 2) the dependency of other samples on this one is unknown.
+ * 3) the existence of redundant coding is unknown.
+ *
+ * When performing trick modes, such as fast-forward, it is possible to use the
+ * first piece of information to locate independently decodable samples.
+ * Similarly, when performing random access, it may be necessary to locate the
+ * previous sync point or random access recovery point, and roll-forward from
+ * the sync point or the pre-roll starting point of the random access recovery
+ * point to the desired point. While rolling forward, samples on which no others
+ * depend need not be retrieved or decoded.
+ *
+
+ * The value of sampleIsDependedOn is independent of the existence of redundant
+ * codings. However, a redundant coding may have different dependencies from the
+ * primary coding; if redundant codings are available, the value of
+ * sampleDependsOn documents only the primary coding.
+ *
+ * A sample dependency Box may also occur in the
+ * {@link Zend_Media_Iso14496_Box_Traf Track Fragment Box}.
+ *
+ * @category Zend
+ * @package Zend_Media
+ * @subpackage ISO 14496
+ * @author Sven Vollbehr
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+final class Zend_Media_Iso14496_Box_Sdtp extends Zend_Media_Iso14496_FullBox
+{
+ /** @var Array */
+ private $_sampleDependencyTypeTable = array();
+
+ /**
+ * Constructs the class with given parameters and reads box related data
+ * from the ISO Base Media file.
+ *
+ * @param Zend_Io_Reader $reader The reader object.
+ * @param Array $options The options array.
+ */
+ public function __construct($reader, &$options = array())
+ {
+ parent::__construct($reader, $options);
+
+ $data = $this->_reader->read
+ ($this->getOffset() + $this->getSize() -
+ $this->_reader->getOffset());
+ $dataSize = strlen($data);
+ for ($i = 1; $i <= $dataSize; $i++) {
+ $this->_sampleDependencyTypeTable[$i] = array
+ ('sampleDependsOn' => (($tmp = ord($data[$i - 1])) >> 4) & 0x3,
+ 'sampleIsDependedOn' => ($tmp >> 2) & 0x3,
+ 'sampleHasRedundancy' => $tmp & 0x3);
+ }
+ }
+
+ /**
+ * Returns an array of values. Each entry is an array containing the
+ * following keys.
+ * o sampleDependsOn -- takes one of the following four values:
+ * 0: the dependency of this sample is unknown;
+ * 1: this sample does depend on others (not an I picture);
+ * 2: this sample does not depend on others (I picture);
+ * 3: reserved
+ * o sampleIsDependedOn -- takes one of the following four values:
+ * 0: the dependency of other samples on this sample is unknown;
+ * 1: other samples depend on this one (not disposable);
+ * 2: no other sample depends on this one (disposable);
+ * 3: reserved
+ * o sampleHasRedundancy -- takes one of the following four values:
+ * 0: it is unknown whether there is redundant coding in this sample;
+ * 1: there is redundant coding in this sample;
+ * 2: there is no redundant coding in this sample;
+ * 3: reserved
+ *
+ * @return Array
+ */
+ public function getSampleDependencyTypeTable()
+ {
+ return $this->_sampleDependencyTypeTable;
+ }
+
+ /**
+ * Sets the array of values. Each entry must be an array containing the
+ * following keys.
+ * o sampleDependsOn -- takes one of the following four values:
+ * 0: the dependency of this sample is unknown;
+ * 1: this sample does depend on others (not an I picture);
+ * 2: this sample does not depend on others (I picture);
+ * 3: reserved
+ * o sampleIsDependedOn -- takes one of the following four values:
+ * 0: the dependency of other samples on this sample is unknown;
+ * 1: other samples depend on this one (not disposable);
+ * 2: no other sample depends on this one (disposable);
+ * 3: reserved
+ * o sampleHasRedundancy -- takes one of the following four values:
+ * 0: it is unknown whether there is redundant coding in this sample;
+ * 1: there is redundant coding in this sample;
+ * 2: there is no redundant coding in this sample;
+ * 3: reserved
+ *
+ * @param Array $sampleDependencyTypeTable The array of values
+ */
+ public function setSampleDependencyTypeTable($sampleDependencyTypeTable)
+ {
+ $this->_sampleDependencyTypeTable = $sampleDependencyTypeTable;
+ }
+
+ /**
+ * Returns the box heap size in bytes.
+ *
+ * @return integer
+ */
+ public function getHeapSize()
+ {
+ return parent::getHeapSize() + count($this->_sampleDependencyTypeTable);
+ }
+
+ /**
+ * Writes the box data.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ protected function _writeData($writer)
+ {
+ parent::_writeData($writer);
+ for ($i = 1; $i <= count($this->_sampleDependencyTypeTable); $i++) {
+ $writer->write(chr(
+ (($this->_sampleDependencyTypeTable[$i]
+ ['sampleDependsOn'] & 0x3) << 4) |
+ (($this->_sampleDependencyTypeTable[$i]
+ ['sampleIsDependedOn'] & 0x3) << 2) |
+ (($this->_sampleDependencyTypeTable[$i]
+ ['sampleHasRedundancy'] & 0x3))));
+ }
+ }
+}
diff --git a/src/Zend/Media/Iso14496/Exception.php b/src/Zend/Media/Iso14496/Exception.php
new file mode 100644
index 0000000..2a0dfa0
--- /dev/null
+++ b/src/Zend/Media/Iso14496/Exception.php
@@ -0,0 +1,49 @@
+
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+class Zend_Media_Iso14496_Exception extends Exception
+{
+}
diff --git a/src/Zend/Media/Iso14496/FullBox.php b/src/Zend/Media/Iso14496/FullBox.php
new file mode 100644
index 0000000..6c5a3e5
--- /dev/null
+++ b/src/Zend/Media/Iso14496/FullBox.php
@@ -0,0 +1,150 @@
+
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+abstract class Zend_Media_Iso14496_FullBox extends Zend_Media_Iso14496_Box
+{
+ /** @var integer */
+ protected $_version = 0;
+
+ /** @var integer */
+ protected $_flags = 0;
+
+ /**
+ * Constructs the class with given parameters and reads box related data
+ * from the ISO Base Media file.
+ *
+ * @param Zend_Io_Reader $reader The reader object.
+ */
+ public function __construct($reader = null, &$options = array())
+ {
+ parent::__construct($reader, $options);
+
+ if ($reader === null) {
+ return;
+ }
+
+ $this->_version =
+ (($field = $this->_reader->readUInt32BE()) >> 24) & 0xff;
+ $this->_flags = $field & 0xffffff;
+ }
+
+ /**
+ * Returns the version of this format of the box.
+ *
+ * @return integer
+ */
+ public function getVersion()
+ {
+ return $this->_version;
+ }
+
+ /**
+ * Sets the version of this format of the box.
+ *
+ * @param integer $version The version.
+ */
+ public function setVersion($version)
+ {
+ $this->_version = $version;
+ }
+
+ /**
+ * Checks whether or not the flag is set. Returns true if the
+ * flag is set, false otherwise.
+ *
+ * @param integer $flag The flag to query.
+ * @return boolean
+ */
+ public function hasFlag($flag)
+ {
+ return ($this->_flags & $flag) == $flag;
+ }
+
+ /**
+ * Returns the map of flags.
+ *
+ * @return integer
+ */
+ public function getFlags()
+ {
+ return $this->_flags;
+ }
+
+ /**
+ * Sets the map of flags.
+ *
+ * @param string $flags The map of flags.
+ */
+ public function setFlags($flags)
+ {
+ $this->_flags = $flags;
+ }
+
+ /**
+ * Returns the box heap size in bytes.
+ *
+ * @return integer
+ */
+ public function getHeapSize()
+ {
+ return parent::getHeapSize() + 4;
+ }
+
+ /**
+ * Writes the box data without the header.
+ *
+ * @param Zend_Io_Writer $writer The writer object.
+ * @return void
+ */
+ protected function _writeData($writer)
+ {
+ parent::_writeData($writer);
+ $writer->writeUInt32BE($this->_version << 24 | $this->_flags);
+ }
+}