PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/public/library/xinha/plugins/MootoolsFileManager/mootools-filemanager/Backend/Assets/getid3/module.audio-video.riff.php

https://bitbucket.org/mayorbrain/precurio-v2
PHP | 2319 lines | 1796 code | 396 blank | 127 comment | 241 complexity | 85abc053d208d778413e3168f5885d64 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause, LGPL-2.0, CC-BY-SA-3.0, MIT

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-2006 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.riff.php |
  18. // | module for analyzing RIFF files: |
  19. // | Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack3, 8SVX |
  20. // | dependencies: module.audio.mp3.php (optional) |
  21. // | module.audio.ac3.php (optional) |
  22. // | module.audio.dts.php (optional) |
  23. // | module.audio-video.mpeg.php (optional) |
  24. // +----------------------------------------------------------------------+
  25. //
  26. // $Id: module.audio-video.riff.php,v 1.10 2006/12/03 20:13:17 ah Exp $
  27. class getid3_riff extends getid3_handler
  28. {
  29. private $endian_function = 'LittleEndian2Int';
  30. public function Analyze() {
  31. $getid3 = $this->getid3;
  32. $getid3->info['riff']['raw'] = array ();
  33. $info_riff = &$getid3->info['riff'];
  34. $info_riff_raw = &$info_riff['raw'];
  35. $info_audio = &$getid3->info['audio'];
  36. $info_video = &$getid3->info['video'];
  37. $info_avdataoffset = &$getid3->info['avdataoffset'];
  38. $info_avdataend = &$getid3->info['avdataend'];
  39. $info_audio_dataformat = &$info_audio['dataformat'];
  40. $info_riff_audio = &$info_riff['audio'];
  41. $info_riff_video = &$info_riff['video'];
  42. $original['avdataend'] = $info_avdataend;
  43. $this->fseek($info_avdataoffset, SEEK_SET);
  44. $riff_header = $this->fread(12);
  45. $riff_sub_type = substr($riff_header, 8, 4);
  46. switch (substr($riff_header, 0, 4)) {
  47. case 'FORM':
  48. $getid3->info['fileformat'] = 'aiff';
  49. $this->endian_function = 'BigEndian2Int';
  50. $riff_header_size = getid3_lib::BigEndian2Int(substr($riff_header, 4, 4));
  51. $info_riff[$riff_sub_type] = $this->ParseRIFF($info_avdataoffset + 12, $info_avdataoffset + $riff_header_size);
  52. $info_riff['header_size'] = $riff_header_size;
  53. break;
  54. case 'RIFF':
  55. case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
  56. case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
  57. if ($riff_sub_type == 'RMP3') {
  58. $riff_sub_type = 'WAVE';
  59. }
  60. $getid3->info['fileformat'] = 'riff';
  61. $this->endian_function = 'LittleEndian2Int';
  62. $riff_header_size = getid3_lib::LittleEndian2Int(substr($riff_header, 4, 4));
  63. $info_riff[$riff_sub_type] = $this->ParseRIFF($info_avdataoffset + 12, $info_avdataoffset + $riff_header_size);
  64. $info_riff['header_size'] = $riff_header_size;
  65. if ($riff_sub_type == 'WAVE') {
  66. $info_riff_wave = &$info_riff['WAVE'];
  67. }
  68. break;
  69. default:
  70. throw new getid3_exception('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$riff_sub_type.'" instead');
  71. }
  72. $endian_function = $this->endian_function;
  73. $stream_index = 0;
  74. switch ($riff_sub_type) {
  75. case 'WAVE':
  76. if (empty($info_audio['bitrate_mode'])) {
  77. $info_audio['bitrate_mode'] = 'cbr';
  78. }
  79. if (empty($info_audio_dataformat)) {
  80. $info_audio_dataformat = 'wav';
  81. }
  82. if (isset($info_riff_wave['data'][0]['offset'])) {
  83. $info_avdataoffset = $info_riff_wave['data'][0]['offset'] + 8;
  84. $info_avdataend = $info_avdataoffset + $info_riff_wave['data'][0]['size'];
  85. }
  86. if (isset($info_riff_wave['fmt '][0]['data'])) {
  87. $info_riff_audio[$stream_index] = getid3_riff::RIFFparseWAVEFORMATex($info_riff_wave['fmt '][0]['data']);
  88. $info_audio['wformattag'] = $info_riff_audio[$stream_index]['raw']['wFormatTag'];
  89. $info_riff_raw['fmt '] = $info_riff_audio[$stream_index]['raw'];
  90. unset($info_riff_audio[$stream_index]['raw']);
  91. $info_audio['streams'][$stream_index] = $info_riff_audio[$stream_index];
  92. $info_audio = getid3_riff::array_merge_noclobber($info_audio, $info_riff_audio[$stream_index]);
  93. if (substr($info_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
  94. $getid3->warning('Audio codec = '.$info_audio['codec']);
  95. }
  96. $info_audio['bitrate'] = $info_riff_audio[$stream_index]['bitrate'];
  97. $getid3->info['playtime_seconds'] = (float)((($info_avdataend - $info_avdataoffset) * 8) / $info_audio['bitrate']);
  98. $info_audio['lossless'] = false;
  99. if (isset($info_riff_wave['data'][0]['offset']) && isset($info_riff_raw['fmt ']['wFormatTag'])) {
  100. switch ($info_riff_raw['fmt ']['wFormatTag']) {
  101. case 0x0001: // PCM
  102. $info_audio['lossless'] = true;
  103. break;
  104. case 0x2000: // AC-3
  105. $info_audio_dataformat = 'ac3';
  106. break;
  107. default:
  108. // do nothing
  109. break;
  110. }
  111. }
  112. $info_audio['streams'][$stream_index]['wformattag'] = $info_audio['wformattag'];
  113. $info_audio['streams'][$stream_index]['bitrate_mode'] = $info_audio['bitrate_mode'];
  114. $info_audio['streams'][$stream_index]['lossless'] = $info_audio['lossless'];
  115. $info_audio['streams'][$stream_index]['dataformat'] = $info_audio_dataformat;
  116. }
  117. if (isset($info_riff_wave['rgad'][0]['data'])) {
  118. // shortcuts
  119. $rgadData = &$info_riff_wave['rgad'][0]['data'];
  120. $info_riff_raw['rgad'] = array ('track'=>array(), 'album'=>array());
  121. $info_riff_raw_rgad = &$info_riff_raw['rgad'];
  122. $info_riff_raw_rgad_track = &$info_riff_raw_rgad['track'];
  123. $info_riff_raw_rgad_album = &$info_riff_raw_rgad['album'];
  124. $info_riff_raw_rgad['fPeakAmplitude'] = getid3_riff::BigEndian2Float(strrev(substr($rgadData, 0, 4))); // LittleEndian2Float()
  125. $info_riff_raw_rgad['nRadioRgAdjust'] = getid3_lib::$endian_function(substr($rgadData, 4, 2));
  126. $info_riff_raw_rgad['nAudiophileRgAdjust'] = getid3_lib::$endian_function(substr($rgadData, 6, 2));
  127. $n_track_rg_adjust_bit_string = str_pad(decbin($info_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
  128. $n_album_rg_adjust_bit_string = str_pad(decbin($info_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
  129. $info_riff_raw_rgad_track['name'] = bindec(substr($n_track_rg_adjust_bit_string, 0, 3));
  130. $info_riff_raw_rgad_track['originator'] = bindec(substr($n_track_rg_adjust_bit_string, 3, 3));
  131. $info_riff_raw_rgad_track['signbit'] = bindec($n_track_rg_adjust_bit_string[6]);
  132. $info_riff_raw_rgad_track['adjustment'] = bindec(substr($n_track_rg_adjust_bit_string, 7, 9));
  133. $info_riff_raw_rgad_album['name'] = bindec(substr($n_album_rg_adjust_bit_string, 0, 3));
  134. $info_riff_raw_rgad_album['originator'] = bindec(substr($n_album_rg_adjust_bit_string, 3, 3));
  135. $info_riff_raw_rgad_album['signbit'] = bindec($n_album_rg_adjust_bit_string[6]);
  136. $info_riff_raw_rgad_album['adjustment'] = bindec(substr($n_album_rg_adjust_bit_string, 7, 9));
  137. $info_riff['rgad']['peakamplitude'] = $info_riff_raw_rgad['fPeakAmplitude'];
  138. if (($info_riff_raw_rgad_track['name'] != 0) && ($info_riff_raw_rgad_track['originator'] != 0)) {
  139. $info_riff['rgad']['track']['name'] = getid3_lib_replaygain::NameLookup($info_riff_raw_rgad_track['name']);
  140. $info_riff['rgad']['track']['originator'] = getid3_lib_replaygain::OriginatorLookup($info_riff_raw_rgad_track['originator']);
  141. $info_riff['rgad']['track']['adjustment'] = getid3_lib_replaygain::AdjustmentLookup($info_riff_raw_rgad_track['adjustment'], $info_riff_raw_rgad_track['signbit']);
  142. }
  143. if (($info_riff_raw_rgad_album['name'] != 0) && ($info_riff_raw_rgad_album['originator'] != 0)) {
  144. $info_riff['rgad']['album']['name'] = getid3_lib_replaygain::NameLookup($info_riff_raw_rgad_album['name']);
  145. $info_riff['rgad']['album']['originator'] = getid3_lib_replaygain::OriginatorLookup($info_riff_raw_rgad_album['originator']);
  146. $info_riff['rgad']['album']['adjustment'] = getid3_lib_replaygain::AdjustmentLookup($info_riff_raw_rgad_album['adjustment'], $info_riff_raw_rgad_album['signbit']);
  147. }
  148. }
  149. if (isset($info_riff_wave['fact'][0]['data'])) {
  150. $info_riff_raw['fact']['NumberOfSamples'] = getid3_lib::$endian_function(substr($info_riff_wave['fact'][0]['data'], 0, 4));
  151. // This should be a good way of calculating exact playtime, but some sample files have had incorrect number of samples, so cannot use this method
  152. // if (!empty($info_riff_raw['fmt ']['nSamplesPerSec'])) {
  153. // $getid3->info['playtime_seconds'] = (float)$info_riff_raw['fact']['NumberOfSamples'] / $info_riff_raw['fmt ']['nSamplesPerSec'];
  154. // }
  155. }
  156. if (!empty($info_riff_raw['fmt ']['nAvgBytesPerSec'])) {
  157. $info_audio['bitrate'] = (int)$info_riff_raw['fmt ']['nAvgBytesPerSec'] * 8;
  158. }
  159. if (isset($info_riff_wave['bext'][0]['data'])) {
  160. $info_riff_wave_bext_0 = &$info_riff_wave['bext'][0];
  161. getid3_lib::ReadSequence('LittleEndian2Int', $info_riff_wave_bext_0, $info_riff_wave_bext_0['data'], 0,
  162. array (
  163. 'title' => -256,
  164. 'author' => -32,
  165. 'reference' => -32,
  166. 'origin_date' => -10,
  167. 'origin_time' => -8,
  168. 'time_reference' => 8,
  169. 'bwf_version' => 1,
  170. 'reserved' => 254
  171. )
  172. );
  173. foreach (array ('title', 'author', 'reference') as $key) {
  174. $info_riff_wave_bext_0[$key] = trim($info_riff_wave_bext_0[$key]);
  175. }
  176. $info_riff_wave_bext_0['coding_history'] = explode("\r\n", trim(substr($info_riff_wave_bext_0['data'], 601)));
  177. $info_riff_wave_bext_0['origin_date_unix'] = gmmktime(substr($info_riff_wave_bext_0['origin_time'], 0, 2),
  178. substr($info_riff_wave_bext_0['origin_time'], 3, 2),
  179. substr($info_riff_wave_bext_0['origin_time'], 6, 2),
  180. substr($info_riff_wave_bext_0['origin_date'], 5, 2),
  181. substr($info_riff_wave_bext_0['origin_date'], 8, 2),
  182. substr($info_riff_wave_bext_0['origin_date'], 0, 4));
  183. $info_riff['comments']['author'][] = $info_riff_wave_bext_0['author'];
  184. $info_riff['comments']['title'][] = $info_riff_wave_bext_0['title'];
  185. }
  186. if (isset($info_riff_wave['MEXT'][0]['data'])) {
  187. $info_riff_wave_mext_0 = &$info_riff_wave['MEXT'][0];
  188. $info_riff_wave_mext_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 0, 2));
  189. $info_riff_wave_mext_0['flags']['homogenous'] = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0001);
  190. if ($info_riff_wave_mext_0['flags']['homogenous']) {
  191. $info_riff_wave_mext_0['flags']['padding'] = ($info_riff_wave_mext_0['raw']['sound_information'] & 0x0002) ? false : true;
  192. $info_riff_wave_mext_0['flags']['22_or_44'] = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0004);
  193. $info_riff_wave_mext_0['flags']['free_format'] = (bool)($info_riff_wave_mext_0['raw']['sound_information'] & 0x0008);
  194. $info_riff_wave_mext_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 2, 2));
  195. }
  196. $info_riff_wave_mext_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 6, 2));
  197. $info_riff_wave_mext_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_mext_0['data'], 8, 2));
  198. $info_riff_wave_mext_0['flags']['anciliary_data_left'] = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0001);
  199. $info_riff_wave_mext_0['flags']['anciliary_data_free'] = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0002);
  200. $info_riff_wave_mext_0['flags']['anciliary_data_right'] = (bool)($info_riff_wave_mext_0['raw']['anciliary_data_def'] & 0x0004);
  201. }
  202. if (isset($info_riff_wave['cart'][0]['data'])) {
  203. $info_riff_wave_cart_0 = &$info_riff_wave['cart'][0];
  204. getid3_lib::ReadSequence('LittleEndian2Int', $info_riff_wave_cart_0, $info_riff_wave_cart_0['data'], 0,
  205. array (
  206. 'version' => -4,
  207. 'title' => -64,
  208. 'artist' => -64,
  209. 'cut_id' => -64,
  210. 'client_id' => -64,
  211. 'category' => -64,
  212. 'classification' => -64,
  213. 'out_cue' => -64,
  214. 'start_date' => -10,
  215. 'start_time' => -8,
  216. 'end_date' => -10,
  217. 'end_time' => -8,
  218. 'producer_app_id' => -64,
  219. 'producer_app_version' => -64,
  220. 'user_defined_text' => -64,
  221. )
  222. );
  223. foreach (array ('artist', 'cut_id', 'client_id', 'category', 'classification', 'out_cue', 'start_date', 'start_time', 'end_date', 'end_time', 'producer_app_id', 'producer_app_version', 'user_defined_text') as $key) {
  224. $info_riff_wave_cart_0[$key] = trim($info_riff_wave_cart_0[$key]);
  225. }
  226. $info_riff_wave_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_cart_0['data'], 680, 4), true);
  227. for ($i = 0; $i < 8; $i++) {
  228. $info_riff_wave_cart_0['post_time'][$i]['usage_fourcc'] = substr($info_riff_wave_cart_0['data'], 684 + ($i * 8), 4);
  229. $info_riff_wave_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($info_riff_wave_cart_0['data'], 684 + ($i * 8) + 4, 4));
  230. }
  231. $info_riff_wave_cart_0['url'] = trim(substr($info_riff_wave_cart_0['data'], 748, 1024));
  232. $info_riff_wave_cart_0['tag_text'] = explode("\r\n", trim(substr($info_riff_wave_cart_0['data'], 1772)));
  233. $info_riff['comments']['artist'][] = $info_riff_wave_cart_0['artist'];
  234. $info_riff['comments']['title'][] = $info_riff_wave_cart_0['title'];
  235. }
  236. if (!isset($info_audio['bitrate']) && isset($info_riff_audio[$stream_index]['bitrate'])) {
  237. $info_audio['bitrate'] = $info_riff_audio[$stream_index]['bitrate'];
  238. $getid3->info['playtime_seconds'] = (float)((($info_avdataend - $info_avdataoffset) * 8) / $info_audio['bitrate']);
  239. }
  240. if (@$getid3->info['wavpack']) {
  241. if (!$this->data_string_flag) {
  242. $info_audio_dataformat = 'wavpack';
  243. $info_audio['bitrate_mode'] = 'vbr';
  244. $info_audio['encoder'] = 'WavPack v'.$getid3->info['wavpack']['version'];
  245. // Reset to the way it was - RIFF parsing will have messed this up
  246. $info_avdataend = $original['avdataend'];
  247. $info_audio['bitrate'] = (($info_avdataend - $info_avdataoffset) * 8) / $getid3->info['playtime_seconds'];
  248. $this->fseek($info_avdataoffset - 44, SEEK_SET);
  249. $riff_data = $this->fread(44);
  250. $orignal_riff_header_size = getid3_lib::LittleEndian2Int(substr($riff_data, 4, 4)) + 8;
  251. $orignal_riff_data_size = getid3_lib::LittleEndian2Int(substr($riff_data, 40, 4)) + 44;
  252. if ($orignal_riff_header_size > $orignal_riff_data_size) {
  253. $info_avdataend -= ($orignal_riff_header_size - $orignal_riff_data_size);
  254. $this->fseek($info_avdataend, SEEK_SET);
  255. $riff_data .= $this->fread($orignal_riff_header_size - $orignal_riff_data_size);
  256. }
  257. // move the data chunk after all other chunks (if any)
  258. // so that the RIFF parser doesn't see EOF when trying
  259. // to skip over the data chunk
  260. $riff_data = substr($riff_data, 0, 36).substr($riff_data, 44).substr($riff_data, 36, 8);
  261. // Save audio info key
  262. $saved_info_audio = $info_audio;
  263. // Analyze riff_data
  264. $this->AnalyzeString($riff_data);
  265. // Restore info key
  266. $info_audio = $saved_info_audio;
  267. }
  268. }
  269. if (isset($info_riff_raw['fmt ']['wFormatTag'])) {
  270. switch ($info_riff_raw['fmt ']['wFormatTag']) {
  271. case 0x08AE: // ClearJump LiteWave
  272. $info_audio['bitrate_mode'] = 'vbr';
  273. $info_audio_dataformat = 'litewave';
  274. //typedef struct tagSLwFormat {
  275. // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
  276. // DWORD m_dwScale; // scale factor for lossy compression
  277. // DWORD m_dwBlockSize; // number of samples in encoded blocks
  278. // WORD m_wQuality; // alias for the scale factor
  279. // WORD m_wMarkDistance; // distance between marks in bytes
  280. // WORD m_wReserved;
  281. //
  282. // //following paramters are ignored if CF_FILESRC is not set
  283. // DWORD m_dwOrgSize; // original file size in bytes
  284. // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
  285. // DWORD m_dwRiffChunkSize; // riff chunk size in the original file
  286. //
  287. // PCMWAVEFORMAT m_OrgWf; // original wave format
  288. // }SLwFormat, *PSLwFormat;
  289. $info_riff['litewave']['raw'] = array ();
  290. $info_riff_litewave = &$info_riff['litewave'];
  291. $info_riff_litewave_raw = &$info_riff_litewave['raw'];
  292. getid3_lib::ReadSequence('LittleEndian2Int', $info_riff_litewave_raw, $info_riff_wave['fmt '][0]['data'], 18,
  293. array (
  294. 'compression_method' => 1,
  295. 'compression_flags' => 1,
  296. 'm_dwScale' => 4,
  297. 'm_dwBlockSize' => 4,
  298. 'm_wQuality' => 2,
  299. 'm_wMarkDistance' => 2,
  300. 'm_wReserved' => 2,
  301. 'm_dwOrgSize' => 4,
  302. 'm_bFactExists' => 2,
  303. 'm_dwRiffChunkSize' => 4
  304. )
  305. );
  306. //$info_riff_litewave['quality_factor'] = intval(round((2000 - $info_riff_litewave_raw['m_dwScale']) / 20));
  307. $info_riff_litewave['quality_factor'] = $info_riff_litewave_raw['m_wQuality'];
  308. $info_riff_litewave['flags']['raw_source'] = ($info_riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
  309. $info_riff_litewave['flags']['vbr_blocksize'] = ($info_riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
  310. $info_riff_litewave['flags']['seekpoints'] = (bool)($info_riff_litewave_raw['compression_flags'] & 0x04);
  311. $info_audio['lossless'] = (($info_riff_litewave_raw['m_wQuality'] == 100) ? true : false);
  312. $info_audio['encoder_options'] = '-q'.$info_riff_litewave['quality_factor'];
  313. break;
  314. }
  315. }
  316. if ($info_avdataend > $getid3->info['filesize']) {
  317. switch (@$info_audio_dataformat) {
  318. case 'wavpack': // WavPack
  319. case 'lpac': // LPAC
  320. case 'ofr': // OptimFROG
  321. case 'ofs': // OptimFROG DualStream
  322. // lossless compressed audio formats that keep original RIFF headers - skip warning
  323. break;
  324. case 'litewave':
  325. if (($info_avdataend - $getid3->info['filesize']) == 1) {
  326. // LiteWave appears to incorrectly *not* pad actual output file
  327. // to nearest WORD boundary so may appear to be short by one
  328. // byte, in which case - skip warning
  329. } else {
  330. // Short by more than one byte, throw warning
  331. $getid3->warning('Probably truncated file - expecting '.$info_riff[$riff_sub_type]['data'][0]['size'].' bytes of data, only found '.($getid3->info['filesize'] - $info_avdataoffset).' (short by '.($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize'] - $info_avdataoffset)).' bytes)');
  332. }
  333. break;
  334. default:
  335. if ((($info_avdataend - $getid3->info['filesize']) == 1) && (($info_riff[$riff_sub_type]['data'][0]['size'] % 2) == 0) && ((($getid3->info['filesize'] - $info_avdataoffset) % 2) == 1)) {
  336. // output file appears to be incorrectly *not* padded to nearest WORD boundary
  337. // Output less severe warning
  338. $getid3->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$info_riff[$riff_sub_type]['data'][0]['size'].' bytes of data, only found '.($getid3->info['filesize'] - $info_avdataoffset).' therefore short by '.($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize'] - $info_avdataoffset)).' bytes)');
  339. $info_avdataend = $getid3->info['filesize'];
  340. break;
  341. }
  342. // Short by more than one byte, throw warning
  343. $getid3->warning('Probably truncated file - expecting '.$info_riff[$riff_sub_type]['data'][0]['size'].' bytes of data, only found '.($getid3->info['filesize'] - $info_avdataoffset).' (short by '.($info_riff[$riff_sub_type]['data'][0]['size'] - ($getid3->info['filesize'] - $info_avdataoffset)).' bytes)');
  344. $info_avdataend = $getid3->info['filesize'];
  345. break;
  346. }
  347. }
  348. if (!empty($getid3->info['mpeg']['audio']['LAME']['audio_bytes'])) {
  349. if ((($info_avdataend - $info_avdataoffset) - $getid3->info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
  350. $info_avdataend--;
  351. $getid3->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
  352. }
  353. }
  354. if (@$info_audio_dataformat == 'ac3') {
  355. unset($info_audio['bits_per_sample']);
  356. if (!empty($getid3->info['ac3']['bitrate']) && ($getid3->info['ac3']['bitrate'] != $info_audio['bitrate'])) {
  357. $info_audio['bitrate'] = $getid3->info['ac3']['bitrate'];
  358. }
  359. }
  360. break;
  361. case 'AVI ':
  362. $info_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
  363. $info_video['dataformat'] = 'avi';
  364. $getid3->info['mime_type'] = 'video/avi';
  365. if (isset($info_riff[$riff_sub_type]['movi']['offset'])) {
  366. $info_avdataoffset = $info_riff[$riff_sub_type]['movi']['offset'] + 8;
  367. $info_avdataend = $info_avdataoffset + $info_riff[$riff_sub_type]['movi']['size'];
  368. if ($info_avdataend > $getid3->info['filesize']) {
  369. $getid3->warning('Probably truncated file - expecting '.$info_riff[$riff_sub_type]['movi']['size'].' bytes of data, only found '.($getid3->info['filesize'] - $info_avdataoffset).' (short by '.($info_riff[$riff_sub_type]['movi']['size'] - ($getid3->info['filesize'] - $info_avdataoffset)).' bytes)');
  370. $info_avdataend = $getid3->info['filesize'];
  371. }
  372. }
  373. if (isset($info_riff['AVI ']['hdrl']['avih'][$stream_index]['data'])) {
  374. $avihData = $info_riff['AVI ']['hdrl']['avih'][$stream_index]['data'];
  375. $info_riff_raw['avih'] = array ();
  376. $info_riff_raw_avih = &$info_riff_raw['avih'];
  377. getid3_lib::ReadSequence($this->endian_function, $info_riff_raw_avih, $avihData, 0,
  378. array (
  379. 'dwMicroSecPerFrame' => 4, // frame display rate (or 0L)
  380. 'dwMaxBytesPerSec' => 4, // max. transfer rate
  381. 'dwPaddingGranularity' => 4, // pad to multiples of this size; normally 2K.
  382. 'dwFlags' => 4, // the ever-present flags
  383. 'dwTotalFrames' => 4, // # frames in file
  384. 'dwInitialFrames' => 4,
  385. 'dwStreams' => 4,
  386. 'dwSuggestedBufferSize' => 4,
  387. 'dwWidth' => 4,
  388. 'dwHeight' => 4,
  389. 'dwScale' => 4,
  390. 'dwRate' => 4,
  391. 'dwStart' => 4,
  392. 'dwLength' => 4
  393. )
  394. );
  395. $info_riff_raw_avih['flags']['hasindex'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000010);
  396. $info_riff_raw_avih['flags']['mustuseindex'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000020);
  397. $info_riff_raw_avih['flags']['interleaved'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000100);
  398. $info_riff_raw_avih['flags']['trustcktype'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00000800);
  399. $info_riff_raw_avih['flags']['capturedfile'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00010000);
  400. $info_riff_raw_avih['flags']['copyrighted'] = (bool)($info_riff_raw_avih['dwFlags'] & 0x00020010);
  401. $info_riff_video[$stream_index] = array ();
  402. $info_riff_video_current = &$info_riff_video[$stream_index];
  403. if ($info_riff_raw_avih['dwWidth'] > 0) {
  404. $info_riff_video_current['frame_width'] = $info_riff_raw_avih['dwWidth'];
  405. $info_video['resolution_x'] = $info_riff_video_current['frame_width'];
  406. }
  407. if ($info_riff_raw_avih['dwHeight'] > 0) {
  408. $info_riff_video_current['frame_height'] = $info_riff_raw_avih['dwHeight'];
  409. $info_video['resolution_y'] = $info_riff_video_current['frame_height'];
  410. }
  411. if ($info_riff_raw_avih['dwTotalFrames'] > 0) {
  412. $info_riff_video_current['total_frames'] = $info_riff_raw_avih['dwTotalFrames'];
  413. $info_video['total_frames'] = $info_riff_video_current['total_frames'];
  414. }
  415. $info_riff_video_current['frame_rate'] = round(1000000 / $info_riff_raw_avih['dwMicroSecPerFrame'], 3);
  416. $info_video['frame_rate'] = $info_riff_video_current['frame_rate'];
  417. }
  418. if (isset($info_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
  419. if (is_array($info_riff['AVI ']['hdrl']['strl']['strh'])) {
  420. for ($i = 0; $i < count($info_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
  421. if (isset($info_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
  422. $strh_data = $info_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
  423. $strh_fcc_type = substr($strh_data, 0, 4);
  424. if (isset($info_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
  425. $strf_data = $info_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
  426. // shortcut
  427. $info_riff_raw_strf_strh_fcc_type_stream_index = &$info_riff_raw['strf'][$strh_fcc_type][$stream_index];
  428. switch ($strh_fcc_type) {
  429. case 'auds':
  430. $info_audio['bitrate_mode'] = 'cbr';
  431. $info_audio_dataformat = 'wav';
  432. if (isset($info_riff_audio) && is_array($info_riff_audio)) {
  433. $stream_index = count($info_riff_audio);
  434. }
  435. $info_riff_audio[$stream_index] = getid3_riff::RIFFparseWAVEFORMATex($strf_data);
  436. $info_audio['wformattag'] = $info_riff_audio[$stream_index]['raw']['wFormatTag'];
  437. // shortcut
  438. $info_audio['streams'][$stream_index] = $info_riff_audio[$stream_index];
  439. $info_audio_streams_currentstream = &$info_audio['streams'][$stream_index];
  440. if (@$info_audio_streams_currentstream['bits_per_sample'] === 0) {
  441. unset($info_audio_streams_currentstream['bits_per_sample']);
  442. }
  443. $info_audio_streams_currentstream['wformattag'] = $info_audio_streams_currentstream['raw']['wFormatTag'];
  444. unset($info_audio_streams_currentstream['raw']);
  445. // shortcut
  446. $info_riff_raw['strf'][$strh_fcc_type][$stream_index] = $info_riff_audio[$stream_index]['raw'];
  447. unset($info_riff_audio[$stream_index]['raw']);
  448. $info_audio = getid3_riff::array_merge_noclobber($info_audio, $info_riff_audio[$stream_index]);
  449. $info_audio['lossless'] = false;
  450. switch ($info_riff_raw_strf_strh_fcc_type_stream_index['wFormatTag']) {
  451. case 0x0001: // PCM
  452. $info_audio_dataformat = 'wav';
  453. $info_audio['lossless'] = true;
  454. break;
  455. case 0x0050: // MPEG Layer 2 or Layer 1
  456. $info_audio_dataformat = 'mp2'; // Assume Layer-2
  457. break;
  458. case 0x0055: // MPEG Layer 3
  459. $info_audio_dataformat = 'mp3';
  460. break;
  461. case 0x00FF: // AAC
  462. $info_audio_dataformat = 'aac';
  463. break;
  464. case 0x0161: // Windows Media v7 / v8 / v9
  465. case 0x0162: // Windows Media Professional v9
  466. case 0x0163: // Windows Media Lossess v9
  467. $info_audio_dataformat = 'wma';
  468. break;
  469. case 0x2000: // AC-3
  470. $info_audio_dataformat = 'ac3';
  471. break;
  472. case 0x2001: // DTS
  473. $info_audio_dataformat = 'dts';
  474. break;
  475. default:
  476. $info_audio_dataformat = 'wav';
  477. break;
  478. }
  479. $info_audio_streams_currentstream['dataformat'] = $info_audio_dataformat;
  480. $info_audio_streams_currentstream['lossless'] = $info_audio['lossless'];
  481. $info_audio_streams_currentstream['bitrate_mode'] = $info_audio['bitrate_mode'];
  482. break;
  483. case 'iavs':
  484. case 'vids':
  485. // shortcut
  486. $info_riff_raw['strh'][$i] = array ();
  487. $info_riff_raw_strh_current = &$info_riff_raw['strh'][$i];
  488. getid3_lib::ReadSequence($this->endian_function, $info_riff_raw_strh_current, $strh_data, 0,
  489. array (
  490. 'fccType' => -4, // same as $strh_fcc_type;
  491. 'fccHandler' => -4,
  492. 'dwFlags' => 4, // Contains AVITF_* flags
  493. 'wPriority' => 2,
  494. 'wLanguage' => 2,
  495. 'dwInitialFrames' => 4,
  496. 'dwScale' => 4,
  497. 'dwRate' => 4,
  498. 'dwStart' => 4,
  499. 'dwLength' => 4,
  500. 'dwSuggestedBufferSize' => 4,
  501. 'dwQuality' => 4,
  502. 'dwSampleSize' => 4,
  503. 'rcFrame' => 4
  504. )
  505. );
  506. $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strh_current['fccHandler']);
  507. $info_video['fourcc'] = $info_riff_raw_strh_current['fccHandler'];
  508. if (!$info_riff_video_current['codec'] && isset($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) && getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'])) {
  509. $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']);
  510. $info_video['fourcc'] = $info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'];
  511. }
  512. $info_video['codec'] = $info_riff_video_current['codec'];
  513. $info_video['pixel_aspect_ratio'] = (float)1;
  514. switch ($info_riff_raw_strh_current['fccHandler']) {
  515. case 'HFYU': // Huffman Lossless Codec
  516. case 'IRAW': // Intel YUV Uncompressed
  517. case 'YUY2': // Uncompressed YUV 4:2:2
  518. $info_video['lossless'] = true;
  519. break;
  520. default:
  521. $info_video['lossless'] = false;
  522. break;
  523. }
  524. switch ($strh_fcc_type) {
  525. case 'vids':
  526. getid3_lib::ReadSequence($this->endian_function, $info_riff_raw_strf_strh_fcc_type_stream_index, $strf_data, 0,
  527. array (
  528. 'biSize' => 4, // number of bytes required by the BITMAPINFOHEADER structure
  529. 'biWidth' => 4, // width of the bitmap in pixels
  530. 'biHeight' => 4, // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
  531. 'biPlanes' => 2, // number of color planes on the target device. In most cases this value must be set to 1
  532. 'biBitCount' => 2, // Specifies the number of bits per pixels
  533. 'fourcc' => -4, //
  534. 'biSizeImage' => 4, // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
  535. 'biXPelsPerMeter' => 4, // horizontal resolution, in pixels per metre, of the target device
  536. 'biYPelsPerMeter' => 4, // vertical resolution, in pixels per metre, of the target device
  537. 'biClrUsed' => 4, // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
  538. 'biClrImportant' => 4 // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
  539. )
  540. );
  541. $info_video['bits_per_sample'] = $info_riff_raw_strf_strh_fcc_type_stream_index['biBitCount'];
  542. if ($info_riff_video_current['codec'] == 'DV') {
  543. $info_riff_video_current['dv_type'] = 2;
  544. }
  545. break;
  546. case 'iavs':
  547. $info_riff_video_current['dv_type'] = 1;
  548. break;
  549. }
  550. break;
  551. default:
  552. $getid3->warning('Unhandled fccType for stream ('.$i.'): "'.$strh_fcc_type.'"');
  553. break;
  554. }
  555. }
  556. }
  557. if (isset($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) && getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'])) {
  558. $info_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']);
  559. $info_video['codec'] = $info_riff_video_current['codec'];
  560. $info_video['fourcc'] = $info_riff_raw_strf_strh_fcc_type_stream_index['fourcc'];
  561. switch ($info_riff_raw_strf_strh_fcc_type_stream_index['fourcc']) {
  562. case 'HFYU': // Huffman Lossless Codec
  563. case 'IRAW': // Intel YUV Uncompressed
  564. case 'YUY2': // Uncompressed YUV 4:2:2
  565. $info_video['lossless'] = true;
  566. $info_video['bits_per_sample'] = 24;
  567. break;
  568. default:
  569. $info_video['lossless'] = false;
  570. $info_video['bits_per_sample'] = 24;
  571. break;
  572. }
  573. }
  574. }
  575. }
  576. }
  577. break;
  578. case 'CDDA':
  579. $info_audio['bitrate_mode'] = 'cbr';
  580. $info_audio_dataformat = 'cda';
  581. $info_audio['lossless'] = true;
  582. unset($getid3->info['mime_type']);
  583. $info_avdataoffset = 44;
  584. if (isset($info_riff['CDDA']['fmt '][0]['data'])) {
  585. $info_riff_cdda_fmt_0 = &$info_riff['CDDA']['fmt '][0];
  586. getid3_lib::ReadSequence($this->endian_function, $info_riff_cdda_fmt_0, $info_riff_cdda_fmt_0['data'], 0,
  587. array (
  588. 'unknown1' => 2,
  589. 'track_num' => 2,
  590. 'disc_id' => 4,
  591. 'start_offset_frame' => 4,
  592. 'playtime_frames' => 4,
  593. 'unknown6' => 4,
  594. 'unknown7' => 4
  595. )
  596. );
  597. $info_riff_cdda_fmt_0['start_offset_seconds'] = (float)$info_riff_cdda_fmt_0['start_offset_frame'] / 75;
  598. $info_riff_cdda_fmt_0['playtime_seconds']

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