diff options
Diffstat (limited to 'extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php')
-rw-r--r-- | extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php new file mode 100644 index 00000000..67ddaece --- /dev/null +++ b/extensions/TimedMediaHandler/handlers/OggHandler/File_Ogg/File/Ogg/Media.php @@ -0,0 +1,262 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------------+ +// | File_Ogg PEAR Package for Accessing Ogg Bitstreams | +// | Copyright (c) 2005-2007 | +// | David Grant <david@grant.org.uk> | +// | Tim Starling <tstarling@wikimedia.org> | +// +----------------------------------------------------------------------------+ +// | This library is free software; you can redistribute it and/or | +// | modify it under the terms of the GNU Lesser General Public | +// | License as published by the Free Software Foundation; either | +// | version 2.1 of the License, or (at your option) any later version. | +// | | +// | This library is distributed in the hope that it will be useful, | +// | but WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | Lesser General Public License for more details. | +// | | +// | You should have received a copy of the GNU Lesser General Public | +// | License along with this library; if not, write to the Free Software | +// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | +// +----------------------------------------------------------------------------+ + + +/** + * Parent class for media bitstreams + * Contains some functions common to various media formats + */ +abstract class File_Ogg_Media extends File_Ogg_Bitstream +{ + /** + * Maximum size of header comment to parse. + * Set to 1 MB by default. Make sure this is less than your PHP memory_limit. + */ + const COMMENT_MAX_SIZE = 1000000; + + /** + * Array to hold each of the comments. + * + * @access private + * @var array + */ + var $_comments = array(); + + /** + * Vendor string for the stream. + * + * @access private + * @var string + */ + var $_vendor; + + /** + * Length of the stream in seconds + */ + var $_streamLength; + + /* Start offset of the stream in seconds */ + var $_startOffset = 0; + + /** + * Get a short string describing the type of the stream + * @return string + */ + abstract function getType(); + + /** + * Get the 6-byte identification string expected in the common header + * @return string + */ + function getIdentificationString() + { + return ''; + } + + /** + * @access private + * @param int $packetType + * @param int $pageOffset + */ + function _decodeCommonHeader($packetType, $pageOffset) + { + fseek($this->_filePointer, $this->_streamData['pages'][$pageOffset]['body_offset'], SEEK_SET); + if ($packetType !== false) { + // Check if this is the correct header. + $packet = unpack("Cdata", fread($this->_filePointer, 1)); + if ($packet['data'] != $packetType) + throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE); + + // The following six characters should be equal to getIdentificationString() + $id = $this->getIdentificationString(); + if ($id !== '' && fread($this->_filePointer, strlen($id)) !== $id) + throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE); + } // else seek only, no common header + } + + /** + * Parse a Vorbis-style comments header. + * + * This function parses the comments header. The comments header contains a series of + * UTF-8 comments related to the audio encoded in the stream. This header also contains + * a string to identify the encoding software. More details on the comments header can + * be found at the following location: http://xiph.org/vorbis/doc/v-comment.html + * + * @access private + */ + function _decodeBareCommentsHeader() + { + // Decode the vendor string length as a 32-bit unsigned integer. + $vendor_len = unpack("Vdata", fread($this->_filePointer, 4)); + if ( $vendor_len['data'] > 0 ) { + // Retrieve the vendor string from the stream. + $this->_vendor = fread($this->_filePointer, $vendor_len['data']); + } else { + $this->_vendor = ''; + } + // Decode the size of the comments list as a 32-bit unsigned integer. + $comment_list_length = unpack("Vdata", fread($this->_filePointer, 4)); + // Iterate through the comments list. + for ($i = 0; $i < $comment_list_length['data']; ++$i) { + // Unpack the length of this comment. + $comment_length = unpack("Vdata", fread($this->_filePointer, 4)); + + // If the comment length is greater than specified limit, skip it. + if ( $comment_length['data'] > self::COMMENT_MAX_SIZE ) { + continue; + } + + // Comments are in the format 'ARTIST=Super Furry Animals', so split it on the equals character. + // NOTE: Equals characters are strictly prohibited in either the COMMENT or DATA parts. + $comment = explode("=", fread($this->_filePointer, $comment_length['data'])); + $comment_title = (string) $comment[0]; + $comment_value = (string) $comment[1]; + + // Check if the comment type (e.g. ARTIST) already exists. If it does, + // take the new value, and the existing value (or array) and insert it + // into a new array. This is important, since each comment type may have + // multiple instances (e.g. ARTIST for a collaboration) and we should not + // overwrite the previous value. + if (isset($this->_comments[$comment_title])) { + if (is_array($this->_comments[$comment_title])) + $this->_comments[$comment_title][] = $comment_value; + else + $this->_comments[$comment_title] = array($this->_comments[$comment_title], $comment_value); + } else + $this->_comments[$comment_title] = $comment_value; + } + } + + /** + * Number of channels used in this stream + * + * This function returns the number of channels used in this stream. This + * can range from 1 to 255, but will likely be 2 (stereo) or 1 (mono). + * + * @access public + * @return int + * @see File_Ogg_Vorbis::isMono() + * @see File_Ogg_Vorbis::isStereo() + * @see File_Ogg_Vorbis::isQuadrophonic() + */ + function getChannels() + { + return ($this->_channels); + } + + /** + * Provides a list of the comments extracted from the Vorbis stream. + * + * It is recommended that the user fully inspect the array returned by this function + * rather than blindly requesting a comment in false belief that it will always + * be present. Whilst the Vorbis specification dictates a number of popular + * comments (e.g. TITLE, ARTIST, etc.) for use in Vorbis streams, they are not + * guaranteed to appear. + * + * @access public + * @return array + */ + function getCommentList() + { + return (array_keys($this->_comments)); + } + + /** + * Provides an interface to the numerous comments located with a Vorbis stream. + * + * A Vorbis stream may contain one or more instances of each comment, so the user + * should check the variable type before printing out the result of this method. + * The situation in which multiple instances of a comment occurring are not as + * rare as one might think, since they are conceivable at least for ARTIST comments + * in the situation where a track is a duet. + * + * @access public + * @param string $commentTitle Comment title to search for, e.g. TITLE. + * @param string $separator String to separate multiple values. + * @return string + */ + function getField($commentTitle, $separator = ", ") + { + if (isset($this->_comments[$commentTitle])) { + if (is_array($this->_comments[$commentTitle])) + return (implode($separator, $this->_comments[$commentTitle])); + else + return ($this->_comments[$commentTitle]); + } else + // The comment doesn't exist in this file. The user should've called getCommentList first. + return (""); + } + + /** + * Get the entire comments array. + * May return an empty array if the bitstream does not support comments. + * + * @access public + * @return array + */ + function getComments() { + return $this->_comments; + } + + /** + * Vendor of software used to encode this stream. + * + * Gives the vendor string for the software used to encode this stream. + * It is common to find libVorbis here. The majority of encoders appear + * to use libvorbis from Xiph.org. + * + * @access public + * @return string + */ + function getVendor() + { + return ($this->_vendor); + } + + /** + * Get an associative array containing header information about the stream + * @access public + * @return array + */ + function getHeader() + { + return array(); + } + + /** + * Get the length of the stream in seconds + * @return float + */ + function getLength() + { + return $this->_streamLength; + } + /** + * Get the start offset of the stream in seconds + * + * @return float + */ + function getStartOffset(){ + return $this->_startOffset; + } +} |