r60492 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r60491‎ | r60492 | r60493 >
Date:08:16, 30 December 2009
Author:tstarling
Status:deferred
Tags:
Comment:
(bug 19476) Fixed out-of-memory errors. Store data only for the first few pages, instead of for every one of the hundreds of thousands of pages that make up a substantial vorbis stream. Tested for Vorbis and Theora, not tested for FLAC and Speex.
Modified paths:
  • /trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg.php (modified) (history)
  • /trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Bitstream.php (modified) (history)
  • /trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Flac.php (modified) (history)
  • /trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Media.php (modified) (history)
  • /trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Speex.php (modified) (history)

Diff [purge]

Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg.php
@@ -164,8 +164,17 @@
165165 * Total length in seconds of the entire file
166166 */
167167 var $_totalLength;
168 - var $_startOffset = false;
 168+ var $_startOffset = false;
 169+
169170 /**
 171+ * Maximum number of pages to store detailed metadata for, per stream.
 172+ * We can't store every page because there could be millions, causing an OOM.
 173+ * This must be big enough so that all the codecs can get the metadata they
 174+ * need without re-reading the file.
 175+ */
 176+ var $_maxPageCacheSize = 4;
 177+
 178+ /**
170179 * Returns an interface to an Ogg physical stream.
171180 *
172181 * This method takes the path to a local file and examines it for a physical
@@ -388,7 +397,29 @@
389398 'data_length' => $pageFinish - $pageOffset,
390399 'group' => $groupId,
391400 );
392 - $this->_streamList[$stream_serial['data']]['stream_page'][ $page_sequence['data'] ] = $page;
 401+ if ( !isset( $this->_streamList[$stream_serial['data']] ) ) {
 402+ $this->_streamList[$stream_serial['data']] = array(
 403+ 'pages' => array(),
 404+ 'data_length' => 0,
 405+ 'first_granule_pos' => null,
 406+ 'last_granule_pos' => null,
 407+ );
 408+ }
 409+ $stream =& $this->_streamList[$stream_serial['data']];
 410+ if ( count( $stream['pages'] ) < $this->_maxPageCacheSize ) {
 411+ $stream['pages'][$page_sequence['data']] = $page;
 412+ }
 413+ $stream['last_page'] = $page;
 414+ $stream['data_length'] += $page['data_length'];
 415+
 416+ # Reject -1 as a granule pos, that means no segment finished in the packet
 417+ if ( $abs_granule_pos !== 'ffffffffffffffff' ) {
 418+ if ( $stream['first_granule_pos'] === null ) {
 419+ $stream['first_granule_pos'] = $abs_granule_pos;
 420+ }
 421+ $stream['last_granule_pos'] = $abs_granule_pos;
 422+ }
 423+
393424 $pageData = null;
394425 return $page;
395426 }
@@ -432,29 +463,29 @@
433464 }
434465 // Loop through the streams, and find out what type of stream is available.
435466 $groupLengths = array();
436 - foreach ($this->_streamList as $stream_serial => $pages) {
437 - fseek($this->_filePointer, $pages['stream_page'][0]['body_offset'], SEEK_SET);
 467+ foreach ($this->_streamList as $stream_serial => $streamData) {
 468+ fseek($this->_filePointer, $streamData['pages'][0]['body_offset'], SEEK_SET);
438469 $pattern = fread($this->_filePointer, 8);
439470 if (preg_match("/" . OGG_STREAM_CAPTURE_VORBIS . "/", $pattern)) {
440471 $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_VORBIS;
441 - $stream = new File_Ogg_Vorbis($stream_serial, $pages['stream_page'], $this->_filePointer);
 472+ $stream = new File_Ogg_Vorbis($stream_serial, $streamData, $this->_filePointer);
442473 } elseif (preg_match("/" . OGG_STREAM_CAPTURE_SPEEX . "/", $pattern)) {
443474 $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_SPEEX;
444 - $stream = new File_Ogg_Speex($stream_serial, $pages['stream_page'], $this->_filePointer);
 475+ $stream = new File_Ogg_Speex($stream_serial, $streamData, $this->_filePointer);
445476 } elseif (preg_match("/" . OGG_STREAM_CAPTURE_FLAC . "/", $pattern)) {
446477 $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_FLAC;
447 - $stream = new File_Ogg_Flac($stream_serial, $pages['stream_page'], $this->_filePointer);
 478+ $stream = new File_Ogg_Flac($stream_serial, $streamData, $this->_filePointer);
448479 } elseif (preg_match("/" . OGG_STREAM_CAPTURE_THEORA . "/", $pattern)) {
449480 $this->_streamList[$stream_serial]['stream_type'] = OGG_STREAM_THEORA;
450 - $stream = new File_Ogg_Theora($stream_serial, $pages['stream_page'], $this->_filePointer);
 481+ $stream = new File_Ogg_Theora($stream_serial, $streamData, $this->_filePointer);
451482 } else {
452 - $pages['stream_type'] = "unknown";
 483+ $streamData['stream_type'] = "unknown";
453484 $stream = false;
454485 }
455486
456487 if ($stream) {
457488 $this->_streams[$stream_serial] = $stream;
458 - $group = $pages['stream_page'][0]['group'];
 489+ $group = $streamData['pages'][0]['group'];
459490 if (isset($groupLengths[$group])) {
460491 $groupLengths[$group] = max($groupLengths[$group], $stream->getLength());
461492 } else {
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Bitstream.php
@@ -43,7 +43,7 @@
4444 /**
4545 * @access private
4646 */
47 - var $_streamList;
 47+ var $_streamData;
4848 /**
4949 * @access private
5050 */
@@ -75,25 +75,12 @@
7676 function __construct($streamSerial, $streamData, $filePointer)
7777 {
7878 $this->_streamSerial = $streamSerial;
79 - $this->_streamList = $streamData;
 79+ $this->_streamData = $streamData;
8080 $this->_filePointer = $filePointer;
81 - $this->_lastGranulePos = 0;
82 - $this->_firstGranulePos = 0;
83 - // This gives an accuracy of approximately 99.7% to the streamsize of ogginfo.
84 - foreach ( $streamData as $packet ) {
85 - $this->_streamSize += $packet['data_length'];
86 - # Reject -1 as a granule pos, that means no segment finished in the packet
87 - if ( $packet['abs_granule_pos'] != 'ffffffffffffffff' ) {
88 - $currentPos = $packet['abs_granule_pos'];
89 - $this->_lastGranulePos = max($this->_lastGranulePos, $currentPos);
90 - //set the _firstGranulePos
91 - if( hexdec( $this->_firstGranulePos ) === 0){
92 - //print "on stream: $streamSerial set first gran:". $currentPos.": ". hexdec( $currentPos ) ."\n";
93 - $this->_firstGranulePos = $currentPos;
94 - }
95 - }
96 - }
97 - $this->_group = $streamData[0]['group'];
 81+ $this->_firstGranulePos = $streamData['first_granule_pos'];
 82+ $this->_lastGranulePos = $streamData['last_granule_pos'];
 83+ $this->_streamSize = $streamData['data_length'];
 84+ $this->_group = $streamData['pages'][0]['group'];
9885 }
9986
10087 /**
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Media.php
@@ -74,7 +74,7 @@
7575 */
7676 function _decodeCommonHeader($packetType, $pageOffset)
7777 {
78 - fseek($this->_filePointer, $this->_streamList[$pageOffset]['body_offset'], SEEK_SET);
 78+ fseek($this->_filePointer, $this->_streamData['pages'][$pageOffset]['body_offset'], SEEK_SET);
7979 if ($packetType !== false) {
8080 // Check if this is the correct header.
8181 $packet = unpack("Cdata", fread($this->_filePointer, 1));
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Speex.php
@@ -77,7 +77,7 @@
7878 */
7979 function _decodeHeader()
8080 {
81 - fseek($this->_filePointer, $this->_streamList[0]['body_offset'], SEEK_SET);
 81+ fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET);
8282 // The first 8 characters should be "Speex ".
8383 if (fread($this->_filePointer, 8) != 'Speex ')
8484 throw new PEAR_Exception("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
@@ -116,7 +116,7 @@
117117 */
118118 function _decodeCommentsHeader()
119119 {
120 - fseek($this->_filePointer, $this->_streamList[1]['body_offset'], SEEK_SET);
 120+ fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET);
121121 $this->_decodeBareCommentsHeader();
122122 }
123123 }
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Flac.php
@@ -62,7 +62,7 @@
6363 */
6464 function _decodeHeader()
6565 {
66 - fseek($this->_filePointer, $this->_streamList[0]['body_offset'], SEEK_SET);
 66+ fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET);
6767 // Check if this is the correct header.
6868 $packet = unpack("Cdata", fread($this->_filePointer, 1));
6969 if ($packet['data'] != 0x7f)
@@ -116,7 +116,7 @@
117117
118118 function _decodeCommentsHeader()
119119 {
120 - fseek($this->_filePointer, $this->_streamList[1]['body_offset'], SEEK_SET);
 120+ fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET);
121121 $blockHeader = File_Ogg::_readBigEndian( $this->_filePointer,
122122 array(
123123 'last_block' => 1,

Follow-up revisions

RevisionCommit summaryAuthorDate
r60495* Removed buggy stopgap solution for bug #19476 (ffmpeg2theora shell call), s...tstarling08:56, 30 December 2009

Status & tagging log