* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev: 107 $ */ abstract class MPEG_Object { /** * The reader object. * * @var Reader */ protected $_reader; /** * The options array. * * @var Array */ private $_options; /** * Constructs the class with given parameters. * * @param Reader $reader The reader object. * @param Array $options The options array. */ public function __construct($reader, &$options = array()) { $this->_reader = $reader; $this->_options = &$options; } /** * Returns the options array. * * @return Array */ public function getOptions() { return $this->_options; } /** * Returns the given option value, or the default value if the option is not * defined. * * @param string $option The name of the option. * @param mixed $defaultValue The default value to be returned. */ public function getOption($option, $defaultValue = false) { if (isset($this->_options[$option])) return $this->_options[$option]; return $defaultValue; } /** * Sets the options array. See {@link MPEG} class for available options. * * @param Array $options The options array. */ public function setOptions(&$options) { $this->_options = &$options; } /** * Sets the given option the given value. * * @param string $option The name of the option. * @param mixed $value The value to set for the option. */ public function setOption($option, $value) { $this->_options[$option] = $value; } /** * Finds and returns the next start code. Start codes are reserved bit * patterns in the video file that do not otherwise occur in the video stream. * * All start codes are byte aligned and start with the following byte * sequence: 0x00 0x00 0x01. * * @return integer */ protected function nextStartCode() { $buffer = " "; for ($i = 0; $i < 4; $i++) { $start = $this->_reader->getOffset(); if (($buffer = substr($buffer, -4) . $this->_reader->read(512)) === false) throw new MPEG_Exception("Invalid data"); $limit = strlen($buffer); $pos = 0; while ($pos < $limit - 3) { if (Transform::fromUInt8($buffer{$pos++}) == 0 && Transform::fromUInt16BE(substr($buffer, $pos, 2)) == 1) { if (($pos += 2) < $limit - 2) if (Transform::fromUInt16BE(substr($buffer, $pos, 2)) == 0 && Transform::fromUInt8($buffer{$pos + 2}) == 1) continue; $this->_reader->setOffset($start + $pos - 3); return Transform::fromUInt8($buffer{$pos++}) & 0xff | 0x100; } } $this->_reader->setOffset($start + $limit); } /* No start code found within 2048 bytes, the maximum size of a pack */ throw new MPEG_Exception("Invalid data"); } /** * Finds and returns the previous start code. Start codes are reserved bit * patterns in the video file that do not otherwise occur in the video stream. * * All start codes are byte aligned and start with the following byte * sequence: 0x00 0x00 0x01. * * @return integer */ protected function prevStartCode() { $buffer = " "; $start; $position = $this->_reader->getOffset(); while ($position > 0) { $start = 0; $position = $position - 512; if ($position < 0) throw new MPEG_Exception("Invalid data"); $this->_reader->setOffset($position); $buffer = $this->_reader->read(512) . substr($buffer, 0, 4); $pos = 512 - 8; while ($pos > 3) { if (Transform::fromUInt8($buffer{$pos}) == 0 && Transform::fromUInt16BE(substr($buffer, $pos + 1, 2)) == 1) { if ($pos + 2 < 512 && Transform::fromUInt16BE(substr($buffer, $pos + 3, 2)) == 0 && Transform::fromUInt8($buffer{$pos + 5}) == 1) { $pos --; continue; } $this->_reader->setOffset($position + $pos); return Transform::fromUInt8($buffer{$pos + 3}) & 0xff | 0x100; } $pos--; } $this->_reader->setOffset($position = $position + 3); } return 0; } /** * Formats given time in seconds into the form of * [hours]:minutes:seconds.milliseconds. * * @param integer $seconds The time to format, in seconds * @return string */ protected function formatTime($seconds) { $milliseconds = round(($seconds - floor($seconds)) * 1000); $seconds = floor($seconds); $minutes = floor($seconds / 60); $hours = floor($minutes / 60); return ($minutes > 0 ? ($hours > 0 ? $hours . ":" . str_pad($minutes % 60, 2, "0", STR_PAD_LEFT) : $minutes % 60) . ":" . str_pad($seconds % 60, 2, "0", STR_PAD_LEFT) : $seconds % 60) . "." . str_pad($milliseconds, 3, "0", STR_PAD_LEFT); } /** * Magic function so that $obj->value will work. * * @param string $name The field name. * @return mixed */ public function __get($name) { if (method_exists($this, "get" . ucfirst($name))) return call_user_func(array($this, "get" . ucfirst($name))); else throw new MPEG_Exception("Unknown field: " . $name); } /** * Magic function so that assignments with $obj->value will work. * * @param string $name The field name. * @param string $value The field value. * @return mixed */ public function __set($name, $value) { if (method_exists($this, "set" . ucfirst($name))) call_user_func (array($this, "set" . ucfirst($name)), $value); else throw new MPEG_Exception("Unknown field: " . $name); } }