Source for file Theora.php
Documentation is available at Theora.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 |
// +----------------------------------------------------------------------------+
require_once('File/Ogg/Bitstream.php');
define( 'OGG_THEORA_IDENTIFICATION_HEADER', 0x80 );
define( 'OGG_THEORA_COMMENTS_HEADER', 0x81 );
define( 'OGG_THEORA_IDENTIFICATION_PAGE_OFFSET', 0 );
define( 'OGG_THEORA_COMMENTS_PAGE_OFFSET', 1 );
* @author David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
* @copyright David Grant <david@grant.org.uk>, Tim Starling <tstarling@wikimedia.org>
* @license http://www.gnu.org/copyleft/lesser.html GNU LGPL
* @link http://pear.php.net/package/File_Ogg
* @link http://www.xiph.org/theora/
* @version CVS: $Id: Theora.php 302834 2010-08-27 02:16:20Z tstarling $
function __construct ($streamSerial, $streamData, $filePointer)
parent ::__construct ($streamSerial, $streamData, $filePointer);
$this->_decodeIdentificationHeader ();
$this->_decodeCommentsHeader ();
//make sure the offset is worth taking into account oggz_chop related hack
$this->_streamLength = $endSec - $startSec;
$this->_startOffset = $startSec;
$this->_streamLength = $endSec;
$this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8 ) / $this->_streamLength : 0;
// Calculate GranulePos seconds
// First make some "numeric strings"
// These might not fit into PHP's integer type, but they will fit into
// the 53-bit mantissa of a double-precision number
// Calculate the keyframe position by shifting right by KFGSHIFT
// We don't use PHP's shift operators because they're terribly broken
// This is made slightly simpler by the fact that KFGSHIFT < 32
$keyFramePos = $topWord / pow(2 , $this->_kfgShift - 32 ) +
floor( $bottomWord / pow(2 , $this->_kfgShift) );
// Calculate the frame offset by masking off the top 64-KFGSHIFT bits
// This requires a bit of floating point trickery
$offset = fmod( $bottomWord, pow(2 , $this->_kfgShift) );
// They didn't teach you that one at school did they?
// Now put it together with the frame rate to calculate time in seconds
return ( $keyFramePos + $offset ) / $this->_frameRate;
* Get the 6-byte identification string expected in the common header
return OGG_STREAM_CAPTURE_THEORA;
* Parse the identification header in a Theora stream.
function _decodeIdentificationHeader ()
$h = File_Ogg::_readBigEndian ( $this->_filePointer, array (
throw new PEAR_Exception ("Stream is undecodable due to a truncated header.", OGG_ERROR_UNDECODABLE );
// Seems overly strict but this is what the spec says
// VREV is for backwards-compatible changes, apparently
if ( $h['VMAJ'] != 3 || $h['VMIN'] != 2 ) {
throw new PEAR_Exception ("Stream is undecodable due to an invalid theora version.", OGG_ERROR_UNDECODABLE );
$this->_theoraVersion = "{ $h['VMAJ']}.{ $h['VMIN']}.{ $h['VREV']}";
if ( !$h['FMBW'] || !$h['FMBH'] ) {
throw new PEAR_Exception ("Stream is undecodable because it has frame size of zero.", OGG_ERROR_UNDECODABLE );
$this->_frameWidth = $h['FMBW'] * 16;
$this->_frameHeight = $h['FMBH'] * 16;
if ( $h['PICW'] > $this->_frameWidth || $h['PICH'] > $this->_frameHeight ) {
throw new PEAR_Exception ("Stream is undecodable because the picture width is greater than the frame width.", OGG_ERROR_UNDECODABLE );
$this->_pictureWidth = $h['PICW'];
$this->_pictureHeight = $h['PICH'];
$this->_offsetX = $h['PICX'];
$this->_offsetY = $h['PICY'];
$this->_frameRate = $h['FRD'] == 0 ? 0 : $h['FRN'] / $h['FRD'];
if ( !$h['PARN'] || !$h['PARD'] ) {
$this->_physicalAspectRatio = 1;
$this->_physicalAspectRatio = $h['PARN'] / $h['PARD'];
if ( isset ( $colorSpaces[$h['CS']] ) ) {
$this->_colorSpace = $colorSpaces[$h['CS']];
$this->_colorSpace = 'Unknown (reserved)';
$this->_nomBitrate = $h['NOMBR'];
$this->_quality = $h['QUAL'];
$this->_kfgShift = $h['KFGSHIFT'];
1 => 'Unknown (reserved)',
$this->_pixelFormat = $pixelFormats[$h['PF']];
floor( ($h['FMBW'] + 1 ) / 2 ) *
floor( ($h['FMBH'] + 1 ) / 2 ) + 2 *
floor( ($h['FMBW'] + 3 ) / 4 ) *
floor( ($h['FMBH'] + 3 ) / 4 );
$h['NBS'] = 6 * $h['FMBW'] * $h['FMBH'];
floor( ($h['FMBW'] + 1 ) / 2 ) *
floor( ($h['FMBH'] + 1 ) / 2 ) + 2 *
floor( ($h['FMBW'] + 3 ) / 4 ) *
floor( ($h['FMBH'] + 1 ) / 2 );
$h['NBS'] = 8 * $h['FMBW'] * $h['FMBH'];
3 * floor( ($h['FMBW'] + 1 ) / 2 ) *
floor( ($h['FMBH'] + 1 ) / 2 );
$h['NBS'] = 12 * $h['FMBW'] * $h['FMBH'];
$h['NSBS'] = $h['NBS'] = 0;
$h['NMBS'] = $h['FMBW'] * $h['FMBH'];
* Get an associative array containing header information about the stream
* Get a short string describing the type of the stream
* Decode the comments header
function _decodeCommentsHeader ()
$this->_decodeBareCommentsHeader ();
Documentation generated on Mon, 11 Mar 2019 15:38:25 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|