PageRenderTime 68ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/components/com_jce/editor/tiny_mce/plugins/mediamanager/classes/getid3/module.audio-video.asf.php

https://bitbucket.org/organicdevelopment/joomla-2.5
PHP | 1707 lines | 1174 code | 206 blank | 327 comment | 120 complexity | 45929fdabad6f00cad2a72af858f1ee7 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, MIT, BSD-3-Clause, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /////////////////////////////////////////////////////////////////
  3. /// getID3() by James Heinrich <info@getid3.org> //
  4. // available at http://getid3.sourceforge.net //
  5. // or http://www.getid3.org //
  6. /////////////////////////////////////////////////////////////////
  7. // See readme.txt for more details //
  8. /////////////////////////////////////////////////////////////////
  9. // //
  10. // module.audio-video.asf.php //
  11. // module for analyzing ASF, WMA and WMV files //
  12. // dependencies: module.audio-video.riff.php //
  13. // ///
  14. /////////////////////////////////////////////////////////////////
  15. getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
  16. class getid3_asf extends getid3_handler
  17. {
  18. function __construct(getID3 $getid3) {
  19. parent::__construct($getid3); // extends getid3_handler::__construct()
  20. // initialize all GUID constants
  21. $GUIDarray = $this->KnownGUIDs();
  22. foreach ($GUIDarray as $GUIDname => $hexstringvalue) {
  23. if (!defined($GUIDname)) {
  24. define($GUIDname, $this->GUIDtoBytestring($hexstringvalue));
  25. }
  26. }
  27. }
  28. function Analyze() {
  29. $info = &$this->getid3->info;
  30. // Shortcuts
  31. $thisfile_audio = &$info['audio'];
  32. $thisfile_video = &$info['video'];
  33. $info['asf'] = array();
  34. $thisfile_asf = &$info['asf'];
  35. $thisfile_asf['comments'] = array();
  36. $thisfile_asf_comments = &$thisfile_asf['comments'];
  37. $thisfile_asf['header_object'] = array();
  38. $thisfile_asf_headerobject = &$thisfile_asf['header_object'];
  39. // ASF structure:
  40. // * Header Object [required]
  41. // * File Properties Object [required] (global file attributes)
  42. // * Stream Properties Object [required] (defines media stream & characteristics)
  43. // * Header Extension Object [required] (additional functionality)
  44. // * Content Description Object (bibliographic information)
  45. // * Script Command Object (commands for during playback)
  46. // * Marker Object (named jumped points within the file)
  47. // * Data Object [required]
  48. // * Data Packets
  49. // * Index Object
  50. // Header Object: (mandatory, one only)
  51. // Field Name Field Type Size (bits)
  52. // Object ID GUID 128 // GUID for header object - GETID3_ASF_Header_Object
  53. // Object Size QWORD 64 // size of header object, including 30 bytes of Header Object header
  54. // Number of Header Objects DWORD 32 // number of objects in header object
  55. // Reserved1 BYTE 8 // hardcoded: 0x01
  56. // Reserved2 BYTE 8 // hardcoded: 0x02
  57. $info['fileformat'] = 'asf';
  58. fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
  59. $HeaderObjectData = fread($this->getid3->fp, 30);
  60. $thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16);
  61. $thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']);
  62. if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) {
  63. $info['warning'][] = 'ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}';
  64. unset($info['fileformat']);
  65. unset($info['asf']);
  66. return false;
  67. break;
  68. }
  69. $thisfile_asf_headerobject['objectsize'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8));
  70. $thisfile_asf_headerobject['headerobjects'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 24, 4));
  71. $thisfile_asf_headerobject['reserved1'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 28, 1));
  72. $thisfile_asf_headerobject['reserved2'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1));
  73. $NextObjectOffset = ftell($this->getid3->fp);
  74. $ASFHeaderData = fread($this->getid3->fp, $thisfile_asf_headerobject['objectsize'] - 30);
  75. $offset = 0;
  76. for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
  77. $NextObjectGUID = substr($ASFHeaderData, $offset, 16);
  78. $offset += 16;
  79. $NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID);
  80. $NextObjectSize = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  81. $offset += 8;
  82. switch ($NextObjectGUID) {
  83. case GETID3_ASF_File_Properties_Object:
  84. // File Properties Object: (mandatory, one only)
  85. // Field Name Field Type Size (bits)
  86. // Object ID GUID 128 // GUID for file properties object - GETID3_ASF_File_Properties_Object
  87. // Object Size QWORD 64 // size of file properties object, including 104 bytes of File Properties Object header
  88. // File ID GUID 128 // unique ID - identical to File ID in Data Object
  89. // File Size QWORD 64 // entire file in bytes. Invalid if Broadcast Flag == 1
  90. // Creation Date QWORD 64 // date & time of file creation. Maybe invalid if Broadcast Flag == 1
  91. // Data Packets Count QWORD 64 // number of data packets in Data Object. Invalid if Broadcast Flag == 1
  92. // Play Duration QWORD 64 // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1
  93. // Send Duration QWORD 64 // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1
  94. // Preroll QWORD 64 // time to buffer data before starting to play file, in 1-millisecond units. If <> 0, PlayDuration and PresentationTime have been offset by this amount
  95. // Flags DWORD 32 //
  96. // * Broadcast Flag bits 1 (0x01) // file is currently being written, some header values are invalid
  97. // * Seekable Flag bits 1 (0x02) // is file seekable
  98. // * Reserved bits 30 (0xFFFFFFFC) // reserved - set to zero
  99. // Minimum Data Packet Size DWORD 32 // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1
  100. // Maximum Data Packet Size DWORD 32 // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1
  101. // Maximum Bitrate DWORD 32 // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead
  102. // shortcut
  103. $thisfile_asf['file_properties_object'] = array();
  104. $thisfile_asf_filepropertiesobject = &$thisfile_asf['file_properties_object'];
  105. $thisfile_asf_filepropertiesobject['offset'] = $NextObjectOffset + $offset;
  106. $thisfile_asf_filepropertiesobject['objectid'] = $NextObjectGUID;
  107. $thisfile_asf_filepropertiesobject['objectid_guid'] = $NextObjectGUIDtext;
  108. $thisfile_asf_filepropertiesobject['objectsize'] = $NextObjectSize;
  109. $thisfile_asf_filepropertiesobject['fileid'] = substr($ASFHeaderData, $offset, 16);
  110. $offset += 16;
  111. $thisfile_asf_filepropertiesobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_filepropertiesobject['fileid']);
  112. $thisfile_asf_filepropertiesobject['filesize'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  113. $offset += 8;
  114. $thisfile_asf_filepropertiesobject['creation_date'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  115. $thisfile_asf_filepropertiesobject['creation_date_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject['creation_date']);
  116. $offset += 8;
  117. $thisfile_asf_filepropertiesobject['data_packets'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  118. $offset += 8;
  119. $thisfile_asf_filepropertiesobject['play_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  120. $offset += 8;
  121. $thisfile_asf_filepropertiesobject['send_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  122. $offset += 8;
  123. $thisfile_asf_filepropertiesobject['preroll'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  124. $offset += 8;
  125. $thisfile_asf_filepropertiesobject['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  126. $offset += 4;
  127. $thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001);
  128. $thisfile_asf_filepropertiesobject['flags']['seekable'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002);
  129. $thisfile_asf_filepropertiesobject['min_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  130. $offset += 4;
  131. $thisfile_asf_filepropertiesobject['max_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  132. $offset += 4;
  133. $thisfile_asf_filepropertiesobject['max_bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  134. $offset += 4;
  135. if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) {
  136. // broadcast flag is set, some values invalid
  137. unset($thisfile_asf_filepropertiesobject['filesize']);
  138. unset($thisfile_asf_filepropertiesobject['data_packets']);
  139. unset($thisfile_asf_filepropertiesobject['play_duration']);
  140. unset($thisfile_asf_filepropertiesobject['send_duration']);
  141. unset($thisfile_asf_filepropertiesobject['min_packet_size']);
  142. unset($thisfile_asf_filepropertiesobject['max_packet_size']);
  143. } else {
  144. // broadcast flag NOT set, perform calculations
  145. $info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000);
  146. //$info['bitrate'] = $thisfile_asf_filepropertiesobject['max_bitrate'];
  147. $info['bitrate'] = ((isset($thisfile_asf_filepropertiesobject['filesize']) ? $thisfile_asf_filepropertiesobject['filesize'] : $info['filesize']) * 8) / $info['playtime_seconds'];
  148. }
  149. break;
  150. case GETID3_ASF_Stream_Properties_Object:
  151. // Stream Properties Object: (mandatory, one per media stream)
  152. // Field Name Field Type Size (bits)
  153. // Object ID GUID 128 // GUID for stream properties object - GETID3_ASF_Stream_Properties_Object
  154. // Object Size QWORD 64 // size of stream properties object, including 78 bytes of Stream Properties Object header
  155. // Stream Type GUID 128 // GETID3_ASF_Audio_Media, GETID3_ASF_Video_Media or GETID3_ASF_Command_Media
  156. // Error Correction Type GUID 128 // GETID3_ASF_Audio_Spread for audio-only streams, GETID3_ASF_No_Error_Correction for other stream types
  157. // Time Offset QWORD 64 // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream
  158. // Type-Specific Data Length DWORD 32 // number of bytes for Type-Specific Data field
  159. // Error Correction Data Length DWORD 32 // number of bytes for Error Correction Data field
  160. // Flags WORD 16 //
  161. // * Stream Number bits 7 (0x007F) // number of this stream. 1 <= valid <= 127
  162. // * Reserved bits 8 (0x7F80) // reserved - set to zero
  163. // * Encrypted Content Flag bits 1 (0x8000) // stream contents encrypted if set
  164. // Reserved DWORD 32 // reserved - set to zero
  165. // Type-Specific Data BYTESTREAM variable // type-specific format data, depending on value of Stream Type
  166. // Error Correction Data BYTESTREAM variable // error-correction-specific format data, depending on value of Error Correct Type
  167. // There is one GETID3_ASF_Stream_Properties_Object for each stream (audio, video) but the
  168. // stream number isn't known until halfway through decoding the structure, hence it
  169. // it is decoded to a temporary variable and then stuck in the appropriate index later
  170. $StreamPropertiesObjectData['offset'] = $NextObjectOffset + $offset;
  171. $StreamPropertiesObjectData['objectid'] = $NextObjectGUID;
  172. $StreamPropertiesObjectData['objectid_guid'] = $NextObjectGUIDtext;
  173. $StreamPropertiesObjectData['objectsize'] = $NextObjectSize;
  174. $StreamPropertiesObjectData['stream_type'] = substr($ASFHeaderData, $offset, 16);
  175. $offset += 16;
  176. $StreamPropertiesObjectData['stream_type_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['stream_type']);
  177. $StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData, $offset, 16);
  178. $offset += 16;
  179. $StreamPropertiesObjectData['error_correct_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['error_correct_type']);
  180. $StreamPropertiesObjectData['time_offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  181. $offset += 8;
  182. $StreamPropertiesObjectData['type_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  183. $offset += 4;
  184. $StreamPropertiesObjectData['error_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  185. $offset += 4;
  186. $StreamPropertiesObjectData['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  187. $offset += 2;
  188. $StreamPropertiesObjectStreamNumber = $StreamPropertiesObjectData['flags_raw'] & 0x007F;
  189. $StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000);
  190. $offset += 4; // reserved - DWORD
  191. $StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['type_data_length']);
  192. $offset += $StreamPropertiesObjectData['type_data_length'];
  193. $StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['error_data_length']);
  194. $offset += $StreamPropertiesObjectData['error_data_length'];
  195. switch ($StreamPropertiesObjectData['stream_type']) {
  196. case GETID3_ASF_Audio_Media:
  197. $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf');
  198. $thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr');
  199. $audiodata = getid3_riff::RIFFparseWAVEFORMATex(substr($StreamPropertiesObjectData['type_specific_data'], 0, 16));
  200. unset($audiodata['raw']);
  201. $thisfile_audio = getid3_lib::array_merge_noclobber($audiodata, $thisfile_audio);
  202. break;
  203. case GETID3_ASF_Video_Media:
  204. $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf');
  205. $thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr');
  206. break;
  207. case GETID3_ASF_Command_Media:
  208. default:
  209. // do nothing
  210. break;
  211. }
  212. $thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData;
  213. unset($StreamPropertiesObjectData); // clear for next stream, if any
  214. break;
  215. case GETID3_ASF_Header_Extension_Object:
  216. // Header Extension Object: (mandatory, one only)
  217. // Field Name Field Type Size (bits)
  218. // Object ID GUID 128 // GUID for Header Extension object - GETID3_ASF_Header_Extension_Object
  219. // Object Size QWORD 64 // size of Header Extension object, including 46 bytes of Header Extension Object header
  220. // Reserved Field 1 GUID 128 // hardcoded: GETID3_ASF_Reserved_1
  221. // Reserved Field 2 WORD 16 // hardcoded: 0x00000006
  222. // Header Extension Data Size DWORD 32 // in bytes. valid: 0, or > 24. equals object size minus 46
  223. // Header Extension Data BYTESTREAM variable // array of zero or more extended header objects
  224. // shortcut
  225. $thisfile_asf['header_extension_object'] = array();
  226. $thisfile_asf_headerextensionobject = &$thisfile_asf['header_extension_object'];
  227. $thisfile_asf_headerextensionobject['offset'] = $NextObjectOffset + $offset;
  228. $thisfile_asf_headerextensionobject['objectid'] = $NextObjectGUID;
  229. $thisfile_asf_headerextensionobject['objectid_guid'] = $NextObjectGUIDtext;
  230. $thisfile_asf_headerextensionobject['objectsize'] = $NextObjectSize;
  231. $thisfile_asf_headerextensionobject['reserved_1'] = substr($ASFHeaderData, $offset, 16);
  232. $offset += 16;
  233. $thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
  234. if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
  235. $info['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).')';
  236. //return false;
  237. break;
  238. }
  239. $thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  240. $offset += 2;
  241. if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
  242. $info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"';
  243. //return false;
  244. break;
  245. }
  246. $thisfile_asf_headerextensionobject['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  247. $offset += 4;
  248. $thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']);
  249. $offset += $thisfile_asf_headerextensionobject['extension_data_size'];
  250. break;
  251. case GETID3_ASF_Codec_List_Object:
  252. // Codec List Object: (optional, one only)
  253. // Field Name Field Type Size (bits)
  254. // Object ID GUID 128 // GUID for Codec List object - GETID3_ASF_Codec_List_Object
  255. // Object Size QWORD 64 // size of Codec List object, including 44 bytes of Codec List Object header
  256. // Reserved GUID 128 // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6
  257. // Codec Entries Count DWORD 32 // number of entries in Codec Entries array
  258. // Codec Entries array of: variable //
  259. // * Type WORD 16 // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec
  260. // * Codec Name Length WORD 16 // number of Unicode characters stored in the Codec Name field
  261. // * Codec Name WCHAR variable // array of Unicode characters - name of codec used to create the content
  262. // * Codec Description Length WORD 16 // number of Unicode characters stored in the Codec Description field
  263. // * Codec Description WCHAR variable // array of Unicode characters - description of format used to create the content
  264. // * Codec Information Length WORD 16 // number of Unicode characters stored in the Codec Information field
  265. // * Codec Information BYTESTREAM variable // opaque array of information bytes about the codec used to create the content
  266. // shortcut
  267. $thisfile_asf['codec_list_object'] = array();
  268. $thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object'];
  269. $thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset;
  270. $thisfile_asf_codeclistobject['objectid'] = $NextObjectGUID;
  271. $thisfile_asf_codeclistobject['objectid_guid'] = $NextObjectGUIDtext;
  272. $thisfile_asf_codeclistobject['objectsize'] = $NextObjectSize;
  273. $thisfile_asf_codeclistobject['reserved'] = substr($ASFHeaderData, $offset, 16);
  274. $offset += 16;
  275. $thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
  276. if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
  277. $info['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}';
  278. //return false;
  279. break;
  280. }
  281. $thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  282. $offset += 4;
  283. for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) {
  284. // shortcut
  285. $thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array();
  286. $thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter];
  287. $thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  288. $offset += 2;
  289. $thisfile_asf_codeclistobject_codecentries_current['type'] = $this->ASFCodecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']);
  290. $CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
  291. $offset += 2;
  292. $thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData, $offset, $CodecNameLength);
  293. $offset += $CodecNameLength;
  294. $CodecDescriptionLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
  295. $offset += 2;
  296. $thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData, $offset, $CodecDescriptionLength);
  297. $offset += $CodecDescriptionLength;
  298. $CodecInformationLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  299. $offset += 2;
  300. $thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData, $offset, $CodecInformationLength);
  301. $offset += $CodecInformationLength;
  302. if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
  303. if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
  304. $info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"';
  305. } else {
  306. list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
  307. $thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']);
  308. if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
  309. $thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000);
  310. }
  311. //if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) {
  312. if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) {
  313. //$thisfile_video['bitrate'] = $thisfile_asf['file_properties_object']['max_bitrate'] - $thisfile_audio['bitrate'];
  314. $thisfile_video['bitrate'] = $info['bitrate'] - $thisfile_audio['bitrate'];
  315. }
  316. $AudioCodecFrequency = (int) trim(str_replace('kHz', '', $AudioCodecFrequency));
  317. switch ($AudioCodecFrequency) {
  318. case 8:
  319. case 8000:
  320. $thisfile_audio['sample_rate'] = 8000;
  321. break;
  322. case 11:
  323. case 11025:
  324. $thisfile_audio['sample_rate'] = 11025;
  325. break;
  326. case 12:
  327. case 12000:
  328. $thisfile_audio['sample_rate'] = 12000;
  329. break;
  330. case 16:
  331. case 16000:
  332. $thisfile_audio['sample_rate'] = 16000;
  333. break;
  334. case 22:
  335. case 22050:
  336. $thisfile_audio['sample_rate'] = 22050;
  337. break;
  338. case 24:
  339. case 24000:
  340. $thisfile_audio['sample_rate'] = 24000;
  341. break;
  342. case 32:
  343. case 32000:
  344. $thisfile_audio['sample_rate'] = 32000;
  345. break;
  346. case 44:
  347. case 441000:
  348. $thisfile_audio['sample_rate'] = 44100;
  349. break;
  350. case 48:
  351. case 48000:
  352. $thisfile_audio['sample_rate'] = 48000;
  353. break;
  354. default:
  355. $info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')';
  356. break;
  357. }
  358. if (!isset($thisfile_audio['channels'])) {
  359. if (strstr($AudioCodecChannels, 'stereo')) {
  360. $thisfile_audio['channels'] = 2;
  361. } elseif (strstr($AudioCodecChannels, 'mono')) {
  362. $thisfile_audio['channels'] = 1;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. break;
  369. case GETID3_ASF_Script_Command_Object:
  370. // Script Command Object: (optional, one only)
  371. // Field Name Field Type Size (bits)
  372. // Object ID GUID 128 // GUID for Script Command object - GETID3_ASF_Script_Command_Object
  373. // Object Size QWORD 64 // size of Script Command object, including 44 bytes of Script Command Object header
  374. // Reserved GUID 128 // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6
  375. // Commands Count WORD 16 // number of Commands structures in the Script Commands Objects
  376. // Command Types Count WORD 16 // number of Command Types structures in the Script Commands Objects
  377. // Command Types array of: variable //
  378. // * Command Type Name Length WORD 16 // number of Unicode characters for Command Type Name
  379. // * Command Type Name WCHAR variable // array of Unicode characters - name of a type of command
  380. // Commands array of: variable //
  381. // * Presentation Time DWORD 32 // presentation time of that command, in milliseconds
  382. // * Type Index WORD 16 // type of this command, as a zero-based index into the array of Command Types of this object
  383. // * Command Name Length WORD 16 // number of Unicode characters for Command Name
  384. // * Command Name WCHAR variable // array of Unicode characters - name of this command
  385. // shortcut
  386. $thisfile_asf['script_command_object'] = array();
  387. $thisfile_asf_scriptcommandobject = &$thisfile_asf['script_command_object'];
  388. $thisfile_asf_scriptcommandobject['offset'] = $NextObjectOffset + $offset;
  389. $thisfile_asf_scriptcommandobject['objectid'] = $NextObjectGUID;
  390. $thisfile_asf_scriptcommandobject['objectid_guid'] = $NextObjectGUIDtext;
  391. $thisfile_asf_scriptcommandobject['objectsize'] = $NextObjectSize;
  392. $thisfile_asf_scriptcommandobject['reserved'] = substr($ASFHeaderData, $offset, 16);
  393. $offset += 16;
  394. $thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
  395. if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
  396. $info['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}';
  397. //return false;
  398. break;
  399. }
  400. $thisfile_asf_scriptcommandobject['commands_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  401. $offset += 2;
  402. $thisfile_asf_scriptcommandobject['command_types_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  403. $offset += 2;
  404. for ($CommandTypesCounter = 0; $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count']; $CommandTypesCounter++) {
  405. $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
  406. $offset += 2;
  407. $thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
  408. $offset += $CommandTypeNameLength;
  409. }
  410. for ($CommandsCounter = 0; $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count']; $CommandsCounter++) {
  411. $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  412. $offset += 4;
  413. $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['type_index'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  414. $offset += 2;
  415. $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
  416. $offset += 2;
  417. $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength);
  418. $offset += $CommandTypeNameLength;
  419. }
  420. break;
  421. case GETID3_ASF_Marker_Object:
  422. // Marker Object: (optional, one only)
  423. // Field Name Field Type Size (bits)
  424. // Object ID GUID 128 // GUID for Marker object - GETID3_ASF_Marker_Object
  425. // Object Size QWORD 64 // size of Marker object, including 48 bytes of Marker Object header
  426. // Reserved GUID 128 // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB
  427. // Markers Count DWORD 32 // number of Marker structures in Marker Object
  428. // Reserved WORD 16 // hardcoded: 0x0000
  429. // Name Length WORD 16 // number of bytes in the Name field
  430. // Name WCHAR variable // name of the Marker Object
  431. // Markers array of: variable //
  432. // * Offset QWORD 64 // byte offset into Data Object
  433. // * Presentation Time QWORD 64 // in 100-nanosecond units
  434. // * Entry Length WORD 16 // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding)
  435. // * Send Time DWORD 32 // in milliseconds
  436. // * Flags DWORD 32 // hardcoded: 0x00000000
  437. // * Marker Description Length DWORD 32 // number of bytes in Marker Description field
  438. // * Marker Description WCHAR variable // array of Unicode characters - description of marker entry
  439. // * Padding BYTESTREAM variable // optional padding bytes
  440. // shortcut
  441. $thisfile_asf['marker_object'] = array();
  442. $thisfile_asf_markerobject = &$thisfile_asf['marker_object'];
  443. $thisfile_asf_markerobject['offset'] = $NextObjectOffset + $offset;
  444. $thisfile_asf_markerobject['objectid'] = $NextObjectGUID;
  445. $thisfile_asf_markerobject['objectid_guid'] = $NextObjectGUIDtext;
  446. $thisfile_asf_markerobject['objectsize'] = $NextObjectSize;
  447. $thisfile_asf_markerobject['reserved'] = substr($ASFHeaderData, $offset, 16);
  448. $offset += 16;
  449. $thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
  450. if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
  451. $info['warning'][] = 'marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}';
  452. break;
  453. }
  454. $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  455. $offset += 4;
  456. $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  457. $offset += 2;
  458. if ($thisfile_asf_markerobject['reserved_2'] != 0) {
  459. $info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"';
  460. break;
  461. }
  462. $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  463. $offset += 2;
  464. $thisfile_asf_markerobject['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['name_length']);
  465. $offset += $thisfile_asf_markerobject['name_length'];
  466. for ($MarkersCounter = 0; $MarkersCounter < $thisfile_asf_markerobject['markers_count']; $MarkersCounter++) {
  467. $thisfile_asf_markerobject['markers'][$MarkersCounter]['offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  468. $offset += 8;
  469. $thisfile_asf_markerobject['markers'][$MarkersCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8));
  470. $offset += 8;
  471. $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  472. $offset += 2;
  473. $thisfile_asf_markerobject['markers'][$MarkersCounter]['send_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  474. $offset += 4;
  475. $thisfile_asf_markerobject['markers'][$MarkersCounter]['flags'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  476. $offset += 4;
  477. $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  478. $offset += 4;
  479. $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']);
  480. $offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
  481. $PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 - 4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'];
  482. if ($PaddingLength > 0) {
  483. $thisfile_asf_markerobject['markers'][$MarkersCounter]['padding'] = substr($ASFHeaderData, $offset, $PaddingLength);
  484. $offset += $PaddingLength;
  485. }
  486. }
  487. break;
  488. case GETID3_ASF_Bitrate_Mutual_Exclusion_Object:
  489. // Bitrate Mutual Exclusion Object: (optional)
  490. // Field Name Field Type Size (bits)
  491. // Object ID GUID 128 // GUID for Bitrate Mutual Exclusion object - GETID3_ASF_Bitrate_Mutual_Exclusion_Object
  492. // Object Size QWORD 64 // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header
  493. // Exlusion Type GUID 128 // nature of mutual exclusion relationship. one of: (GETID3_ASF_Mutex_Bitrate, GETID3_ASF_Mutex_Unknown)
  494. // Stream Numbers Count WORD 16 // number of video streams
  495. // Stream Numbers WORD variable // array of mutually exclusive video stream numbers. 1 <= valid <= 127
  496. // shortcut
  497. $thisfile_asf['bitrate_mutual_exclusion_object'] = array();
  498. $thisfile_asf_bitratemutualexclusionobject = &$thisfile_asf['bitrate_mutual_exclusion_object'];
  499. $thisfile_asf_bitratemutualexclusionobject['offset'] = $NextObjectOffset + $offset;
  500. $thisfile_asf_bitratemutualexclusionobject['objectid'] = $NextObjectGUID;
  501. $thisfile_asf_bitratemutualexclusionobject['objectid_guid'] = $NextObjectGUIDtext;
  502. $thisfile_asf_bitratemutualexclusionobject['objectsize'] = $NextObjectSize;
  503. $thisfile_asf_bitratemutualexclusionobject['reserved'] = substr($ASFHeaderData, $offset, 16);
  504. $thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
  505. $offset += 16;
  506. if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
  507. $info['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).'}';
  508. //return false;
  509. break;
  510. }
  511. $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  512. $offset += 2;
  513. for ($StreamNumberCounter = 0; $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count']; $StreamNumberCounter++) {
  514. $thisfile_asf_bitratemutualexclusionobject['stream_numbers'][$StreamNumberCounter] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  515. $offset += 2;
  516. }
  517. break;
  518. case GETID3_ASF_Error_Correction_Object:
  519. // Error Correction Object: (optional, one only)
  520. // Field Name Field Type Size (bits)
  521. // Object ID GUID 128 // GUID for Error Correction object - GETID3_ASF_Error_Correction_Object
  522. // Object Size QWORD 64 // size of Error Correction object, including 44 bytes of Error Correction Object header
  523. // Error Correction Type GUID 128 // type of error correction. one of: (GETID3_ASF_No_Error_Correction, GETID3_ASF_Audio_Spread)
  524. // Error Correction Data Length DWORD 32 // number of bytes in Error Correction Data field
  525. // Error Correction Data BYTESTREAM variable // structure depends on value of Error Correction Type field
  526. // shortcut
  527. $thisfile_asf['error_correction_object'] = array();
  528. $thisfile_asf_errorcorrectionobject = &$thisfile_asf['error_correction_object'];
  529. $thisfile_asf_errorcorrectionobject['offset'] = $NextObjectOffset + $offset;
  530. $thisfile_asf_errorcorrectionobject['objectid'] = $NextObjectGUID;
  531. $thisfile_asf_errorcorrectionobject['objectid_guid'] = $NextObjectGUIDtext;
  532. $thisfile_asf_errorcorrectionobject['objectsize'] = $NextObjectSize;
  533. $thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData, $offset, 16);
  534. $offset += 16;
  535. $thisfile_asf_errorcorrectionobject['error_correction_guid'] = $this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']);
  536. $thisfile_asf_errorcorrectionobject['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
  537. $offset += 4;
  538. switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) {
  539. case GETID3_ASF_No_Error_Correction:
  540. // should be no data, but just in case there is, skip to the end of the field
  541. $offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length'];
  542. break;
  543. case GETID3_ASF_Audio_Spread:
  544. // Field Name Field Type Size (bits)
  545. // Span BYTE 8 // number of packets over which audio will be spread.
  546. // Virtual Packet Length WORD 16 // size of largest audio payload found in audio stream
  547. // Virtual Chunk Length WORD 16 // size of largest audio payload found in audio stream
  548. // Silence Data Length WORD 16 // number of bytes in Silence Data field
  549. // Silence Data BYTESTREAM variable // hardcoded: 0x00 * (Silence Data Length) bytes
  550. $thisfile_asf_errorcorrectionobject['span'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 1));
  551. $offset += 1;
  552. $thisfile_asf_errorcorrectionobject['virtual_packet_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  553. $offset += 2;
  554. $thisfile_asf_errorcorrectionobject['virtual_chunk_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  555. $offset += 2;
  556. $thisfile_asf_errorcorrectionobject['silence_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  557. $offset += 2;
  558. $thisfile_asf_errorcorrectionobject['silence_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_errorcorrectionobject['silence_data_length']);
  559. $offset += $thisfile_asf_errorcorrectionobject['silence_data_length'];
  560. break;
  561. default:
  562. $info['warning'][] = 'error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} 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).'}';
  563. //return false;
  564. break;
  565. }
  566. break;
  567. case GETID3_ASF_Content_Description_Object:
  568. // Content Description Object: (optional, one only)
  569. // Field Name Field Type Size (bits)
  570. // Object ID GUID 128 // GUID for Content Description object - GETID3_ASF_Content_Description_Object
  571. // Object Size QWORD 64 // size of Content Description object, including 34 bytes of Content Description Object header
  572. // Title Length WORD 16 // number of bytes in Title field
  573. // Author Length WORD 16 // number of bytes in Author field
  574. // Copyright Length WORD 16 // number of bytes in Copyright field
  575. // Description Length WORD 16 // number of bytes in Description field
  576. // Rating Length WORD 16 // number of bytes in Rating field
  577. // Title WCHAR 16 // array of Unicode characters - Title
  578. // Author WCHAR 16 // array of Unicode characters - Author
  579. // Copyright WCHAR 16 // array of Unicode characters - Copyright
  580. // Description WCHAR 16 // array of Unicode characters - Description
  581. // Rating WCHAR 16 // array of Unicode characters - Rating
  582. // shortcut
  583. $thisfile_asf['content_description_object'] = array();
  584. $thisfile_asf_contentdescriptionobject = &$thisfile_asf['content_description_object'];
  585. $thisfile_asf_contentdescriptionobject['offset'] = $NextObjectOffset + $offset;
  586. $thisfile_asf_contentdescriptionobject['objectid'] = $NextObjectGUID;
  587. $thisfile_asf_contentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext;
  588. $thisfile_asf_contentdescriptionobject['objectsize'] = $NextObjectSize;
  589. $thisfile_asf_contentdescriptionobject['title_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  590. $offset += 2;
  591. $thisfile_asf_contentdescriptionobject['author_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  592. $offset += 2;
  593. $thisfile_asf_contentdescriptionobject['copyright_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  594. $offset += 2;
  595. $thisfile_asf_contentdescriptionobject['description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  596. $offset += 2;
  597. $thisfile_asf_contentdescriptionobject['rating_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
  598. $offset += 2;
  599. $thisfile_asf_contentdescriptionobject['title'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['title_length']);
  600. $offset += $thisfile_asf_contentdescriptionobject['title_length'];
  601. $thisfile_asf_contentdescriptionobject['author'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['author_length']);
  602. $offset += $thisfile_asf_contentdescriptionobject['author_length'];
  603. $thisfile_asf_contentdescriptionobject['copyright'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['copyright_length']);
  604. $offset += $thisfile_asf_contentdescriptionobject['copyright_length'];
  605. $thisfile_asf_contentdescriptionobject['description'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['description_length']);
  606. $offset += $thisfile_asf_contentdescriptionobject['description_length'];
  607. $thisfile_asf_contentdescriptionobject['rating'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['rating_length']);
  608. $offset += $thisfile_asf_contentdescriptionobject['rating_length'];
  609. $ASFcommentKeysToCopy = array('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating');
  610. foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) {
  611. if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) {
  612. $thisfile_asf_comments[$keytocopyto][] = $this->TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]);
  613. }
  614. }
  615. break;
  616. case GETID3_ASF_Extended_Content_Description_Object:
  617. // Extended Content Description Object: (optional, one only)
  618. // Field Name Field Type Size (bits)
  619. // Object ID GUID 128 // GUID for Extended Content Description object - GETID3_ASF_Extended_Content_Description_Object
  620. // Object Size QWORD 64 // size of ExtendedContent Description object, including 26 bytes of Extended Content Description Object header
  621. // Content Descriptors Count WORD 16 // number of entries in Content Descriptors list
  622. // Content Descriptors array of: variable //
  623. // * Descriptor Name Length WORD 16 // size in bytes of Descriptor Name field
  624. // * Descriptor Name WCHAR variable // array of Unicode characters - Descriptor Name
  625. // * Descriptor Value Data Type WORD 16 // Lookup array:
  626. // 0x0000 = Unicode String (variable length)
  627. // 0x0001 = BYTE array (variable length)
  628. // 0x0002 = BOOL (DWORD, 32 bits)
  629. // 0x0003 = DWORD (DWORD, 32 bits)
  630. // 0x0004 = QWORD (QWORD, 64 bits)
  631. // 0x0005 = WORD (WORD, 16 bits)
  632. // * Descriptor Value Length WORD 16 // number of bytes stored in Descriptor Value field
  633. // * Descriptor Value…

Large files files are truncated, but you can click here to view the full file