Add support for Vorbis setup header

git-svn-id: http://php-reader.googlecode.com/svn/trunk@239 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
svollbehr
2011-06-04 09:35:48 +00:00
parent 85cee10135
commit 9e17c99318
5 changed files with 133 additions and 20 deletions

View File

@@ -47,7 +47,7 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
private $_pages = array(); private $_pages = array();
/** @var integer */ /** @var integer */
private $_currentPage = 0; private $_currentPageNumber = 0;
/** @var integer */ /** @var integer */
private $_currentPagePosition = 0; private $_currentPagePosition = 0;
@@ -65,13 +65,15 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
$fileSize = $reader->getSize(); $fileSize = $reader->getSize();
while ($reader->getOffset() < $fileSize) { while ($reader->getOffset() < $fileSize) {
$this->_pages[] = array( $this->_pages[] = array(
'page' => $page = new Zend_Media_Ogg_Page($reader), 'offset' => $reader->getOffset(),
'offset' => $reader->getOffset() 'page' => $page = new Zend_Media_Ogg_Page($reader)
); );
$this->_size += $page->getPageSize(); $this->_size += $page->getPageSize();
$reader->skip($page->getPageSize()); $reader->skip($page->getPageSize());
} }
$reader->setOffset($this->_pages[$this->_currentPage]['offset']); $reader->setOffset
($this->_pages[$this->_currentPageNumber]['offset'] +
$this->_pages[$this->_currentPageNumber]['page']->getHeaderSize());
$this->_fd = $reader->getFileDescriptor(); $this->_fd = $reader->getFileDescriptor();
} }
@@ -84,7 +86,7 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
public function getOffset() public function getOffset()
{ {
$offset = 0; $offset = 0;
for ($i = 0; $i < $this->_currentPage; $i++) { for ($i = 0; $i < $this->_currentPageNumber; $i++) {
$offset += $this->_pages[$i]['page']->getPageSize(); $offset += $this->_pages[$i]['page']->getPageSize();
} }
return $offset += $this->_currentPagePosition; return $offset += $this->_currentPagePosition;
@@ -102,9 +104,11 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
$streamSize = 0; $streamSize = 0;
for ($i = 0, $pageCount = count($this->_pages); $i < $pageCount; $i++) { for ($i = 0, $pageCount = count($this->_pages); $i < $pageCount; $i++) {
if (($streamSize + $this->_pages[$i]['page']->getPageSize()) >= $offset) { if (($streamSize + $this->_pages[$i]['page']->getPageSize()) >= $offset) {
$this->_currentPage = $i; $this->_currentPageNumber = $i;
$this->_currentPagePosition = $offset - $streamSize; $this->_currentPagePosition = $offset - $streamSize;
parent::setOffset($this->_pages[$i]['offset'] + $this->_currentPagePosition); parent::setOffset
($this->_pages[$i]['offset'] + $this->_pages[$i]['page']->getHeaderSize() +
$this->_currentPagePosition);
break; break;
} }
$streamSize += $this->_pages[$i]['page']->getPageSize(); $streamSize += $this->_pages[$i]['page']->getPageSize();
@@ -120,12 +124,12 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
*/ */
public function skip($size) public function skip($size)
{ {
$currentPageSize = $this->_pages[$this->_currentPage]['page']->getPageSize(); $currentPageSize = $this->_pages[$this->_currentPageNumber]['page']->getPageSize();
if (($this->_currentPagePosition + $size) >= $currentPageSize) { if (($this->_currentPagePosition + $size) >= $currentPageSize) {
parent::skip parent::skip
(($currentPageSize - $this->_currentPagePosition) + (($currentPageSize - $this->_currentPagePosition) +
$this->_pages[++$this->_currentPage]['page']->getHeaderSize() + $this->_pages[++$this->_currentPageNumber]['page']->getHeaderSize() +
($this->_currentPagePosition = ($size - $currentPageSize - $this->_currentPagePosition))); ($this->_currentPagePosition = ($size - ($currentPageSize - $this->_currentPagePosition))));
} else { } else {
$this->_currentPagePosition += $size; $this->_currentPagePosition += $size;
parent::skip($size); parent::skip($size);
@@ -141,10 +145,10 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
*/ */
public function read($length) public function read($length)
{ {
$currentPageSize = $this->_pages[$this->_currentPage]['page']->getPageSize(); $currentPageSize = $this->_pages[$this->_currentPageNumber]['page']->getPageSize();
if (($this->_currentPagePosition + $length) >= $currentPageSize) { if (($this->_currentPagePosition + $length) >= $currentPageSize) {
$buffer = parent::read($currentPageSize - $this->_currentPagePosition); $buffer = parent::read($currentPageSize - $this->_currentPagePosition);
parent::skip($this->_pages[++$this->_currentPage]['page']->getHeaderSize()); parent::skip($this->_pages[++$this->_currentPageNumber]['page']->getHeaderSize());
return $buffer . parent::read return $buffer . parent::read
($this->_currentPagePosition = ($length - ($currentPageSize - $this->_currentPagePosition))); ($this->_currentPagePosition = ($length - ($currentPageSize - $this->_currentPagePosition)));
} else { } else {
@@ -153,4 +157,35 @@ final class Zend_Media_Ogg_Reader extends Zend_Io_Reader
return $buffer; return $buffer;
} }
} }
/**
* Returns the underlying Ogg page at given number.
*
* @param integer $pageNumber The number of the page to return.
* @return Zend_Media_Ogg_Page
*/
public function getPage($pageNumber)
{
return $this->_pages[$pageNumber]['page'];
}
/**
* Returns the underlying Ogg page number.
*
* @return integer
*/
public function getCurrentPageNumber()
{
return $this->_currentPageNumber;
}
/**
* Returns the underlying Ogg page position, in bytes.
*
* @return integer
*/
public function getCurrentPagePosition()
{
return $this->_currentPagePosition;
}
} }

View File

@@ -61,11 +61,11 @@ final class Zend_Media_Vorbis
/** @var Zend_Media_Vorbis_Header_Comment */ /** @var Zend_Media_Vorbis_Header_Comment */
private $_commentHeader; private $_commentHeader;
// /** @var Zend_Media_Vorbis_Header_Setup */ /** @var Zend_Media_Vorbis_Header_Setup */
// private $_setupHeader; private $_setupHeader;
/** /**
* Constructs the . * Constructs the Zend_Media_Vorbis class with given file.
* *
* @param string|resource|Zend_Io_Reader $filename The path to the file, * @param string|resource|Zend_Io_Reader $filename The path to the file,
* file descriptor of an opened file, or a {@link Zend_Io_Reader} instance. * file descriptor of an opened file, or a {@link Zend_Io_Reader} instance.
@@ -90,7 +90,7 @@ final class Zend_Media_Vorbis
$this->_identificationHeader = new Zend_Media_Vorbis_Header_Identification($this->_reader); $this->_identificationHeader = new Zend_Media_Vorbis_Header_Identification($this->_reader);
$this->_commentHeader = new Zend_Media_Vorbis_Header_Comment($this->_reader); $this->_commentHeader = new Zend_Media_Vorbis_Header_Comment($this->_reader);
// $this->_setupHeader = new Zend_Media_Vorbis_Header_Setup($this->_reader); $this->_setupHeader = new Zend_Media_Vorbis_Header_Setup($this->_reader);
} }
/** /**
@@ -120,9 +120,7 @@ final class Zend_Media_Vorbis
*/ */
public function getSetupHeader() public function getSetupHeader()
{ {
require_once 'Zend/Media/Vorbis/Exception.php'; return $this->_setupHeader;
throw new Zend_Media_Vorbis_Exception('Not yet supported');
// return $this->_setupHeader;
} }
/** /**

View File

@@ -53,6 +53,9 @@ abstract class Zend_Media_Vorbis_Header
*/ */
protected $_packetType; protected $_packetType;
/** $var integer */
protected $_packetSize = 0;
/** /**
* Constructs the class with given parameters. * Constructs the class with given parameters.
* *
@@ -62,7 +65,6 @@ abstract class Zend_Media_Vorbis_Header
public function __construct($reader) public function __construct($reader)
{ {
$this->_reader = $reader; $this->_reader = $reader;
if (!in_array($this->_packetType = $this->_reader->readUInt8(), array(1, 3, 5))) { if (!in_array($this->_packetType = $this->_reader->readUInt8(), array(1, 3, 5))) {
require_once 'Zend/Media/Vorbis/Exception.php'; require_once 'Zend/Media/Vorbis/Exception.php';
throw new Zend_Media_Vorbis_Exception('Unknown header packet type: ' . $this->_packetType); throw new Zend_Media_Vorbis_Exception('Unknown header packet type: ' . $this->_packetType);
@@ -71,6 +73,28 @@ abstract class Zend_Media_Vorbis_Header
require_once 'Zend/Media/Vorbis/Exception.php'; require_once 'Zend/Media/Vorbis/Exception.php';
throw new Zend_Media_Vorbis_Exception('Unknown header packet: ' . $vorbis); throw new Zend_Media_Vorbis_Exception('Unknown header packet: ' . $vorbis);
} }
$skipBytes = $this->_reader->getCurrentPagePosition();
for ($page = $this->_reader->getCurrentPageNumber(); /* goes on until we find packet end */; $page++) {
$segments = $this->_reader->getPage($page)->getSegmentTable();
for ($i = 0, $skippedSegments = 0; $i < count($segments); $i++) {
// Skip page segments that are already read in
if ($skipBytes > $segments[$i]) {
$skipBytes -= $segments[$i];
continue;
}
// Skip segments that are full
if ($segments[$i] == 255 && ++$skippedSegments) {
continue;
}
// Record packet size from the first non-255 segment
$this->_packetSize += $i * 255 + $segments[$i];
break 2;
}
$this->_packetSize += $skippedSegments * 255;
}
} }
/** /**

View File

@@ -87,6 +87,7 @@ final class Zend_Media_Vorbis_Header_Comment extends Zend_Media_Vorbis_Header
require_once 'Zend/Media/Vorbis/Exception.php'; require_once 'Zend/Media/Vorbis/Exception.php';
throw new Zend_Media_Vorbis_Exception('Undecodable Vorbis stream'); throw new Zend_Media_Vorbis_Exception('Undecodable Vorbis stream');
} }
$this->_reader->skip($this->_packetSize - $this->_reader->getOffset() + 30 /* header */);
} }
/** /**

View File

@@ -0,0 +1,55 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Media
* @subpackage Vorbis
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**#@+ @ignore */
require_once 'Zend/Media/Vorbis/Header.php';
/**#@-*/
/**
* The setup header contains the bulk of the codec setup information needed for decode. The setup header contains, in
* order, the lists of codebook con gurations, time-domain transform con gurations (placeholders in Vorbis I), oor con
* gurations, residue con gurations, channel mapping con gurations and mode con gurations. It finishes with a framing
* bit of '1'.
*
* @category Zend
* @package Zend_Media
* @subpackage Vorbis
* @author Sven Vollbehr <sven@vollbehr.eu>
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
* @todo Implementation
*/
final class Zend_Media_Vorbis_Header_Setup extends Zend_Media_Vorbis_Header
{
/**
* Constructs the class with given parameters.
*
* @param Zend_Io_Reader $reader The reader object.
*/
public function __construct($reader)
{
parent::__construct($reader);
$this->_reader->skip($this->_packetSize - 7 /* header */);
}
}