PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/application/libraries/getid3/module.audio-video.asf.php

https://github.com/libis/Flandrica
PHP | 1862 lines | 1154 code | 392 blank | 316 comment | 112 complexity | b542342119f02f24fa48a7bb09994f00 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, Apache-2.0

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

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP version 5 |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 2002-2009 James Heinrich, Allan Hansen |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2 of the GPL license, |
  8. // | that is bundled with this package in the file license.txt and is |
  9. // | available through the world-wide-web at the following url: |
  10. // | http://www.gnu.org/copyleft/gpl.html |
  11. // +----------------------------------------------------------------------+
  12. // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org |
  13. // +----------------------------------------------------------------------+
  14. // | Authors: James Heinrich <infoŘgetid3*org> |
  15. // | Allan Hansen <ahŘartemis*dk> |
  16. // +----------------------------------------------------------------------+
  17. // | module.audio-video.php |
  18. // | Module for analyzing Microsoft ASF, WMA and WMV files. |
  19. // | dependencies: module.audio-video.riff.php |
  20. // +----------------------------------------------------------------------+
  21. //
  22. // $Id: module.audio-video.asf.php,v 1.7 2006/12/01 22:39:48 ah Exp $
  23. class getid3_asf extends getid3_handler
  24. {
  25. const Extended_Stream_Properties_Object = '14E6A5CB-C672-4332-8399-A96952065B5A';
  26. const Padding_Object = '1806D474-CADF-4509-A4BA-9AABCB96AAE8';
  27. const Payload_Ext_Syst_Pixel_Aspect_Ratio = '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8';
  28. const Script_Command_Object = '1EFB1A30-0B62-11D0-A39B-00A0C90348F6';
  29. const No_Error_Correction = '20FB5700-5B55-11CF-A8FD-00805F5C442B';
  30. const Content_Branding_Object = '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E';
  31. const Content_Encryption_Object = '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E';
  32. const Digital_Signature_Object = '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E';
  33. const Extended_Content_Encryption_Object = '298AE614-2622-4C17-B935-DAE07EE9289C';
  34. const Simple_Index_Object = '33000890-E5B1-11CF-89F4-00A0C90349CB';
  35. const Degradable_JPEG_Media = '35907DE0-E415-11CF-A917-00805F5C442B';
  36. const Payload_Extension_System_Timecode = '399595EC-8667-4E2D-8FDB-98814CE76C1E';
  37. const Binary_Media = '3AFB65E2-47EF-40F2-AC2C-70A90D71D343';
  38. const Timecode_Index_Object = '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C';
  39. const Metadata_Library_Object = '44231C94-9498-49D1-A141-1D134E457054';
  40. const Reserved_3 = '4B1ACBE3-100B-11D0-A39B-00A0C90348F6';
  41. const Reserved_4 = '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB';
  42. const Command_Media = '59DACFC0-59E6-11D0-A3AC-00A0C90348F6';
  43. const Header_Extension_Object = '5FBF03B5-A92E-11CF-8EE3-00C00C205365';
  44. const Media_Object_Index_Parameters_Obj = '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7';
  45. const Header_Object = '75B22630-668E-11CF-A6D9-00AA0062CE6C';
  46. const Content_Description_Object = '75B22633-668E-11CF-A6D9-00AA0062CE6C';
  47. const Error_Correction_Object = '75B22635-668E-11CF-A6D9-00AA0062CE6C';
  48. const Data_Object = '75B22636-668E-11CF-A6D9-00AA0062CE6C';
  49. const Web_Stream_Media_Subtype = '776257D4-C627-41CB-8F81-7AC7FF1C40CC';
  50. const Stream_Bitrate_Properties_Object = '7BF875CE-468D-11D1-8D82-006097C9A2B2';
  51. const Language_List_Object = '7C4346A9-EFE0-4BFC-B229-393EDE415C85';
  52. const Codec_List_Object = '86D15240-311D-11D0-A3A4-00A0C90348F6';
  53. const Reserved_2 = '86D15241-311D-11D0-A3A4-00A0C90348F6';
  54. const File_Properties_Object = '8CABDCA1-A947-11CF-8EE4-00C00C205365';
  55. const File_Transfer_Media = '91BD222C-F21C-497A-8B6D-5AA86BFC0185';
  56. const Old_RTP_Extension_Data = '96800C63-4C94-11D1-837B-0080C7A37F95';
  57. const Advanced_Mutual_Exclusion_Object = 'A08649CF-4775-4670-8A16-6E35357566CD';
  58. const Bandwidth_Sharing_Object = 'A69609E6-517B-11D2-B6AF-00C04FD908E9';
  59. const Reserved_1 = 'ABD3D211-A9BA-11CF-8EE6-00C00C205365';
  60. const Bandwidth_Sharing_Exclusive = 'AF6060AA-5197-11D2-B6AF-00C04FD908E9';
  61. const Bandwidth_Sharing_Partial = 'AF6060AB-5197-11D2-B6AF-00C04FD908E9';
  62. const JFIF_Media = 'B61BE100-5B4E-11CF-A8FD-00805F5C442B';
  63. const Stream_Properties_Object = 'B7DC0791-A9B7-11CF-8EE6-00C00C205365';
  64. const Video_Media = 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B';
  65. const Audio_Spread = 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220';
  66. const Metadata_Object = 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA';
  67. const Payload_Ext_Syst_Sample_Duration = 'C6BD9450-867F-4907-83A3-C77921B733AD';
  68. const Group_Mutual_Exclusion_Object = 'D1465A40-5A79-4338-B71B-E36B8FD6C249';
  69. const Extended_Content_Description_Object = 'D2D0A440-E307-11D2-97F0-00A0C95EA850';
  70. const Stream_Prioritization_Object = 'D4FED15B-88D3-454F-81F0-ED5C45999E24';
  71. const Payload_Ext_System_Content_Type = 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC';
  72. const Old_File_Properties_Object = 'D6E229D0-35DA-11D1-9034-00A0C90349BE';
  73. const Old_ASF_Header_Object = 'D6E229D1-35DA-11D1-9034-00A0C90349BE';
  74. const Old_ASF_Data_Object = 'D6E229D2-35DA-11D1-9034-00A0C90349BE';
  75. const Index_Object = 'D6E229D3-35DA-11D1-9034-00A0C90349BE';
  76. const Old_Stream_Properties_Object = 'D6E229D4-35DA-11D1-9034-00A0C90349BE';
  77. const Old_Content_Description_Object = 'D6E229D5-35DA-11D1-9034-00A0C90349BE';
  78. const Old_Script_Command_Object = 'D6E229D6-35DA-11D1-9034-00A0C90349BE';
  79. const Old_Marker_Object = 'D6E229D7-35DA-11D1-9034-00A0C90349BE';
  80. const Old_Component_Download_Object = 'D6E229D8-35DA-11D1-9034-00A0C90349BE';
  81. const Old_Stream_Group_Object = 'D6E229D9-35DA-11D1-9034-00A0C90349BE';
  82. const Old_Scalable_Object = 'D6E229DA-35DA-11D1-9034-00A0C90349BE';
  83. const Old_Prioritization_Object = 'D6E229DB-35DA-11D1-9034-00A0C90349BE';
  84. const Bitrate_Mutual_Exclusion_Object = 'D6E229DC-35DA-11D1-9034-00A0C90349BE';
  85. const Old_Inter_Media_Dependency_Object = 'D6E229DD-35DA-11D1-9034-00A0C90349BE';
  86. const Old_Rating_Object = 'D6E229DE-35DA-11D1-9034-00A0C90349BE';
  87. const Index_Parameters_Object = 'D6E229DF-35DA-11D1-9034-00A0C90349BE';
  88. const Old_Color_Table_Object = 'D6E229E0-35DA-11D1-9034-00A0C90349BE';
  89. const Old_Language_List_Object = 'D6E229E1-35DA-11D1-9034-00A0C90349BE';
  90. const Old_Audio_Media = 'D6E229E2-35DA-11D1-9034-00A0C90349BE';
  91. const Old_Video_Media = 'D6E229E3-35DA-11D1-9034-00A0C90349BE';
  92. const Old_Image_Media = 'D6E229E4-35DA-11D1-9034-00A0C90349BE';
  93. const Old_Timecode_Media = 'D6E229E5-35DA-11D1-9034-00A0C90349BE';
  94. const Old_Text_Media = 'D6E229E6-35DA-11D1-9034-00A0C90349BE';
  95. const Old_MIDI_Media = 'D6E229E7-35DA-11D1-9034-00A0C90349BE';
  96. const Old_Command_Media = 'D6E229E8-35DA-11D1-9034-00A0C90349BE';
  97. const Old_No_Error_Concealment = 'D6E229EA-35DA-11D1-9034-00A0C90349BE';
  98. const Old_Scrambled_Audio = 'D6E229EB-35DA-11D1-9034-00A0C90349BE';
  99. const Old_No_Color_Table = 'D6E229EC-35DA-11D1-9034-00A0C90349BE';
  100. const Old_SMPTE_Time = 'D6E229ED-35DA-11D1-9034-00A0C90349BE';
  101. const Old_ASCII_Text = 'D6E229EE-35DA-11D1-9034-00A0C90349BE';
  102. const Old_Unicode_Text = 'D6E229EF-35DA-11D1-9034-00A0C90349BE';
  103. const Old_HTML_Text = 'D6E229F0-35DA-11D1-9034-00A0C90349BE';
  104. const Old_URL_Command = 'D6E229F1-35DA-11D1-9034-00A0C90349BE';
  105. const Old_Filename_Command = 'D6E229F2-35DA-11D1-9034-00A0C90349BE';
  106. const Old_ACM_Codec = 'D6E229F3-35DA-11D1-9034-00A0C90349BE';
  107. const Old_VCM_Codec = 'D6E229F4-35DA-11D1-9034-00A0C90349BE';
  108. const Old_QuickTime_Codec = 'D6E229F5-35DA-11D1-9034-00A0C90349BE';
  109. const Old_DirectShow_Transform_Filter = 'D6E229F6-35DA-11D1-9034-00A0C90349BE';
  110. const Old_DirectShow_Rendering_Filter = 'D6E229F7-35DA-11D1-9034-00A0C90349BE';
  111. const Old_No_Enhancement = 'D6E229F8-35DA-11D1-9034-00A0C90349BE';
  112. const Old_Unknown_Enhancement_Type = 'D6E229F9-35DA-11D1-9034-00A0C90349BE';
  113. const Old_Temporal_Enhancement = 'D6E229FA-35DA-11D1-9034-00A0C90349BE';
  114. const Old_Spatial_Enhancement = 'D6E229FB-35DA-11D1-9034-00A0C90349BE';
  115. const Old_Quality_Enhancement = 'D6E229FC-35DA-11D1-9034-00A0C90349BE';
  116. const Old_Number_of_Channels_Enhancement = 'D6E229FD-35DA-11D1-9034-00A0C90349BE';
  117. const Old_Frequency_Response_Enhancement = 'D6E229FE-35DA-11D1-9034-00A0C90349BE';
  118. const Old_Media_Object = 'D6E229FF-35DA-11D1-9034-00A0C90349BE';
  119. const Mutex_Language = 'D6E22A00-35DA-11D1-9034-00A0C90349BE';
  120. const Mutex_Bitrate = 'D6E22A01-35DA-11D1-9034-00A0C90349BE';
  121. const Mutex_Unknown = 'D6E22A02-35DA-11D1-9034-00A0C90349BE';
  122. const Old_ASF_Placeholder_Object = 'D6E22A0E-35DA-11D1-9034-00A0C90349BE';
  123. const Old_Data_Unit_Extension_Object = 'D6E22A0F-35DA-11D1-9034-00A0C90349BE';
  124. const Web_Stream_Format = 'DA1E6B13-8359-4050-B398-388E965BF00C';
  125. const Payload_Ext_System_File_Name = 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B';
  126. const Marker_Object = 'F487CD01-A951-11CF-8EE6-00C00C205365';
  127. const Timecode_Index_Parameters_Object = 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24';
  128. const Audio_Media = 'F8699E40-5B4D-11CF-A8FD-00805F5C442B';
  129. const Media_Object_Index_Object = 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C';
  130. const Alt_Extended_Content_Encryption_Obj = 'FF889EF1-ADEE-40DA-9E71-98704BB928CE';
  131. public function Analyze() {
  132. $getid3 = $this->getid3;
  133. $getid3->include_module('audio-video.riff');
  134. !isset($getid3->info['audio']) and $getid3->info['audio'] = array();
  135. !isset($getid3->info['video']) and $getid3->info['video'] = array();
  136. $getid3->info['asf']['comments'] = $getid3->info['asf']['header_object'] = array();
  137. $info_audio = &$getid3->info['audio'];
  138. $info_video = &$getid3->info['video'];
  139. $info_asf = &$getid3->info['asf'];
  140. $info_asf_comments = &$info_asf['comments'];
  141. $info_asf_header_object = &$info_asf['header_object'];
  142. // ASF structure:
  143. // * Header Object [required]
  144. // * File Properties Object [required] (global file attributes)
  145. // * Stream Properties Object [required] (defines media stream & characteristics)
  146. // * Header Extension Object [required] (additional functionality)
  147. // * Content Description Object (bibliographic information)
  148. // * Script Command Object (commands for during playback)
  149. // * Marker Object (named jumped points within the file)
  150. // * Data Object [required]
  151. // * Data Packets
  152. // * Index Object
  153. // Header Object: (mandatory, one only)
  154. // Field Name Field Type Size (bits)
  155. // Object ID GUID 128 // GUID for header object - getid3_asf::Header_Object
  156. // Object Size QWORD 64 // size of header object, including 30 bytes of Header Object header
  157. // Number of Header Objects DWORD 32 // number of objects in header object
  158. // Reserved1 BYTE 8 // hardcoded: 0x01
  159. // Reserved2 BYTE 8 // hardcoded: 0x02
  160. $getid3->info['fileformat'] = 'asf';
  161. fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
  162. $header_object_data = fread($getid3->fp, 30);
  163. $info_asf_header_object['objectid_guid'] = getid3_asf::BytestringToGUID(substr($header_object_data, 0, 16));
  164. if ($info_asf_header_object['objectid_guid'] != getid3_asf::Header_Object) {
  165. throw new getid3_exception('ASF header GUID {'.$info_asf_header_object['objectid_guid'].'} does not match expected "getid3_asf::Header_Object" GUID {'.getid3_asf::Header_Object.'}');
  166. }
  167. getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_header_object, $header_object_data, 16,
  168. array(
  169. 'objectsize' => 8,
  170. 'headerobjects' => 4,
  171. 'reserved1' => 1,
  172. 'reserved2' => 1
  173. )
  174. );
  175. $asf_header_data = fread($getid3->fp, $info_asf_header_object['objectsize'] - 30);
  176. $offset = 0;
  177. for ($header_objects_counter = 0; $header_objects_counter < $info_asf_header_object['headerobjects']; $header_objects_counter++) {
  178. $next_object_guid = substr($asf_header_data, $offset, 16);
  179. $offset += 16;
  180. $next_object_size = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 8));
  181. $offset += 8;
  182. $next_object_guidtext = getid3_asf::BytestringToGUID($next_object_guid);
  183. switch ($next_object_guidtext) {
  184. case getid3_asf::File_Properties_Object:
  185. // File Properties Object: (mandatory, one only)
  186. // Field Name Field Type Size (bits)
  187. // Object ID GUID 128 // GUID for file properties object - getid3_asf::File_Properties_Object
  188. // Object Size QWORD 64 // size of file properties object, including 104 bytes of File Properties Object header
  189. // File ID GUID 128 // unique ID - identical to File ID in Data Object
  190. // File Size QWORD 64 // entire file in bytes. Invalid if Broadcast Flag == 1
  191. // Creation Date QWORD 64 // date & time of file creation. Maybe invalid if Broadcast Flag == 1
  192. // Data Packets Count QWORD 64 // number of data packets in Data Object. Invalid if Broadcast Flag == 1
  193. // Play Duration QWORD 64 // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1
  194. // Send Duration QWORD 64 // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1
  195. // 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
  196. // Flags DWORD 32 //
  197. // * Broadcast Flag bits 1 (0x01) // file is currently being written, some header values are invalid
  198. // * Seekable Flag bits 1 (0x02) // is file seekable
  199. // * Reserved bits 30 (0xFFFFFFFC) // reserved - set to zero
  200. // Minimum Data Packet Size DWORD 32 // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1
  201. // Maximum Data Packet Size DWORD 32 // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1
  202. // Maximum Bitrate DWORD 32 // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead
  203. $info_asf['file_properties_object'] = array();
  204. $info_asf_file_properties_object = &$info_asf['file_properties_object'];
  205. $info_asf_file_properties_object['objectid_guid'] = $next_object_guidtext;
  206. $info_asf_file_properties_object['objectsize'] = $next_object_size;
  207. $info_asf_file_properties_object['fileid_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  208. $offset += 16;
  209. getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_file_properties_object, $asf_header_data, $offset,
  210. array(
  211. 'filesize' => 8,
  212. 'creation_date' => 8,
  213. 'data_packets' => 8,
  214. 'play_duration' => 8,
  215. 'send_duration' => 8,
  216. 'preroll' => 8,
  217. 'flags_raw' => 4,
  218. 'min_packet_size' => 4,
  219. 'max_packet_size' => 4,
  220. 'max_bitrate' => 4
  221. )
  222. );
  223. $offset += 64;
  224. if ($info_asf_file_properties_object['filesize'] > $getid3->info['filesize']) {
  225. $getid3->warning('Probable truncated file: file_properties_object.filesize ('.number_format($info_asf_file_properties_object['filesize']).') > filesize ('.number_format($getid3->info['filesize']).')');
  226. }
  227. $info_asf_file_properties_object['creation_date_unix'] = getid3_asf::FiletimeToUNIXtime($info_asf_file_properties_object['creation_date']);
  228. $info_asf_file_properties_object['flags']['broadcast'] = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0001);
  229. $info_asf_file_properties_object['flags']['seekable'] = (bool)($info_asf_file_properties_object['flags_raw'] & 0x0002);
  230. $getid3->info['playtime_seconds'] = ($info_asf_file_properties_object['play_duration'] / 10000000) - ($info_asf_file_properties_object['preroll'] / 1000);
  231. $getid3->info['bitrate'] = ($info_asf_file_properties_object['filesize'] * 8) / $getid3->info['playtime_seconds'];
  232. break;
  233. case getid3_asf::Stream_Properties_Object:
  234. // Stream Properties Object: (mandatory, one per media stream)
  235. // Field Name Field Type Size (bits)
  236. // Object ID GUID 128 // GUID for stream properties object - getid3_asf::Stream_Properties_Object
  237. // Object Size QWORD 64 // size of stream properties object, including 78 bytes of Stream Properties Object header
  238. // Stream Type GUID 128 // getid3_asf::Audio_Media, getid3_asf::Video_Media or getid3_asf::Command_Media
  239. // Error Correction Type GUID 128 // getid3_asf::Audio_Spread for audio-only streams, getid3_asf::No_Error_Correction for other stream types
  240. // Time Offset QWORD 64 // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream
  241. // Type-Specific Data Length DWORD 32 // number of bytes for Type-Specific Data field
  242. // Error Correction Data Length DWORD 32 // number of bytes for Error Correction Data field
  243. // Flags WORD 16 //
  244. // * Stream Number bits 7 (0x007F) // number of this stream. 1 <= valid <= 127
  245. // * Reserved bits 8 (0x7F80) // reserved - set to zero
  246. // * Encrypted Content Flag bits 1 (0x8000) // stream contents encrypted if set
  247. // Reserved DWORD 32 // reserved - set to zero
  248. // Type-Specific Data BYTESTREAM variable // type-specific format data, depending on value of Stream Type
  249. // Error Correction Data BYTESTREAM variable // error-correction-specific format data, depending on value of Error Correct Type
  250. // There is one getid3_asf::Stream_Properties_Object for each stream (audio, video) but the
  251. // stream number isn't known until halfway through decoding the structure, hence it
  252. // it is decoded to a temporary variable and then stuck in the appropriate index later
  253. $stream_properties_object_data['objectid_guid'] = $next_object_guidtext;
  254. $stream_properties_object_data['objectsize'] = $next_object_size;
  255. getid3_lib::ReadSequence('LittleEndian2Int', $stream_properties_object_data, $asf_header_data, $offset,
  256. array(
  257. 'stream_type' => -16,
  258. 'error_correct_type' => -16,
  259. 'time_offset' => 8,
  260. 'type_data_length' => 4,
  261. 'error_data_length' => 4,
  262. 'flags_raw' => 2
  263. )
  264. );
  265. $stream_properties_stream_number = $stream_properties_object_data['flags_raw'] & 0x007F;
  266. $stream_properties_object_data['flags']['encrypted'] = (bool)($stream_properties_object_data['flags_raw'] & 0x8000);
  267. $stream_properties_object_data['stream_type_guid'] = getid3_asf::BytestringToGUID($stream_properties_object_data['stream_type']);
  268. $stream_properties_object_data['error_correct_guid'] = getid3_asf::BytestringToGUID($stream_properties_object_data['error_correct_type']);
  269. $offset += 54; // 50 bytes + 4 bytes reserved - DWORD
  270. $stream_properties_object_data['type_specific_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['type_data_length']);
  271. $offset += $stream_properties_object_data['type_data_length'];
  272. $stream_properties_object_data['error_correct_data'] = substr($asf_header_data, $offset, $stream_properties_object_data['error_data_length']);
  273. $offset += $stream_properties_object_data['error_data_length'];
  274. switch ($stream_properties_object_data['stream_type_guid']) {
  275. case getid3_asf::Audio_Media:
  276. $info_audio['dataformat'] = (@$info_audio['dataformat'] ? $info_audio['dataformat'] : 'asf');
  277. $info_audio['bitrate_mode'] = (@$info_audio['bitrate_mode'] ? $info_audio['bitrate_mode'] : 'cbr');
  278. $audiodata = getid3_riff::RIFFparseWAVEFORMATex(substr($stream_properties_object_data['type_specific_data'], 0, 16));
  279. unset($audiodata['raw']);
  280. $info_audio = getid3_riff::array_merge_noclobber($audiodata, $info_audio);
  281. break;
  282. case getid3_asf::Video_Media:
  283. $info_video['dataformat'] = (@$info_video['dataformat'] ? $info_video['dataformat'] : 'asf');
  284. $info_video['bitrate_mode'] = (@$info_video['bitrate_mode'] ? $info_video['bitrate_mode'] : 'cbr');
  285. break;
  286. /* does nothing but eat memory
  287. case getid3_asf::Command_Media:
  288. default:
  289. // do nothing
  290. break;
  291. */
  292. }
  293. $info_asf['stream_properties_object'][$stream_properties_stream_number] = $stream_properties_object_data;
  294. unset($stream_properties_object_data); // clear for next stream, if any
  295. break;
  296. case getid3_asf::Header_Extension_Object:
  297. // Header Extension Object: (mandatory, one only)
  298. // Field Name Field Type Size (bits)
  299. // Object ID GUID 128 // GUID for Header Extension object - getid3_asf::Header_Extension_Object
  300. // Object Size QWORD 64 // size of Header Extension object, including 46 bytes of Header Extension Object header
  301. // Reserved Field 1 GUID 128 // hardcoded: getid3_asf::Reserved_1
  302. // Reserved Field 2 WORD 16 // hardcoded: 0x00000006
  303. // Header Extension Data Size DWORD 32 // in bytes. valid: 0, or > 24. equals object size minus 46
  304. // Header Extension Data BYTESTREAM variable // array of zero or more extended header objects
  305. $info_asf['header_extension_object'] = array();
  306. $info_asf_header_extension_object = &$info_asf['header_extension_object'];
  307. $info_asf_header_extension_object['objectid_guid'] = $next_object_guidtext;
  308. $info_asf_header_extension_object['objectsize'] = $next_object_size;
  309. $info_asf_header_extension_object['reserved_1_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  310. $offset += 16;
  311. if ($info_asf_header_extension_object['reserved_1_guid'] != getid3_asf::Reserved_1) {
  312. $getid3->warning('header_extension_object.reserved_1 GUID ('.$info_asf_header_extension_object['reserved_1_guid'].') does not match expected "getid3_asf::Reserved_1" GUID ('.getid3_asf::Reserved_1.')');
  313. break;
  314. }
  315. $info_asf_header_extension_object['reserved_2'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  316. $offset += 2;
  317. if ($info_asf_header_extension_object['reserved_2'] != 6) {
  318. $getid3->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($info_asf_header_extension_object['reserved_2']).') does not match expected value of "6"');
  319. break;
  320. }
  321. $info_asf_header_extension_object['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
  322. $offset += 4;
  323. $info_asf_header_extension_object['extension_data'] = substr($asf_header_data, $offset, $info_asf_header_extension_object['extension_data_size']);
  324. $offset += $info_asf_header_extension_object['extension_data_size'];
  325. break;
  326. case getid3_asf::Codec_List_Object:
  327. // Codec List Object: (optional, one only)
  328. // Field Name Field Type Size (bits)
  329. // Object ID GUID 128 // GUID for Codec List object - getid3_asf::Codec_List_Object
  330. // Object Size QWORD 64 // size of Codec List object, including 44 bytes of Codec List Object header
  331. // Reserved GUID 128 // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6
  332. // Codec Entries Count DWORD 32 // number of entries in Codec Entries array
  333. // Codec Entries array of: variable //
  334. // * Type WORD 16 // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec
  335. // * Codec Name Length WORD 16 // number of Unicode characters stored in the Codec Name field
  336. // * Codec Name WCHAR variable // array of Unicode characters - name of codec used to create the content
  337. // * Codec Description Length WORD 16 // number of Unicode characters stored in the Codec Description field
  338. // * Codec Description WCHAR variable // array of Unicode characters - description of format used to create the content
  339. // * Codec Information Length WORD 16 // number of Unicode characters stored in the Codec Information field
  340. // * Codec Information BYTESTREAM variable // opaque array of information bytes about the codec used to create the content
  341. $info_asf['codec_list_object'] = array();
  342. $info_asf_codec_list_object = &$info_asf['codec_list_object'];
  343. $info_asf_codec_list_object['objectid_guid'] = $next_object_guidtext;
  344. $info_asf_codec_list_object['objectsize'] = $next_object_size;
  345. $info_asf_codec_list_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  346. $offset += 16;
  347. if ($info_asf_codec_list_object['reserved_guid'] != '86D15241-311D-11D0-A3A4-00A0C90348F6') {
  348. $getid3->warning('codec_list_object.reserved GUID {'.$info_asf_codec_list_object['reserved_guid'].'} does not match expected "getid3_asf::Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
  349. break;
  350. }
  351. $info_asf_codec_list_object['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
  352. $offset += 4;
  353. for ($codec_entry_counter = 0; $codec_entry_counter < $info_asf_codec_list_object['codec_entries_count']; $codec_entry_counter++) {
  354. $info_asf_codec_list_object['codec_entries'][$codec_entry_counter] = array();
  355. $info_asf_codec_list_object_codecentries_current = &$info_asf_codec_list_object['codec_entries'][$codec_entry_counter];
  356. $info_asf_codec_list_object_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  357. $offset += 2;
  358. $info_asf_codec_list_object_codecentries_current['type'] = getid3_asf::ASFCodecListObjectTypeLookup($info_asf_codec_list_object_codecentries_current['type_raw']);
  359. $codec_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
  360. $offset += 2;
  361. $info_asf_codec_list_object_codecentries_current['name'] = substr($asf_header_data, $offset, $codec_name_length);
  362. $offset += $codec_name_length;
  363. $codec_description_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
  364. $offset += 2;
  365. $info_asf_codec_list_object_codecentries_current['description'] = substr($asf_header_data, $offset, $codec_description_length);
  366. $offset += $codec_description_length;
  367. $codec_information_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  368. $offset += 2;
  369. $info_asf_codec_list_object_codecentries_current['information'] = substr($asf_header_data, $offset, $codec_information_length);
  370. $offset += $codec_information_length;
  371. if ($info_asf_codec_list_object_codecentries_current['type_raw'] == 2) { // audio codec
  372. if (strpos($info_asf_codec_list_object_codecentries_current['description'], ',') === false) {
  373. $getid3->warning('[asf][codec_list_object][codec_entries]['.$codec_entry_counter.'][description] expected to contain comma-seperated list of parameters: "'.$info_asf_codec_list_object_codecentries_current['description'].'"');
  374. } else {
  375. list($audio_codec_bitrate, $audio_codec_frequency, $audio_codec_channels) = explode(',', $this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']));
  376. $info_audio['codec'] = $this->TrimConvert($info_asf_codec_list_object_codecentries_current['name']);
  377. if (!isset($info_audio['bitrate']) && strstr($audio_codec_bitrate, 'kbps')) {
  378. $info_audio['bitrate'] = (int)(trim(str_replace('kbps', '', $audio_codec_bitrate)) * 1000);
  379. }
  380. if (!isset($info_video['bitrate']) && isset($info_audio['bitrate']) && isset($info_asf['file_properties_object']['max_bitrate']) && ($info_asf_codec_list_object['codec_entries_count'] > 1)) {
  381. $info_video['bitrate'] = $info_asf['file_properties_object']['max_bitrate'] - $info_audio['bitrate'];
  382. }
  383. if (!@$info_video['bitrate'] && @$info_audio['bitrate'] && @$getid3->info['bitrate']) {
  384. $info_video['bitrate'] = $getid3->info['bitrate'] - $info_audio['bitrate'];
  385. }
  386. $audio_codec_frequency = (int)trim(str_replace('kHz', '', $audio_codec_frequency));
  387. static $sample_rate_lookup = array(
  388. 8 => 8000, 8000 => 8000,
  389. 11 => 11025, 11025 => 11025,
  390. 12 => 12000, 12000 => 12000,
  391. 16 => 16000, 16000 => 16000,
  392. 22 => 22050, 22050 => 22050,
  393. 24 => 24000, 24000 => 24000,
  394. 32 => 32000, 32000 => 32000,
  395. 44 => 44100, 44100 => 44100,
  396. 48 => 48000, 48000 => 48000,
  397. );
  398. $info_audio['sample_rate'] = @$sample_rate_lookup[$audio_codec_frequency];
  399. if (!$info_audio['sample_rate']) {
  400. $getid3->warning('unknown frequency: "'.$audio_codec_frequency.'" ('.$this->TrimConvert($info_asf_codec_list_object_codecentries_current['description']).')');
  401. break;
  402. }
  403. if (!isset($info_audio['channels'])) {
  404. if (strstr($audio_codec_channels, 'stereo')) {
  405. $info_audio['channels'] = 2;
  406. } elseif (strstr($audio_codec_channels, 'mono')) {
  407. $info_audio['channels'] = 1;
  408. }
  409. }
  410. }
  411. }
  412. }
  413. break;
  414. case getid3_asf::Script_Command_Object:
  415. // Script Command Object: (optional, one only)
  416. // Field Name Field Type Size (bits)
  417. // Object ID GUID 128 // GUID for Script Command object - getid3_asf::Script_Command_Object
  418. // Object Size QWORD 64 // size of Script Command object, including 44 bytes of Script Command Object header
  419. // Reserved GUID 128 // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6
  420. // Commands Count WORD 16 // number of Commands structures in the Script Commands Objects
  421. // Command Types Count WORD 16 // number of Command Types structures in the Script Commands Objects
  422. // Command Types array of: variable //
  423. // * Command Type Name Length WORD 16 // number of Unicode characters for Command Type Name
  424. // * Command Type Name WCHAR variable // array of Unicode characters - name of a type of command
  425. // Commands array of: variable //
  426. // * Presentation Time DWORD 32 // presentation time of that command, in milliseconds
  427. // * Type Index WORD 16 // type of this command, as a zero-based index into the array of Command Types of this object
  428. // * Command Name Length WORD 16 // number of Unicode characters for Command Name
  429. // * Command Name WCHAR variable // array of Unicode characters - name of this command
  430. // shortcut
  431. $info_asf['script_command_object'] = array();
  432. $info_asf_script_command_object = &$info_asf['script_command_object'];
  433. $info_asf_script_command_object['objectid_guid'] = $next_object_guidtext;
  434. $info_asf_script_command_object['objectsize'] = $next_object_size;
  435. $info_asf_script_command_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  436. $offset += 16;
  437. if ($info_asf_script_command_object['reserved_guid'] != '4B1ACBE3-100B-11D0-A39B-00A0C90348F6') {
  438. $getid3->warning('script_command_object.reserved GUID {'.$info_asf_script_command_object['reserved_guid'].'} does not match expected GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
  439. break;
  440. }
  441. $info_asf_script_command_object['commands_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  442. $offset += 2;
  443. $info_asf_script_command_object['command_types_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  444. $offset += 2;
  445. for ($command_types_counter = 0; $command_types_counter < $info_asf_script_command_object['command_types_count']; $command_types_counter++) {
  446. $command_type_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
  447. $offset += 2;
  448. $info_asf_script_command_object['command_types'][$command_types_counter]['name'] = substr($asf_header_data, $offset, $command_type_name_length);
  449. $offset += $command_type_name_length;
  450. }
  451. for ($commands_counter = 0; $commands_counter < $info_asf_script_command_object['commands_count']; $commands_counter++) {
  452. $info_asf_script_command_object['commands'][$commands_counter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
  453. $offset += 4;
  454. $info_asf_script_command_object['commands'][$commands_counter]['type_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  455. $offset += 2;
  456. $command_type_name_length = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2)) * 2; // 2 bytes per character
  457. $offset += 2;
  458. $info_asf_script_command_object['commands'][$commands_counter]['name'] = substr($asf_header_data, $offset, $command_type_name_length);
  459. $offset += $command_type_name_length;
  460. }
  461. break;
  462. case getid3_asf::Marker_Object:
  463. // Marker Object: (optional, one only)
  464. // Field Name Field Type Size (bits)
  465. // Object ID GUID 128 // GUID for Marker object - getid3_asf::Marker_Object
  466. // Object Size QWORD 64 // size of Marker object, including 48 bytes of Marker Object header
  467. // Reserved GUID 128 // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB
  468. // Markers Count DWORD 32 // number of Marker structures in Marker Object
  469. // Reserved WORD 16 // hardcoded: 0x0000
  470. // Name Length WORD 16 // number of bytes in the Name field
  471. // Name WCHAR variable // name of the Marker Object
  472. // Markers array of: variable //
  473. // * Offset QWORD 64 // byte offset into Data Object
  474. // * Presentation Time QWORD 64 // in 100-nanosecond units
  475. // * Entry Length WORD 16 // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding)
  476. // * Send Time DWORD 32 // in milliseconds
  477. // * Flags DWORD 32 // hardcoded: 0x00000000
  478. // * Marker Description Length DWORD 32 // number of bytes in Marker Description field
  479. // * Marker Description WCHAR variable // array of Unicode characters - description of marker entry
  480. // * Padding BYTESTREAM variable // optional padding bytes
  481. $info_asf['marker_object'] = array();
  482. $info_asf_marker_object = &$info_asf['marker_object'];
  483. $info_asf_marker_object['objectid_guid'] = $next_object_guidtext;
  484. $info_asf_marker_object['objectsize'] = $next_object_size;
  485. $info_asf_marker_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  486. $offset += 16;
  487. if ($info_asf_marker_object['reserved_guid'] != '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB') {
  488. $getid3->warning('marker_object.reserved GUID {'.$info_asf_marker_object['reserved_guid'].'} does not match expected GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
  489. break;
  490. }
  491. $info_asf_marker_object['markers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 4));
  492. $offset += 4;
  493. $info_asf_marker_object['reserved_2'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  494. $offset += 2;
  495. if ($info_asf_marker_object['reserved_2'] != 0) {
  496. $getid3->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($info_asf_marker_object['reserved_2']).') does not match expected value of "0"');
  497. break;
  498. }
  499. $info_asf_marker_object['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  500. $offset += 2;
  501. $info_asf_marker_object['name'] = substr($asf_header_data, $offset, $info_asf_marker_object['name_length']);
  502. $offset += $info_asf_marker_object['name_length'];
  503. for ($markers_counter = 0; $markers_counter < $info_asf_marker_object['markers_count']; $markers_counter++) {
  504. getid3_lib::ReadSequence('LittleEndian2Int', $info_asf_marker_object['markers'][$markers_counter], $asf_header_data, $offset,
  505. array(
  506. 'offset' => 8,
  507. 'presentation_time' => 8,
  508. 'entry_length' => 2,
  509. 'send_time' => 4,
  510. 'flags' => 4,
  511. 'marker_description_length' => 4
  512. )
  513. );
  514. $offset += 30;
  515. $info_asf_marker_object['markers'][$markers_counter]['marker_description'] = substr($asf_header_data, $offset, $info_asf_marker_object['markers'][$markers_counter]['marker_description_length']);
  516. $offset += $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
  517. $padding_length = $info_asf_marker_object['markers'][$markers_counter]['entry_length'] - 4 - 4 - 4 - $info_asf_marker_object['markers'][$markers_counter]['marker_description_length'];
  518. if ($padding_length > 0) {
  519. $info_asf_marker_object['markers'][$markers_counter]['padding'] = substr($asf_header_data, $offset, $padding_length);
  520. $offset += $padding_length;
  521. }
  522. }
  523. break;
  524. case getid3_asf::Bitrate_Mutual_Exclusion_Object:
  525. // Bitrate Mutual Exclusion Object: (optional)
  526. // Field Name Field Type Size (bits)
  527. // Object ID GUID 128 // GUID for Bitrate Mutual Exclusion object - getid3_asf::Bitrate_Mutual_Exclusion_Object
  528. // Object Size QWORD 64 // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header
  529. // Exlusion Type GUID 128 // nature of mutual exclusion relationship. one of: (getid3_asf::Mutex_Bitrate, getid3_asf::Mutex_Unknown)
  530. // Stream Numbers Count WORD 16 // number of video streams
  531. // Stream Numbers WORD variable // array of mutually exclusive video stream numbers. 1 <= valid <= 127
  532. // shortcut
  533. $info_asf['bitrate_mutual_exclusion_object'] = array();
  534. $info_asf_bitrate_mutual_exclusion_object = &$info_asf['bitrate_mutual_exclusion_object'];
  535. $info_asf_bitrate_mutual_exclusion_object['objectid_guid'] = $next_object_guidtext;
  536. $info_asf_bitrate_mutual_exclusion_object['objectsize'] = $next_object_size;
  537. $info_asf_bitrate_mutual_exclusion_object['reserved_guid'] = getid3_asf::BytestringToGUID(substr($asf_header_data, $offset, 16));
  538. $offset += 16;
  539. if ($info_asf_bitrate_mutual_exclusion_object['reserved_guid'] != getid3_asf::Mutex_Bitrate && $info_asf_bitrate_mutual_exclusion_object['reserved_guid'] != getid3_asf::Mutex_Unknown) {
  540. $getid3->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$info_asf_bitrate_mutual_exclusion_object['reserved_guid'].'} does not match expected "getid3_asf::Mutex_Bitrate" GUID {'.getid3_asf::Mutex_Bitrate.'} or "getid3_asf::Mutex_Unknown" GUID {'.getid3_asf::Mutex_Unknown.'}');
  541. break;
  542. }
  543. $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_data, $offset, 2));
  544. $offset += 2;
  545. for ($stream_number_counter = 0; $stream_number_counter < $info_asf_bitrate_mutual_exclusion_object['stream_numbers_count']; $stream_number_counter++) {
  546. $info_asf_bitrate_mut

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