|
<?php |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!defined('GETID3_INCLUDEPATH')) { |
|
exit; |
|
} |
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); |
|
|
|
class getid3_asf extends getid3_handler |
|
{ |
|
protected static $ASFIndexParametersObjectIndexSpecifiersIndexTypes = array( |
|
1 => 'Nearest Past Data Packet', |
|
2 => 'Nearest Past Media Object', |
|
3 => 'Nearest Past Cleanpoint' |
|
); |
|
|
|
protected static $ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes = array( |
|
1 => 'Nearest Past Data Packet', |
|
2 => 'Nearest Past Media Object', |
|
3 => 'Nearest Past Cleanpoint', |
|
0xFF => 'Frame Number Offset' |
|
); |
|
|
|
protected static $ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes = array( |
|
2 => 'Nearest Past Media Object', |
|
3 => 'Nearest Past Cleanpoint' |
|
); |
|
|
|
|
|
|
|
|
|
public function __construct(getID3 $getid3) { |
|
parent::__construct($getid3); |
|
|
|
|
|
$GUIDarray = $this->KnownGUIDs(); |
|
foreach ($GUIDarray as $GUIDname => $hexstringvalue) { |
|
if (!defined($GUIDname)) { |
|
define($GUIDname, $this->GUIDtoBytestring($hexstringvalue)); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
public function Analyze() { |
|
$info = &$this->getid3->info; |
|
|
|
|
|
$thisfile_audio = &$info['audio']; |
|
$thisfile_video = &$info['video']; |
|
$info['asf'] = array(); |
|
$thisfile_asf = &$info['asf']; |
|
$thisfile_asf['comments'] = array(); |
|
$thisfile_asf_comments = &$thisfile_asf['comments']; |
|
$thisfile_asf['header_object'] = array(); |
|
$thisfile_asf_headerobject = &$thisfile_asf['header_object']; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$info['fileformat'] = 'asf'; |
|
|
|
$this->fseek($info['avdataoffset']); |
|
$HeaderObjectData = $this->fread(30); |
|
|
|
$thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16); |
|
$thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']); |
|
if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) { |
|
unset($info['fileformat'], $info['asf']); |
|
return $this->error('ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}'); |
|
} |
|
$thisfile_asf_headerobject['objectsize'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8)); |
|
$thisfile_asf_headerobject['headerobjects'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 24, 4)); |
|
$thisfile_asf_headerobject['reserved1'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 28, 1)); |
|
$thisfile_asf_headerobject['reserved2'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1)); |
|
|
|
$NextObjectOffset = $this->ftell(); |
|
$ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30); |
|
$offset = 0; |
|
$thisfile_asf_streambitratepropertiesobject = array(); |
|
$thisfile_asf_codeclistobject = array(); |
|
$StreamPropertiesObjectData = array(); |
|
|
|
for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { |
|
$NextObjectGUID = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID); |
|
$NextObjectSize = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
switch ($NextObjectGUID) { |
|
|
|
case GETID3_ASF_File_Properties_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['file_properties_object'] = array(); |
|
$thisfile_asf_filepropertiesobject = &$thisfile_asf['file_properties_object']; |
|
|
|
$thisfile_asf_filepropertiesobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_filepropertiesobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_filepropertiesobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_filepropertiesobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_filepropertiesobject['fileid'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_filepropertiesobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_filepropertiesobject['fileid']); |
|
$thisfile_asf_filepropertiesobject['filesize'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['creation_date'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$thisfile_asf_filepropertiesobject['creation_date_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject['creation_date']); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['data_packets'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['play_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['send_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['preroll'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_filepropertiesobject['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001); |
|
$thisfile_asf_filepropertiesobject['flags']['seekable'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002); |
|
|
|
$thisfile_asf_filepropertiesobject['min_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_filepropertiesobject['max_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_filepropertiesobject['max_bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
|
|
if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) { |
|
|
|
|
|
unset($thisfile_asf_filepropertiesobject['filesize']); |
|
unset($thisfile_asf_filepropertiesobject['data_packets']); |
|
unset($thisfile_asf_filepropertiesobject['play_duration']); |
|
unset($thisfile_asf_filepropertiesobject['send_duration']); |
|
unset($thisfile_asf_filepropertiesobject['min_packet_size']); |
|
unset($thisfile_asf_filepropertiesobject['max_packet_size']); |
|
|
|
} else { |
|
|
|
|
|
$info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000); |
|
|
|
|
|
$info['bitrate'] = getid3_lib::SafeDiv($thisfile_asf_filepropertiesobject['filesize'] * 8, $info['playtime_seconds']); |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Stream_Properties_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$StreamPropertiesObjectData['offset'] = $NextObjectOffset + $offset; |
|
$StreamPropertiesObjectData['objectid'] = $NextObjectGUID; |
|
$StreamPropertiesObjectData['objectid_guid'] = $NextObjectGUIDtext; |
|
$StreamPropertiesObjectData['objectsize'] = $NextObjectSize; |
|
$StreamPropertiesObjectData['stream_type'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$StreamPropertiesObjectData['stream_type_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['stream_type']); |
|
$StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$StreamPropertiesObjectData['error_correct_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['error_correct_type']); |
|
$StreamPropertiesObjectData['time_offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$StreamPropertiesObjectData['type_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$StreamPropertiesObjectData['error_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$StreamPropertiesObjectData['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$StreamPropertiesObjectStreamNumber = $StreamPropertiesObjectData['flags_raw'] & 0x007F; |
|
$StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000); |
|
|
|
$offset += 4; |
|
$StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['type_data_length']); |
|
$offset += $StreamPropertiesObjectData['type_data_length']; |
|
$StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['error_data_length']); |
|
$offset += $StreamPropertiesObjectData['error_data_length']; |
|
|
|
switch ($StreamPropertiesObjectData['stream_type']) { |
|
|
|
case GETID3_ASF_Audio_Media: |
|
$thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf'); |
|
$thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr'); |
|
|
|
$audiodata = getid3_riff::parseWAVEFORMATex(substr($StreamPropertiesObjectData['type_specific_data'], 0, 16)); |
|
unset($audiodata['raw']); |
|
$thisfile_audio = getid3_lib::array_merge_noclobber($audiodata, $thisfile_audio); |
|
break; |
|
|
|
case GETID3_ASF_Video_Media: |
|
$thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf'); |
|
$thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr'); |
|
break; |
|
|
|
case GETID3_ASF_Command_Media: |
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
$thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData; |
|
unset($StreamPropertiesObjectData); |
|
break; |
|
|
|
case GETID3_ASF_Header_Extension_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['header_extension_object'] = array(); |
|
$thisfile_asf_headerextensionobject = &$thisfile_asf['header_extension_object']; |
|
|
|
$thisfile_asf_headerextensionobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_headerextensionobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_headerextensionobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_headerextensionobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_headerextensionobject['reserved_1'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']); |
|
if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) { |
|
$this->warning('header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')'); |
|
|
|
break; |
|
} |
|
$thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) { |
|
$this->warning('header_extension_object.reserved_2 ('.$thisfile_asf_headerextensionobject['reserved_2'].') does not match expected value of "6"'); |
|
|
|
break; |
|
} |
|
$thisfile_asf_headerextensionobject['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']); |
|
$unhandled_sections = 0; |
|
$thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections); |
|
if ($unhandled_sections === 0) { |
|
unset($thisfile_asf_headerextensionobject['extension_data']); |
|
} |
|
$offset += $thisfile_asf_headerextensionobject['extension_data_size']; |
|
break; |
|
|
|
case GETID3_ASF_Codec_List_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['codec_list_object'] = array(); |
|
|
|
$thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object']; |
|
|
|
$thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_codeclistobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_codeclistobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_codeclistobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_codeclistobject['reserved'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']); |
|
if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) { |
|
$this->warning('codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}'); |
|
|
|
break; |
|
} |
|
$thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
if ($thisfile_asf_codeclistobject['codec_entries_count'] > 0) { |
|
$thisfile_asf_codeclistobject['codec_entries'] = array(); |
|
} |
|
$offset += 4; |
|
for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) { |
|
|
|
$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array(); |
|
$thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter]; |
|
|
|
$thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_codeclistobject_codecentries_current['type'] = self::codecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']); |
|
|
|
$CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; |
|
$offset += 2; |
|
$thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData, $offset, $CodecNameLength); |
|
$offset += $CodecNameLength; |
|
|
|
$CodecDescriptionLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; |
|
$offset += 2; |
|
$thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData, $offset, $CodecDescriptionLength); |
|
$offset += $CodecDescriptionLength; |
|
|
|
$CodecInformationLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData, $offset, $CodecInformationLength); |
|
$offset += $CodecInformationLength; |
|
|
|
if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { |
|
|
|
if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) { |
|
$this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"'); |
|
} else { |
|
|
|
list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description'])); |
|
$thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']); |
|
|
|
if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) { |
|
$thisfile_audio['bitrate'] = (int) trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000; |
|
} |
|
|
|
if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) { |
|
|
|
$thisfile_video['bitrate'] = $info['bitrate'] - $thisfile_audio['bitrate']; |
|
} |
|
|
|
$AudioCodecFrequency = (int) trim(str_replace('kHz', '', $AudioCodecFrequency)); |
|
switch ($AudioCodecFrequency) { |
|
case 8: |
|
case 8000: |
|
$thisfile_audio['sample_rate'] = 8000; |
|
break; |
|
|
|
case 11: |
|
case 11025: |
|
$thisfile_audio['sample_rate'] = 11025; |
|
break; |
|
|
|
case 12: |
|
case 12000: |
|
$thisfile_audio['sample_rate'] = 12000; |
|
break; |
|
|
|
case 16: |
|
case 16000: |
|
$thisfile_audio['sample_rate'] = 16000; |
|
break; |
|
|
|
case 22: |
|
case 22050: |
|
$thisfile_audio['sample_rate'] = 22050; |
|
break; |
|
|
|
case 24: |
|
case 24000: |
|
$thisfile_audio['sample_rate'] = 24000; |
|
break; |
|
|
|
case 32: |
|
case 32000: |
|
$thisfile_audio['sample_rate'] = 32000; |
|
break; |
|
|
|
case 44: |
|
case 441000: |
|
$thisfile_audio['sample_rate'] = 44100; |
|
break; |
|
|
|
case 48: |
|
case 48000: |
|
$thisfile_audio['sample_rate'] = 48000; |
|
break; |
|
|
|
default: |
|
$this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')'); |
|
break; |
|
} |
|
|
|
if (!isset($thisfile_audio['channels'])) { |
|
if (strstr($AudioCodecChannels, 'stereo')) { |
|
$thisfile_audio['channels'] = 2; |
|
} elseif (strstr($AudioCodecChannels, 'mono')) { |
|
$thisfile_audio['channels'] = 1; |
|
} |
|
} |
|
|
|
} |
|
} |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Script_Command_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['script_command_object'] = array(); |
|
$thisfile_asf_scriptcommandobject = &$thisfile_asf['script_command_object']; |
|
|
|
$thisfile_asf_scriptcommandobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_scriptcommandobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_scriptcommandobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_scriptcommandobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_scriptcommandobject['reserved'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']); |
|
if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) { |
|
$this->warning('script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}'); |
|
|
|
break; |
|
} |
|
$thisfile_asf_scriptcommandobject['commands_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_scriptcommandobject['command_types_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
for ($CommandTypesCounter = 0; $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count']; $CommandTypesCounter++) { |
|
$CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; |
|
$offset += 2; |
|
$thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength); |
|
$offset += $CommandTypeNameLength; |
|
} |
|
for ($CommandsCounter = 0; $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count']; $CommandsCounter++) { |
|
$thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['type_index'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
|
|
$CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; |
|
$offset += 2; |
|
$thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength); |
|
$offset += $CommandTypeNameLength; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Marker_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['marker_object'] = array(); |
|
$thisfile_asf_markerobject = &$thisfile_asf['marker_object']; |
|
|
|
$thisfile_asf_markerobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_markerobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_markerobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_markerobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_markerobject['reserved'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']); |
|
if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) { |
|
$this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}'); |
|
break; |
|
} |
|
$thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
if ($thisfile_asf_markerobject['reserved_2'] != 0) { |
|
$this->warning('marker_object.reserved_2 ('.$thisfile_asf_markerobject['reserved_2'].') does not match expected value of "0"'); |
|
break; |
|
} |
|
$thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_markerobject['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['name_length']); |
|
$offset += $thisfile_asf_markerobject['name_length']; |
|
for ($MarkersCounter = 0; $MarkersCounter < $thisfile_asf_markerobject['markers_count']; $MarkersCounter++) { |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['send_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['flags'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']); |
|
$offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']; |
|
$PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 - 4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']; |
|
if ($PaddingLength > 0) { |
|
$thisfile_asf_markerobject['markers'][$MarkersCounter]['padding'] = substr($ASFHeaderData, $offset, $PaddingLength); |
|
$offset += $PaddingLength; |
|
} |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Bitrate_Mutual_Exclusion_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['bitrate_mutual_exclusion_object'] = array(); |
|
$thisfile_asf_bitratemutualexclusionobject = &$thisfile_asf['bitrate_mutual_exclusion_object']; |
|
|
|
$thisfile_asf_bitratemutualexclusionobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_bitratemutualexclusionobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_bitratemutualexclusionobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_bitratemutualexclusionobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_bitratemutualexclusionobject['reserved'] = substr($ASFHeaderData, $offset, 16); |
|
$thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']); |
|
$offset += 16; |
|
if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) { |
|
$this->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}'); |
|
|
|
break; |
|
} |
|
$thisfile_asf_bitratemutualexclusionobject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
for ($StreamNumberCounter = 0; $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count']; $StreamNumberCounter++) { |
|
$thisfile_asf_bitratemutualexclusionobject['stream_numbers'][$StreamNumberCounter] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Error_Correction_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['error_correction_object'] = array(); |
|
$thisfile_asf_errorcorrectionobject = &$thisfile_asf['error_correction_object']; |
|
|
|
$thisfile_asf_errorcorrectionobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_errorcorrectionobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_errorcorrectionobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_errorcorrectionobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_errorcorrectionobject['error_correction_guid'] = $this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']); |
|
$thisfile_asf_errorcorrectionobject['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) { |
|
case GETID3_ASF_No_Error_Correction: |
|
|
|
$offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length']; |
|
break; |
|
|
|
case GETID3_ASF_Audio_Spread: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf_errorcorrectionobject['span'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 1)); |
|
$offset += 1; |
|
$thisfile_asf_errorcorrectionobject['virtual_packet_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_errorcorrectionobject['virtual_chunk_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_errorcorrectionobject['silence_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_errorcorrectionobject['silence_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_errorcorrectionobject['silence_data_length']); |
|
$offset += $thisfile_asf_errorcorrectionobject['silence_data_length']; |
|
break; |
|
|
|
default: |
|
$this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}'); |
|
|
|
break; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Content_Description_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['content_description_object'] = array(); |
|
$thisfile_asf_contentdescriptionobject = &$thisfile_asf['content_description_object']; |
|
|
|
$thisfile_asf_contentdescriptionobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_contentdescriptionobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_contentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_contentdescriptionobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_contentdescriptionobject['title_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_contentdescriptionobject['author_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_contentdescriptionobject['copyright_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_contentdescriptionobject['description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_contentdescriptionobject['rating_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_contentdescriptionobject['title'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['title_length']); |
|
$offset += $thisfile_asf_contentdescriptionobject['title_length']; |
|
$thisfile_asf_contentdescriptionobject['author'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['author_length']); |
|
$offset += $thisfile_asf_contentdescriptionobject['author_length']; |
|
$thisfile_asf_contentdescriptionobject['copyright'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['copyright_length']); |
|
$offset += $thisfile_asf_contentdescriptionobject['copyright_length']; |
|
$thisfile_asf_contentdescriptionobject['description'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['description_length']); |
|
$offset += $thisfile_asf_contentdescriptionobject['description_length']; |
|
$thisfile_asf_contentdescriptionobject['rating'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['rating_length']); |
|
$offset += $thisfile_asf_contentdescriptionobject['rating_length']; |
|
|
|
$ASFcommentKeysToCopy = array('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating'); |
|
foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) { |
|
if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) { |
|
$thisfile_asf_comments[$keytocopyto][] = $this->TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]); |
|
} |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Extended_Content_Description_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['extended_content_description_object'] = array(); |
|
$thisfile_asf_extendedcontentdescriptionobject = &$thisfile_asf['extended_content_description_object']; |
|
|
|
$thisfile_asf_extendedcontentdescriptionobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_extendedcontentdescriptionobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_extendedcontentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_extendedcontentdescriptionobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
for ($ExtendedContentDescriptorsCounter = 0; $ExtendedContentDescriptorsCounter < $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count']; $ExtendedContentDescriptorsCounter++) { |
|
|
|
$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter] = array(); |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current = &$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter]; |
|
|
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['base_offset'] = $offset + 30; |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']); |
|
$offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']; |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']); |
|
$offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']; |
|
switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) { |
|
case 0x0000: |
|
break; |
|
|
|
case 0x0001: |
|
|
|
break; |
|
|
|
case 0x0002: |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = (bool) getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); |
|
break; |
|
|
|
case 0x0003: |
|
case 0x0004: |
|
case 0x0005: |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); |
|
break; |
|
|
|
default: |
|
$this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')'); |
|
|
|
break; |
|
} |
|
switch ($this->TrimConvert(strtolower($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']))) { |
|
|
|
case 'wm/albumartist': |
|
case 'artist': |
|
|
|
$thisfile_asf_comments['albumartist'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'wm/albumtitle': |
|
case 'album': |
|
$thisfile_asf_comments['album'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'wm/genre': |
|
case 'genre': |
|
$thisfile_asf_comments['genre'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'wm/partofset': |
|
$thisfile_asf_comments['partofset'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'wm/tracknumber': |
|
case 'tracknumber': |
|
|
|
$thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
foreach ($thisfile_asf_comments['track_number'] as $key => $value) { |
|
if (preg_match('/^[0-9\x00]+$/', $value)) { |
|
$thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value)); |
|
} |
|
} |
|
break; |
|
|
|
case 'wm/track': |
|
if (empty($thisfile_asf_comments['track_number'])) { |
|
$thisfile_asf_comments['track_number'] = array(1 + (int) $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
} |
|
break; |
|
|
|
case 'wm/year': |
|
case 'year': |
|
case 'date': |
|
$thisfile_asf_comments['year'] = array( $this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'wm/lyrics': |
|
case 'lyrics': |
|
$thisfile_asf_comments['lyrics'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
break; |
|
|
|
case 'isvbr': |
|
if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) { |
|
$thisfile_audio['bitrate_mode'] = 'vbr'; |
|
$thisfile_video['bitrate_mode'] = 'vbr'; |
|
} |
|
break; |
|
|
|
case 'id3': |
|
$this->getid3->include_module('tag.id3v2'); |
|
|
|
$getid3_id3v2 = new getid3_id3v2($this->getid3); |
|
$getid3_id3v2->AnalyzeString($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); |
|
unset($getid3_id3v2); |
|
|
|
if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] > 1024) { |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = '<value too large to display>'; |
|
} |
|
break; |
|
|
|
case 'wm/encodingtime': |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); |
|
$thisfile_asf_comments['encoding_time_unix'] = array($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix']); |
|
break; |
|
|
|
case 'wm/picture': |
|
$WMpicture = $this->ASF_WMpicture($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); |
|
foreach ($WMpicture as $key => $value) { |
|
$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[$key] = $value; |
|
} |
|
unset($WMpicture); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
default: |
|
switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) { |
|
case 0: |
|
if (substr($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']), 0, 3) == 'WM/') { |
|
$thisfile_asf_comments[str_replace('wm/', '', strtolower($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'])))] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); |
|
} |
|
break; |
|
|
|
case 1: |
|
break; |
|
} |
|
break; |
|
} |
|
|
|
} |
|
break; |
|
|
|
case GETID3_ASF_Stream_Bitrate_Properties_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['stream_bitrate_properties_object'] = array(); |
|
$thisfile_asf_streambitratepropertiesobject = &$thisfile_asf['stream_bitrate_properties_object']; |
|
|
|
$thisfile_asf_streambitratepropertiesobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_streambitratepropertiesobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_streambitratepropertiesobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_streambitratepropertiesobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_streambitratepropertiesobject['bitrate_records_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) { |
|
$thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags']['stream_number'] = $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] & 0x007F; |
|
$thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); |
|
$offset += 4; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Padding_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['padding_object'] = array(); |
|
$thisfile_asf_paddingobject = &$thisfile_asf['padding_object']; |
|
|
|
$thisfile_asf_paddingobject['offset'] = $NextObjectOffset + $offset; |
|
$thisfile_asf_paddingobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_paddingobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_paddingobject['objectsize'] = $NextObjectSize; |
|
$thisfile_asf_paddingobject['padding_length'] = $thisfile_asf_paddingobject['objectsize'] - 16 - 8; |
|
$thisfile_asf_paddingobject['padding'] = substr($ASFHeaderData, $offset, $thisfile_asf_paddingobject['padding_length']); |
|
$offset += ($NextObjectSize - 16 - 8); |
|
break; |
|
|
|
case GETID3_ASF_Extended_Content_Encryption_Object: |
|
case GETID3_ASF_Content_Encryption_Object: |
|
|
|
$offset += ($NextObjectSize - 16 - 8); |
|
break; |
|
|
|
default: |
|
|
|
if ($this->GUIDname($NextObjectGUIDtext)) { |
|
$this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8)); |
|
} else { |
|
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8)); |
|
} |
|
$offset += ($NextObjectSize - 16 - 8); |
|
break; |
|
} |
|
} |
|
if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) { |
|
$ASFbitrateAudio = 0; |
|
$ASFbitrateVideo = 0; |
|
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) { |
|
if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) { |
|
switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) { |
|
case 1: |
|
$ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; |
|
break; |
|
|
|
case 2: |
|
$ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; |
|
break; |
|
|
|
default: |
|
|
|
break; |
|
} |
|
} |
|
} |
|
if ($ASFbitrateAudio > 0) { |
|
$thisfile_audio['bitrate'] = $ASFbitrateAudio; |
|
} |
|
if ($ASFbitrateVideo > 0) { |
|
$thisfile_video['bitrate'] = $ASFbitrateVideo; |
|
} |
|
} |
|
if (isset($thisfile_asf['stream_properties_object']) && is_array($thisfile_asf['stream_properties_object'])) { |
|
|
|
$thisfile_audio['bitrate'] = 0; |
|
$thisfile_video['bitrate'] = 0; |
|
|
|
foreach ($thisfile_asf['stream_properties_object'] as $streamnumber => $streamdata) { |
|
|
|
switch ($streamdata['stream_type']) { |
|
case GETID3_ASF_Audio_Media: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['audio_media'][$streamnumber] = array(); |
|
$thisfile_asf_audiomedia_currentstream = &$thisfile_asf['audio_media'][$streamnumber]; |
|
|
|
$audiomediaoffset = 0; |
|
|
|
$thisfile_asf_audiomedia_currentstream = getid3_riff::parseWAVEFORMATex(substr($streamdata['type_specific_data'], $audiomediaoffset, 16)); |
|
$audiomediaoffset += 16; |
|
|
|
$thisfile_audio['lossless'] = false; |
|
switch ($thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']) { |
|
case 0x0001: |
|
case 0x0163: |
|
$thisfile_audio['lossless'] = true; |
|
break; |
|
} |
|
|
|
if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { |
|
foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { |
|
if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { |
|
$thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate']; |
|
$thisfile_audio['bitrate'] += $dataarray['bitrate']; |
|
break; |
|
} |
|
} |
|
} else { |
|
if (!empty($thisfile_asf_audiomedia_currentstream['bytes_sec'])) { |
|
$thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bytes_sec'] * 8; |
|
} elseif (!empty($thisfile_asf_audiomedia_currentstream['bitrate'])) { |
|
$thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bitrate']; |
|
} |
|
} |
|
$thisfile_audio['streams'][$streamnumber] = $thisfile_asf_audiomedia_currentstream; |
|
$thisfile_audio['streams'][$streamnumber]['wformattag'] = $thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']; |
|
$thisfile_audio['streams'][$streamnumber]['lossless'] = $thisfile_audio['lossless']; |
|
$thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; |
|
$thisfile_audio['streams'][$streamnumber]['dataformat'] = 'wma'; |
|
unset($thisfile_audio['streams'][$streamnumber]['raw']); |
|
|
|
$thisfile_asf_audiomedia_currentstream['codec_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $audiomediaoffset, 2)); |
|
$audiomediaoffset += 2; |
|
$thisfile_asf_audiomedia_currentstream['codec_data'] = substr($streamdata['type_specific_data'], $audiomediaoffset, $thisfile_asf_audiomedia_currentstream['codec_data_size']); |
|
$audiomediaoffset += $thisfile_asf_audiomedia_currentstream['codec_data_size']; |
|
|
|
break; |
|
|
|
case GETID3_ASF_Video_Media: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['video_media'][$streamnumber] = array(); |
|
$thisfile_asf_videomedia_currentstream = &$thisfile_asf['video_media'][$streamnumber]; |
|
|
|
$videomediaoffset = 0; |
|
$thisfile_asf_videomedia_currentstream['image_width'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['image_height'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['flags'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 1)); |
|
$videomediaoffset += 1; |
|
$thisfile_asf_videomedia_currentstream['format_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); |
|
$videomediaoffset += 2; |
|
$thisfile_asf_videomedia_currentstream['format_data']['format_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['image_width'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['image_height'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['reserved'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); |
|
$videomediaoffset += 2; |
|
$thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); |
|
$videomediaoffset += 2; |
|
$thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'] = substr($streamdata['type_specific_data'], $videomediaoffset, 4); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['image_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['horizontal_pels'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['vertical_pels'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['colors_used'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['colors_important'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); |
|
$videomediaoffset += 4; |
|
$thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'], $videomediaoffset); |
|
|
|
if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { |
|
foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { |
|
if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { |
|
$thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate']; |
|
$thisfile_video['streams'][$streamnumber]['bitrate'] = $dataarray['bitrate']; |
|
$thisfile_video['bitrate'] += $dataarray['bitrate']; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
$thisfile_asf_videomedia_currentstream['format_data']['codec'] = getid3_riff::fourccLookup($thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']); |
|
|
|
$thisfile_video['streams'][$streamnumber]['fourcc'] = $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']; |
|
$thisfile_video['streams'][$streamnumber]['codec'] = $thisfile_asf_videomedia_currentstream['format_data']['codec']; |
|
$thisfile_video['streams'][$streamnumber]['resolution_x'] = $thisfile_asf_videomedia_currentstream['image_width']; |
|
$thisfile_video['streams'][$streamnumber]['resolution_y'] = $thisfile_asf_videomedia_currentstream['image_height']; |
|
$thisfile_video['streams'][$streamnumber]['bits_per_sample'] = $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel']; |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
} |
|
|
|
while ($this->ftell() < $info['avdataend']) { |
|
$NextObjectDataHeader = $this->fread(24); |
|
$offset = 0; |
|
$NextObjectGUID = substr($NextObjectDataHeader, 0, 16); |
|
$offset += 16; |
|
$NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID); |
|
$NextObjectSize = getid3_lib::LittleEndian2Int(substr($NextObjectDataHeader, $offset, 8)); |
|
$offset += 8; |
|
|
|
switch ($NextObjectGUID) { |
|
case GETID3_ASF_Data_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['data_object'] = array(); |
|
$thisfile_asf_dataobject = &$thisfile_asf['data_object']; |
|
|
|
$DataObjectData = $NextObjectDataHeader.$this->fread(50 - 24); |
|
$offset = 24; |
|
|
|
$thisfile_asf_dataobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_dataobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_dataobject['objectsize'] = $NextObjectSize; |
|
|
|
$thisfile_asf_dataobject['fileid'] = substr($DataObjectData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_dataobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_dataobject['fileid']); |
|
$thisfile_asf_dataobject['total_data_packets'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2)); |
|
$offset += 2; |
|
if ($thisfile_asf_dataobject['reserved'] != 0x0101) { |
|
$this->warning('data_object.reserved (0x'.sprintf('%04X', $thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'); |
|
|
|
break; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$info['avdataoffset'] = $this->ftell(); |
|
$this->fseek(($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); |
|
$info['avdataend'] = $this->ftell(); |
|
break; |
|
|
|
case GETID3_ASF_Simple_Index_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['simple_index_object'] = array(); |
|
$thisfile_asf_simpleindexobject = &$thisfile_asf['simple_index_object']; |
|
|
|
$SimpleIndexObjectData = $NextObjectDataHeader.$this->fread(56 - 24); |
|
$offset = 24; |
|
|
|
$thisfile_asf_simpleindexobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_simpleindexobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_simpleindexobject['objectsize'] = $NextObjectSize; |
|
|
|
$thisfile_asf_simpleindexobject['fileid'] = substr($SimpleIndexObjectData, $offset, 16); |
|
$offset += 16; |
|
$thisfile_asf_simpleindexobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_simpleindexobject['fileid']); |
|
$thisfile_asf_simpleindexobject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 8)); |
|
$offset += 8; |
|
$thisfile_asf_simpleindexobject['maximum_packet_count'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_simpleindexobject['index_entries_count'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
|
|
$IndexEntriesData = $SimpleIndexObjectData.$this->fread(6 * $thisfile_asf_simpleindexobject['index_entries_count']); |
|
for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) { |
|
$thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_count'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4)); |
|
$offset += 2; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Index_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisfile_asf['asf_index_object'] = array(); |
|
$thisfile_asf_asfindexobject = &$thisfile_asf['asf_index_object']; |
|
|
|
$ASFIndexObjectData = $NextObjectDataHeader.$this->fread(34 - 24); |
|
$offset = 24; |
|
|
|
$thisfile_asf_asfindexobject['objectid'] = $NextObjectGUID; |
|
$thisfile_asf_asfindexobject['objectid_guid'] = $NextObjectGUIDtext; |
|
$thisfile_asf_asfindexobject['objectsize'] = $NextObjectSize; |
|
|
|
$thisfile_asf_asfindexobject['entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
$thisfile_asf_asfindexobject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_asfindexobject['index_blocks_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
|
|
$ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count']); |
|
for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { |
|
$IndexSpecifierStreamNumber = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['stream_number'] = $IndexSpecifierStreamNumber; |
|
$thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); |
|
$offset += 2; |
|
$thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type_text'] = $this->ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type']); |
|
} |
|
|
|
$ASFIndexObjectData .= $this->fread(4); |
|
$thisfile_asf_asfindexobject['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
|
|
$ASFIndexObjectData .= $this->fread(8 * $thisfile_asf_asfindexobject['index_specifiers_count']); |
|
for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { |
|
$thisfile_asf_asfindexobject['block_positions'][$IndexSpecifiersCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8)); |
|
$offset += 8; |
|
} |
|
|
|
$ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']); |
|
for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) { |
|
for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { |
|
$thisfile_asf_asfindexobject['offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); |
|
$offset += 4; |
|
} |
|
} |
|
break; |
|
|
|
|
|
default: |
|
|
|
if ($this->GUIDname($NextObjectGUIDtext)) { |
|
$this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8)); |
|
} else { |
|
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8)); |
|
} |
|
$this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR); |
|
break; |
|
} |
|
} |
|
|
|
if (isset($thisfile_asf_codeclistobject['codec_entries']) && is_array($thisfile_asf_codeclistobject['codec_entries'])) { |
|
foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) { |
|
switch ($streamdata['information']) { |
|
case 'WMV1': |
|
case 'WMV2': |
|
case 'WMV3': |
|
case 'MSS1': |
|
case 'MSS2': |
|
case 'WMVA': |
|
case 'WVC1': |
|
case 'WMVP': |
|
case 'WVP2': |
|
$thisfile_video['dataformat'] = 'wmv'; |
|
$info['mime_type'] = 'video/x-ms-wmv'; |
|
break; |
|
|
|
case 'MP42': |
|
case 'MP43': |
|
case 'MP4S': |
|
case 'mp4s': |
|
$thisfile_video['dataformat'] = 'asf'; |
|
$info['mime_type'] = 'video/x-ms-asf'; |
|
break; |
|
|
|
default: |
|
switch ($streamdata['type_raw']) { |
|
case 1: |
|
if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) { |
|
$thisfile_video['dataformat'] = 'wmv'; |
|
if ($info['mime_type'] == 'video/x-ms-asf') { |
|
$info['mime_type'] = 'video/x-ms-wmv'; |
|
} |
|
} |
|
break; |
|
|
|
case 2: |
|
if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) { |
|
$thisfile_audio['dataformat'] = 'wma'; |
|
if ($info['mime_type'] == 'video/x-ms-asf') { |
|
$info['mime_type'] = 'audio/x-ms-wma'; |
|
} |
|
} |
|
break; |
|
|
|
} |
|
break; |
|
} |
|
} |
|
} |
|
|
|
switch (isset($thisfile_audio['codec']) ? $thisfile_audio['codec'] : '') { |
|
case 'MPEG Layer-3': |
|
$thisfile_audio['dataformat'] = 'mp3'; |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
if (isset($thisfile_asf_codeclistobject['codec_entries'])) { |
|
foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) { |
|
switch ($streamdata['type_raw']) { |
|
|
|
case 1: |
|
$thisfile_video['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']); |
|
break; |
|
|
|
case 2: |
|
$thisfile_audio['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']); |
|
|
|
|
|
$thisfile_audio['encoder_options'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][0]['description']); |
|
|
|
$thisfile_audio['codec'] = $thisfile_audio['encoder']; |
|
break; |
|
|
|
default: |
|
$this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']); |
|
break; |
|
|
|
} |
|
} |
|
} |
|
|
|
if (isset($info['audio'])) { |
|
$thisfile_audio['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false); |
|
$thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf'); |
|
} |
|
if (!empty($thisfile_video['dataformat'])) { |
|
$thisfile_video['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false); |
|
$thisfile_video['pixel_aspect_ratio'] = (isset($thisfile_audio['pixel_aspect_ratio']) ? $thisfile_audio['pixel_aspect_ratio'] : (float) 1); |
|
$thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf'); |
|
} |
|
if (!empty($thisfile_video['streams'])) { |
|
$thisfile_video['resolution_x'] = 0; |
|
$thisfile_video['resolution_y'] = 0; |
|
foreach ($thisfile_video['streams'] as $key => $valuearray) { |
|
if (($valuearray['resolution_x'] > $thisfile_video['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['resolution_y'])) { |
|
$thisfile_video['resolution_x'] = $valuearray['resolution_x']; |
|
$thisfile_video['resolution_y'] = $valuearray['resolution_y']; |
|
} |
|
} |
|
} |
|
$info['bitrate'] = 0 + (isset($thisfile_audio['bitrate']) ? $thisfile_audio['bitrate'] : 0) + (isset($thisfile_video['bitrate']) ? $thisfile_video['bitrate'] : 0); |
|
|
|
if ((!isset($info['playtime_seconds']) || ($info['playtime_seconds'] <= 0)) && ($info['bitrate'] > 0)) { |
|
$info['playtime_seconds'] = ($info['filesize'] - $info['avdataoffset']) / ($info['bitrate'] / 8); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function codecListObjectTypeLookup($CodecListType) { |
|
static $lookup = array( |
|
0x0001 => 'Video Codec', |
|
0x0002 => 'Audio Codec', |
|
0xFFFF => 'Unknown Codec' |
|
); |
|
|
|
return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type'); |
|
} |
|
|
|
|
|
|
|
|
|
public static function KnownGUIDs() { |
|
static $GUIDarray = array( |
|
'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A', |
|
'GETID3_ASF_Padding_Object' => '1806D474-CADF-4509-A4BA-9AABCB96AAE8', |
|
'GETID3_ASF_Payload_Ext_Syst_Pixel_Aspect_Ratio' => '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8', |
|
'GETID3_ASF_Script_Command_Object' => '1EFB1A30-0B62-11D0-A39B-00A0C90348F6', |
|
'GETID3_ASF_No_Error_Correction' => '20FB5700-5B55-11CF-A8FD-00805F5C442B', |
|
'GETID3_ASF_Content_Branding_Object' => '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E', |
|
'GETID3_ASF_Content_Encryption_Object' => '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E', |
|
'GETID3_ASF_Digital_Signature_Object' => '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E', |
|
'GETID3_ASF_Extended_Content_Encryption_Object' => '298AE614-2622-4C17-B935-DAE07EE9289C', |
|
'GETID3_ASF_Simple_Index_Object' => '33000890-E5B1-11CF-89F4-00A0C90349CB', |
|
'GETID3_ASF_Degradable_JPEG_Media' => '35907DE0-E415-11CF-A917-00805F5C442B', |
|
'GETID3_ASF_Payload_Extension_System_Timecode' => '399595EC-8667-4E2D-8FDB-98814CE76C1E', |
|
'GETID3_ASF_Binary_Media' => '3AFB65E2-47EF-40F2-AC2C-70A90D71D343', |
|
'GETID3_ASF_Timecode_Index_Object' => '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C', |
|
'GETID3_ASF_Metadata_Library_Object' => '44231C94-9498-49D1-A141-1D134E457054', |
|
'GETID3_ASF_Reserved_3' => '4B1ACBE3-100B-11D0-A39B-00A0C90348F6', |
|
'GETID3_ASF_Reserved_4' => '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB', |
|
'GETID3_ASF_Command_Media' => '59DACFC0-59E6-11D0-A3AC-00A0C90348F6', |
|
'GETID3_ASF_Header_Extension_Object' => '5FBF03B5-A92E-11CF-8EE3-00C00C205365', |
|
'GETID3_ASF_Media_Object_Index_Parameters_Obj' => '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7', |
|
'GETID3_ASF_Header_Object' => '75B22630-668E-11CF-A6D9-00AA0062CE6C', |
|
'GETID3_ASF_Content_Description_Object' => '75B22633-668E-11CF-A6D9-00AA0062CE6C', |
|
'GETID3_ASF_Error_Correction_Object' => '75B22635-668E-11CF-A6D9-00AA0062CE6C', |
|
'GETID3_ASF_Data_Object' => '75B22636-668E-11CF-A6D9-00AA0062CE6C', |
|
'GETID3_ASF_Web_Stream_Media_Subtype' => '776257D4-C627-41CB-8F81-7AC7FF1C40CC', |
|
'GETID3_ASF_Stream_Bitrate_Properties_Object' => '7BF875CE-468D-11D1-8D82-006097C9A2B2', |
|
'GETID3_ASF_Language_List_Object' => '7C4346A9-EFE0-4BFC-B229-393EDE415C85', |
|
'GETID3_ASF_Codec_List_Object' => '86D15240-311D-11D0-A3A4-00A0C90348F6', |
|
'GETID3_ASF_Reserved_2' => '86D15241-311D-11D0-A3A4-00A0C90348F6', |
|
'GETID3_ASF_File_Properties_Object' => '8CABDCA1-A947-11CF-8EE4-00C00C205365', |
|
'GETID3_ASF_File_Transfer_Media' => '91BD222C-F21C-497A-8B6D-5AA86BFC0185', |
|
'GETID3_ASF_Old_RTP_Extension_Data' => '96800C63-4C94-11D1-837B-0080C7A37F95', |
|
'GETID3_ASF_Advanced_Mutual_Exclusion_Object' => 'A08649CF-4775-4670-8A16-6E35357566CD', |
|
'GETID3_ASF_Bandwidth_Sharing_Object' => 'A69609E6-517B-11D2-B6AF-00C04FD908E9', |
|
'GETID3_ASF_Reserved_1' => 'ABD3D211-A9BA-11cf-8EE6-00C00C205365', |
|
'GETID3_ASF_Bandwidth_Sharing_Exclusive' => 'AF6060AA-5197-11D2-B6AF-00C04FD908E9', |
|
'GETID3_ASF_Bandwidth_Sharing_Partial' => 'AF6060AB-5197-11D2-B6AF-00C04FD908E9', |
|
'GETID3_ASF_JFIF_Media' => 'B61BE100-5B4E-11CF-A8FD-00805F5C442B', |
|
'GETID3_ASF_Stream_Properties_Object' => 'B7DC0791-A9B7-11CF-8EE6-00C00C205365', |
|
'GETID3_ASF_Video_Media' => 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B', |
|
'GETID3_ASF_Audio_Spread' => 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220', |
|
'GETID3_ASF_Metadata_Object' => 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA', |
|
'GETID3_ASF_Payload_Ext_Syst_Sample_Duration' => 'C6BD9450-867F-4907-83A3-C77921B733AD', |
|
'GETID3_ASF_Group_Mutual_Exclusion_Object' => 'D1465A40-5A79-4338-B71B-E36B8FD6C249', |
|
'GETID3_ASF_Extended_Content_Description_Object' => 'D2D0A440-E307-11D2-97F0-00A0C95EA850', |
|
'GETID3_ASF_Stream_Prioritization_Object' => 'D4FED15B-88D3-454F-81F0-ED5C45999E24', |
|
'GETID3_ASF_Payload_Ext_System_Content_Type' => 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC', |
|
'GETID3_ASF_Old_File_Properties_Object' => 'D6E229D0-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_ASF_Header_Object' => 'D6E229D1-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_ASF_Data_Object' => 'D6E229D2-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Index_Object' => 'D6E229D3-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Stream_Properties_Object' => 'D6E229D4-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Content_Description_Object' => 'D6E229D5-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Script_Command_Object' => 'D6E229D6-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Marker_Object' => 'D6E229D7-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Component_Download_Object' => 'D6E229D8-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Stream_Group_Object' => 'D6E229D9-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Scalable_Object' => 'D6E229DA-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Prioritization_Object' => 'D6E229DB-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Bitrate_Mutual_Exclusion_Object' => 'D6E229DC-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Inter_Media_Dependency_Object' => 'D6E229DD-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Rating_Object' => 'D6E229DE-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Index_Parameters_Object' => 'D6E229DF-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Color_Table_Object' => 'D6E229E0-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Language_List_Object' => 'D6E229E1-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Audio_Media' => 'D6E229E2-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Video_Media' => 'D6E229E3-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Image_Media' => 'D6E229E4-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Timecode_Media' => 'D6E229E5-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Text_Media' => 'D6E229E6-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_MIDI_Media' => 'D6E229E7-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Command_Media' => 'D6E229E8-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_No_Error_Concealment' => 'D6E229EA-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Scrambled_Audio' => 'D6E229EB-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_No_Color_Table' => 'D6E229EC-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_SMPTE_Time' => 'D6E229ED-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_ASCII_Text' => 'D6E229EE-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Unicode_Text' => 'D6E229EF-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_HTML_Text' => 'D6E229F0-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_URL_Command' => 'D6E229F1-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Filename_Command' => 'D6E229F2-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_ACM_Codec' => 'D6E229F3-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_VCM_Codec' => 'D6E229F4-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_QuickTime_Codec' => 'D6E229F5-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_DirectShow_Transform_Filter' => 'D6E229F6-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_DirectShow_Rendering_Filter' => 'D6E229F7-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_No_Enhancement' => 'D6E229F8-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Unknown_Enhancement_Type' => 'D6E229F9-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Temporal_Enhancement' => 'D6E229FA-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Spatial_Enhancement' => 'D6E229FB-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Quality_Enhancement' => 'D6E229FC-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Number_of_Channels_Enhancement' => 'D6E229FD-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Frequency_Response_Enhancement' => 'D6E229FE-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Media_Object' => 'D6E229FF-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Mutex_Language' => 'D6E22A00-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Mutex_Bitrate' => 'D6E22A01-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Mutex_Unknown' => 'D6E22A02-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_ASF_Placeholder_Object' => 'D6E22A0E-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Old_Data_Unit_Extension_Object' => 'D6E22A0F-35DA-11D1-9034-00A0C90349BE', |
|
'GETID3_ASF_Web_Stream_Format' => 'DA1E6B13-8359-4050-B398-388E965BF00C', |
|
'GETID3_ASF_Payload_Ext_System_File_Name' => 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B', |
|
'GETID3_ASF_Marker_Object' => 'F487CD01-A951-11CF-8EE6-00C00C205365', |
|
'GETID3_ASF_Timecode_Index_Parameters_Object' => 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24', |
|
'GETID3_ASF_Audio_Media' => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B', |
|
'GETID3_ASF_Media_Object_Index_Object' => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C', |
|
'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE', |
|
'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', |
|
'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', |
|
'GETID3_ASF_Media_Object_Index_Parameters_Object'=> '6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7', |
|
); |
|
return $GUIDarray; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function GUIDname($GUIDstring) { |
|
static $GUIDarray = array(); |
|
if (empty($GUIDarray)) { |
|
$GUIDarray = self::KnownGUIDs(); |
|
} |
|
return array_search($GUIDstring, $GUIDarray); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function ASFIndexObjectIndexTypeLookup($id) { |
|
static $ASFIndexObjectIndexTypeLookup = array(); |
|
if (empty($ASFIndexObjectIndexTypeLookup)) { |
|
$ASFIndexObjectIndexTypeLookup[1] = 'Nearest Past Data Packet'; |
|
$ASFIndexObjectIndexTypeLookup[2] = 'Nearest Past Media Object'; |
|
$ASFIndexObjectIndexTypeLookup[3] = 'Nearest Past Cleanpoint'; |
|
} |
|
return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function GUIDtoBytestring($GUIDstring) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$hexbytecharstring = chr(hexdec(substr($GUIDstring, 6, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 4, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 2, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 0, 2))); |
|
|
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 11, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 9, 2))); |
|
|
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 16, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 14, 2))); |
|
|
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 19, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 21, 2))); |
|
|
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 24, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 26, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 28, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 30, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 32, 2))); |
|
$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 34, 2))); |
|
|
|
return $hexbytecharstring; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function BytestringToGUID($Bytestring) { |
|
$GUIDstring = str_pad(dechex(ord($Bytestring[3])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[2])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[1])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[0])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= '-'; |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[5])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[4])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= '-'; |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[7])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[6])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= '-'; |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[8])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[9])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= '-'; |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT); |
|
$GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT); |
|
|
|
return strtoupper($GUIDstring); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function FILETIMEtoUNIXtime($FILETIME, $round=true) { |
|
|
|
|
|
|
|
|
|
if ($round) { |
|
return intval(round(($FILETIME - 116444736000000000) / 10000000)); |
|
} |
|
return ($FILETIME - 116444736000000000) / 10000000; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function WMpictureTypeLookup($WMpictureType) { |
|
static $lookup = null; |
|
if ($lookup === null) { |
|
$lookup = array( |
|
0x03 => 'Front Cover', |
|
0x04 => 'Back Cover', |
|
0x00 => 'User Defined', |
|
0x05 => 'Leaflet Page', |
|
0x06 => 'Media Label', |
|
0x07 => 'Lead Artist', |
|
0x08 => 'Artist', |
|
0x09 => 'Conductor', |
|
0x0A => 'Band', |
|
0x0B => 'Composer', |
|
0x0C => 'Lyricist', |
|
0x0D => 'Recording Location', |
|
0x0E => 'During Recording', |
|
0x0F => 'During Performance', |
|
0x10 => 'Video Screen Capture', |
|
0x12 => 'Illustration', |
|
0x13 => 'Band Logotype', |
|
0x14 => 'Publisher Logotype' |
|
); |
|
$lookup = array_map(function($str) { |
|
return getid3_lib::iconv_fallback('UTF-8', 'UTF-16LE', $str); |
|
}, $lookup); |
|
} |
|
|
|
return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : ''); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { |
|
|
|
|
|
$offset = 0; |
|
$objectOffset = 0; |
|
$HeaderExtensionObjectParsed = array(); |
|
while ($objectOffset < strlen($asf_header_extension_object_data)) { |
|
$offset = $objectOffset; |
|
$thisObject = array(); |
|
|
|
$thisObject['guid'] = substr($asf_header_extension_object_data, $offset, 16); |
|
$offset += 16; |
|
$thisObject['guid_text'] = $this->BytestringToGUID($thisObject['guid']); |
|
$thisObject['guid_name'] = $this->GUIDname($thisObject['guid_text']); |
|
|
|
$thisObject['size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); |
|
$offset += 8; |
|
if ($thisObject['size'] <= 0) { |
|
break; |
|
} |
|
|
|
switch ($thisObject['guid']) { |
|
case GETID3_ASF_Extended_Stream_Properties_Object: |
|
$thisObject['start_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); |
|
$offset += 8; |
|
$thisObject['start_time_unix'] = $this->FILETIMEtoUNIXtime($thisObject['start_time']); |
|
|
|
$thisObject['end_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); |
|
$offset += 8; |
|
$thisObject['end_time_unix'] = $this->FILETIMEtoUNIXtime($thisObject['end_time']); |
|
|
|
$thisObject['data_bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['buffer_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['initial_buffer_fullness'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['alternate_data_bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['alternate_buffer_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['alternate_initial_buffer_fullness'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['maximum_object_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
$thisObject['flags']['reliable'] = (bool) $thisObject['flags_raw'] & 0x00000001; |
|
$thisObject['flags']['seekable'] = (bool) $thisObject['flags_raw'] & 0x00000002; |
|
$thisObject['flags']['no_cleanpoints'] = (bool) $thisObject['flags_raw'] & 0x00000004; |
|
$thisObject['flags']['resend_live_cleanpoints'] = (bool) $thisObject['flags_raw'] & 0x00000008; |
|
|
|
$thisObject['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$thisObject['stream_language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); |
|
$offset += 8; |
|
|
|
$thisObject['stream_name_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$thisObject['payload_extension_system_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['stream_name_count']; $i++) { |
|
$streamName = array(); |
|
|
|
$streamName['language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$streamName['stream_name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$streamName['stream_name'] = substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length']); |
|
$offset += $streamName['stream_name_length']; |
|
|
|
$thisObject['stream_names'][$i] = $streamName; |
|
} |
|
|
|
for ($i = 0; $i < $thisObject['payload_extension_system_count']; $i++) { |
|
$payloadExtensionSystem = array(); |
|
|
|
$payloadExtensionSystem['extension_system_id'] = substr($asf_header_extension_object_data, $offset, 16); |
|
$offset += 16; |
|
$payloadExtensionSystem['extension_system_id_text'] = $this->BytestringToGUID($payloadExtensionSystem['extension_system_id']); |
|
|
|
$payloadExtensionSystem['extension_system_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
if ($payloadExtensionSystem['extension_system_size'] <= 0) { |
|
break 2; |
|
} |
|
|
|
$payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$payloadExtensionSystem['extension_system_info'] = substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length']); |
|
$offset += $payloadExtensionSystem['extension_system_info_length']; |
|
|
|
$thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Advanced_Mutual_Exclusion_Object: |
|
$thisObject['exclusion_type'] = substr($asf_header_extension_object_data, $offset, 16); |
|
$offset += 16; |
|
$thisObject['exclusion_type_text'] = $this->BytestringToGUID($thisObject['exclusion_type']); |
|
|
|
$thisObject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['stream_numbers_count']; $i++) { |
|
$thisObject['stream_numbers'][$i] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Stream_Prioritization_Object: |
|
$thisObject['priority_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['priority_records_count']; $i++) { |
|
$priorityRecord = array(); |
|
|
|
$priorityRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$priorityRecord['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$priorityRecord['flags']['mandatory'] = (bool) $priorityRecord['flags_raw'] & 0x00000001; |
|
|
|
$thisObject['priority_records'][$i] = $priorityRecord; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Padding_Object: |
|
|
|
break; |
|
|
|
case GETID3_ASF_Metadata_Object: |
|
$thisObject['description_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['description_record_counts']; $i++) { |
|
$descriptionRecord = array(); |
|
|
|
$descriptionRecord['reserved_1'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); |
|
|
|
$descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$descriptionRecord['name'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['name_length']); |
|
$offset += $descriptionRecord['name_length']; |
|
|
|
$descriptionRecord['data'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['data_length']); |
|
$offset += $descriptionRecord['data_length']; |
|
switch ($descriptionRecord['data_type']) { |
|
case 0x0000: |
|
break; |
|
|
|
case 0x0001: |
|
|
|
break; |
|
|
|
case 0x0002: |
|
$descriptionRecord['data'] = (bool) getid3_lib::LittleEndian2Int($descriptionRecord['data']); |
|
break; |
|
|
|
case 0x0003: |
|
case 0x0004: |
|
case 0x0005: |
|
$descriptionRecord['data'] = getid3_lib::LittleEndian2Int($descriptionRecord['data']); |
|
break; |
|
|
|
case 0x0006: |
|
$descriptionRecord['data_text'] = $this->BytestringToGUID($descriptionRecord['data']); |
|
break; |
|
} |
|
|
|
$thisObject['description_record'][$i] = $descriptionRecord; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Language_List_Object: |
|
$thisObject['language_id_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['language_id_record_counts']; $i++) { |
|
$languageIDrecord = array(); |
|
|
|
$languageIDrecord['language_id_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1)); |
|
$offset += 1; |
|
|
|
$languageIDrecord['language_id'] = substr($asf_header_extension_object_data, $offset, $languageIDrecord['language_id_length']); |
|
$offset += $languageIDrecord['language_id_length']; |
|
|
|
$thisObject['language_id_record'][$i] = $languageIDrecord; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Metadata_Library_Object: |
|
$thisObject['description_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['description_records_count']; $i++) { |
|
$descriptionRecord = array(); |
|
|
|
$descriptionRecord['language_list_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); |
|
|
|
$descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$descriptionRecord['name'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['name_length']); |
|
$offset += $descriptionRecord['name_length']; |
|
|
|
$descriptionRecord['data'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['data_length']); |
|
$offset += $descriptionRecord['data_length']; |
|
|
|
if (preg_match('#^WM/Picture$#', str_replace("\x00", '', trim($descriptionRecord['name'])))) { |
|
$WMpicture = $this->ASF_WMpicture($descriptionRecord['data']); |
|
foreach ($WMpicture as $key => $value) { |
|
$descriptionRecord['data'] = $WMpicture; |
|
} |
|
unset($WMpicture); |
|
} |
|
|
|
$thisObject['description_record'][$i] = $descriptionRecord; |
|
} |
|
break; |
|
|
|
case GETID3_ASF_Index_Parameters_Object: |
|
$thisObject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) { |
|
$indexSpecifier = array(); |
|
|
|
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$indexSpecifier['index_type_text'] = isset(static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]) |
|
? static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']] |
|
: 'invalid' |
|
; |
|
|
|
$thisObject['index_specifiers'][$i] = $indexSpecifier; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Media_Object_Index_Parameters_Object: |
|
$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) { |
|
$indexSpecifier = array(); |
|
|
|
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$indexSpecifier['index_type_text'] = isset(static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]) |
|
? static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']] |
|
: 'invalid' |
|
; |
|
|
|
$thisObject['index_specifiers'][$i] = $indexSpecifier; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Timecode_Index_Parameters_Object: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) { |
|
$indexSpecifier = array(); |
|
|
|
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
|
|
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); |
|
$offset += 2; |
|
$indexSpecifier['index_type_text'] = isset(static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]) |
|
? static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']] |
|
: 'invalid' |
|
; |
|
|
|
$thisObject['index_specifiers'][$i] = $indexSpecifier; |
|
} |
|
|
|
break; |
|
|
|
case GETID3_ASF_Compatibility_Object: |
|
$thisObject['profile'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1)); |
|
$offset += 1; |
|
|
|
$thisObject['mode'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1)); |
|
$offset += 1; |
|
|
|
break; |
|
|
|
default: |
|
$unhandled_sections++; |
|
if ($this->GUIDname($thisObject['guid_text'])) { |
|
$this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8)); |
|
} else { |
|
$this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8)); |
|
} |
|
break; |
|
} |
|
$HeaderExtensionObjectParsed[] = $thisObject; |
|
|
|
$objectOffset += $thisObject['size']; |
|
} |
|
return $HeaderExtensionObjectParsed; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function metadataLibraryObjectDataTypeLookup($id) { |
|
static $lookup = array( |
|
0x0000 => 'Unicode string', |
|
0x0001 => 'BYTE array', |
|
0x0002 => 'BOOL', |
|
0x0003 => 'DWORD', |
|
0x0004 => 'QWORD', |
|
0x0005 => 'WORD', |
|
0x0006 => 'GUID', |
|
); |
|
return (isset($lookup[$id]) ? $lookup[$id] : 'invalid'); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function ASF_WMpicture(&$data) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$WMpicture = array(); |
|
|
|
$offset = 0; |
|
$WMpicture['image_type_id'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 1)); |
|
$offset += 1; |
|
$WMpicture['image_type'] = self::WMpictureTypeLookup($WMpicture['image_type_id']); |
|
$WMpicture['image_size'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 4)); |
|
$offset += 4; |
|
|
|
$WMpicture['image_mime'] = ''; |
|
do { |
|
$next_byte_pair = substr($data, $offset, 2); |
|
$offset += 2; |
|
$WMpicture['image_mime'] .= $next_byte_pair; |
|
} while ($next_byte_pair !== "\x00\x00"); |
|
|
|
$WMpicture['image_description'] = ''; |
|
do { |
|
$next_byte_pair = substr($data, $offset, 2); |
|
$offset += 2; |
|
$WMpicture['image_description'] .= $next_byte_pair; |
|
} while ($next_byte_pair !== "\x00\x00"); |
|
|
|
$WMpicture['dataoffset'] = $offset; |
|
$WMpicture['data'] = substr($data, $offset); |
|
|
|
$imageinfo = array(); |
|
$WMpicture['image_mime'] = ''; |
|
$imagechunkcheck = getid3_lib::GetDataImageSize($WMpicture['data'], $imageinfo); |
|
unset($imageinfo); |
|
if (!empty($imagechunkcheck)) { |
|
$WMpicture['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]); |
|
} |
|
if (!isset($this->getid3->info['asf']['comments']['picture'])) { |
|
$this->getid3->info['asf']['comments']['picture'] = array(); |
|
} |
|
$this->getid3->info['asf']['comments']['picture'][] = array('data'=>$WMpicture['data'], 'image_mime'=>$WMpicture['image_mime']); |
|
|
|
return $WMpicture; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function TrimConvert($string) { |
|
return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' '); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function TrimTerm($string) { |
|
|
|
if (substr($string, -2) === "\x00\x00") { |
|
$string = substr($string, 0, -2); |
|
} |
|
return $string; |
|
} |
|
|
|
} |
|
|