Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg.php |
— | — | @@ -164,8 +164,17 @@ |
165 | 165 | * Total length in seconds of the entire file |
166 | 166 | */ |
167 | 167 | var $_totalLength; |
168 | | - var $_startOffset = false; |
| 168 | + var $_startOffset = false; |
| 169 | + |
169 | 170 | /** |
| 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 | + /** |
170 | 179 | * Returns an interface to an Ogg physical stream. |
171 | 180 | * |
172 | 181 | * This method takes the path to a local file and examines it for a physical |
— | — | @@ -388,7 +397,29 @@ |
389 | 398 | 'data_length' => $pageFinish - $pageOffset, |
390 | 399 | 'group' => $groupId, |
391 | 400 | ); |
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 | + |
393 | 424 | $pageData = null; |
394 | 425 | return $page; |
395 | 426 | } |
— | — | @@ -432,29 +463,29 @@ |
433 | 464 | } |
434 | 465 | // Loop through the streams, and find out what type of stream is available. |
435 | 466 | $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); |
438 | 469 | $pattern = fread($this->_filePointer, 8); |
439 | 470 | if (preg_match("/" . OGG_STREAM_CAPTURE_VORBIS . "/", $pattern)) { |
440 | 471 | $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); |
442 | 473 | } elseif (preg_match("/" . OGG_STREAM_CAPTURE_SPEEX . "/", $pattern)) { |
443 | 474 | $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); |
445 | 476 | } elseif (preg_match("/" . OGG_STREAM_CAPTURE_FLAC . "/", $pattern)) { |
446 | 477 | $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); |
448 | 479 | } elseif (preg_match("/" . OGG_STREAM_CAPTURE_THEORA . "/", $pattern)) { |
449 | 480 | $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); |
451 | 482 | } else { |
452 | | - $pages['stream_type'] = "unknown"; |
| 483 | + $streamData['stream_type'] = "unknown"; |
453 | 484 | $stream = false; |
454 | 485 | } |
455 | 486 | |
456 | 487 | if ($stream) { |
457 | 488 | $this->_streams[$stream_serial] = $stream; |
458 | | - $group = $pages['stream_page'][0]['group']; |
| 489 | + $group = $streamData['pages'][0]['group']; |
459 | 490 | if (isset($groupLengths[$group])) { |
460 | 491 | $groupLengths[$group] = max($groupLengths[$group], $stream->getLength()); |
461 | 492 | } else { |
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Bitstream.php |
— | — | @@ -43,7 +43,7 @@ |
44 | 44 | /** |
45 | 45 | * @access private |
46 | 46 | */ |
47 | | - var $_streamList; |
| 47 | + var $_streamData; |
48 | 48 | /** |
49 | 49 | * @access private |
50 | 50 | */ |
— | — | @@ -75,25 +75,12 @@ |
76 | 76 | function __construct($streamSerial, $streamData, $filePointer) |
77 | 77 | { |
78 | 78 | $this->_streamSerial = $streamSerial; |
79 | | - $this->_streamList = $streamData; |
| 79 | + $this->_streamData = $streamData; |
80 | 80 | $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']; |
98 | 85 | } |
99 | 86 | |
100 | 87 | /** |
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Media.php |
— | — | @@ -74,7 +74,7 @@ |
75 | 75 | */ |
76 | 76 | function _decodeCommonHeader($packetType, $pageOffset) |
77 | 77 | { |
78 | | - fseek($this->_filePointer, $this->_streamList[$pageOffset]['body_offset'], SEEK_SET); |
| 78 | + fseek($this->_filePointer, $this->_streamData['pages'][$pageOffset]['body_offset'], SEEK_SET); |
79 | 79 | if ($packetType !== false) { |
80 | 80 | // Check if this is the correct header. |
81 | 81 | $packet = unpack("Cdata", fread($this->_filePointer, 1)); |
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Speex.php |
— | — | @@ -77,7 +77,7 @@ |
78 | 78 | */ |
79 | 79 | function _decodeHeader() |
80 | 80 | { |
81 | | - fseek($this->_filePointer, $this->_streamList[0]['body_offset'], SEEK_SET); |
| 81 | + fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET); |
82 | 82 | // The first 8 characters should be "Speex ". |
83 | 83 | if (fread($this->_filePointer, 8) != 'Speex ') |
84 | 84 | throw new PEAR_Exception("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE); |
— | — | @@ -116,7 +116,7 @@ |
117 | 117 | */ |
118 | 118 | function _decodeCommentsHeader() |
119 | 119 | { |
120 | | - fseek($this->_filePointer, $this->_streamList[1]['body_offset'], SEEK_SET); |
| 120 | + fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET); |
121 | 121 | $this->_decodeBareCommentsHeader(); |
122 | 122 | } |
123 | 123 | } |
Index: trunk/extensions/OggHandler/PEAR/File_Ogg/File/Ogg/Flac.php |
— | — | @@ -62,7 +62,7 @@ |
63 | 63 | */ |
64 | 64 | function _decodeHeader() |
65 | 65 | { |
66 | | - fseek($this->_filePointer, $this->_streamList[0]['body_offset'], SEEK_SET); |
| 66 | + fseek($this->_filePointer, $this->_streamData['pages'][0]['body_offset'], SEEK_SET); |
67 | 67 | // Check if this is the correct header. |
68 | 68 | $packet = unpack("Cdata", fread($this->_filePointer, 1)); |
69 | 69 | if ($packet['data'] != 0x7f) |
— | — | @@ -116,7 +116,7 @@ |
117 | 117 | |
118 | 118 | function _decodeCommentsHeader() |
119 | 119 | { |
120 | | - fseek($this->_filePointer, $this->_streamList[1]['body_offset'], SEEK_SET); |
| 120 | + fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET); |
121 | 121 | $blockHeader = File_Ogg::_readBigEndian( $this->_filePointer, |
122 | 122 | array( |
123 | 123 | 'last_block' => 1, |