Пример #1
0
 /**
  * Decode the stream header
  * @access  private
  */
 function _decodeHeader()
 {
     fseek($this->_filePointer, $this->_streamList[0]['body_offset'], SEEK_SET);
     // The first 8 characters should be "Speex   ".
     if (fread($this->_filePointer, 8) != 'Speex   ') {
         throw new PEAR_Exception("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
     }
     $this->_version = fread($this->_filePointer, 20);
     $this->_header = File_Ogg::_readLittleEndian($this->_filePointer, array('speex_version_id' => 32, 'header_size' => 32, 'rate' => 32, 'mode' => 32, 'mode_bitstream_version' => 32, 'nb_channels' => 32, 'bitrate' => 32, 'frame_size' => 32, 'vbr' => 32, 'frames_per_packet' => 32, 'extra_headers' => 32, 'reserved1' => 32, 'reserved2' => 32));
     $this->_header['speex_version'] = $this->_version;
 }
Пример #2
0
	function getMetadata( $image, $path ) {
		$metadata = array( 'version' => self::METADATA_VERSION );

		if ( !class_exists( 'File_Ogg' ) ) {
			require( 'File/Ogg.php' );
		}
		try {
			$f = new File_Ogg( $path );
			$streams = array();
			foreach ( $f->listStreams() as $streamIDs ) {
				foreach ( $streamIDs as $streamID ) {
					$stream = $f->getStream( $streamID );
					$streams[$streamID] = array(
						'serial' => $stream->getSerial(),
						'group' => $stream->getGroup(),
						'type' => $stream->getType(),
						'vendor' => $stream->getVendor(),
						'length' => $stream->getLength(),
						'size' => $stream->getSize(),
						'header' => $stream->getHeader(),
						'comments' => $stream->getComments()
					);
				}
			}
			$metadata['streams'] = $streams;
			$metadata['length'] = $f->getLength();
			// Get the offset of the file (in cases where the file is a segment copy)
			$metadata['offset'] = $f->getStartOffset();
		} catch ( PEAR_Exception $e ) {
			// File not found, invalid stream, etc.
			$metadata['error'] = array(
				'message' => $e->getMessage(),
				'code' => $e->getCode()
			);
		}
		return serialize( $metadata );
	}
Пример #3
0
 /**
  * Parse the identification header (the first of three headers) in a Vorbis stream.
  *
  * This function parses the identification header.  The identification header
  * contains simple audio characteristics, such as sample rate and number of
  * channels.  There are a number of error-checking provisions laid down in the Vorbis
  * specification to ensure the stream is pure.
  *
  * @access  private
  */
 function _decodeIdentificationHeader()
 {
     $this->_decodeCommonHeader(OGG_VORBIS_IDENTIFICATION_HEADER, OGG_VORBIS_IDENTIFICATION_PAGE_OFFSET);
     $h = File_Ogg::_readLittleEndian($this->_filePointer, array('vorbis_version' => 32, 'audio_channels' => 8, 'audio_sample_rate' => 32, 'bitrate_maximum' => 32, 'bitrate_nominal' => 32, 'bitrate_minimum' => 32, 'blocksize_0' => 4, 'blocksize_1' => 4, 'framing_flag' => 1));
     // The Vorbis stream version must be 0.
     if ($h['vorbis_version'] == 0) {
         $this->_version = $h['vorbis_version'];
     } else {
         throw new PEAR_Exception("Stream is undecodable due to an invalid vorbis stream version.", OGG_VORBIS_ERROR_UNDECODABLE);
     }
     // The number of channels MUST be greater than 0.
     if ($h['audio_channels'] == 0) {
         throw new PEAR_Exception("Stream is undecodable due to zero channels.", OGG_VORBIS_ERROR_UNDECODABLE);
     } else {
         $this->_channels = $h['audio_channels'];
     }
     // The sample rate MUST be greater than 0.
     if ($h['audio_sample_rate'] == 0) {
         throw new PEAR_Exception("Stream is undecodable due to a zero sample rate.", OGG_VORBIS_ERROR_UNDECODABLE);
     } else {
         $this->_sampleRate = $h['audio_sample_rate'];
     }
     // Extract the various bitrates
     $this->_maxBitrate = $h['bitrate_maximum'];
     $this->_nomBitrate = $h['bitrate_nominal'];
     $this->_minBitrate = $h['bitrate_minimum'];
     // Powers of two between 6 and 13 inclusive.
     $valid_block_sizes = array(64, 128, 256, 512, 1024, 2048, 4096, 8192);
     // blocksize_0 MUST be a valid blocksize.
     $blocksize_0 = pow(2, $h['blocksize_0']);
     if (FALSE == in_array($blocksize_0, $valid_block_sizes)) {
         throw new PEAR_Exception("Stream is undecodable because blocksize_0 is {$blocksize_0}, which is not a valid size.", OGG_VORBIS_ERROR_UNDECODABLE);
     }
     // Extract bits 5 to 8 from the character data.
     // blocksize_1 MUST be a valid blocksize.
     $blocksize_1 = pow(2, $h['blocksize_1']);
     if (FALSE == in_array($blocksize_1, $valid_block_sizes)) {
         throw new PEAR_Exception("Stream is undecodable because blocksize_1 is not a valid size.", OGG_VORBIS_ERROR_UNDECODABLE);
     }
     // blocksize 0 MUST be less than or equal to blocksize 1.
     if ($blocksize_0 > $blocksize_1) {
         throw new PEAR_Exception("Stream is undecodable because blocksize_0 is not less than or equal to blocksize_1.", OGG_VORBIS_ERROR_UNDECODABLE);
     }
     // The framing bit MUST be set to mark the end of the identification header.
     // Some encoders are broken though -- TS
     /*
             if ($h['framing_flag'] == 0)
        throw new PEAR_Exception("Stream in undecodable because the framing bit is not non-zero.", OGG_VORBIS_ERROR_UNDECODABLE);
     */
     $this->_idHeader = $h;
 }
Пример #4
0
 function _decodeCommentsHeader()
 {
     fseek($this->_filePointer, $this->_streamData['pages'][1]['body_offset'], SEEK_SET);
     $blockHeader = File_Ogg::_readBigEndian($this->_filePointer, array('last_block' => 1, 'block_type' => 7, 'length' => 24));
     if ($blockHeader['block_type'] != 4) {
         throw new PEAR_Exception("Stream Undecodable", OGG_ERROR_UNDECODABLE);
     }
     $this->_decodeBareCommentsHeader();
 }
Пример #5
0
 /**
  * Parse the identification header in a Theora stream.
  * @access  private
  */
 function _decodeIdentificationHeader()
 {
     $this->_decodeCommonHeader(OGG_THEORA_IDENTIFICATION_HEADER, OGG_THEORA_IDENTIFICATION_PAGE_OFFSET);
     $h = File_Ogg::_readBigEndian($this->_filePointer, array('VMAJ' => 8, 'VMIN' => 8, 'VREV' => 8, 'FMBW' => 16, 'FMBH' => 16, 'PICW' => 24, 'PICH' => 24, 'PICX' => 8, 'PICY' => 8, 'FRN' => 32, 'FRD' => 32, 'PARN' => 24, 'PARD' => 24, 'CS' => 8, 'NOMBR' => 24, 'QUAL' => 6, 'KFGSHIFT' => 5, 'PF' => 2));
     if (!$h) {
         throw new PEAR_Exception("Stream is undecodable due to a truncated header.", OGG_ERROR_UNDECODABLE);
     }
     // Theora version
     // 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']}";
     // Frame height/width
     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;
     // Picture height/width
     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'];
     // Picture offset
     $this->_offsetX = $h['PICX'];
     $this->_offsetY = $h['PICY'];
     // Frame rate
     $this->_frameRate = $h['FRD'] == 0 ? 0 : $h['FRN'] / $h['FRD'];
     // Physical aspect ratio
     if (!$h['PARN'] || !$h['PARD']) {
         $this->_physicalAspectRatio = 1;
     } else {
         $this->_physicalAspectRatio = $h['PARN'] / $h['PARD'];
     }
     // Color space
     $colorSpaces = array(0 => 'Undefined', 1 => 'Rec. 470M', 2 => 'Rec. 470BG');
     if (isset($colorSpaces[$h['CS']])) {
         $this->_colorSpace = $colorSpaces[$h['CS']];
     } else {
         $this->_colorSpace = 'Unknown (reserved)';
     }
     $this->_nomBitrate = $h['NOMBR'];
     $this->_quality = $h['QUAL'];
     $this->_kfgShift = $h['KFGSHIFT'];
     $pixelFormats = array(0 => '4:2:0', 1 => 'Unknown (reserved)', 2 => '4:2:2', 3 => '4:4:4');
     $this->_pixelFormat = $pixelFormats[$h['PF']];
     switch ($h['PF']) {
         case 0:
             $h['NSBS'] = 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'];
             break;
         case 2:
             $h['NSBS'] = 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'];
             break;
         case 3:
             $h['NSBS'] = 3 * floor(($h['FMBW'] + 1) / 2) * floor(($h['FMBH'] + 1) / 2);
             $h['NBS'] = 12 * $h['FMBW'] * $h['FMBH'];
             break;
         default:
             $h['NSBS'] = $h['NBS'] = 0;
     }
     $h['NMBS'] = $h['FMBW'] * $h['FMBH'];
     $this->_idHeader = $h;
 }
Пример #6
0
 function loadMeta()
 {
     //load from the file:
     if (is_file($this->oggPath . OGGCHOP_META_EXT)) {
         $oggMeta = file_get_contents($this->oggPath . OGGCHOP_META_EXT);
         //check if a separate request is working on generating the file:
         if (trim($oggMeta) == 'loading') {
             if ($this->loadWaitCount >= 24) {
                 //we have waited 2 min with no luck..
                 //@@todo we should flag that ogg file as broken?
                 // and just redirect to normal output? (for now just set meta to false)
                 $this->meta = false;
                 //fail:
                 return false;
             } else {
                 //some other request is "loading" metadata sleep for 5 seconds and try again
                 sleep(5);
                 $this->loadWaitCount++;
                 return $this->loadMeta();
             }
         } else {
             $this->meta = unserialize($oggMeta);
             if ($this->meta['version'] == 'OGGCHOP_META_VERSION') {
                 //we have a good version of the metadata return true:
                 return true;
             } else {
                 $this->meta = false;
             }
         }
     }
     //if the file does not exist or $this->meta is still false::
     if (!is_file($this->oggPath . OGGCHOP_META_EXT) || $this->meta === false) {
         //set the meta file to "loading" (avoids multiple indexing requests)
         file_put_contents($this->oggPath . OGGCHOP_META_EXT, 'loading');
         //load up the File/Ogg Pear module
         if (!class_exists('File_Ogg')) {
             require 'File/Ogg.php';
         }
         $f = new File_Ogg($this->oggPath);
         $streams = array();
         $this->meta = array('version' => OGGCHOP_META_VERSION);
         foreach ($f->listStreams() as $streamType => $streamIDs) {
             foreach ($streamIDs as $streamID) {
                 $stream = $f->getStream($streamID);
                 //for now only support a fist theora stream we find:
                 if (strtolower($stream->getType()) == 'theora') {
                     $this->meta['theoraKeyFrameInx'] = $stream->getKeyFrameIndex();
                     //set the width and height:
                     $head = $stream->getHeader();
                     $this->meta['width'] = $head['PICW'];
                     $this->meta['height'] = $head['PICH'];
                     break;
                 }
                 /* more detailed per-stream metadata::
                 			 * $this->meta['streams'][$streamID] = array(
                 				'serial' => $stream->getSerial(),
                 				'group' => $stream->getGroup(),
                 				'type' => $stream->getType(),
                 				'vendor' => $stream->getVendor(),
                 				'length' => $stream->getLength(),
                 				'size' => $stream->getSize(),
                 				'header' => $stream->getHeader(),
                 				'comments' => $stream->getComments()
                 			);*/
             }
         }
         $this->meta['duration'] = $f->getLength();
         //cache the metadata::
         file_put_contents($this->oggPath . OGGCHOP_META_EXT, serialize($this->meta));
         return true;
     }
 }