From c6c10d7ce85c82d31f6b02a384eb4dea3bf56bdb Mon Sep 17 00:00:00 2001 From: svollbehr Date: Thu, 19 Feb 2009 14:10:37 +0000 Subject: [PATCH] Add write support for ASF header objects git-svn-id: http://php-reader.googlecode.com/svn/trunk@139 51a70ab9-7547-0410-9469-37e369ee0574 --- src/ASF.php | 95 +++++- src/ASF/Object.php | 142 +++++++-- src/ASF/Object/AdvancedContentEncryption.php | 85 ++++- src/ASF/Object/AdvancedMutualExclusion.php | 67 +++- src/ASF/Object/BandwidthSharing.php | 101 +++++- src/ASF/Object/BitrateMutualExclusion.php | 68 +++- src/ASF/Object/CodecList.php | 95 +++++- src/ASF/Object/Compatibility.php | 60 +++- src/ASF/Object/Container.php | 197 ++++++++++-- src/ASF/Object/ContentBranding.php | 90 +++++- src/ASF/Object/ContentDescription.php | 117 ++++++- src/ASF/Object/ContentEncryption.php | 89 +++++- src/ASF/Object/Data.php | 31 +- src/ASF/Object/DigitalSignature.php | 72 ++++- src/ASF/Object/ErrorCorrection.php | 60 +++- src/ASF/Object/ExtendedContentDescription.php | 122 +++++++- src/ASF/Object/ExtendedContentEncryption.php | 43 ++- src/ASF/Object/ExtendedStreamProperties.php | 293 +++++++++++++++++- src/ASF/Object/FileProperties.php | 188 ++++++++++- src/ASF/Object/GroupMutualExclusion.php | 71 ++++- src/ASF/Object/Header.php | 68 ++-- src/ASF/Object/HeaderExtension.php | 69 +++-- src/ASF/Object/LanguageList.php | 57 +++- src/ASF/Object/Marker.php | 96 +++++- src/ASF/Object/Metadata.php | 154 +++++++-- src/ASF/Object/MetadataLibrary.php | 127 +++++++- src/ASF/Object/Padding.php | 49 ++- src/ASF/Object/ScriptCommand.php | 102 ++++-- src/ASF/Object/StreamBitrateProperties.php | 68 +++- src/ASF/Object/StreamPrioritization.php | 63 +++- src/ASF/Object/StreamProperties.php | 236 +++++++++++++- src/ASF/Object/Unknown.php | 87 ++++++ 32 files changed, 2981 insertions(+), 281 deletions(-) create mode 100644 src/ASF/Object/Unknown.php diff --git a/src/ASF.php b/src/ASF.php index c3f18d0..e2edf9d 100644 --- a/src/ASF.php +++ b/src/ASF.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -56,19 +56,12 @@ require_once("ASF/Object/Container.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ class ASF extends ASF_Object_Container { - const HEADER = "75b22630-668e-11cf-a6d9-00aa0062ce6c"; - const DATA = "75b22636-668e-11cf-a6d9-00aa0062ce6c"; - const SIMPLE_INDEX = "33000890-e5b1-11cf-89f4-00a0c90349cb"; - const INDEX = "d6e229d3-35da-11d1-9034-00a0c90349be"; - const MEDIA_OBJECT_INDEX = "feb103f8-12ad-4c64-840f-2a1d2f7ad48c"; - const TIMECODE_INDEX = "3cb73fd0-0c4a-4803-953d-edf7b6228f0c"; - /** @var string */ private $_filename; @@ -140,12 +133,84 @@ class ASF extends ASF_Object_Container /** * Writes the changes back to the original media file. - * - * Please note: currently the method writes only Content Description and - * Extended Content Description Objects. */ - public function write() + public function write($filename = false) { - throw new ASF_Exception("Not yet supported"); + if ($filename === false) + $filename = $this->_filename; + if ($filename !== false && $this->_filename !== false && + realpath($filename) != realpath($this->_filename) && + !copy($this->_filename, $filename)) { + require_once("ASF/Exception.php"); + throw new ASF_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("ASF/Exception.php"); + throw new ASF_Exception("Unable to open file for writing: " . $filename); + } + + $header = $this->getHeader(); + $headerLengthOld = $header->getSize(); + $header->removeObjectsByIdentifier(ASF_Object::PADDING); + $header->headerExtension->removeObjectsByIdentifier(ASF_Object::PADDING); + + $headerData = $header->__toString(); + $headerLengthNew = $header->getSize(); + + // Fits right in + if ($headerLengthOld == $headerLengthNew) { + } + + // Fits with adjusted padding + else if ($headerLengthOld >= $headerLengthNew + 24 /* for header */) { + $header->headerExtension->padding->setSize + ($headerLengthOld - $headerLengthNew); + $headerData = $header->__toString(); + $headerLengthNew = $header->getSize(); + } + + // Must expand + else { + $header->headerExtension->padding->setSize(4096); + $headerData = $header->__toString(); + $headerLengthNew = $header->getSize(); + + fseek($fd, 0, SEEK_END); + $oldFileSize = ftell($fd); + ftruncate + ($fd, $newFileSize = $headerLengthNew - $headerLengthOld + + $oldFileSize); + for ($i = 1, $cur = $oldFileSize; $cur > 0; $cur -= 1024, $i++) { + fseek($fd, -(($i * 1024) + ($newFileSize - $oldFileSize)), SEEK_END); + $buffer = fread($fd, 1024); + fseek($fd, -($i * 1024), SEEK_END); + fwrite($fd, $buffer, 1024); + } + } + + fseek($fd, 0); + fwrite($fd, $headerData, $headerLengthNew); + fclose($fd); + + $this->_filename = $filename; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } } diff --git a/src/ASF/Object.php b/src/ASF/Object.php index c3c0a60..b1dcb14 100644 --- a/src/ASF/Object.php +++ b/src/ASF/Object.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,13 +31,12 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ /**#@+ @ignore */ -require_once("ASF/Exception.php"); /**#@-*/ /** @@ -48,12 +47,53 @@ require_once("ASF/Exception.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ -class ASF_Object +abstract class ASF_Object { + /* ASF Objects */ + const HEADER = "75b22630-668e-11cf-a6d9-00aa0062ce6c"; + const DATA = "75b22636-668e-11cf-a6d9-00aa0062ce6c"; + const SIMPLE_INDEX = "33000890-e5b1-11cf-89f4-00a0c90349cb"; + const INDEX = "d6e229d3-35da-11d1-9034-00a0c90349be"; + const MEDIA_OBJECT_INDEX = "feb103f8-12ad-4c64-840f-2a1d2f7ad48c"; + const TIMECODE_INDEX = "3cb73fd0-0c4a-4803-953d-edf7b6228f0c"; + + /* Header Objects */ + const FILE_PROPERTIES = "8cabdca1-a947-11cf-8ee4-00c00c205365"; + const STREAM_PROPERTIES = "b7dc0791-a9b7-11cf-8ee6-00c00c205365"; + const HEADER_EXTENSION = "5fbf03b5-a92e-11cf-8ee3-00c00c205365"; + const CODEC_LIST = "86d15240-311d-11d0-a3a4-00a0c90348f6"; + const SCRIPT_COMMAND = "1efb1a30-0b62-11d0-a39b-00a0c90348f6"; + const MARKER = "f487cd01-a951-11cf-8ee6-00c00c205365"; + const BITRATE_MUTUAL_EXCLUSION = "d6e229dc-35da-11d1-9034-00a0c90349be"; + const ERROR_CORRECTION = "75b22635-668e-11cf-a6d9-00aa0062ce6c"; + const CONTENT_DESCRIPTION = "75b22633-668e-11cf-a6d9-00aa0062ce6c"; + const EXTENDED_CONTENT_DESCRIPTION = "d2d0a440-e307-11d2-97f0-00a0c95ea850"; + const CONTENT_BRANDING = "2211b3fa-bd23-11d2-b4b7-00a0c955fc6e"; + const STREAM_BITRATE_PROPERTIES = "7bf875ce-468d-11d1-8d82-006097c9a2b2"; + const CONTENT_ENCRYPTION = "2211b3fb-bd23-11d2-b4b7-00a0c955fc6e"; + const EXTENDED_CONTENT_ENCRYPTION = "298ae614-2622-4c17-b935-dae07ee9289c"; + const DIGITAL_SIGNATURE = "2211b3fc-bd23-11d2-b4b7-00a0c955fc6e"; + const PADDING = "1806d474-cadf-4509-a4ba-9aabcb96aae8"; + + /* Header Extension Objects */ + const EXTENDED_STREAM_PROPERTIES = "14e6a5cb-c672-4332-8399-a96952065b5a"; + const ADVANCED_MUTUAL_EXCLUSION = "a08649cf-4775-4670-8a16-6e35357566cd"; + const GROUP_MUTUAL_EXCLUSION = "d1465a40-5a79-4338-b71b-e36b8fd6c249"; + const STREAM_PRIORITIZATION = "d4fed15b-88d3-454f-81f0-ed5c45999e24"; + const BANDWIDTH_SHARING = "a69609e6-517b-11d2-b6af-00c04fd908e9"; + const LANGUAGE_LIST = "7c4346a9-efe0-4bfc-b229-393ede415c85"; + const METADATA = "c5f8cbea-5baf-4877-8467-aa8c44fa4cca"; + const METADATA_LIBRARY = "44231c94-9498-49d1-a141-1d134e457054"; + const INDEX_PARAMETERS = "d6e229df-35da-11d1-9034-00a0c90349be"; + const MEDIA_OBJECT_INDEX_PARAMETERS = "6b203bad-3f11-48e4-aca8-d7613de2cfa7"; + const TIMECODE_INDEX_PARAMETERS = "f55e496d-9797-4b5d-8c8b-604dfe9bfb24"; + const COMPATIBILITY = "75b22630-668e-11cf-a6d9-00aa0062ce6c"; + const ADVANCED_CONTENT_ENCRYPTION = "43058533-6981-49e6-9b74-ad12cb86d58c"; + /** * The reader object. * @@ -69,13 +109,13 @@ class ASF_Object protected $_options; /** @var integer */ - private $_offset = -1; + private $_offset = false; /** @var string */ - private $_id; + private $_identifier = false; /** @var integer */ - private $_size = -1; + private $_size = false; /** @var ASF_Object */ private $_parent = null; @@ -89,53 +129,69 @@ class ASF_Object public function __construct($reader, &$options = array()) { $this->_reader = $reader; - $this->_options = $options; - $this->_offset = $this->_reader->getOffset(); - $this->_id = $this->_reader->readGUID(); - $this->_size = $this->_reader->readInt64LE(); + $this->_options = &$options; + + if ($reader === null) { + if (defined($constant = "self::" . strtoupper + (preg_replace + ("/(?<=[a-z])[A-Z]/", "_$0", substr(get_class($this), 11))))) + $this->_identifier = constant($constant); + else { + require_once("ASF/Exception.php"); + throw new ASF_Exception("Object identifier could not be determined"); + } + } else { + $this->_offset = $this->_reader->getOffset(); + $this->_identifier = $this->_reader->readGUID(); + $this->_size = $this->_reader->readInt64LE(); + } } /** - * Returns the file offset to box start, or -1 if the box was created on heap. + * Returns the file offset to object start, or false if the object + * was created on heap. * * @return integer */ - public function getOffset() { return $this->_offset; } + public final function getOffset() { return $this->_offset; } /** - * Sets the file offset where the box starts. + * Sets the file offset where the object starts. * - * @param integer $offset The file offset to box start. + * @param integer $offset The file offset to object start. */ - public function setOffset($offset) { $this->_offset = $offset; } + public final function setOffset($offset) { $this->_offset = $offset; } /** * Returns the GUID of the ASF object. * * @return string */ - public function getIdentifier() { return $this->_id; } + public final function getIdentifier() { return $this->_identifier; } /** * Set the GUID of the ASF object. * * @param string $id The GUID */ - public function setIdentifier($id) { $this->_id = $id; } + public final function setIdentifier($identifier) + { + $this->_identifier = $identifier; + } /** * Returns the object size in bytes, including the header. * * @return integer */ - public function getSize() { return $this->_size; } + public final function getSize() { return $this->_size; } /** - * Sets the box size. The size must include the header. + * Sets the object size. The size must include the 24 byte header. * - * @param integer $size The box size. + * @param integer $size The object size. */ - public function setSize($size) + public final function setSize($size) { if ($this->_parent !== null) $this->_parent->setSize @@ -149,7 +205,7 @@ class ASF_Object * * @return Array */ - public function getOptions() { return $this->_options; } + public final function getOptions() { return $this->_options; } /** * Returns the given option value, or the default value if the option is not @@ -158,7 +214,7 @@ class ASF_Object * @param string $option The name of the option. * @param mixed $defaultValue The default value to be returned. */ - public function getOption($option, $defaultValue = false) + public final function getOption($option, $defaultValue = false) { if (isset($this->_options[$option])) return $this->_options[$option]; @@ -166,11 +222,11 @@ class ASF_Object } /** - * Sets the options array. See {@link ISO14496} class for available options. + * Sets the options array. See {@link ASF} class for available options. * * @param Array $options The options array. */ - public function setOptions(&$options) { $this->_options = $options; } + public final function setOptions(&$options) { $this->_options = &$options; } /** * Sets the given option the given value. @@ -178,24 +234,24 @@ class ASF_Object * @param string $option The name of the option. * @param mixed $value The value to set for the option. */ - public function setOption($option, $value) + public final function setOption($option, $value) { $this->_options[$option] = $value; } /** - * Returns the parent object containing this box. + * Returns the parent object containing this object. * * @return ASF_Object */ - public function getParent() { return $this->_parent; } + public final function getParent() { return $this->_parent; } /** * Sets the parent containing object. * * @param ASF_Object $parent The parent object. */ - public function setParent(&$parent) { $this->_parent = $parent; } + public final function setParent(&$parent) { $this->_parent = $parent; } /** * Magic function so that $obj->value will work. @@ -207,6 +263,9 @@ class ASF_Object { if (method_exists($this, "get" . ucfirst($name))) return call_user_func(array($this, "get" . ucfirst($name))); + if (method_exists($this, "is" . ucfirst($name))) + return call_user_func(array($this, "is" . ucfirst($name))); + require_once("ASF/Exception.php"); throw new ASF_Exception("Unknown field: " . $name); } @@ -221,6 +280,25 @@ class ASF_Object { if (method_exists($this, "set" . ucfirst($name))) call_user_func(array($this, "set" . ucfirst($name)), $value); - else throw new ASF_Exception("Unknown field: " . $name); + else { + require_once("ASF/Exception.php"); + throw new ASF_Exception("Unknown field: " . $name); + } } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public abstract function isMandatory(); + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public abstract function isMultiple(); } diff --git a/src/ASF/Object/AdvancedContentEncryption.php b/src/ASF/Object/AdvancedContentEncryption.php index 55d390b..9a5583d 100644 --- a/src/ASF/Object/AdvancedContentEncryption.php +++ b/src/ASF/Object/AdvancedContentEncryption.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -47,7 +48,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -96,7 +97,9 @@ final class ASF_Object_AdvancedContentEncryption extends ASF_Object * system. * * o streamNumbers -- An array of stream numbers a particular Content - * Encryption Record is associated with. + * Encryption Record is associated with. A value of 0 in this field + * indicates that it applies to the whole file; otherwise, the entry + * applies only to the indicated stream number. * * o data -- The content protection data for this Content Encryption Record. * @@ -106,4 +109,78 @@ final class ASF_Object_AdvancedContentEncryption extends ASF_Object { return $this->_contentEncryptionRecords; } + + /** + * Sets the array of content encryption records. Each record must consist of + * the following keys. + * + * o systemId -- Specifies the unique identifier for the content encryption + * system. + * + * o systemVersion -- Specifies the version of the content encryption + * system. + * + * o streamNumbers -- An array of stream numbers a particular Content + * Encryption Record is associated with. A value of 0 in this field + * indicates that it applies to the whole file; otherwise, the entry + * applies only to the indicated stream number. + * + * o data -- The content protection data for this Content Encryption Record. + * + * @param Array $contentEncryptionRecords The array of content encryption + * records. + */ + public function setContentEncryptionRecords($contentEncryptionRecords) + { + $this->_contentEncryptionRecords = $contentEncryptionRecords; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toUInt16LE + ($contentEncryptionRecordsCount = + count($this->_contentEncryptionRecords)); + for ($i = 0; $i < $contentEncryptionRecordsCount; $i++) { + $data .= + Transform::toGUID($this->_contentEncryptionRecords["systemId"]) . + Transform::toUInt32LE + ($this->_contentEncryptionRecords["systemVersion"]) . + Transform::toUInt16LE + ($encryptedObjectRecordCount = + $this->_contentEncryptionRecords["streamNumbers"]); + for ($j = 0; $j < $encryptedObjectRecordCount; $j++) + $data .= + Transform::toUInt16LE(1) . Transform::toUInt16LE(2) . + Transform::toUInt16LE + ($this->_contentEncryptionRecords["streamNumbers"][$j]); + $data .= strlen($this->_contentEncryptionRecords["data"]) . + $this->_contentEncryptionRecords; + } + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/AdvancedMutualExclusion.php b/src/ASF/Object/AdvancedMutualExclusion.php index 09f1484..8600655 100644 --- a/src/ASF/Object/AdvancedMutualExclusion.php +++ b/src/ASF/Object/AdvancedMutualExclusion.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -52,7 +53,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -75,9 +76,13 @@ final class ASF_Object_AdvancedMutualExclusion extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + + if ($reader === null) + return; + $this->_exclusionType = $this->_reader->readGUID(); $streamNumbersCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $streamNumbersCount; $i++) @@ -91,10 +96,64 @@ final class ASF_Object_AdvancedMutualExclusion extends ASF_Object */ public function getExclusionType() { return $this->_exclusionType; } + /** + * Returns the nature of the mutual exclusion relationship. + * + * @return string + */ + public function setExclusionType($exclusionType) + { + $this->_exclusionType = $exclusionType; + } + /** * Returns an array of stream numbers. * * @return Array */ public function getStreamNumbers() { return $this->_streamNumbers; } + + /** + * Sets the array of stream numbers. + * + * @return Array + */ + public function setStreamNumbers($streamNumbers) + { + $this->_streamNumbers = $streamNumbers; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_exclusionType) . + Transform::toUInt16LE($streamNumbersCount = count($this->_streamNumbers)); + for ($i = 0; $i < $streamNumbersCount; $i++) + $data .= Transform::toUInt16LE($this->_streamNumbers[$i]); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/BandwidthSharing.php b/src/ASF/Object/BandwidthSharing.php index 3ef4aab..959cd3a 100644 --- a/src/ASF/Object/BandwidthSharing.php +++ b/src/ASF/Object/BandwidthSharing.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +30,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -49,7 +49,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -79,7 +79,10 @@ final class ASF_Object_BandwidthSharing extends ASF_Object */ public function __construct($reader, &$options = array()) { - parent::__construct($reader, $options); + parent::__construct($reader = null, $options); + + if ($reader === null) + return; $this->_sharingType = $this->_reader->readGUID(); $this->_dataBitrate = $this->_reader->readUInt32LE(); @@ -100,6 +103,20 @@ final class ASF_Object_BandwidthSharing extends ASF_Object */ public function getSharingType() { return $this->_sharingType; } + /** + * Sets the type of sharing relationship for this object. Two types are + * predefined: SHARING_PARTIAL, in which any number of the streams in the + * relationship may be streaming data at any given time; and + * SHARING_EXCLUSIVE, in which only one of the streams in the relationship + * may be streaming data at any given time. + * + * @return string + */ + public function setSharingType($sharingType) + { + $this->_sharingType = $sharingType; + } + /** * Returns the leak rate R, in bits per second, of a leaky bucket that * contains the data portion of all of the streams, excluding all ASF Data @@ -113,6 +130,22 @@ final class ASF_Object_BandwidthSharing extends ASF_Object */ public function getDataBitrate() { return $this->_dataBitrate; } + /** + * Sets the leak rate R, in bits per second, of a leaky bucket that contains + * the data portion of all of the streams, excluding all ASF Data Packet + * overhead, without overflowing. The size of the leaky bucket is specified by + * the value of the Buffer Size field. This value can be less than the sum of + * all of the data bit rates in the + * {@link ASF_Object_ExtendedStreamProperties Extended Stream Properties} + * Objects for the streams contained in this bandwidth-sharing relationship. + * + * @param integer $dataBitrate The data bitrate. + */ + public function setDataBitrate($dataBitrate) + { + $this->_dataBitrate = $dataBitrate; + } + /** * Specifies the size B, in bits, of the leaky bucket used in the Data Bitrate * definition. This value can be less than the sum of all of the buffer sizes @@ -124,10 +157,70 @@ final class ASF_Object_BandwidthSharing extends ASF_Object */ public function getBufferSize() { return $this->_bufferSize; } + /** + * Sets the size B, in bits, of the leaky bucket used in the Data Bitrate + * definition. This value can be less than the sum of all of the buffer sizes + * in the {@link ASF_Object_ExtendedStreamProperties Extended Stream + * Properties} Objects for the streams contained in this bandwidth-sharing + * relationship. + * + * @param integer $bufferSize The buffer size. + */ + public function setBufferSize($bufferSize) + { + $this->_bufferSize = $bufferSize; + } + /** * Returns an array of stream numbers. * * @return Array */ public function getStreamNumbers() { return $this->_streamNumbers; } + + /** + * Sets the array of stream numbers. + * + * @param Array $streamNumbers The array of stream numbers. + */ + public function setStreamNumbers($streamNumbers) + { + $this->_streamNumbers = $streamNumbers; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_sharingType) . + Transform::toUInt32LE($this->_dataBitrate) . + Transform::toUInt32LE($this->_bufferSize) . + Transform::toUInt16LE($streamNumbersCount = count($this->_streamNumber)); + for ($i = 0; $i < $streamNumbersCount; $i++) + $data .= Transform::toUInt16LE($this->_streamNumbers[$i]); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/BitrateMutualExclusion.php b/src/ASF/Object/BitrateMutualExclusion.php index 41fe13c..dbb321b 100644 --- a/src/ASF/Object/BitrateMutualExclusion.php +++ b/src/ASF/Object/BitrateMutualExclusion.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -52,7 +53,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -75,9 +76,13 @@ final class ASF_Object_BitrateMutualExclusion extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + + if ($reader === null) + return; + $this->_exclusionType = $this->_reader->readGUID(); $streamNumbersCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $streamNumbersCount; $i++) @@ -91,10 +96,65 @@ final class ASF_Object_BitrateMutualExclusion extends ASF_Object */ public function getExclusionType() { return $this->_exclusionType; } + /** + * Sets the nature of the mutual exclusion relationship. + * + * @param string $exclusionType The nature of the mutual exclusion + * relationship. + */ + public function setExclusionType($exclusionType) + { + $this->_exclusionType = $exclusionType; + } + /** * Returns an array of stream numbers. * * @return Array */ public function getStreamNumbers() { return $this->_streamNumbers; } + + /** + * Sets the array of stream numbers. + * + * @param Array $streamNumbers The array of stream numbers. + */ + public function setStreamNumbers($streamNumbers) + { + $this->_streamNumbers = $streamNumbers; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_exclusionType) . + Transform::toUInt16LE($streamNumbersCount = count($this->_streamNumbers)); + for ($i = 0; $i < $streamNumbersCount; $i++) + $data .= Transform::toUInt16LE($this->_streamNumbers[$i]); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/CodecList.php b/src/ASF/Object/CodecList.php index 5227474..3228bfd 100644 --- a/src/ASF/Object/CodecList.php +++ b/src/ASF/Object/CodecList.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -46,7 +47,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -56,6 +57,9 @@ final class ASF_Object_CodecList extends ASF_Object const AUDIO_CODEC = 0x2; const UNKNOWN_CODEC = 0xffff; + /** @var string */ + private $_reserved; + /** @var Array */ private $_entries = array(); @@ -66,11 +70,14 @@ final class ASF_Object_CodecList extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - $this->_reader->skip(16); + if ($reader === null) + return; + + $this->_reserved = $this->_reader->readGUID(); $codecEntriesCount = $this->_reader->readUInt32LE(); for ($i = 0; $i < $codecEntriesCount; $i++) { $entry = array("type" => $this->_reader->readUInt16LE()); @@ -90,9 +97,85 @@ final class ASF_Object_CodecList extends ASF_Object } /** - * Returns the array of codec entries. + * Returns the array of codec entries. Each record consists of the following + * keys. + * + * o type -- Specifies the type of the codec used. Use one of the following + * values: VIDEO_CODEC, AUDIO_CODEC, or UNKNOWN_CODEC. + * + * o codecName -- Specifies the name of the codec used to create the + * content. * + * o codecDescription -- Specifies the description of the format used to + * create the content. + * + * o codecInformation -- Specifies an opaque array of information bytes + * about the codec used to create the content. The meaning of these bytes + * is determined by the codec. + * * @return Array */ public function getEntries() { return $this->_entries; } + + /** + * Sets the array of codec entries. Each record must consist of the following + * keys. + * + * o codecName -- Specifies the name of the codec used to create the + * content. + * + * o codecDescription -- Specifies the description of the format used to + * create the content. + * + * o codecInformation -- Specifies an opaque array of information bytes + * about the codec used to create the content. The meaning of these bytes + * is determined by the codec. + * + * @param Array $entries The array of codec entries. + */ + public function setEntries($entries) { $this->_entries = $entries; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toGUID($this->_reserved) . + Transform::toUInt32LE($codecEntriesCount = count($this->_entries)); + for ($i = 0; $i < $codecEntriesCount; $i++) { + $data .= Transform::toUInt16LE($this->_entries[$i]["type"]) . + Transform::toUInt16LE(strlen($codecName = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_entries[$i]["codecName"]) . "\0\0") / 2) . + Transform::toString16LE($codecName) . + Transform::toUInt16LE(strlen($codecDescription = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_entries[$i]["codecDescription"]) . "\0\0") / 2) . + Transform::toString16LE($codecDescription) . + Transform::toUInt16LE(strlen($this->_entries[$i]["codecInformation"])) . + $this->_entries[$i]["codecInformation"]; + } + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Compatibility.php b/src/ASF/Object/Compatibility.php index c7ea0e4..6e71a5f 100644 --- a/src/ASF/Object/Compatibility.php +++ b/src/ASF/Object/Compatibility.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -45,7 +46,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -64,10 +65,13 @@ final class ASF_Object_Compatibility extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + + if ($reader === null) + return; + $this->_profile = $this->_reader->readUInt8(); $this->_mode = $this->_reader->readUInt8(); } @@ -79,10 +83,56 @@ final class ASF_Object_Compatibility extends ASF_Object */ public function getProfile() { return $this->_profile; } + /** + * Returns the profile field. This field is reserved and is set to 2. + * + * @param integer $profile The profile. + */ + public function setProfile($profile) { $this->_profile = $profile; } + /** * Returns the mode field. This field is reserved and is set to 1. * * @return integer */ public function getMode() { return $this->_mode; } + + /** + * Sets the mode field. This field is reserved and is set to 1. + * + * @param integer $mode The mode. + */ + public function setMode($mode) { $this->_mode = $mode; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toUInt8($this->_profile) . + Transform::toUInt8($this->_mode); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Container.php b/src/ASF/Object/Container.php index fa421a3..81f424c 100644 --- a/src/ASF/Object/Container.php +++ b/src/ASF/Object/Container.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,13 +31,14 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ /**#@+ @ignore */ require_once("ASF/Object.php"); +require_once("ASF/Object/Unknown.php"); /**#@-*/ /** @@ -45,7 +47,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -57,7 +59,7 @@ abstract class ASF_Object_Container extends ASF_Object /** * Reads and constructs the objects found within this object. */ - protected function constructObjects($defaultclassnames = array()) + protected final function constructObjects($defaultclassnames = array()) { while (true) { $offset = $this->_reader->getOffset(); @@ -75,9 +77,9 @@ abstract class ASF_Object_Container extends ASF_Object ($classname = "ASF_Object_" . $defaultclassnames[$guid])) $object = new $classname($this->_reader, $this->_options); else - $object = new ASF_Object($this->_reader, $this->_options); + $object = new ASF_Object_Unknown($this->_reader, $this->_options); } else - $object = new ASF_Object($this->_reader, $this->_options); + $object = new ASF_Object_Unknown($this->_reader, $this->_options); $object->setParent($this); if (!$this->hasObject($object->getIdentifier())) $this->_objects[$object->getIdentifier()] = array(); @@ -87,15 +89,26 @@ abstract class ASF_Object_Container extends ASF_Object } /** - * Checks whether the object with given GUID is present in the file. Returns - * true if one or more objects are present, false - * otherwise. + * Checks whether the object with given identifier is present in the file. The + * identifier can either be the object GUID, or name of the constant + * containing the GUID, or the name of the object class. * + * Returns true if one or more objects are present, + * false otherwise. + * + * @param string $identifier The object GUID, name of the GUID constant, or + * object class name. * @return boolean */ - public function hasObject($identifier) + public final function hasObject($identifier) { - return isset($this->_objects[$identifier]); + if (defined($constname = get_class($this) . "::" . strtoupper + (preg_replace("/[A-Z]/", "_$0", $identifier)))) { + $objects = $this->getObjectsByIdentifier(constant($constname)); + return isset($objects[0]); + } + else + return isset($this->_objects[$identifier]); } /** @@ -105,10 +118,7 @@ abstract class ASF_Object_Container extends ASF_Object * * @return Array */ - public function getObjects() - { - return $this->_objects; - } + public final function getObjects() { return $this->_objects; } /** * Returns an array of objects matching the given object GUID or an empty @@ -117,14 +127,11 @@ abstract class ASF_Object_Container extends ASF_Object * 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 object GUID. * @return Array */ - public function getObjectsByIdentifier($identifier) + public final function getObjectsByIdentifier($identifier) { $matches = array(); $searchPattern = "/^" . @@ -136,13 +143,81 @@ abstract class ASF_Object_Container extends ASF_Object return $matches; } + /** + * Returns an array of objects matching the given object constant name or an + * empty array if no object matched the name. + * + * The object constant name can be given in three forms; either using the full + * name of the constant, the name of the class or the shorthand style of the + * class name having its first letter in lower case. + * + * One may use the shorthand $obj->name to access the first box with the name + * given directly. Shorthands will not work with user defined uuid types. + * + * The name may not contain wildcard characters. + * + * @param string $name The object constant name or class name. + * @return Array + */ + public final function getObjectsByName($name) + { + if (defined($constname = get_class($this) . "::" . $name) || + defined($constname = get_class($this) . "::" . strtoupper + (preg_replace + ("/^_/", "", preg_replace("/[A-Z]/", "_$0", $name))))) + return $this->getObjectsByIdentifier(constant($constname)); + return array(); + } + + /** + * Removes any objects matching the given object GUID. + * + * 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->name) to achieve the same + * result. Wildcards cannot be used with the shorthand method. + * + * @param string $identifier The object GUID. + */ + public final function removeObjectsByIdentifier($identifier) + { + $searchPattern = "/^" . + str_replace(array("*", "?"), array(".*", "."), $identifier) . "$/i"; + foreach ($this->_objects as $identifier => $objects) + if (preg_match($searchPattern, $identifier)) + unset($this->_objects[$identifier]); + } + + /** + * Removes any objects matching the given object name. + * + * The name can be given in three forms; either using the full name of the + * constant, the name of the class or the shorthand style of the class name + * having its first letter in lower case. + * + * One may also use the shorthand unset($obj->name) to achieve the same + * result. + * + * The name may not contain wildcard characters. + * + * @param string $name The object constant name or class name. + */ + public final function removeObjectsByName($name) + { + if (defined($constname = get_class($this) . "::" . strtoupper + (preg_replace("/[A-Z]/", "_$0", $name)))) + unset($this->_objects[constant($constname)]); + } + /** * Adds a new object into the current object and returns it. * - * @param ASF_Object The object to add + * @param ASF_Object $object The object to add * @return ASF_Object */ - public function addObject($object) + public final function addObject($object) { $object->setParent($this); $object->setOptions($this->_options); @@ -151,6 +226,20 @@ abstract class ASF_Object_Container extends ASF_Object return $this->_objects[$object->getIdentifier()][] = $object; } + /** + * Removes the object. + * + * @param ASF_Object $object The object to remove + */ + public final function removeObject($object) + { + if ($this->hasObject($object->getIdentifier())) { + foreach ($this->_objects[$object->getIdentifier()] as $key => $value) + if ($object === $value) + unset($this->_objects[$object->getIdentifier()][$key]); + } + } + /** * Override magic function so that $obj->value will work as expected. * @@ -158,6 +247,8 @@ abstract class ASF_Object_Container extends ASF_Object * field with given name is found, the method attempts to return the right * object instead. In other words, calling $obj->value will attempt to return * the first object returned by $this->getObjectsByIdentifier(self::value). + * If no object is found by the given value, a respective class name is tried + * to instantiate and add to the container. * * @param string $name The field or object name. * @return mixed @@ -166,30 +257,74 @@ abstract class ASF_Object_Container extends ASF_Object { if (method_exists($this, "get" . ucfirst($name))) return call_user_func(array($this, "get" . ucfirst($name))); + if (method_exists($this, "is" . ucfirst($name))) + return call_user_func(array($this, "is" . ucfirst($name))); if (defined($constname = get_class($this) . "::" . strtoupper (preg_replace("/[A-Z]/", "_$0", $name)))) { $objects = $this->getObjectsByIdentifier(constant($constname)); if (isset($objects[0])) return $objects[0]; + else { + if (@fopen($filename = "ASF/Object/" . ucfirst($name) . + ".php", "r", true) !== false) + require_once($filename); + if (class_exists + ($classname = "ASF_Object_" . ucfirst($name))) { + $obj = new $classname(); + $obj->setIdentifier(constant($constname)); + return $this->addObject($obj); + } + } } + require_once("ASF/Exception.php"); throw new ASF_Exception("Unknown field/object: " . $name); } /** - * Magic function so that isset($obj->value) will work. This method checks - * whether the object by given identifier is contained by this container. + * Override magic function so that $obj->value will work as expected. + * + * The method first attempts to call the appropriate setter method. If no + * field with given name is found, the method attempts to set the right + * object instead. In other words, assigning to $obj->value will attempt to + * set the object with given value's identifier. + * + * Please note that using this method will override any prior objects having + * the same object identifier. * - * @param string $name The object name. - * @return boolean + * @param string $name The field or object name. + * @param string $value The field value or object. + * @return mixed */ - public function __isset($name) + public function __set($name, $value) { + if (method_exists($this, "set" . ucfirst($name))) + call_user_func(array($this, "set" . ucfirst($name)), $value); if (defined($constname = get_class($this) . "::" . strtoupper (preg_replace("/[A-Z]/", "_$0", $name)))) { - $objects = $this->getObjectsByIdentifier(constant($constname)); - return isset($objects[0]); + $value->setOptions($this->_options); + $this->_objects[constant($constname)] = array($value); + } + else { + require_once("ASF/Exception.php"); + throw new ASF_Exception("Unknown field/object: " . $name); } - else - return isset($this->_objects[$name]); } + + /** + * Magic function so that isset($obj->value) will work. This method checks + * whether the object by given identifier or name is contained by this + * container. + * + * @param string $name The object identifier or logical name. + * @return boolean + */ + public function __isset($name) { return $this->hasObject($name); } + + /** + * Magic function so that unset($obj->value) will work. This method removes + * all the objects with the given identifier or name. + * + * @param string $name The object identifier or logical name. + */ + public function __unset($name) { $this->removeObjectsByName($name); } } diff --git a/src/ASF/Object/ContentBranding.php b/src/ASF/Object/ContentBranding.php index 8b3e13f..9c372f9 100644 --- a/src/ASF/Object/ContentBranding.php +++ b/src/ASF/Object/ContentBranding.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -47,7 +48,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -110,6 +111,21 @@ final class ASF_Object_ContentBranding extends ASF_Object */ public function getBannerImageType() { return $this->_bannerImageType; } + /** + * Sets the type of data contained in the Banner Image Data. Valid + * values are 0 to indicate that there is no banner image data; 1 to indicate + * that the data represent a bitmap; 2 to indicate that the data represents a + * JPEG; and 3 to indicate that the data represents a GIF. If this value is + * set to 0, then the Banner Image Data Size field is set to 0, and the + * Banner Image Data field is empty. + * + * @param integer $bannerImageType The type of data. + */ + public function setBannerImageType($bannerImageType) + { + $this->_bannerImageType = $bannerImageType; + } + /** * Returns the entire banner image, including the header for the appropriate * image format. @@ -118,6 +134,17 @@ final class ASF_Object_ContentBranding extends ASF_Object */ public function getBannerImageData() { return $this->_bannerImageData; } + /** + * Sets the entire banner image, including the header for the appropriate + * image format. + * + * @param string $bannerImageData The entire banner image. + */ + public function setBannerImageData($bannerImageData) + { + $this->_bannerImageData = $bannerImageData; + } + /** * Returns, if present, a link to more information about the banner image. * @@ -125,6 +152,16 @@ final class ASF_Object_ContentBranding extends ASF_Object */ public function getBannerImageUrl() { return $this->_bannerImageUrl; } + /** + * Sets a link to more information about the banner image. + * + * @param string $bannerImageUrl The link. + */ + public function setBannerImageUrl($bannerImageUrl) + { + $this->_bannerImageUrl = $bannerImageUrl; + } + /** * Returns, if present, a link to more information about the copyright for the * content. @@ -132,4 +169,51 @@ final class ASF_Object_ContentBranding extends ASF_Object * @return string */ public function getCopyrightUrl() { return $this->_copyrightUrl; } + + /** + * Sets a link to more information about the copyright for the content. + * + * @param string $copyrightUrl The copyright link. + */ + public function setCopyrightUrl($copyrightUrl) + { + $this->_copyrightUrl = $copyrightUrl; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toUInt32LE($this->_bannerImageType) . + Transform::toUInt32LE(count($this->_bannerImageData)) . + $this->_bannerImageData . + Transform::toUInt32LE(count($this->_bannerImageUrl)) . + $this->_bannerImageUrl . + Transform::toUInt32LE(count($this->_copyrightUrl)) . + $this->_copyrightUrl; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ContentDescription.php b/src/ASF/Object/ContentDescription.php index cfa4a3e..94ade54 100644 --- a/src/ASF/Object/ContentDescription.php +++ b/src/ASF/Object/ContentDescription.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -49,7 +49,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -77,10 +77,13 @@ final class ASF_Object_ContentDescription extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + + if ($reader === null) + return; + $titleLen = $this->_reader->readUInt16LE(); $authorLen = $this->_reader->readUInt16LE(); $copyrightLen = $this->_reader->readUInt16LE(); @@ -103,39 +106,133 @@ final class ASF_Object_ContentDescription extends ASF_Object ("utf-16le", $this->getOption("encoding"), $this->_reader->readString16LE($ratingLen)); } - + /** * Returns the title information. * * @return string */ public function getTitle() { return $this->_title; } - + + /** + * Sets the title information. + * + * @param string $title The title information. + */ + public function setTitle($title) { $this->_title = $title; } + /** * Returns the author information. * * @return string */ public function getAuthor() { return $this->_author; } - + + /** + * Sets the author information. + * + * @param string $author The author information. + */ + public function setAuthor($author) { $this->_author = $author; } + /** * Returns the copyright information. * * @return string */ public function getCopyright() { return $this->_copyright; } - + + /** + * Sets the copyright information. + * + * @param string $copyright The copyright information. + */ + public function setCopyright($copyright) { $this->_copyright = $copyright; } + /** * Returns the description information. * * @return string */ public function getDescription() { return $this->_description; } - + + /** + * Sets the description information. + * + * @param string $description The description information. + */ + public function setDescription($description) + { + $this->_description = $description; + } + /** * Returns the rating information. * * @return string */ public function getRating() { return $this->_rating; } + + /** + * Sets the rating information. + * + * @param string $rating The rating information. + */ + public function setRating($rating) { $this->_rating = $rating; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $title = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_title ? $this->_title . "\0" : ""); + $author = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_author ? $this->_author . "\0" : ""); + $copyright = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_copyright ? $this->_copyright . "\0" : ""); + $description = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_description ? $this->_description . "\0" : ""); + $rating = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_rating ? $this->_rating . "\0" : ""); + + $data = + Transform::toUInt16LE(strlen($title)) . + Transform::toUInt16LE(strlen($author)) . + Transform::toUInt16LE(strlen($copyright)) . + Transform::toUInt16LE(strlen($description)) . + Transform::toUInt16LE(strlen($rating)) . + Transform::toString16LE($title) . + Transform::toString16LE($author) . + Transform::toString16LE($copyright) . + Transform::toString16LE($description) . + Transform::toString16LE($rating); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ContentEncryption.php b/src/ASF/Object/ContentEncryption.php index 466f449..0773ff7 100644 --- a/src/ASF/Object/ContentEncryption.php +++ b/src/ASF/Object/ContentEncryption.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -46,7 +47,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -71,10 +72,13 @@ final class ASF_Object_ContentEncryption extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $secretDataLength = $this->_reader->readUInt32LE(); $this->_secretData = $this->_reader->read($secretDataLength); $protectionTypeLength = $this->_reader->readUInt32LE(); @@ -92,6 +96,16 @@ final class ASF_Object_ContentEncryption extends ASF_Object */ public function getSecretData() { return $this->_secretData; } + /** + * Sets the secret data. + * + * @param string $secretData The secret data. + */ + public function setSecretData($secretData) + { + $this->_secretData = $secretData; + } + /** * Returns the type of protection mechanism used. The value of this field * is set to "DRM". @@ -100,6 +114,17 @@ final class ASF_Object_ContentEncryption extends ASF_Object */ public function getProtectionType() { return $this->_protectionType; } + /** + * Sets the type of protection mechanism used. The value of this field + * is to be set to "DRM". + * + * @param string $protectionType The protection mechanism used. + */ + public function setProtectionType($protectionType) + { + $this->_protectionType = $protectionType; + } + /** * Returns the key ID used. * @@ -107,6 +132,13 @@ final class ASF_Object_ContentEncryption extends ASF_Object */ public function getKeyId() { return $this->_keyId; } + /** + * Sets the key ID used. + * + * @param string $keyId The key ID used. + */ + public function setKeyId($keyId) { $this->_keyId = $keyId; } + /** * Returns the URL from which a license to manipulate the content can be * acquired. @@ -114,4 +146,53 @@ final class ASF_Object_ContentEncryption extends ASF_Object * @return string */ public function getLicenseUrl() { return $this->_licenseUrl; } + + /** + * Returns the URL from which a license to manipulate the content can be + * acquired. + * + * @param string $licenseUrl The URL from which a license can be acquired. + */ + public function setLicenseUrl($licenseUrl) + { + $this->_licenseUrl = $licenseUrl; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toUInt32LE(strlen($this->_secretData)) . + $this->_secretData . + Transform::toUInt32LE($len = strlen($this->_protectionType) + 1) . + Transform::toString8($this->_protectionType, $len) . + Transform::toUInt32LE($len = strlen($this->_keyId) + 1) . + Transform::toString8($this->_keyId, $len) . + Transform::toUInt32LE($len = strlen($this->_licenseUrl) + 1) . + Transform::toString8($this->_licenseUrl, $len); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Data.php b/src/ASF/Object/Data.php index 466efa7..058310f 100644 --- a/src/ASF/Object/Data.php +++ b/src/ASF/Object/Data.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -57,7 +58,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -86,10 +87,9 @@ final class ASF_Object_Data extends ASF_Object $this->_fileId = $this->_reader->readGUID(); $this->_totalDataPackets = $this->_reader->readInt64LE(); $this->_reader->skip(2); - /* Data packets are not supported - * for ($i = 0; $i < $this->_totalDataPackets; $i++) { + /* Support for Data Packets is not done yet + * for ($i = 0; $i < $this->_totalDataPackets; $i++) * $this->_dataPackets[] = new ASF_Object_Data_Packet($reader); - * } */ } @@ -120,6 +120,23 @@ final class ASF_Object_Data extends ASF_Object */ public function getDataPackets() { - throw new ASF_Exception("Data packets are not supported."); + require_once("ASF/Exception.php"); + throw new ASF_Exception("Support for Data Packets is not done yet"); } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } } diff --git a/src/ASF/Object/DigitalSignature.php b/src/ASF/Object/DigitalSignature.php index 25ab068..600f096 100644 --- a/src/ASF/Object/DigitalSignature.php +++ b/src/ASF/Object/DigitalSignature.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -47,17 +48,17 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_DigitalSignature extends ASF_Object { /** @var integer */ - private $_signatureType; + private $_type; /** @var string */ - private $_signatureData; + private $_data; /** * Constructs the class with given parameters and reads object related data @@ -66,13 +67,16 @@ final class ASF_Object_DigitalSignature extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - $this->_signatureType = $this->_reader->readUInt32LE(); - $signatureDataLength = $this->_reader->readUInt32LE(); - $this->_signatureData = $this->_reader->read($signatureDataLength); + if ($reader === null) + return; + + $this->_type = $this->_reader->readUInt32LE(); + $dataLength = $this->_reader->readUInt32LE(); + $this->_data = $this->_reader->read($dataLength); } /** @@ -80,12 +84,58 @@ final class ASF_Object_DigitalSignature extends ASF_Object * * @return integer */ - public function getSignatureType() { return $this->_signatureType; } + public function getType() { return $this->_type; } + + /** + * Sets the type of digital signature used. This field must be set to 2. + * + * @param integer $type The type of digital signature used. + */ + public function setType($type) { $this->_type = $type; } /** * Returns the digital signature data. * * @return string */ - public function getSignatureData() { return $this->_signatureData; } + public function getData() { return $this->_data; } + + /** + * Sets the digital signature data. + * + * @return string + */ + public function setData($data) { $this->_data = $data; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toUInt32LE($this->_type) . + Transform::toUInt32LE(strlen($this->_data)) . $this->_data; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ErrorCorrection.php b/src/ASF/Object/ErrorCorrection.php index 6a943df..6beecd9 100644 --- a/src/ASF/Object/ErrorCorrection.php +++ b/src/ASF/Object/ErrorCorrection.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -54,7 +55,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -73,10 +74,13 @@ final class ASF_Object_ErrorCorrection extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $this->_type = $this->_reader->readGUID(); $dataLength = $this->_reader->readUInt32LE(); $this->_data = $this->_reader->read($dataLength); @@ -89,6 +93,13 @@ final class ASF_Object_ErrorCorrection extends ASF_Object */ public function getType() { return $this->_type; } + /** + * Sets the type of error correction. + * + * @param string $type The type of error correction. + */ + public function setType($type) { $this->_type = $type; } + /** * Returns the data specific to the error correction scheme. The structure for * the Error Correction Data field is determined by the value stored in @@ -97,4 +108,45 @@ final class ASF_Object_ErrorCorrection extends ASF_Object * @return Array */ public function getData() { return $this->_data; } + + /** + * Sets the data specific to the error correction scheme. The structure for + * the Error Correction Data field is determined by the value stored in + * the Error Correction Type field. + * + * @param Array $data The error correction specific data. + */ + public function setData($data) { $this->_data = $data; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_type) . + Transform::toUInt32LE(strlen($this->_data)) . $this->_data; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ExtendedContentDescription.php b/src/ASF/Object/ExtendedContentDescription.php index 72eb5fc..625af54 100644 --- a/src/ASF/Object/ExtendedContentDescription.php +++ b/src/ASF/Object/ExtendedContentDescription.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -48,7 +48,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -64,10 +64,13 @@ final class ASF_Object_ExtendedContentDescription extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + + if ($reader === null) + return; + $contentDescriptorsCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $contentDescriptorsCount; $i++) { $nameLen = $this->_reader->readUInt16LE(); @@ -76,14 +79,20 @@ final class ASF_Object_ExtendedContentDescription extends ASF_Object $this->_reader->readString16LE($nameLen)); $valueDataType = $this->_reader->readUInt16LE(); $valueLen = $this->_reader->readUInt16LE(); + switch ($valueDataType) { - case 0: - case 1: // string + case 0: // string $this->_contentDescriptors[$name] = iconv ("utf-16le", $this->getOption("encoding"), $this->_reader->readString16LE($valueLen)); break; + case 1: // byte array + $this->_contentDescriptors[$name] = $this->_reader->read($valueLen); + break; case 2: // bool + $this->_contentDescriptors[$name] = + $this->_reader->readUInt32LE() == 1 ? true : false; + break; case 3: // 32-bit integer $this->_contentDescriptors[$name] = $this->_reader->readUInt32LE(); break; @@ -111,6 +120,18 @@ final class ASF_Object_ExtendedContentDescription extends ASF_Object return $this->_contentDescriptors[$name]; return false; } + + /** + * Sets the given descriptor a new value. + * + * @param string $name The name of the descriptor. + * @param string $value The value of the field. + * @return string|false + */ + public function setDescriptor($name, $value) + { + $this->_contentDescriptors[$name] = $value; + } /** * Returns an associate array of all the descriptors defined having the names @@ -119,4 +140,91 @@ final class ASF_Object_ExtendedContentDescription extends ASF_Object * @return Array */ public function getDescriptors() { return $this->_contentDescriptors; } + + /** + * Sets the content descriptor associate array having the descriptor names as + * array keys and their values as associated value. The descriptor names and + * all string values must be encoded in the default character encoding given + * as an option to {@link ASF} class. + * + * @param Array $contentDescriptors The content descriptors + */ + public function setDescriptors($contentDescriptors) + { + $this->_contentDescriptors = $contentDescriptors; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE(count($this->_contentDescriptors)); + + foreach ($this->_contentDescriptors as $name => $value) { + $descriptor = iconv + ($this->getOption("encoding"), "utf-16le", $name ? $name . "\0" : ""); + $data .= Transform::toUInt16LE(strlen($descriptor)) . + Transform::toString16LE($descriptor); + + if (is_string($value)) { + /* There is no way to distinguish byte arrays from unicode strings and + * hence the need for a list of fields of type byte array */ + static $byteArray = array ( + "W\0M\0/\0M\0C\0D\0I\0\0\0", + "W\0M\0/\0U\0s\0e\0r\0W\0e\0b\0U\0R\0L\0\0\0", + "W\0M\0/\0L\0y\0r\0i\0c\0s\0_\0S\0y\0n\0c\0h\0r\0o\0n\0i\0s\0e\0d\0\0\0", + "W\0M\0/\0P\0i\0c\0t\0u\0r\0e\0\0\0" + ); // TODO: Add to the list if you encounter one + + if (in_array($descriptor, $byteArray)) + $data .= Transform::toUInt16LE(1) . + Transform::toUInt16LE(strlen($value)) . $value; + else { + $value = iconv + ($this->getOption("encoding"), "utf-16le", $value) . "\0\0"; + $data .= Transform::toUInt16LE(0) . + Transform::toUInt16LE(strlen($value)) . + Transform::toString16LE($value); + } + } + else if (is_bool($value)) + $data .= Transform::toUInt16LE(2) . Transform::toUInt16LE(4) . + Transform::toUInt32LE($value ? 1 : 0); + else if (is_int($value)) + $data .= Transform::toUInt16LE(3) . Transform::toUInt16LE(4) . + Transform::toUInt32LE($value); + else if (is_float($value)) + $data .= Transform::toUInt16LE(4) . Transform::toUInt16LE(8) . + Transform::toInt64LE($value); + else { + // Invalid value and there is nothing to be done so cause a fatal error + require_once("ASF/Exception.php"); + throw new ASF_Exception("Invalid data type"); + } + } + + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ExtendedContentEncryption.php b/src/ASF/Object/ExtendedContentEncryption.php index 6d2e7ad..7f7580c 100644 --- a/src/ASF/Object/ExtendedContentEncryption.php +++ b/src/ASF/Object/ExtendedContentEncryption.php @@ -62,10 +62,13 @@ final class ASF_Object_ExtendedContentEncryption extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $dataSize = $this->_reader->readUInt32LE(); $this->_data = $this->_reader->read($dataSize); } @@ -77,4 +80,42 @@ final class ASF_Object_ExtendedContentEncryption extends ASF_Object * @return string */ public function getData() { return $this->_data; } + + /** + * Sets the array of bytes required by the DRM client to manipulate the + * protected content. + * + * @param string $data The data. + */ + public function setData($data) { $this->_data = $data; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt32LE(strlen($this->_data)) . $this->_data; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/ExtendedStreamProperties.php b/src/ASF/Object/ExtendedStreamProperties.php index 733fbd4..17770e5 100644 --- a/src/ASF/Object/ExtendedStreamProperties.php +++ b/src/ASF/Object/ExtendedStreamProperties.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -62,7 +63,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -178,10 +179,13 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + + if ($reader === null) + return; + $this->_startTime = $this->_reader->readInt64LE(); $this->_endTime = $this->_reader->readInt64LE(); $this->_dataBitrate = $this->_reader->readUInt32LE(); @@ -229,6 +233,19 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object */ public function getStartTime() { return $this->_startTime; } + /** + * Sets the presentation time of the first object, indicating where this + * digital media stream starts within the context of the timeline of the ASF + * file as a whole. This time value corresponds to presentation times as they + * appear in the data packets (adjusted by the preroll). + * + * The given value must be in units of milliseconds or optionally be set to 0, + * in which case the field will be ignored. + * + * @param integer $startTime The presentation time of the first object. + */ + public function setStartTime($startTime) { $this->_startTime = $startTime; } + /** * Returns the presentation time of the last object plus the duration of play, * indicating where this digital media stream ends within the context of the @@ -241,6 +258,21 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object */ public function getEndTime() { return $this->_endTime; } + /** + * Sets the presentation time of the last object plus the duration of play, + * indicating where this digital media stream ends within the context of the + * timeline of the ASF file as a whole. This time value corresponds to + * presentation times as they appear in the data packets (adjusted by the + * preroll). + * + * The given value must be given in units of milliseconds or optionally be set + * to 0, in which case the field will be ignored. + * + * @param integer $endTime The presentation time of the last object plus the + * duration of play. + */ + public function setEndTime($endTime) { $this->_endTime = $endTime; } + /** * Returns the leak rate R, in bits per second, of a leaky bucket that * contains the data portion of the stream without overflowing, excluding all @@ -251,6 +283,21 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object */ public function getDataBitrate() { return $this->_dataBitrate; } + /** + * Sets the leak rate R, in bits per second, of a leaky bucket that + * contains the data portion of the stream without overflowing, excluding all + * ASF Data Packet overhead. The size of the leaky bucket is specified by the + * value of the Buffer Size field. + * + * This field must be given a non-zero value. + * + * @param integer $dataBitrate The leak rate. + */ + public function setDataBitrate($dataBitrate) + { + $this->_dataBitrate = $dataBitrate; + } + /** * Returns the size B, in milliseconds, of the leaky bucket used in the * Data Bitrate definition. @@ -259,6 +306,17 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object */ public function getBufferSize() { return $this->_bufferSize; } + /** + * Sets the size B, in milliseconds, of the leaky bucket used in the + * Data Bitrate definition. + * + * @param integer $bufferSize The size. + */ + public function setBufferSize($bufferSize) + { + $this->_bufferSize = $bufferSize; + } + /** * Returns the initial fullness, in milliseconds, of the leaky bucket used in * the Data Bitrate definition. This is the fullness of the buffer at @@ -273,6 +331,20 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_initialBufferFullness; } + /** + * Sets the initial fullness, in milliseconds, of the leaky bucket used in the + * Data Bitrate definition. This is the fullness of the buffer at the + * instant before the first bit in the stream is dumped into the bucket. + * Typically, this value is set to 0. This value shall not exceed the value in + * the Buffer Size field. + * + * @param integer $initialBufferFullness The initial fullness. + */ + public function setInitialBufferFullness($initialBufferFullness) + { + $this->_initialBufferFullness = $initialBufferFullness; + } + /** * Returns the leak rate RAlt, in bits per second, of a leaky bucket that * contains the data portion of the stream without overflowing, excluding all @@ -290,6 +362,23 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_alternateDataBitrate; } + /** + * Sets the leak rate RAlt, in bits per second, of a leaky bucket that + * contains the data portion of the stream without overflowing, excluding all + * ASF Data Packet overhead. The size of the leaky bucket is specified + * by the value of the Alternate Buffer Size field. This value is + * relevant in most scenarios where the bit rate is not exactly constant, but + * it is especially useful for streams that have highly variable bit rates. + * This field can optionally be set to the same value as the Data + * Bitrate field. + * + * @param integer $alternateDataBitrate The alternate leak rate. + */ + public function setAlternateDataBitrate($alternateDataBitrate) + { + $this->_alternateDataBitrate = $alternateDataBitrate; + } + /** * Returns the size BAlt, in milliseconds, of the leaky bucket used in the * Alternate Data Bitrate definition. This value is relevant in most @@ -304,6 +393,20 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_alternateBufferSize; } + /** + * Sets the size BAlt, in milliseconds, of the leaky bucket used in the + * Alternate Data Bitrate definition. This value is relevant in most + * scenarios where the bit rate is not exactly constant, but it is especially + * useful for streams that have highly variable bit rates. This field can + * optionally be set to the same value as the Buffer Size field. + * + * @param integer $alternateBufferSize + */ + public function setAlternateBufferSize($alternateBufferSize) + { + $this->_alternateBufferSize = $alternateBufferSize; + } + /** * Returns the initial fullness, in milliseconds, of the leaky bucket used in * the Alternate Data Bitrate definition. This is the fullness of the @@ -318,6 +421,22 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_alternateInitialBufferFullness; } + /** + * Sets the initial fullness, in milliseconds, of the leaky bucket used in the + * Alternate Data Bitrate definition. This is the fullness of the + * buffer at the instant before the first bit in the stream is dumped into the + * bucket. Typically, this value is set to 0. This value does not exceed the + * value of the Alternate Buffer Size field. + * + * @param integer $alternateInitialBufferFullness The alternate initial + * fullness. + */ + public function setAlternateInitialBufferFullness + ($alternateInitialBufferFullness) + { + $this->_alternateInitialBufferFullness = $alternateInitialBufferFullness; + } + /** * Returns the maximum size of the largest sample stored in the data packets * for a stream. A value of 0 means unknown. @@ -329,6 +448,17 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_maximumObjectSize; } + /** + * Sets the maximum size of the largest sample stored in the data packets for + * a stream. A value of 0 means unknown. + * + * @param integer $maximumObjectSize The maximum size of the largest sample. + */ + public function setMaximumObjectSize($maximumObjectSize) + { + $this->_maximumObjectSize = $maximumObjectSize; + } + /** * Returns the average time duration, measured in 100-nanosecond units, of * each frame. This number should be rounded to the nearest integer. This @@ -342,6 +472,19 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_averageTimePerFrame; } + /** + * Sets the average time duration, measured in 100-nanosecond units, of + * each frame. This number should be rounded to the nearest integer. This + * field can optionally be set to 0 if the average time per frame is unknown + * or unimportant. It is recommended that this field be set for video. + * + * @param integer $averageTimePerFrame The average time duration. + */ + public function setAverageTimePerFrame($averageTimePerFrame) + { + $this->_averageTimePerFrame = $averageTimePerFrame; + } + /** * Returns the number of this stream. 0 is an invalid stream number (that is, * other Header Objects use stream number 0 to refer to the entire file @@ -355,6 +498,19 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_streamNumber; } + /** + * Sets the number of this stream. 0 is an invalid stream number (that is, + * other Header Objects use stream number 0 to refer to the entire file + * as a whole rather than to a specific media stream within the file). Valid + * values are between 1 and 127. + * + * @param integer $streamNumber The number of this stream. + */ + public function setStreamNumber($streamNumber) + { + $this->_streamNumber = $streamNumber; + } + /** * Returns the language, if any, which the content of the stream uses or * assumes. Refer to the {@link LanguageList Language List Object} description @@ -370,12 +526,27 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_streamLanguageIndex; } + /** + * Sets the language, if any, which the content of the stream uses or assumes. + * Refer to the {@link LanguageList Language List Object} description for the + * details concerning how the Stream Language Index and Language + * Index fields should be used. Note that this is an index into the + * languages listed in the Language List Object rather than a language + * identifier. + * + * @param integer $streamLanguageIndex The language index. + */ + public function setStreamLanguageIndex($streamLanguageIndex) + { + $this->_streamLanguageIndex = $streamLanguageIndex; + } + /** * Returns an array of Stream Names. Each stream name instance is potentially * localized into a specific language. The Language Index field * indicates the language in which the Stream Name has been written. * - * The array contains the following keys: + * The array entry contains the following keys: * o languageIndex -- The language index * o streamName -- The localized stream name * @@ -386,6 +557,22 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object return $this->_streamNames; } + /** + * Sets the array of stream names. Each stream name instance is potentially + * localized into a specific language. The Language Index field + * indicates the language in which the Stream Name has been written. + * + * The array entries are to contain the following keys: + * o languageIndex -- The language index + * o streamName -- The localized stream name + * + * @param Array $streamNames The array of stream names + */ + public function setStreamNames($streamNames) + { + $this->_streamNames = $streamNames; + } + /** * Returns an array of payload extension systems. Payload extensions provide a * way for content creators to specify kinds of data that will appear in the @@ -397,7 +584,7 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object * Extended Stream Properties Object for each type of per-media-object * properties that will appear with the payloads for this stream. * - * The array contains the following keys: + * The array entry contains the following keys: * o extensionSystemId -- Specifies a unique identifier for the extension * system. * o extensionDataSize -- Specifies the fixed size of the extension data for @@ -415,4 +602,96 @@ final class ASF_Object_ExtendedStreamProperties extends ASF_Object { return $this->_payloadExtensionSystems; } + + /** + * Sets an array of payload extension systems. Payload extensions provide a + * way for content creators to specify kinds of data that will appear in the + * payload header for every payload from this stream. This system is used when + * stream properties must be conveyed at the media object level. The + * Replicated Data bytes in the payload header will contain these + * properties in the order in which the Payload Extension Systems + * appear in this object. A Payload Extension System must appear in the + * Extended Stream Properties Object for each type of per-media-object + * properties that will appear with the payloads for this stream. + * + * The array enties are to contain the following keys: + * o extensionSystemId -- Specifies a unique identifier for the extension + * system. + * o extensionDataSize -- Specifies the fixed size of the extension data for + * this system that will appear in the replicated data alongside every + * payload for this stream. If this extension system uses variable-size + * data, then this should be set to 0xffff. Note, however, that replicated + * data length is limited to 255 bytes, which limits the total size of all + * extension systems for a particular stream. + * o extensionSystemInfo -- Specifies additional information to describe + * this extension system (optional). + * + * @param Array $payloadExtensionSystems The array of payload extension + * systems. + */ + public function setPayloadExtensionSystems($payloadExtensionSystems) + { + $this->_payloadExtensionSystems = $payloadExtensionSystems; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toInt64LE($this->_startTime) . + Transform::toInt64LE($this->_endTime) . + Transform::toUInt32LE($this->_dataBitrate) . + Transform::toUInt32LE($this->_bufferSize) . + Transform::toUInt32LE($this->_initialBufferFullness) . + Transform::toUInt32LE($this->_alternateDataBitrate) . + Transform::toUInt32LE($this->_alternateBufferSize) . + Transform::toUInt32LE($this->_alternateInitialBufferFullness) . + Transform::toUInt32LE($this->_maximumObjectSize) . + Transform::toUInt32LE($this->_flags) . + Transform::toUInt16LE($this->_streamNumber) . + Transform::toUInt16LE($this->_streamLanguageIndex) . + Transform::toInt64LE($this->_averageTimePerFrame) . + Transform::toUInt16LE($streamNameCount = count($this->_streamNames)) . + Transform::toUInt16LE + ($payloadExtensionSystemCount = count($this->_payloadExtensionSystems)); + for ($i = 0; $i < $streamNameCount; $i++) + $data .= + Transform::toUInt16LE($this->_streamNames["languageIndex"]) . + Transform::toUInt16LE(strlen($streamName = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_streamNames["streamName"]) . "\0\0")) . + Transform::toString16LE($streamName); + for ($i = 0; $i < $payloadExtensionSystemCount; $i++) + $data .= + Transform::toGUID($this->_streamNames["extensionSystemId"]) . + Transform::toUInt16LE($this->_streamNames["extensionDataSize"]) . + Transform::toUInt16LE(strlen($extensionSystemInfo = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_streamNames["extensionSystemInfo"]) . "\0\0")) . + Transform::toString16LE($extensionSystemInfo); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/FileProperties.php b/src/ASF/Object/FileProperties.php index 5479312..e6de8d1 100644 --- a/src/ASF/Object/FileProperties.php +++ b/src/ASF/Object/FileProperties.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -47,7 +47,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -129,14 +129,21 @@ final class ASF_Object_FileProperties extends ASF_Object $this->_maximumDataPacketSize = $this->_reader->readUInt32LE(); $this->_maximumBitrate = $this->_reader->readUInt32LE(); } - + /** * Returns the file id field. * * @return integer */ public function getFileId() { return $this->_fileId; } - + + /** + * Sets the file id field. + * + * @param GUID $fileId The new file id. + */ + public function setFileId($fileId) { $this->_fileId = $fileId; } + /** * Returns the size, in bytes, of the entire file. The value of this field is * invalid if the broadcast flag bit in the flags field is set to 1. @@ -144,7 +151,15 @@ final class ASF_Object_FileProperties extends ASF_Object * @return integer */ public function getFileSize() { return $this->_fileSize; } - + + /** + * Sets the size, in bytes, of the entire file. The value of this field is + * invalid if the broadcast flag bit in the flags field is set to 1. + * + * @param integer $fileSize The size of the entire file. + */ + public function setFileSize($fileSize) { $this->_fileSize = $fileSize; } + /** * Returns the date and time of the initial creation of the file. The value is * given as the number of 100-nanosecond intervals since January 1, 1601, @@ -155,7 +170,22 @@ final class ASF_Object_FileProperties extends ASF_Object * @return integer */ public function getCreationDate() { return $this->_creationDate; } - + + /** + * Sets the date and time of the initial creation of the file. The value is + * given as the number of 100-nanosecond intervals since January 1, 1601, + * according to Coordinated Universal Time (Greenwich Mean Time). The value of + * this field may be invalid if the broadcast flag bit in the flags field is + * set to 1. + * + * @param integer $creationDate The date and time of the initial creation of + * the file. + */ + public function setCreationDate($creationDate) + { + $this->_creationDate = $creationDate; + } + /** * Returns the number of Data Packet entries that exist within the * {@link ASF_Object_Data Data Object}. The value of this field is invalid if @@ -164,6 +194,18 @@ final class ASF_Object_FileProperties extends ASF_Object * @return integer */ public function getDataPacketsCount() { return $this->_dataPacketsCount; } + + /** + * Sets the number of Data Packet entries that exist within the + * {@link ASF_Object_Data Data Object}. The value of this field is invalid if + * the broadcast flag bit in the flags field is set to 1. + * + * @param integer $dataPacketsCount The number of Data Packet entries. + */ + public function setDataPacketsCount($dataPacketsCount) + { + $this->_dataPacketsCount = $dataPacketsCount; + } /** * Returns the time needed to play the file in 100-nanosecond units. This @@ -176,6 +218,20 @@ final class ASF_Object_FileProperties extends ASF_Object */ public function getPlayDuration() { return $this->_playDuration; } + /** + * Sets the time needed to play the file in 100-nanosecond units. This + * value should include the duration (estimated, if an exact value is + * unavailable) of the the last media object in the presentation. The value of + * this field is invalid if the broadcast flag bit in the flags field is set + * to 1. + * + * @param integer $playDuration The time needed to play the file. + */ + public function setPlayDuration($playDuration) + { + $this->_playDuration = $playDuration; + } + /** * Returns the time needed to send the file in 100-nanosecond units. This * value should include the duration of the last packet in the content. The @@ -186,6 +242,19 @@ final class ASF_Object_FileProperties extends ASF_Object */ public function getSendDuration() { return $this->_sendDuration; } + /** + * Sets the time needed to send the file in 100-nanosecond units. This + * value should include the duration of the last packet in the content. The + * value of this field is invalid if the broadcast flag bit in the flags field + * is set to 1. + * + * @param integer $sendDuration The time needed to send the file. + */ + public function setSendDuration($sendDuration) + { + $this->_sendDuration = $sendDuration; + } + /** * Returns the amount of time to buffer data before starting to play the file, * in millisecond units. If this value is nonzero, the Play Duration @@ -198,6 +267,18 @@ final class ASF_Object_FileProperties extends ASF_Object */ public function getPreroll() { return $this->_preroll; } + /** + * Sets the amount of time to buffer data before starting to play the file, + * in millisecond units. If this value is nonzero, the Play Duration + * field and all of the payload Presentation Time fields have been + * offset by this amount. Therefore, player software must subtract the value + * in the preroll field from the play duration and presentation times to + * calculate their actual values. + * + * @param integer $preroll The amount of time to buffer data. + */ + public function setPreroll($preroll) { $this->_preroll = $preroll; } + /** * Checks whether or not the flag is set. Returns true if the flag * is set, false otherwise. @@ -214,6 +295,13 @@ final class ASF_Object_FileProperties extends ASF_Object */ public function getFlags() { return $this->_flags; } + /** + * Sets the flags field. + * + * @param integer $flags The flags field. + */ + public function setFlags($flags) { $this->_flags = $flags; } + /** * Returns the minimum Data Packet size in bytes. In general, the value * of this field is invalid if the broadcast flag bit in the flags field is @@ -229,6 +317,22 @@ final class ASF_Object_FileProperties extends ASF_Object return $this->_minimumDataPacketSize; } + /** + * Sets the minimum Data Packet size in bytes. In general, the value + * of this field is invalid if the broadcast flag bit in the flags field is + * set to 1. However, the values for the Minimum Data Packet Size and + * Maximum Data Packet Size fields shall be set to the same value, and + * this value should be set to the packet size, even when the broadcast flag + * in the flags field is set to 1. + * + * @param integer $minimumDataPacketSize The minimum Data Packet size + * in bytes. + */ + public function setMinimumDataPacketSize($minimumDataPacketSize) + { + $this->_minimumDataPacketSize = $minimumDataPacketSize; + } + /** * Returns the maximum Data Packet size in bytes. In general, the value * of this field is invalid if the broadcast flag bit in the flags field is @@ -244,6 +348,22 @@ final class ASF_Object_FileProperties extends ASF_Object return $this->_maximumDataPacketSize; } + /** + * Sets the maximum Data Packet size in bytes. In general, the value + * of this field is invalid if the broadcast flag bit in the flags field is + * set to 1. However, the values for the Minimum Data Packet Size and + * Maximum Data Packet Size fields shall be set to the same value, and + * this value should be set to the packet size, even when the broadcast flag + * in the flags field is set to 1. + * + * @param integer $maximumDataPacketSize The maximum Data Packet size + * in bytes + */ + public function setMaximumDataPacketSize($maximumDataPacketSize) + { + $this->_maximumDataPacketSize = $maximumDataPacketSize; + } + /** * Returns the maximum instantaneous bit rate in bits per second for the * entire file. This is equal the sum of the bit rates of the individual @@ -252,4 +372,58 @@ final class ASF_Object_FileProperties extends ASF_Object * @return integer */ public function getMaximumBitrate() { return $this->_maximumBitrate; } + + /** + * Sets the maximum instantaneous bit rate in bits per second for the + * entire file. This is equal the sum of the bit rates of the individual + * digital media streams. + * + * @param integer $maximumBitrate The maximum instantaneous bit rate in bits + * per second. + */ + public function setMaximumBitrate($maximumBitrate) + { + $this->_maximumBitrate = $maximumBitrate; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_fileId) . + Transform::toInt64LE($this->_fileSize) . + Transform::toInt64LE($this->_creationDate) . + Transform::toInt64LE($this->_dataPacketsCount) . + Transform::toInt64LE($this->_playDuration) . + Transform::toInt64LE($this->_sendDuration) . + Transform::toInt64LE($this->_preroll) . + Transform::toUInt32LE($this->_flags) . + Transform::toUInt32LE($this->_minimumDataPacketSize) . + Transform::toUInt32LE($this->_maximumDataPacketSize) . + Transform::toUInt32LE($this->_maximumBitrate); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/GroupMutualExclusion.php b/src/ASF/Object/GroupMutualExclusion.php index 6719e1a..7e8f1dc 100644 --- a/src/ASF/Object/GroupMutualExclusion.php +++ b/src/ASF/Object/GroupMutualExclusion.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -51,7 +52,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -74,9 +75,13 @@ final class ASF_Object_GroupMutualExclusion extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + + if ($reader === null) + return; + $this->_exclusionType = $this->_reader->readGUID(); $recordCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $recordCount; $i++) { @@ -96,6 +101,16 @@ final class ASF_Object_GroupMutualExclusion extends ASF_Object */ public function getExclusionType() { return $this->_exclusionType; } + /** + * Sets the nature of the mutual exclusion relationship. + * + * @param string $exclusionType The exclusion type. + */ + public function setExclusionType($exclusionType) + { + $this->_exclusionType = $exclusionType; + } + /** * Returns an array of records. Each record consists of the following keys. * @@ -105,4 +120,52 @@ final class ASF_Object_GroupMutualExclusion extends ASF_Object * @return Array */ public function getRecords() { return $this->_records; } + + /** + * Sets an array of records. Each record is to consist of the following keys. + * + * o streamNumbers -- Specifies the stream numbers for this record. Valid + * values are between 1 and 127. + * + * @param Array $records The array of records + */ + public function setRecords($records) { $this->_records = $records; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_exclusionType) . + Transform::toUInt16LE($recordCount = count($this->_records)); + for ($i = 0; $i < $recordCount; $i++) { + $data .= + Transform::toUInt16LE($streamNumbersCount = count($this->_records[$i])); + for ($j = 0; $j < $streamNumbersCount; $j++) + $data .= Transform::toUInt16LE($this->_records[$i][$j]["streamNumbers"]); + } + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Header.php b/src/ASF/Object/Header.php index 3ce7bf2..9f92fdc 100644 --- a/src/ASF/Object/Header.php +++ b/src/ASF/Object/Header.php @@ -2,7 +2,7 @@ /** * PHP Reader Library * - * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights + * Copyright (c) 2006-2009 The PHP Reader Project Workgroup. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -69,28 +69,17 @@ require_once("ASF/Object/Container.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2006-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_Header extends ASF_Object_Container { - const FILE_PROPERTIES = "8cabdca1-a947-11cf-8ee4-00c00c205365"; - const STREAM_PROPERTIES = "b7dc0791-a9b7-11cf-8ee6-00c00c205365"; - const HEADER_EXTENSION = "5fbf03b5-a92e-11cf-8ee3-00c00c205365"; - const CODEC_LIST = "86d15240-311d-11d0-a3a4-00a0c90348f6"; - const SCRIPT_COMMAND = "1efb1a30-0b62-11d0-a39b-00a0c90348f6"; - const MARKER = "f487cd01-a951-11cf-8ee6-00c00c205365"; - const BITRATE_MUTUAL_EXCLUSION = "d6e229dc-35da-11d1-9034-00a0c90349be"; - const ERROR_CORRECTION = "75b22635-668e-11cf-a6d9-00aa0062ce6c"; - const CONTENT_DESCRIPTION = "75b22633-668e-11cf-a6d9-00aa0062ce6c"; - const EXTENDED_CONTENT_DESCRIPTION = "d2d0a440-e307-11d2-97f0-00a0c95ea850"; - const CONTENT_BRANDING = "2211b3fa-bd23-11d2-b4b7-00a0c955fc6e"; - const STREAM_BITRATE_PROPERTIES = "7bf875ce-468d-11d1-8d82-006097c9a2b2"; - const CONTENT_ENCRYPTION = "2211b3fb-bd23-11d2-b4b7-00a0c955fc6e"; - const EXTENDED_CONTENT_ENCRYPTION = "298ae614-2622-4c17-b935-dae07ee9289c"; - const DIGITAL_SIGNATURE = "2211b3fc-bd23-11d2-b4b7-00a0c955fc6e"; - const PADDING = "1806d474-cadf-4509-a4ba-9aabcb96aae8"; + /** @var integer */ + private $_reserved1; + + /** @var integer */ + private $_reserved2; /** * Constructs the class with given parameters and options. @@ -102,7 +91,9 @@ final class ASF_Object_Header extends ASF_Object_Container { parent::__construct($reader, $options); - $this->_reader->skip(6); + $this->_reader->skip(4); + $this->_reserved1 = $this->_reader->readInt8(); + $this->_reserved2 = $this->_reader->readInt8(); $this->constructObjects (array (self::FILE_PROPERTIES => "FileProperties", @@ -122,4 +113,41 @@ final class ASF_Object_Header extends ASF_Object_Container self::DIGITAL_SIGNATURE => "DigitalSignature", self::PADDING => "Padding")); } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = ""; + foreach ($this->getObjects() as $objects) + foreach ($objects as $object) + $data .= $object->__toString(); + $this->setSize + (24 /* for header */ + 6 + strlen($data) /* for object data */); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . + Transform::toUInt32LE(count($this->getObjects())) . + Transform::toInt8($this->_reserved1) . + Transform::toInt8($this->_reserved2) . $data; + } } diff --git a/src/ASF/Object/HeaderExtension.php b/src/ASF/Object/HeaderExtension.php index bb0db0a..dbbb569 100644 --- a/src/ASF/Object/HeaderExtension.php +++ b/src/ASF/Object/HeaderExtension.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -48,27 +49,18 @@ require_once("ASF/Object/Container.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_HeaderExtension extends ASF_Object_Container { - const EXTENDED_STREAM_PROPERTIES = "14e6a5cb-c672-4332-8399-a96952065b5a"; - const ADVANCED_MUTUAL_EXCLUSION = "a08649cf-4775-4670-8a16-6e35357566cd"; - const GROUP_MUTUAL_EXCLUSION = "d1465a40-5a79-4338-b71b-e36b8fd6c249"; - const STREAM_PRIORITIZATION = "d4fed15b-88d3-454f-81f0-ed5c45999e24"; - const BANDWIDTH_SHARING = "a69609e6-517b-11d2-b6af-00c04fd908e9"; - const LANGUAGE_LIST = "7c4346a9-efe0-4bfc-b229-393ede415c85"; - const METADATA = "c5f8cbea-5baf-4877-8467-aa8c44fa4cca"; - const METADATA_LIBRARY = "44231c94-9498-49d1-a141-1d134e457054"; - const INDEX_PARAMETERS = "d6e229df-35da-11d1-9034-00a0c90349be"; - const MEDIA_OBJECT_INDEX_PARAMETERS = "6b203bad-3f11-48e4-aca8-d7613de2cfa7"; - const TIMECODE_INDEX_PARAMETERS = "f55e496d-9797-4b5d-8c8b-604dfe9bfb24"; - const COMPATIBILITY = "75b22630-668e-11cf-a6d9-00aa0062ce6c"; - const ADVANCED_CONTENT_ENCRYPTION = "43058533-6981-49e6-9b74-ad12cb86d58c"; - const PADDING = "1806d474-cadf-4509-a4ba-9aabcb96aae8"; - + /** @var string */ + private $_reserved1; + + /** @var integer */ + private $_reserved2; + /** * Constructs the class with given parameters and reads object related data * from the ASF file. @@ -80,7 +72,9 @@ final class ASF_Object_HeaderExtension extends ASF_Object_Container { parent::__construct($reader, $options); - $this->_reader->skip(22); + $this->_reserved1 = $this->_reader->readGUID(); + $this->_reserved2 = $this->_reader->readUInt16LE(); + $this->_reader->skip(4); $this->constructObjects (array (self::EXTENDED_STREAM_PROPERTIES => "ExtendedStreamProperties", @@ -98,4 +92,41 @@ final class ASF_Object_HeaderExtension extends ASF_Object_Container self::ADVANCED_CONTENT_ENCRYPTION => "AdvancedContentEncryption", self::PADDING => "Padding")); } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = ""; + foreach ($this->getObjects() as $objects) + foreach ($objects as $object) + $data .= $object->__toString(); + $this->setSize + (24 /* for header */ + 22 + strlen($data) /* for object data */); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . + Transform::toGUID($this->_reserved1) . + Transform::toUInt16LE($this->_reserved2) . + Transform::toUInt32LE(strlen($data)) . $data; + } } diff --git a/src/ASF/Object/LanguageList.php b/src/ASF/Object/LanguageList.php index c0195ff..a39e61d 100644 --- a/src/ASF/Object/LanguageList.php +++ b/src/ASF/Object/LanguageList.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -47,7 +48,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -63,10 +64,13 @@ final class ASF_Object_LanguageList extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $languageIdRecordsCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $languageIdRecordsCount; $i++) { $languageIdLength = $this->_reader->readInt8(); @@ -81,5 +85,48 @@ final class ASF_Object_LanguageList extends ASF_Object * * @return Array */ - public function getLanguage() { return $this->_languages; } + public function getLanguages() { return $this->_languages; } + + /** + * Sets the array of language ids. + * + * @param Array $languages The array of language ids. + */ + public function setLanguages($languages) { $this->_languages = $languages; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE + ($languageIdRecordsCount = count($this->_languages)); + for ($i = 0; $i < $languageIdRecordsCount; $i++) + $data .= + Transform::toInt8(strlen($languageId = iconv + ($this->getOption("encoding"), "utf-16le", $this->_languages[$i]) . + "\0\0")) . Transform::toString16LE($languageId); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Marker.php b/src/ASF/Object/Marker.php index f8e5140..78ca2ec 100644 --- a/src/ASF/Object/Marker.php +++ b/src/ASF/Object/Marker.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -45,12 +46,19 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_Marker extends ASF_Object { + + /** @var string */ + private $_reserved1; + + /** @var integer */ + private $_reserved2; + /** @var string */ private $_name; @@ -68,9 +76,9 @@ final class ASF_Object_Marker extends ASF_Object { parent::__construct($reader, $options); - $this->_reader->skip(16); + $this->_reserved1 = $this->_reader->readGUID(); $markersCount = $this->_reader->readUInt32LE(); - $this->_reader->skip(2); + $this->_reserved2 = $this->_reader->readUInt16LE(); $nameLength = $this->_reader->readUInt16LE(); $this->_name = iconv ("utf-16le", $this->getOption("encoding"), @@ -96,6 +104,13 @@ final class ASF_Object_Marker extends ASF_Object * @return Array */ public function getName() { return $this->_name; } + + /** + * Returns the name of the Marker Object. + * + * @param string $name The name. + */ + public function setName($name) { $this->_name = $name; } /** * Returns an array of markers. Each entry consists of the following keys. @@ -118,4 +133,75 @@ final class ASF_Object_Marker extends ASF_Object * @return Array */ public function getMarkers() { return $this->_markers; } + + /** + * Sets the array of markers. Each entry is to consist of the following keys. + * + * o offset -- Specifies a byte offset into the Data Object to the + * actual position of the marker in the Data Object. ASF parsers + * must seek to this position to properly display data at the specified + * marker Presentation Time. + * + * o presentationTime -- Specifies the presentation time of the marker, in + * 100-nanosecond units. + * + * o sendTime -- Specifies the send time of the marker entry, in + * milliseconds. + * + * o flags -- Flags are reserved and should be set to 0. + * + * o description -- Specifies a description of the marker entry. + * + * @param Array $markers The array of markers. + */ + public function setMarkers($markers) { $this->_markers = $markers; } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_reserved1) . + Transform::toUInt32LE($markersCount = count($this->_markers)) . + Transform::toUInt16LE($this->_reserved2) . + Transform::toUInt16LE + (strlen($name = iconv + ($this->getOption("encoding"), "utf-16le", $this->_name) . "\0\0")) . + Transform::toString16LE($name); + for ($i = 0; $i < $markersCount; $i++) + $data .= + Transform::toInt64LE($this->_markers[$i]["offset"]) . + Transform::toInt64LE($this->_markers[$i]["presentationTime"]) . + Transform::toUInt16LE + (12 + ($descriptionLength = strlen($description = iconv + ("utf-16le", $this->getOption("encoding"), + $this->_markers[$i]["description"]) . "\0\0"))) . + Transform::toUInt32LE($this->_markers[$i]["sendTime"]) . + Transform::toUInt32LE($this->_markers[$i]["flags"]) . + Transform::toUInt32LE($descriptionLength) . + Transform::toString16LE($description); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Metadata.php b/src/ASF/Object/Metadata.php index 066334c..88a5130 100644 --- a/src/ASF/Object/Metadata.php +++ b/src/ASF/Object/Metadata.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -48,14 +49,14 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_Metadata extends ASF_Object { /** @var Array */ - private $_descriptions = array(); + private $_descriptionRecords = array(); /** * Constructs the class with given parameters and reads object related data @@ -64,50 +65,157 @@ final class ASF_Object_Metadata extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $descriptionRecordsCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $descriptionRecordsCount; $i++) { $this->_reader->skip(2); - $record = array("streamNumber" => $this->_reader->readUInt16LE()); + $descriptionRecord = array("streamNumber" => $this->_reader->readUInt16LE()); $nameLength = $this->_reader->readUInt16LE(); $dataType = $this->_reader->readUInt16LE(); $dataLength = $this->_reader->readUInt32LE(); - $record["name"] = iconv + $descriptionRecord["name"] = iconv ("utf-16le", $this->getOption("encoding"), $this->_reader->readString16LE($nameLength)); switch ($dataType) { - case 0: - $record["data"] = iconv + case 0: // Unicode string + $descriptionRecord["data"] = iconv ("utf-16le", $this->getOption("encoding"), $this->_reader->readString16LE($dataLength)); break; - case 1: - $record["data"] = $this->_reader->readString16LE($dataLength); + case 1: // BYTE array + $descriptionRecord["data"] = $this->_reader->read($dataLength); break; - case 2: - $record["data"] = $this->_reader->readUInt16LE() ? true : false; + case 2: // BOOL + $descriptionRecord["data"] = $this->_reader->readUInt16LE() == 1; break; - case 3: - $record["data"] = $this->_reader->readUInt32LE(); + case 3: // DWORD + $descriptionRecord["data"] = $this->_reader->readUInt32LE(); break; - case 4: - $record["data"] = $this->_reader->readInt64LE(); + case 4: // QWORD + $descriptionRecord["data"] = $this->_reader->readInt64LE(); break; - case 5: - $record["data"] = $this->_reader->readUInt16LE(); + case 5: // WORD + $descriptionRecord["data"] = $this->_reader->readUInt16LE(); break; } - $this->_descriptions[] = $record; + $this->_descriptionRecords[] = $descriptionRecord; } } - + /** - * Returns the array of description records. + * Returns the array of description records. Each record consists of the + * following keys. + * + * o streamNumber -- Specifies the stream number. Valid values are between + * 1 and 127. + * + * o name -- Specifies the name that uniquely identifies the attribute being + * described. Names are case-sensitive. + * + * o data -- Specifies the actual metadata being stored. * * @return Array */ - public function getDescriptions() { return $this->_descriptions; } + public function getDescriptionRecords() { return $this->_descriptionRecords; } + + /** + * Sets the array of description records. Each record must consist of the + * following keys. + * + * o streamNumber -- Specifies the stream number. Valid values are between + * 1 and 127. + * + * o name -- Specifies the name that uniquely identifies the attribute being + * described. Names are case-sensitive. + * + * o data -- Specifies the actual metadata being stored. + * + * @param Array $descriptionRecords The array of description records. + */ + public function setDescriptionRecords($descriptionRecords) + { + $this->_descriptionRecords = $descriptionRecords; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE + ($descriptionRecordsCount = count($this->_descriptionRecords)); + for ($i = 0; $i < $descriptionRecordsCount; $i++) { + $data .= Transform::toUInt16LE(0) . + Transform::toUInt16LE($this->_descriptionRecords[$i]["streamNumber"]) . + Transform::toUInt16LE(strlen($name = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_descriptionRecords[$i]["name"]) . "\0\0")); + if (is_string($this->_descriptionRecords[$i]["data"])) { + /* There is no way to distinguish byte arrays from unicode strings and + * hence the need for a list of fields of type byte array */ + static $byteArray = array ( + "" + ); // TODO: Add to the list if you encounter one + + if (in_array($name, $byteArray)) + $data .= Transform::toUInt16LE(1) . Transform::toUInt32LE + (strlen($this->_descriptionRecords[$i]["data"])) . $name . + $this->_descriptionRecords[$i]["data"]; + else { + $value = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_descriptionRecords[$i]["data"]); + $value = ($value ? $value . "\0\0" : ""); + $data .= Transform::toUInt16LE(0) . + Transform::toUInt32LE(strlen($value)) . $name . + Transform::toString16LE($value); + } + } + else if (is_bool($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(2) . Transform::toUInt32LE(2) . $name . + Transform::toUInt16LE($this->_descriptionRecords[$i]["data"] ? 1 : 0); + } + else if (is_int($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(3) . Transform::toUInt32LE(4) . $name . + Transform::toUInt32LE($this->_descriptionRecords[$i]["data"]); + } + else if (is_float($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(4) . Transform::toUInt32LE(8) . $name . + Transform::toInt64LE($this->_descriptionRecords[$i]["data"]); + } + else { + // Invalid value and there is nothing to be done so cause a fatal error + require_once("ASF/Exception.php"); + throw new ASF_Exception("Invalid data type"); + } + } + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/MetadataLibrary.php b/src/ASF/Object/MetadataLibrary.php index c9dd673..0f95381 100644 --- a/src/ASF/Object/MetadataLibrary.php +++ b/src/ASF/Object/MetadataLibrary.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -52,7 +53,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -68,10 +69,13 @@ final class ASF_Object_MetadataLibrary extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $descriptionRecordsCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $descriptionRecordsCount; $i++) { $descriptionRecord = array @@ -116,6 +120,30 @@ final class ASF_Object_MetadataLibrary extends ASF_Object * Returns an array of description records. Each record consists of the * following keys. * + * o languageIndex -- Specifies the index into the + * {@link LanguageList Language List Object} that identifies the language + * of this attribute. If there is no Language List Object present, + * this field is zero. + * + * o streamNumber -- Specifies whether the entry applies to a specific + * digital media stream or whether it applies to the whole file. A value + * of 0 in this field indicates that it applies to the whole file; + * otherwise, the entry applies only to the indicated stream number. Valid + * values are between 1 and 127. + * + * o name -- Specifies the name that identifies the attribute being + * described. + * + * o data -- Specifies the actual metadata being stored. + * + * @return Array + */ + public function getDescriptionRecords() { return $this->_descriptionRecords; } + + /** + * Sets an array of description records. Each record must consist of the + * following keys. + * * o languageIndex -- Specifies the index into the Language List * Object that identifies the language of this attribute. If there is * no Language List Object present, this field is zero. @@ -133,5 +161,94 @@ final class ASF_Object_MetadataLibrary extends ASF_Object * * @return Array */ - public function getDescriptionRecords() { return $this->_descriptionRecords; } + public function setDescriptionRecords($descriptionRecords) + { + $this->_descriptionRecords = $descriptionRecords; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE + ($descriptionRecordsCount = count($this->_descriptionRecords)); + for ($i = 0; $i < $descriptionRecordsCount; $i++) { + $data .= + Transform::toUInt16LE($this->_descriptionRecords[$i]["languageIndex"]) . + Transform::toUInt16LE($this->_descriptionRecords[$i]["streamNumber"]) . + Transform::toUInt16LE(strlen($name = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_descriptionRecords[$i]["name"]) . "\0\0")); + if (is_string($this->_descriptionRecords[$i]["data"])) { + $chunks = array(); + if (preg_match + ("/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i", + $this->_descriptionRecords[$i]["data"])) + $data .= Transform::toUInt16LE(6) . Transform::toUInt32LE(16) . + $name . Transform::toGUID($this->_descriptionRecords[$i]["data"]); + else { + /* There is no way to distinguish byte arrays from unicode strings and + * hence the need for a list of fields of type byte array */ + static $byteArray = array ( + "W\0M\0/\0L\0y\0r\0i\0c\0s\0_\0S\0y\0n\0c\0h\0r\0o\0n\0i\0s\0e\0d\0\0\0", + "W\0M\0/\0P\0i\0c\0t\0u\0r\0e\0\0\0" + ); // TODO: Add to the list if you encounter one + + if (in_array($name, $byteArray)) + $data .= Transform::toUInt16LE(1) . Transform::toUInt32LE + (strlen($this->_descriptionRecords[$i]["data"])) . $name . + $this->_descriptionRecords[$i]["data"]; + else { + $value = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_descriptionRecords[$i]["data"]); + $value = ($value ? $value . "\0\0" : ""); + $data .= Transform::toUInt16LE(0) . + Transform::toUInt32LE(strlen($value)) . $name . + Transform::toString16LE($value); + } + } + } + else if (is_bool($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(2) . Transform::toUInt32LE(2) . $name . + Transform::toUInt16LE($this->_descriptionRecords[$i]["data"] ? 1 : 0); + } + else if (is_int($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(3) . Transform::toUInt32LE(4) . $name . + Transform::toUInt32LE($this->_descriptionRecords[$i]["data"]); + } + else if (is_float($this->_descriptionRecords[$i]["data"])) { + $data .= Transform::toUInt16LE(4) . Transform::toUInt32LE(8) . $name . + Transform::toInt64LE($this->_descriptionRecords[$i]["data"]); + } + else { + // Invalid value and there is nothing to be done so cause a fatal error + require_once("ASF/Exception.php"); + throw new ASF_Exception("Invalid data type"); + } + } + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Padding.php b/src/ASF/Object/Padding.php index 8e2a20d..c068ac8 100644 --- a/src/ASF/Object/Padding.php +++ b/src/ASF/Object/Padding.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -55,10 +56,52 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_Padding extends ASF_Object { + /** + * Constructs the class with given parameters and reads object related data + * from the ASF file. + * + * @param Reader $reader The reader object. + * @param Array $options The options array. + */ + public function __construct($reader = null, &$options = array()) + { + parent::__construct($reader, $options); + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + if ($this->getSize() == 0) + $this->setSize(24); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . + str_pad("", $this->getSize() - 24 /* header */, "\0"); + } } diff --git a/src/ASF/Object/ScriptCommand.php b/src/ASF/Object/ScriptCommand.php index 413797d..8e67b5a 100644 --- a/src/ASF/Object/ScriptCommand.php +++ b/src/ASF/Object/ScriptCommand.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -55,18 +56,34 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ final class ASF_Object_ScriptCommand extends ASF_Object { - /** @var Array */ - private $_commandTypes = array(); - + /** @var string */ + private $_reserved; + /** @var Array */ private $_commands = array(); + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + /** * Constructs the class with given parameters and reads object related data * from the ASF file. @@ -74,23 +91,27 @@ final class ASF_Object_ScriptCommand extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - $this->_reader->skip(16); + if ($reader === null) + return; + + $this->_reserved = $this->_reader->readGUID(); $commandsCount = $this->_reader->readUInt16LE(); $commandTypesCount = $this->_reader->readUInt16LE(); + $commandTypes = array(); for ($i = 0; $i < $commandTypesCount; $i++) { $commandTypeNameLength = $this->_reader->readUInt16LE(); - $this->_commandTypes[] = iconv + $commandTypes[] = iconv ("utf-16le", $this->getOption("encoding"), $this->_reader->readString16LE($commandTypeNameLength * 2)); } for ($i = 0; $i < $commandsCount; $i++) { $command = array ("presentationTime" => $this->_reader->readUInt32LE(), - "typeIndex" => $this->_reader->readUInt16LE()); + "type" => $commandTypes[$this->_reader->readUInt16LE()]); $commandNameLength = $this->_reader->readUInt16LE(); $command["name"] = iconv ("utf-16le", $this->getOption("encoding"), @@ -99,13 +120,6 @@ final class ASF_Object_ScriptCommand extends ASF_Object } } - /** - * Returns an array of command type names. - * - * @return Array - */ - public function getCommandTypes() { return $this->_commandTypes; } - /** * Returns an array of index entries. Each entry consists of the following * keys. @@ -113,12 +127,62 @@ final class ASF_Object_ScriptCommand extends ASF_Object * o presentationTime -- Specifies the presentation time of the command, in * milliseconds. * - * o typeIndex -- Specifies the type of this command, as a zero-based index - * into the array of Command Types of this object. + * o type -- Specifies the type of this command. * * o name -- Specifies the name of this command. * * @return Array */ public function getCommands() { return $this->_commands; } + + /** + * Sets the array of index entries. Each entry is to consist of the following + * keys. + * + * o presentationTime -- Specifies the presentation time of the command, in + * milliseconds. + * + * o type -- Specifies the type of this command. + * + * o name -- Specifies the name of this command. + * + * @param Array $commands The array of index entries. + */ + public function setCommands($commands) { $this->_commands = $commands; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $commandTypes = array(); + foreach ($this->_commands as $command) + if (!in_array($command["type"], $commandTypes)) + $commandTypes[] = $command["type"]; + $data = + Transform::toGUID($this->_reserved) . + Transform::toUInt16LE($commandsCount = count($this->_commands)) . + Transform::toUInt16LE($commandTypesCount = count($commandTypes)); + for ($i = 0; $i < $commandTypesCount; $i++) + $data .= + Transform::toUInt16LE + (strlen($commandType = iconv + ($this->getOption("encoding"), "utf-16le", + $commandTypes[$i])) / 2) . $commandType; + for ($i = 0; $i < $commandsCount; $i++) + $data .= + Transform::toUInt32LE($this->_commands[$i]["presentationTime"]) . + Transform::toUInt16LE + (array_search($this->_commands[$i]["type"], $commandTypes)) . + Transform::toUInt16LE + (strlen($command = iconv + ($this->getOption("encoding"), "utf-16le", + $this->_commands[$i]["name"])) / 2) . $command; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/StreamBitrateProperties.php b/src/ASF/Object/StreamBitrateProperties.php index 69b457d..e28a55d 100644 --- a/src/ASF/Object/StreamBitrateProperties.php +++ b/src/ASF/Object/StreamBitrateProperties.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -46,7 +47,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -62,10 +63,13 @@ final class ASF_Object_StreamBitrateProperties extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + if ($reader === null) + return; + $bitrateRecordsCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $bitrateRecordsCount; $i++) $this->_bitrateRecords[] = array @@ -90,4 +94,60 @@ final class ASF_Object_StreamBitrateProperties extends ASF_Object * @return Array */ public function getBitrateRecords() { return $this->_bitrateRecords; } + + /** + * Sets an array of bitrate records. Each record consists of the following + * keys. + * + * o streamNumber -- Specifies the number of this stream described by this + * record. 0 is an invalid stream. Valid values are between 1 and 127. + * + * o flags -- These bits are reserved and should be set to 0. + * + * o averageBitrate -- Specifies the average bit rate of the stream in bits + * per second. This value should include an estimate of ASF packet and + * payload overhead associated with this stream. + * + * @param Array $bitrateRecords The array of bitrate records. + */ + public function setBitrateRecords($bitrateRecords) + { + $this->_bitrateRecords = $bitrateRecords; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE + ($bitrateRecordsCount = count($this->_bitrateRecords)); + for ($i = 0; $i < $bitrateRecordsCount; $i++) + $data .= Transform::toUInt16LE + (($this->_bitrateRecords[$i]["flags"] << 5) | + ($this->_bitrateRecords[$i]["streamNumber"] & 0x1f)) . + Transform::toUInt32LE($this->_bitrateRecords[$i]["averageBitrate"]); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/StreamPrioritization.php b/src/ASF/Object/StreamPrioritization.php index fe9b6f9..54c085d 100644 --- a/src/ASF/Object/StreamPrioritization.php +++ b/src/ASF/Object/StreamPrioritization.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -59,7 +60,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -75,9 +76,13 @@ final class ASF_Object_StreamPrioritization extends ASF_Object * @param Reader $reader The reader object. * @param Array $options The options array. */ - public function __construct($reader, &$options = array()) + public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); + + if ($reader === null) + return; + $priorityRecordCount = $this->_reader->readUInt16LE(); for ($i = 0; $i < $priorityRecordCount; $i++) $this->_priorityRecords[] = array @@ -96,4 +101,54 @@ final class ASF_Object_StreamPrioritization extends ASF_Object * @return Array */ public function getPriorityRecords() { return $this->_priorityRecords; } + + /** + * Sets the array of records. Each record consists of the following keys. + * + * o streamNumber -- Specifies the stream number. Valid values are between + * 1 and 127. + * + * o flags -- Specifies the flags. The mandatory flag is the bit 1 (LSB). + * + * @param Array $priorityRecords The array of records. + */ + public function setPriorityRecords($priorityRecords) + { + $this->_priorityRecords = $priorityRecords; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = Transform::toUInt16LE + ($priorityRecordCount = count($this->_priorityRecords)); + for ($i = 0; $i < $priorityRecordCount; $i++) + $data .= + Transform::toUInt16LE($this->_priorityRecords[$i]["streamNumber"]) . + Transform::toUInt16LE($this->_priorityRecords[$i]["flags"]); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/StreamProperties.php b/src/ASF/Object/StreamProperties.php index 46e3a66..9dd4a3e 100644 --- a/src/ASF/Object/StreamProperties.php +++ b/src/ASF/Object/StreamProperties.php @@ -2,7 +2,8 @@ /** * PHP Reader Library * - * Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved. + * Copyright (c) 2008-2009 The PHP Reader Project Workgroup. All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -30,7 +31,7 @@ * * @package php-reader * @subpackage ASF - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Id$ */ @@ -53,7 +54,7 @@ require_once("ASF/Object.php"); * @package php-reader * @subpackage ASF * @author Sven Vollbehr - * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup + * @copyright Copyright (c) 2008-2009 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ */ @@ -88,6 +89,9 @@ final class ASF_Object_StreamProperties extends ASF_Object /** @var integer */ private $_flags; + /** @var integer */ + private $_reserved; + /** @var Array */ private $_typeSpecificData = array(); @@ -111,7 +115,8 @@ final class ASF_Object_StreamProperties extends ASF_Object $typeSpecificDataLength = $this->_reader->readUInt32LE(); $errorCorrectionDataLength = $this->_reader->readUInt32LE(); $this->_flags = $this->_reader->readUInt16LE(); - $this->_reader->skip(4); + $this->_reserved = $this->_reader->readUInt32LE(); + switch ($this->_streamType) { case self::AUDIO_MEDIA: $this->_typeSpecificData = array @@ -208,6 +213,23 @@ final class ASF_Object_StreamProperties extends ASF_Object */ public function getStreamNumber() { return $this->_flags & 0x3f; } + /** + * Returns the number of this stream. 0 is an invalid stream. Valid values are + * between 1 and 127. The numbers assigned to streams in an ASF presentation + * may be any combination of unique values; parsing logic must not assume that + * streams are numbered sequentially. + * + * @param integer $streamNumber The number of this stream. + */ + public function setStreamNumber($streamNumber) + { + if ($streamNumber < 1 || $streamNumber > 127) { + require_once("ASF/Exception.php"); + throw new ASF_Exception("Invalid argument"); + } + $this->_flags = ($this->_flags & 0xffc0) | ($streamNumber & 0x3f); + } + /** * Returns the type of the stream (for example, audio, video, and so on). * @@ -215,6 +237,16 @@ final class ASF_Object_StreamProperties extends ASF_Object */ public function getStreamType() { return $this->_streamType; } + /** + * Sets the type of the stream (for example, audio, video, and so on). + * + * @param integer $streamType The type of the stream. + */ + public function setStreamType($streamType) + { + $this->_streamType = $streamType; + } + /** * Returns the error correction type used by this digital media stream. For * streams other than audio, this value should be set to NO_ERROR_CORRECTION. @@ -227,6 +259,19 @@ final class ASF_Object_StreamProperties extends ASF_Object return $this->_errorCorrectionType; } + /** + * Sets the error correction type used by this digital media stream. For + * streams other than audio, this value should be set to NO_ERROR_CORRECTION. + * For audio streams, this value should be set to AUDIO_SPREAD. + * + * @param integer $errorCorrectionType The error correction type used by this + * digital media stream. + */ + public function setErrorCorrectionType($errorCorrectionType) + { + $this->_errorCorrectionType = $errorCorrectionType; + } + /** * Returns the presentation time offset of the stream in 100-nanosecond units. * The value of this field is added to all of the timestamps of the samples in @@ -241,6 +286,23 @@ final class ASF_Object_StreamProperties extends ASF_Object */ public function getTimeOffset() { return $this->_timeOffset; } + /** + * Sets the presentation time offset of the stream in 100-nanosecond units. + * The value of this field is added to all of the timestamps of the samples in + * the stream. This value shall be equal to the send time of the first + * interleaved packet in the data section. The value of this field is + * typically 0. It is non-zero in the case when an ASF file is edited and it + * is not possible for the editor to change the presentation times and send + * times of ASF packets. Note that if more than one stream is present in an + * ASF file the offset values of all stream properties objects must be equal. + * + * @param integer $timeOffset The presentation time offset of the stream. + */ + public function setTimeOffset($timeOffset) + { + $this->_timeOffset = $timeOffset; + } + /** * Checks whether or not the flag is set. Returns true if the flag * is set, false otherwise. @@ -257,6 +319,13 @@ final class ASF_Object_StreamProperties extends ASF_Object */ public function getFlags() { return $this->_flags; } + /** + * Sets the flags field. + * + * @param integer $flags The flags field. + */ + public function setFlags($flags) { $this->_flags = $flags; } + /** * Returns type-specific format data. The structure for the Type-Specific * Data field is determined by the value stored in the Stream Type @@ -268,6 +337,19 @@ final class ASF_Object_StreamProperties extends ASF_Object * @return Array */ public function getTypeSpecificData() { return $this->_typeSpecificData; } + + /** + * Sets type-specific format data. The structure for the Type-Specific + * Data field is determined by the value stored in the Stream Type + * field. + * + * @param Array $typeSpecificData The type-specific data as key-value pairs of + * an associate array. + */ + public function setTypeSpecificData($typeSpecificData) + { + $this->_typeSpecificData = $typeSpecificData; + } /** * Returns data specific to the error correction type. The structure for the @@ -285,4 +367,150 @@ final class ASF_Object_StreamProperties extends ASF_Object { return $this->_errorCorrectionData; } + + /** + * Sets data specific to the error correction type. The structure for the + * Error Correction Data field is determined by the value stored in the + * Error Correction Type field. For example, an audio data stream might + * need to know how codec chunks were redistributed, or it might need a sample + * of encoded silence. + * + * @param Array $errorCorrectionData The error correction type-specific data + * as key-value pairs of an associate array. + */ + public function setErrorCorrectionData($errorCorrectionData) + { + $this->_errorCorrectionData = $errorCorrectionData; + } + + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return true; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return false; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $data = + Transform::toGUID($this->_streamType) . + Transform::toGUID($this->_errorCorrectionType) . + Transform::toInt64LE($this->_timeOffset); + + switch ($this->_streamType) { + case self::AUDIO_MEDIA: + $typeSpecificData = + Transform::toUInt16LE($this->_typeSpecificData["codecId"]) . + Transform::toUInt16LE($this->_typeSpecificData["numberOfChannels"]) . + Transform::toUInt32LE($this->_typeSpecificData["samplesPerSecond"]) . + Transform::toUInt32LE + ($this->_typeSpecificData["avgNumBytesPerSecond"]) . + Transform::toUInt16LE($this->_typeSpecificData["blockAlignment"]) . + Transform::toUInt16LE($this->_typeSpecificData["bitsPerSample"]) . + Transform::toUInt16LE + (strlen($this->_typeSpecificData["codecSpecificData"])) . + $this->_typeSpecificData["codecSpecificData"]; + break; + case self::VIDEO_MEDIA: + $typeSpecificData = + Transform::toUInt32LE($this->_typeSpecificData["encodedImageWidth"]) . + Transform::toUInt32LE($this->_typeSpecificData["encodedImageHeight"]) . + Transform::toInt8($this->_typeSpecificData["reservedFlags"]) . + Transform::toUInt16LE(0) . // Reserved + Transform::toUInt32LE + (38 + strlen($this->_typeSpecificData["codecSpecificData"])) . + Transform::toUInt32LE($this->_typeSpecificData["imageWidth"]) . + Transform::toUInt32LE($this->_typeSpecificData["imageHeight"]) . + Transform::toUInt16LE($this->_typeSpecificData["reserved"]) . + Transform::toUInt16LE($this->_typeSpecificData["bitsPerPixelCount"]) . + Transform::toUInt32LE($this->_typeSpecificData["compressionId"]) . + Transform::toUInt32LE($this->_typeSpecificData["imageSize"]) . + Transform::toUInt32LE + ($this->_typeSpecificData["horizontalPixelsPerMeter"]) . + Transform::toUInt32LE + ($this->_typeSpecificData["verticalPixelsPerMeter"]) . + Transform::toUInt32LE($this->_typeSpecificData["colorsUsedCount"]) . + Transform::toUInt32LE + ($this->_typeSpecificData["importantColorsCount"]) . + $this->_typeSpecificData["codecSpecificData"]; + break; + case self::JFIF_MEDIA: + $typeSpecificData = + Transform::toUInt32LE($this->_typeSpecificData["imageWidth"]) . + Transform::toUInt32LE($this->_typeSpecificData["imageHeight"]) . + Transform::toUInt32LE(0); + break; + case self::DEGRADABLE_JPEG_MEDIA: + $typeSpecificData = + Transform::toUInt32LE($this->_typeSpecificData["imageWidth"]) . + Transform::toUInt32LE($this->_typeSpecificData["imageHeight"]) . + Transform::toUInt16LE(0) . + Transform::toUInt16LE(0) . + Transform::toUInt16LE(0); + $interchangeDataSize = strlen + ($this->_typeSpecificData["interchangeData"]); + if ($interchangeDataSize == 1) + $interchangeDataSize = 0; + $typeSpecificData .= + Transform::toUInt16LE($interchangeDataSize) . + $this->_typeSpecificData["interchangeData"]; + break; + case self::FILE_TRANSFER_MEDIA: + case self::BINARY_MEDIA: + $typeSpecificData = + Transform::toGUID($this->_typeSpecificData["majorMediaType"]) . + Transform::toGUID($this->_typeSpecificData["mediaSubtype"]) . + Transform::toUInt32LE($this->_typeSpecificData["fixedSizeSamples"]) . + Transform::toUInt32LE($this->_typeSpecificData["temporalCompression"]) . + Transform::toUInt32LE($this->_typeSpecificData["sampleSize"]) . + Transform::toGUID($this->_typeSpecificData["formatType"]) . + Transform::toUInt32LE(strlen($this->_typeSpecificData["formatData"])) . + $this->_typeSpecificData["formatData"]; + break; + case self::COMMAND_MEDIA: + default: + $typeSpecificData = ""; + } + switch ($this->_errorCorrectionType) { + case self::AUDIO_SPREAD: + $errorCorrectionData = + Transform::toInt8($this->_errorCorrectionData["span"]) . + Transform::toUInt16LE + ($this->_errorCorrectionData["virtualPacketLength"]) . + Transform::toUInt16LE + ($this->_errorCorrectionData["virtualChunkLength"]) . + Transform::toUInt16LE + (strlen($this->_errorCorrectionData["silenceData"])) . + $this->_errorCorrectionData["silenceData"]; + break; + case self::NO_ERROR_CORRECTION: + default: + $errorCorrectionData = ""; + } + + $data .= + Transform::toUInt32LE(strlen($typeSpecificData)) . + Transform::toUInt32LE(strlen($errorCorrectionData)) . + Transform::toUInt16LE($this->_flags) . + Transform::toUInt32LE($this->_reserved) . + $typeSpecificData . $errorCorrectionData; + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } } diff --git a/src/ASF/Object/Unknown.php b/src/ASF/Object/Unknown.php new file mode 100644 index 0000000..73f726b --- /dev/null +++ b/src/ASF/Object/Unknown.php @@ -0,0 +1,87 @@ +Unknown Object represents objects that are not known to the + * library. + * + * @package php-reader + * @subpackage ASF + * @author Sven Vollbehr + * @copyright Copyright (c) 2009 The PHP Reader Project Workgroup + * @license http://code.google.com/p/php-reader/wiki/License New BSD License + * @version $Rev$ + */ +final class ASF_Object_Unknown extends ASF_Object +{ + /** + * Returns the whether the object is required to be present, or whether + * minimum cardinality is 1. + * + * @return boolean + */ + public function isMandatory() { return false; } + + /** + * Returns whether multiple instances of this object can be present, or + * whether maximum cardinality is greater than 1. + * + * @return boolean + */ + public function isMultiple() { return true; } + + /** + * Returns the object data with headers. + * + * @return string + */ + public function __toString() + { + $offset = $this->_reader->getOffset(); + $this->_reader->setOffset($this->getOffset() + 24 /* for header */); + $data = $this->_reader->read($this->getSize() - 24 /* for header */); + $this->_reader->setOffset($offset); + $this->setSize(24 /* for header */ + strlen($data)); + return + Transform::toGUID($this->getIdentifier()) . + Transform::toInt64LE($this->getSize()) . $data; + } +}