Stream Properties Object defines the specific properties and
* characteristics of a digital media stream. This object defines how a digital
* media stream within the Data Object is interpreted, as well as the
* specific format (of elements) of the Data Packet itself.
*
* Whereas every stream in an ASF presentation, including each stream in a
* mutual exclusion relationship, must be represented by a Stream Properties
* Object, in certain cases, this object might be found embedded in the
* Extended Stream Properties Object.
*
* @package php-reader
* @subpackage ASF
* @author Sven Vollbehr
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev: 102 $
*/
final class ASF_Object_StreamProperties extends ASF_Object
{
/**
* Indicates, if set, that the data contained in this stream is encrypted and
* will be unreadable unless there is a way to decrypt the stream.
*/
const ENCRYPTED_CONTENT = 0x8000;
const AUDIO_MEDIA = "f8699e40-5b4d-11cf-a8fd-00805f5c442b";
const VIDEO_MEDIA = "bc19efc0-5b4d-11cf-a8fd-00805f5c442b";
const COMMAND_MEDIA = "59dacfc0-59e6-11d0-a3ac-00a0c90348f6";
const JFIF_MEDIA = "b61be100-5b4e-11cf-a8fD-00805f5c442b";
const DEGRADABLE_JPEG_MEDIA = "35907dE0-e415-11cf-a917-00805f5c442b";
const FILE_TRANSFER_MEDIA = "91bd222c-f21c-497a-8b6d-5aa86bfc0185";
const BINARY_MEDIA = "3afb65e2-47ef-40f2-ac2c-70a90d71d343";
const NO_ERROR_CORRECTION = "20fb5700-5b55-11cf-a8fd-00805f5c442b";
const AUDIO_SPREAD = "bfc3cd50-618f-11cf-8bb2-00aa00b4e220";
/** @var string */
private $_streamType;
/** @var string */
private $_errorCorrectionType;
/** @var integer */
private $_timeOffset;
/** @var integer */
private $_flags;
/** @var Array */
private $_typeSpecificData = array();
/** @var Array */
private $_errorCorrectionData = array();
/**
* Constructs the class with given parameters and reads object related data
* from the ASF file.
*
* @param Reader $reader The reader object.
* @param Array $options The options array.
*/
public function __construct($reader, &$options = array())
{
parent::__construct($reader, $options);
$this->_streamType = $this->_reader->readGUID();
$this->_errorCorrectionType = $this->_reader->readGUID();
$this->_timeOffset = $this->_reader->readInt64LE();
$typeSpecificDataLength = $this->_reader->readUInt32LE();
$errorCorrectionDataLength = $this->_reader->readUInt32LE();
$this->_flags = $this->_reader->readUInt16LE();
$this->_reader->skip(4);
switch ($this->_streamType) {
case self::AUDIO_MEDIA:
$this->_typeSpecificData = array
("codecId" => $this->_reader->readUInt16LE(),
"numberOfChannels" => $this->_reader->readUInt16LE(),
"samplesPerSecond" => $this->_reader->readUInt32LE(),
"avgNumBytesPerSecond" => $this->_reader->readUInt32LE(),
"blockAlignment" => $this->_reader->readUInt16LE(),
"bitsPerSample" => $this->_reader->readUInt16LE());
$codecSpecificDataSize = $this->_reader->readUInt16LE();
$this->_typeSpecificData["codecSpecificData"] =
$this->_reader->read($codecSpecificDataSize);
break;
case self::VIDEO_MEDIA:
$this->_typeSpecificData = array
("encodedImageWidth" => $this->_reader->readUInt32LE(),
"encodedImageHeight" => $this->_reader->readUInt32LE(),
"reservedFlags" => $this->_reader->readInt8());
$this->_reader->skip(2);
$formatDataSize = $this->_reader->readUInt32LE();
$this->_typeSpecificData = array_merge
($this->_typeSpecificData, array
("imageWidth" => $this->_reader->readUInt32LE(),
"imageHeight" => $this->_reader->readUInt32LE(),
"reserved" => $this->_reader->readUInt16LE(),
"bitsPerPixelCount" => $this->_reader->readUInt16LE(),
"compressionId" => $this->_reader->readUInt32LE(),
"imageSize" => $this->_reader->readUInt32LE(),
"horizontalPixelsPerMeter" => $this->_reader->readUInt32LE(),
"verticalPixelsPerMeter" => $this->_reader->readUInt32LE(),
"colorsUsedCount" => $this->_reader->readUInt32LE(),
"importantColorsCount" => $this->_reader->readUInt32LE(),
"codecSpecificData" => $this->_reader->read($formatDataSize - 38)));
break;
case self::JFIF_MEDIA:
$this->_typeSpecificData = array
("imageWidth" => $this->_reader->readUInt32LE(),
"imageHeight" => $this->_reader->readUInt32LE(),
"reserved" => $this->_reader->readUInt32LE());
break;
case self::DEGRADABLE_JPEG_MEDIA:
$this->_typeSpecificData = array
("imageWidth" => $this->_reader->readUInt32LE(),
"imageHeight" => $this->_reader->readUInt32LE(),
$this->_reader->readUInt16LE(),
$this->_reader->readUInt16LE(),
$this->_reader->readUInt16LE());
$interchangeDataSize = $this->_reader->readUInt16LE();
if ($interchangeDataSize == 0)
$interchangeDataSize++;
$this->_typeSpecificData["interchangeData"] =
$this->_reader->read($interchangeDataSize);
break;
case self::FILE_TRANSFER_MEDIA:
case self::BINARY_MEDIA:
$this->_typeSpecificData = array
("majorMediaType" => $this->_reader->getGUID(),
"mediaSubtype" => $this->_reader->getGUID(),
"fixedSizeSamples" => $this->_reader->readUInt32LE(),
"temporalCompression" => $this->_reader->readUInt32LE(),
"sampleSize" => $this->_reader->readUInt32LE(),
"formatType" => $this->_reader->getGUID());
$formatDataSize = $this->_reader->readUInt32LE();
$this->_typeSpecificData["formatData"] =
$this->_reader->read($formatDataSize);
break;
case self::COMMAND_MEDIA:
default:
$this->_reader->skip($typeSpecificDataLength);
}
switch ($this->_errorCorrectionType) {
case self::AUDIO_SPREAD:
$this->_errorCorrectionData = array
("span" => $this->_reader->readInt8(),
"virtualPacketLength" => $this->_reader->readUInt16LE(),
"virtualChunkLength" => $this->_reader->readUInt16LE());
$silenceDataSize = $this->_reader->readUInt16LE();
$this->_errorCorrectionData["silenceData"] =
$this->_reader->read($silenceDataSize);
break;
case self::NO_ERROR_CORRECTION:
default:
$this->_reader->skip($errorCorrectionDataLength);
}
}
/**
* Returns the number of this stream. 0 is an invalid stream. Valid values are
* between 1 and 127. The numbers assigned to streams in an ASF presentation
* may be any combination of unique values; parsing logic must not assume that
* streams are numbered sequentially.
*
* @return integer
*/
public function getStreamNumber() { return $this->_flags & 0x3f; }
/**
* Returns the type of the stream (for example, audio, video, and so on).
*
* @return string
*/
public function getStreamType() { return $this->_streamType; }
/**
* Returns the error correction type used by this digital media stream. For
* streams other than audio, this value should be set to NO_ERROR_CORRECTION.
* For audio streams, this value should be set to AUDIO_SPREAD.
*
* @return string
*/
public function getErrorCorrectionType()
{
return $this->_errorCorrectionType;
}
/**
* Returns the presentation time offset of the stream in 100-nanosecond units.
* The value of this field is added to all of the timestamps of the samples in
* the stream. This value shall be equal to the send time of the first
* interleaved packet in the data section. The value of this field is
* typically 0. It is non-zero in the case when an ASF file is edited and it
* is not possible for the editor to change the presentation times and send
* times of ASF packets. Note that if more than one stream is present in an
* ASF file the offset values of all stream properties objects must be equal.
*
* @return integer
*/
public function getTimeOffset() { return $this->_timeOffset; }
/**
* Checks whether or not the flag is set. Returns true if the flag
* is set, false otherwise.
*
* @param integer $flag The flag to query.
* @return boolean
*/
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; }
/**
* Returns the flags field.
*
* @return integer
*/
public function getFlags() { return $this->_flags; }
/**
* Returns type-specific format data. The structure for the Type-Specific
* Data field is determined by the value stored in the Stream Type
* field.
*
* The type-specific data is returned as key-value pairs of an associate
* array.
*
* @return Array
*/
public function getTypeSpecificData() { return $this->_typeSpecificData; }
/**
* Returns data specific to the error correction type. The structure for the
* Error Correction Data field is determined by the value stored in the
* Error Correction Type field. For example, an audio data stream might
* need to know how codec chunks were redistributed, or it might need a sample
* of encoded silence.
*
* The error correction type-specific data is returned as key-value pairs of
* an associate array.
*
* @return integer
*/
public function getErrorCorrectionData()
{
return $this->_errorCorrectionData;
}
}