Paladox has uploaded a new change for review. https://gerrit.wikimedia.org/r/145562
Change subject: Update OggHandler ...................................................................... Update OggHandler * Adds support for Opus codac * Updates File_Ogg to 0.3.1 beta. File source * https://github.com/pear/File_Ogg Change-Id: Icd6aa705e8d3b3496bc68fd80bdb0a617e39d006 --- M OggHandler.php A PEAR/File_Ogg/.gitignore M PEAR/File_Ogg/File/Ogg.php M PEAR/File_Ogg/File/Ogg/Bitstream.php M PEAR/File_Ogg/File/Ogg/Flac.php M PEAR/File_Ogg/File/Ogg/Media.php A PEAR/File_Ogg/File/Ogg/Opus.php M PEAR/File_Ogg/File/Ogg/Speex.php M PEAR/File_Ogg/File/Ogg/Theora.php M PEAR/File_Ogg/File/Ogg/Vorbis.php D PEAR/File_Ogg/File/README A PEAR/File_Ogg/composer.json M PEAR/File_Ogg/package.xml M i18n/ru.json 14 files changed, 267 insertions(+), 75 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/OggHandler refs/changes/62/145562/1 diff --git a/OggHandler.php b/OggHandler.php index 72aff4a..65b76ef 100644 --- a/OggHandler.php +++ b/OggHandler.php @@ -57,7 +57,7 @@ * These types will be described as audio, but only Vorbis is widely supported * by the client-side plugins. */ -$wgOggAudioTypes = array( 'Vorbis', 'Speex', 'FLAC' ); +$wgOggAudioTypes = array( 'Vorbis', 'Speex', 'FLAC', 'Opus' ); /** * Location of the FFmpeg binary, or false to use oggThumb. See the notes diff --git a/PEAR/File_Ogg/.gitignore b/PEAR/File_Ogg/.gitignore new file mode 100644 index 0000000..869f498 --- /dev/null +++ b/PEAR/File_Ogg/.gitignore @@ -0,0 +1,4 @@ +# composer related +composer.lock +composer.phar +vendor diff --git a/PEAR/File_Ogg/File/Ogg.php b/PEAR/File_Ogg/File/Ogg.php index ce7a94f..1c29bd9 100644 --- a/PEAR/File_Ogg/File/Ogg.php +++ b/PEAR/File_Ogg/File/Ogg.php @@ -28,7 +28,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL * @link http://pear.php.net/package/File_Ogg * @package File_Ogg - * @version CVS: $Id: Ogg.php,v 1.14 2005/11/19 09:06:30 djg Exp $ + * @version CVS: $Id$ */ /** @@ -47,6 +47,10 @@ * @access public */ define("OGG_STREAM_FLAC", 4); +/** + * @access public + */ +define("OGG_STREAM_OPUS", 5); /** * Capture pattern to determine if a file is an Ogg physical stream. @@ -86,6 +90,11 @@ */ define("OGG_STREAM_CAPTURE_THEORA", "theora"); /** + * Capture pattern for an Ogg Opus logical stream. + * @access private + */ +define("OGG_STREAM_CAPTURE_OPUS", "OpusHead"); +/** * Error thrown if the file location passed is nonexistant or unreadable. * * @access private @@ -118,6 +127,7 @@ require_once("File/Ogg/Speex.php"); require_once("File/Ogg/Theora.php"); require_once("File/Ogg/Vorbis.php"); +require_once("File/Ogg/Opus.php"); /** @@ -420,6 +430,7 @@ $stream['last_granule_pos'] = $abs_granule_pos; } + $pageData = null; return $page; } @@ -476,6 +487,9 @@ } elseif (preg_match("/" . OGG_STREAM_CAPTURE_THEORA . "/", $pattern)) { $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_THEORA; $stream = new File_Ogg_Theora($stream_serial, $streamData, $this->_filePointer); + } elseif (preg_match("/" . OGG_STREAM_CAPTURE_OPUS . "/", $pattern)) { + $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_OPUS; + $stream = new File_Ogg_Opus($stream_serial, $streamData, $this->_filePointer); } else { $streamData['stream_type'] = "unknown"; $stream = false; @@ -491,7 +505,7 @@ } //just store the startOffset for the first stream: if( $this->_startOffset === false ){ - $this->_startOffset = $stream->getStartOffset(); + $this->_startOffset = $stream->getStartOffset(); } } @@ -512,8 +526,8 @@ function getOverhead() { $header_size = 0; $stream_size = 0; - foreach ($this->_streams as $stream) { - foreach ($stream->_streamList as $stream_data) { + foreach ($this->_streams as $serial => $stream) { + foreach ($stream->_streamList as $offset => $stream_data) { $header_size += $stream_data['body_offset'] - $stream_data['head_offset']; $stream_size = $stream_data['body_finish']; } @@ -611,11 +625,11 @@ * * @return unknown */ - function getStartOffset(){ - if( $this->_startOffset === false) - return 0; - return $this->_startOffset; - } + function getStartOffset(){ + if( $this->_startOffset === false) + return 0; + return $this->_startOffset; + } /** * Get the total length of the group of streams */ diff --git a/PEAR/File_Ogg/File/Ogg/Bitstream.php b/PEAR/File_Ogg/File/Ogg/Bitstream.php index 1a46223..c9368c2 100644 --- a/PEAR/File_Ogg/File/Ogg/Bitstream.php +++ b/PEAR/File_Ogg/File/Ogg/Bitstream.php @@ -29,7 +29,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL * @link http://pear.php.net/package/File_Ogg * @package File_Ogg - * @version CVS: $Id: Bitstream.php,v 1.3 2005/11/08 19:36:18 djg Exp $ + * @version CVS: $Id$ */ class File_Ogg_Bitstream { diff --git a/PEAR/File_Ogg/File/Ogg/Flac.php b/PEAR/File_Ogg/File/Ogg/Flac.php index e72aac0..3651ef2 100644 --- a/PEAR/File_Ogg/File/Ogg/Flac.php +++ b/PEAR/File_Ogg/File/Ogg/Flac.php @@ -31,14 +31,14 @@ * @link http://pear.php.net/package/File_Ogg * @link http://flac.sourceforge.net/documentation.html * @package File_Ogg - * @version CVS: $Id: Flac.php,v 1.9 2005/11/16 20:43:27 djg Exp $ + * @version CVS: $Id$ */ class File_Ogg_Flac extends File_Ogg_Media { /** * @access private */ - function __construct($streamSerial, $streamData, $filePointer) + function __construct($streamSerial, $streamData, $filePointer) { parent::__construct($streamSerial, $streamData, $filePointer); $this->_decodeHeader(); diff --git a/PEAR/File_Ogg/File/Ogg/Media.php b/PEAR/File_Ogg/File/Ogg/Media.php index 2639772..46af57e 100644 --- a/PEAR/File_Ogg/File/Ogg/Media.php +++ b/PEAR/File_Ogg/File/Ogg/Media.php @@ -48,7 +48,7 @@ * Length of the stream in seconds */ var $_streamLength; - + /* Start offset of the stream in seconds */ var $_startOffset = 0; @@ -135,6 +135,23 @@ } } + /** + * 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. * @@ -228,6 +245,6 @@ * @return float */ function getStartOffset(){ - return $this->_startOffset; + return $this->_startOffset; } } diff --git a/PEAR/File_Ogg/File/Ogg/Opus.php b/PEAR/File_Ogg/File/Ogg/Opus.php new file mode 100644 index 0000000..314f85a --- /dev/null +++ b/PEAR/File_Ogg/File/Ogg/Opus.php @@ -0,0 +1,127 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------------+ +// | File_Ogg PEAR Package for Accessing Ogg Bitstreams | +// | Copyright (c) 2013 | +// | Jan Gerber <jger...@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/Media.php'); + +define( 'OGG_OPUS_COMMENTS_PAGE_OFFSET', 1 ); + +/** + * @author Jan Gerber <jger...@wikimedia.org> + * @category File + * @copyright Jan Gerber <jger...@wikimedia.org> + * @license http://www.gnu.org/copyleft/lesser.html GNU LGPL + * @link http://pear.php.net/package/File_Ogg + * @link http://www.opus-codec.org/ + * @package File_Ogg + * @version 1 + */ +class File_Ogg_Opus extends File_Ogg_Media +{ + /** + * @access private + */ + function __construct($streamSerial, $streamData, $filePointer) + { + parent::__construct($streamSerial, $streamData, $filePointer); + $this->_decodeHeader(); + $this->_decodeCommentsHeader(); + + $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos ); + $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos ); + + if( $startSec > 1){ + $this->_streamLength = $endSec - $startSec; + $this->_startOffset = $startSec; + }else{ + $this->_streamLength = $endSec; + } + $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0; + } + + function getSecondsFromGranulePos( $granulePos ){ + return (( '0x' . substr( $granulePos, 0, 8 ) ) * pow(2, 32) + + ( '0x' . substr( $granulePos, 8, 8 ) ) + - $this->_header['pre_skip']) + / 48000; + } + + /** + * Get a short string describing the type of the stream + * @return string + */ + function getType() + { + return 'Opus'; + } + + /** + * Decode the stream header + * @access private + */ + function _decodeHeader() + { + fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET); + // The first 8 characters should be "OpusHead". + if (fread($this->_filePointer, 8) != 'OpusHead') + throw new PEAR_Exception("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE); + + $this->_header = File_Ogg::_readLittleEndian($this->_filePointer, array( + 'opus_version' => 8, + 'nb_channels' => 8, + 'pre_skip' => 16, + 'audio_sample_rate' => 32, + 'output_gain' => 16, + 'channel_mapping_family'=> 8, + )); + $this->_channels = $this->_header['nb_channels']; + } + + /** + * Get an associative array containing header information about the stream + * @access public + * @return array + */ + function getHeader() { + return $this->_header; + } + + function getSampleRate() + { + //Opus always outputs 48kHz, the header only lists + //the samplerate of the source as reference + return 48000; + } + + /** + * Decode the comments header + * @access private + */ + function _decodeCommentsHeader() + { + $id = 'OpusTags'; + $this->_decodeCommonHeader(false, OGG_OPUS_COMMENTS_PAGE_OFFSET); + if(fread($this->_filePointer, strlen($id)) !== $id) + throw new PEAR_Exception("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE); + $this->_decodeBareCommentsHeader(); + } +} +?> diff --git a/PEAR/File_Ogg/File/Ogg/Speex.php b/PEAR/File_Ogg/File/Ogg/Speex.php index 27f4496..ac0ba04 100644 --- a/PEAR/File_Ogg/File/Ogg/Speex.php +++ b/PEAR/File_Ogg/File/Ogg/Speex.php @@ -31,7 +31,7 @@ * @link http://pear.php.net/package/File_Ogg * @link http://www.speex.org/docs.html * @package File_Ogg - * @version CVS: $Id: Speex.php,v 1.10 2005/11/16 20:43:27 djg Exp $ + * @version CVS: $Id$ */ class File_Ogg_Speex extends File_Ogg_Media { @@ -48,18 +48,18 @@ + ( '0x' . substr( $this->_lastGranulePos, 8, 8 ) )) / $this->_header['rate']; - $startSec = + $startSec = (( '0x' . substr( $this->_firstGranulePos, 0, 8 ) ) * pow(2, 32) + ( '0x' . substr( $this->_firstGranulePos, 8, 8 ) )) / $this->_header['rate']; //make sure the offset is worth taking into account oggz_chop related hack - if( $startSec > 1){ + if( $startSec > 1){ $this->_streamLength = $endSec - $startSec; $this->_startOffset = $startSec; - }else{ + }else{ $this->_streamLength = $endSec; - } + } } /** diff --git a/PEAR/File_Ogg/File/Ogg/Theora.php b/PEAR/File_Ogg/File/Ogg/Theora.php index d93e905..6e347e7 100644 --- a/PEAR/File_Ogg/File/Ogg/Theora.php +++ b/PEAR/File_Ogg/File/Ogg/Theora.php @@ -37,7 +37,7 @@ * @link http://pear.php.net/package/File_Ogg * @link http://www.xiph.org/theora/ * @package File_Ogg - * @version CVS: $Id: Theora.php,v 1.9 2005/11/16 20:43:27 djg Exp $ + * @version CVS: $Id$ */ class File_Ogg_Theora extends File_Ogg_Media { @@ -49,22 +49,22 @@ parent::__construct($streamSerial, $streamData, $filePointer); $this->_decodeIdentificationHeader(); $this->_decodeCommentsHeader(); - $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos ); + $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos ); $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos ); //make sure the offset is worth taking into account oggz_chop related hack - if( $startSec > 1){ + if( $startSec > 1){ $this->_streamLength = $endSec - $startSec; $this->_startOffset = $startSec; - }else{ + }else{ $this->_streamLength = $endSec; - } + } $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0; } - function getSecondsFromGranulePos($granulePos){ - // Calculate GranulePos seconds + function getSecondsFromGranulePos($granulePos){ + // 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 @@ -80,8 +80,8 @@ $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; - } + return ( $keyFramePos + $offset ) / $this->_frameRate; + } /** * Get the 6-byte identification string expected in the common header */ diff --git a/PEAR/File_Ogg/File/Ogg/Vorbis.php b/PEAR/File_Ogg/File/Ogg/Vorbis.php index 8f7f379..7f7056c 100644 --- a/PEAR/File_Ogg/File/Ogg/Vorbis.php +++ b/PEAR/File_Ogg/File/Ogg/Vorbis.php @@ -81,7 +81,7 @@ * @link http://pear.php.net/package/File_Ogg * @link http://www.xiph.org/vorbis/doc/ * @package File_Ogg - * @version CVS: $Id: Vorbis.php,v 1.13 2005/11/19 09:06:32 djg Exp $ + * @version CVS: $Id$ */ class File_Ogg_Vorbis extends File_Ogg_Media { @@ -173,23 +173,23 @@ $this->_decodeCommentsHeader(OGG_VORBIS_COMMENTS_HEADER, OGG_VORBIS_COMMENTS_PAGE_OFFSET); $endSec = $this->getSecondsFromGranulePos( $this->_lastGranulePos ); - $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos ); + $startSec = $this->getSecondsFromGranulePos( $this->_firstGranulePos ); - //make sure the offset is worth taking into account oggz_chop related hack - if( $startSec > 1){ + //make sure the offset is worth taking into account oggz_chop related hack + if( $startSec > 1){ $this->_streamLength = $endSec - $startSec; $this->_startOffset = $startSec; - }else{ + }else{ $this->_streamLength = $endSec; - } + } $this->_avgBitrate = $this->_streamLength ? ($this->_streamSize * 8) / $this->_streamLength : 0; } - function getSecondsFromGranulePos( $granulePos ){ - return (( '0x' . substr( $granulePos, 0, 8 ) ) * pow(2, 32) + function getSecondsFromGranulePos( $granulePos ){ + return (( '0x' . substr( $granulePos, 0, 8 ) ) * pow(2, 32) + ( '0x' . substr( $granulePos, 8, 8 ) )) / $this->_idHeader['audio_sample_rate']; - } + } /** * Get a short string describing the type of the stream */ @@ -314,23 +314,6 @@ } /** - * 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); - } - - /** * Samples per second. * * This function returns the number of samples used per second in this @@ -388,13 +371,13 @@ { return ($this->_streamLength); } - /** + /** * Get the start offset of the stream in seconds * @access public * @return int */ function getStartOffset(){ - return ($this->_startOffset); + return ($this->_startOffset); } /** * States whether this logical stream was encoded in mono. diff --git a/PEAR/File_Ogg/File/README b/PEAR/File_Ogg/File/README deleted file mode 100644 index 16e83a5..0000000 --- a/PEAR/File_Ogg/File/README +++ /dev/null @@ -1,4 +0,0 @@ -This was originally a fork of the File_Ogg package in PEAR. I (TS) have now taken -over maintainership of that package, and have merged my work back to there, -starting with version 0.3.0. - diff --git a/PEAR/File_Ogg/composer.json b/PEAR/File_Ogg/composer.json new file mode 100644 index 0000000..af0fcdc --- /dev/null +++ b/PEAR/File_Ogg/composer.json @@ -0,0 +1,31 @@ +{ + "authors": [ + { + "email": "tstarl...@wikimedia.org", + "name": "Tim Starling", + "role": "Lead" + } + ], + "autoload": { + "psr-0": { + "File": "./" + } + }, + "description": "More info available on: http://pear.php.net/package/File_Ogg", + "include-path": [ + "./" + ], + "license": "GNU LGPL", + "name": "pear/file_ogg", + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=File_Ogg", + "source": "https://github.com/pear/File_Ogg" + }, + "type": "library", + "require": { + "pear/pear_exception": "*" + }, + "require-dev": { + "phpunit/phpunit": "*" + } +} \ No newline at end of file diff --git a/PEAR/File_Ogg/package.xml b/PEAR/File_Ogg/package.xml index c4ea13a..9e63804 100644 --- a/PEAR/File_Ogg/package.xml +++ b/PEAR/File_Ogg/package.xml @@ -13,26 +13,23 @@ <email>tstarl...@wikimedia.org</email> <active>yes</active> </lead> - <date>2008-01-31</date> - <time>15:25:07</time> + <date>2010-08-27</date> + <time>12:24:21</time> <version> - <release>0.3.0</release> - <api>0.3.0</api> + <release>0.3.1</release> + <api>0.3.1</api> </version> <stability> <release>beta</release> <api>beta</api> </stability> <license>GNU LGPL</license> - <notes>* Change in maintainership -* Added header parsing for Theora, Speex and Flac. -* Removed partially written save/encode code. -* Introduced some PHP 5 features, no longer supports PHP 4. -* Introduced convenience functions getHeader() and getComments() to retrieve metadata in associative array format. -* Fixed the error handling, using exceptions instead of inappropriate continuation. -* Added overall length calculation for multiplexed streams -* Fixed a page splitting bug - + <notes>* Updated to the version in MediaWiki trunk r71623 +* Fixed bug in theora length calculation (was always zero) +* Updated to handle oggz_chop files +* Provide access to stream offset time +* Optimised memory usage, should now be able to process arbitrarily large files + </notes> <contents> <dir name="/"> @@ -63,6 +60,29 @@ <changelog> <release> <version> + <release>0.3.0</release> + <api>0.3.0</api> + </version> + <stability> + <release>beta</release> + <api>beta</api> + </stability> + <date>2008-01-31</date> + <license>GNU LGPL</license> + <notes>* Change in maintainership +* Added header parsing for Theora, Speex and Flac. +* Removed partially written save/encode code. +* Introduced some PHP 5 features, no longer supports PHP 4. +* Introduced convenience functions getHeader() and getComments() to retrieve metadata in associative array format. +* Fixed the error handling, using exceptions instead of inappropriate continuation. +* Added overall length calculation for multiplexed streams +* Fixed a page splitting bug + + </notes> + + </release> + <release> + <version> <release>0.2.1</release> <api>0.2.1</api> </version> diff --git a/i18n/ru.json b/i18n/ru.json index 23a7899..af82c52 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -17,7 +17,7 @@ "ogg-short-general": "Медиа-файл Ogg $1, $2", "ogg-long-audio": "звуковой файл Ogg $1, длительность $2, $3", "ogg-long-video": "видео-файл Ogg $1, длительность $2, $4×$5 {{PLURAL:$5|пиксель|пикселей|пикселя}}, $3", - "ogg-long-multiplexed": "мультиплексный аудио/видео-файл Ogg, $1, длительность $2, $4×$5 {{PLURAL:$5|пиксель|пикселей|пикселя}}, $3 всего", + "ogg-long-multiplexed": "мультиплексный аудио/видеофайл Ogg, $1, длительность $2, $4×$5 {{PLURAL:$5|пиксель|пикселей|пикселя}}, $3 всего", "ogg-long-general": "медиафайл Ogg, длительность $2, $3", "ogg-long-error": "неправильный Ogg-файл: $1", "ogg-play": "Воспроизвести", -- To view, visit https://gerrit.wikimedia.org/r/145562 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Icd6aa705e8d3b3496bc68fd80bdb0a617e39d006 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/OggHandler Gerrit-Branch: master Gerrit-Owner: Paladox <thomasmulhall...@yahoo.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits