[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 ///////////////////////////////////////////////////////////////// 4 /// getID3() by James Heinrich <info@getid3.org> // 5 // available at https://github.com/JamesHeinrich/getID3 // 6 // or https://www.getid3.org // 7 // or http://getid3.sourceforge.net // 8 // see readme.txt for more details // 9 ///////////////////////////////////////////////////////////////// 10 // // 11 // module.audio-video.riff.php // 12 // module for analyzing RIFF files // 13 // multiple formats supported by this module: // 14 // Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX // 15 // dependencies: module.audio.mp3.php // 16 // module.audio.ac3.php // 17 // module.audio.dts.php // 18 // /// 19 ///////////////////////////////////////////////////////////////// 20 21 /** 22 * @todo Parse AC-3/DTS audio inside WAVE correctly 23 * @todo Rewrite RIFF parser totally 24 */ 25 26 if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers 27 exit; 28 } 29 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true); 30 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true); 31 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); 32 33 class getid3_riff extends getid3_handler 34 { 35 protected $container = 'riff'; // default 36 37 /** 38 * @return bool 39 * 40 * @throws getid3_exception 41 */ 42 public function Analyze() { 43 $info = &$this->getid3->info; 44 45 // initialize these values to an empty array, otherwise they default to NULL 46 // and you can't append array values to a NULL value 47 $info['riff'] = array('raw'=>array()); 48 49 // Shortcuts 50 $thisfile_riff = &$info['riff']; 51 $thisfile_riff_raw = &$thisfile_riff['raw']; 52 $thisfile_audio = &$info['audio']; 53 $thisfile_video = &$info['video']; 54 $thisfile_audio_dataformat = &$thisfile_audio['dataformat']; 55 $thisfile_riff_audio = &$thisfile_riff['audio']; 56 $thisfile_riff_video = &$thisfile_riff['video']; 57 $thisfile_riff_WAVE = array(); 58 59 $Original = array(); 60 $Original['avdataoffset'] = $info['avdataoffset']; 61 $Original['avdataend'] = $info['avdataend']; 62 63 $this->fseek($info['avdataoffset']); 64 $RIFFheader = $this->fread(12); 65 $offset = $this->ftell(); 66 $RIFFtype = substr($RIFFheader, 0, 4); 67 $RIFFsize = substr($RIFFheader, 4, 4); 68 $RIFFsubtype = substr($RIFFheader, 8, 4); 69 70 switch ($RIFFtype) { 71 72 case 'FORM': // AIFF, AIFC 73 //$info['fileformat'] = 'aiff'; 74 $this->container = 'aiff'; 75 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 76 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 77 break; 78 79 case 'RIFF': // AVI, WAV, etc 80 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) 81 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s 82 //$info['fileformat'] = 'riff'; 83 $this->container = 'riff'; 84 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 85 if ($RIFFsubtype == 'RMP3') { 86 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s 87 $RIFFsubtype = 'WAVE'; 88 } 89 if ($RIFFsubtype != 'AMV ') { 90 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size 91 // Handled separately in ParseRIFFAMV() 92 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 93 } 94 if (($info['avdataend'] - $info['filesize']) == 1) { 95 // LiteWave appears to incorrectly *not* pad actual output file 96 // to nearest WORD boundary so may appear to be short by one 97 // byte, in which case - skip warning 98 $info['avdataend'] = $info['filesize']; 99 } 100 101 $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset 102 while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) { 103 try { 104 $this->fseek($nextRIFFoffset); 105 } catch (getid3_exception $e) { 106 if ($e->getCode() == 10) { 107 //$this->warning('RIFF parser: '.$e->getMessage()); 108 $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong'); 109 $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present'); 110 break; 111 } else { 112 throw $e; 113 } 114 } 115 $nextRIFFheader = $this->fread(12); 116 if ($nextRIFFoffset == ($info['avdataend'] - 1)) { 117 if (substr($nextRIFFheader, 0, 1) == "\x00") { 118 // RIFF padded to WORD boundary, we're actually already at the end 119 break; 120 } 121 } 122 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4); 123 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4)); 124 $nextRIFFtype = substr($nextRIFFheader, 8, 4); 125 $chunkdata = array(); 126 $chunkdata['offset'] = $nextRIFFoffset + 8; 127 $chunkdata['size'] = $nextRIFFsize; 128 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size']; 129 130 switch ($nextRIFFheaderID) { 131 case 'RIFF': 132 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset); 133 if (!isset($thisfile_riff[$nextRIFFtype])) { 134 $thisfile_riff[$nextRIFFtype] = array(); 135 } 136 $thisfile_riff[$nextRIFFtype][] = $chunkdata; 137 break; 138 139 case 'AMV ': 140 unset($info['riff']); 141 $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset); 142 break; 143 144 case 'JUNK': 145 // ignore 146 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata; 147 break; 148 149 case 'IDVX': 150 $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size'])); 151 break; 152 153 default: 154 if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) { 155 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12); 156 if (substr($DIVXTAG, -7) == 'DIVXTAG') { 157 // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file 158 $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway'); 159 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG); 160 break 2; 161 } 162 } 163 $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file'); 164 break 2; 165 166 } 167 168 } 169 if ($RIFFsubtype == 'WAVE') { 170 $thisfile_riff_WAVE = &$thisfile_riff['WAVE']; 171 } 172 break; 173 174 default: 175 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead'); 176 //unset($info['fileformat']); 177 return false; 178 } 179 180 $streamindex = 0; 181 switch ($RIFFsubtype) { 182 183 // http://en.wikipedia.org/wiki/Wav 184 case 'WAVE': 185 $info['fileformat'] = 'wav'; 186 187 if (empty($thisfile_audio['bitrate_mode'])) { 188 $thisfile_audio['bitrate_mode'] = 'cbr'; 189 } 190 if (empty($thisfile_audio_dataformat)) { 191 $thisfile_audio_dataformat = 'wav'; 192 } 193 194 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) { 195 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8; 196 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size']; 197 } 198 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) { 199 200 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']); 201 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 202 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) { 203 $this->error('Corrupt RIFF file: bitrate_audio == zero'); 204 return false; 205 } 206 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw']; 207 unset($thisfile_riff_audio[$streamindex]['raw']); 208 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; 209 210 $thisfile_audio = (array) getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 211 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { 212 $this->warning('Audio codec = '.$thisfile_audio['codec']); 213 } 214 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; 215 216 if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV) 217 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); 218 } 219 220 $thisfile_audio['lossless'] = false; 221 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { 222 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { 223 224 case 0x0001: // PCM 225 $thisfile_audio['lossless'] = true; 226 break; 227 228 case 0x2000: // AC-3 229 $thisfile_audio_dataformat = 'ac3'; 230 break; 231 232 default: 233 // do nothing 234 break; 235 236 } 237 } 238 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag']; 239 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 240 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless']; 241 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat; 242 } 243 244 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) { 245 246 // shortcuts 247 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data']; 248 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array()); 249 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad']; 250 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track']; 251 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album']; 252 253 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4)); 254 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2)); 255 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2)); 256 257 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT); 258 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT); 259 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3)); 260 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3)); 261 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1)); 262 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9)); 263 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3)); 264 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3)); 265 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1)); 266 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9)); 267 268 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude']; 269 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) { 270 $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']); 271 $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']); 272 $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']); 273 } 274 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) { 275 $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']); 276 $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']); 277 $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']); 278 } 279 } 280 281 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) { 282 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4)); 283 284 // This should be a good way of calculating exact playtime, 285 // but some sample files have had incorrect number of samples, 286 // so cannot use this method 287 288 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) { 289 // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec']; 290 // } 291 } 292 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) { 293 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8); 294 } 295 296 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) { 297 // shortcut 298 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0]; 299 300 $thisfile_riff_WAVE_bext_0['title'] = substr($thisfile_riff_WAVE_bext_0['data'], 0, 256); 301 $thisfile_riff_WAVE_bext_0['author'] = substr($thisfile_riff_WAVE_bext_0['data'], 256, 32); 302 $thisfile_riff_WAVE_bext_0['reference'] = substr($thisfile_riff_WAVE_bext_0['data'], 288, 32); 303 foreach (array('title','author','reference') as $bext_key) { 304 // Some software (notably Logic Pro) may not blank existing data before writing a null-terminated string to the offsets 305 // assigned for text fields, resulting in a null-terminated string (or possibly just a single null) followed by garbage 306 // Keep only string as far as first null byte, discard rest of fixed-width data 307 // https://github.com/JamesHeinrich/getID3/issues/263 308 $null_terminator_offset = strpos($thisfile_riff_WAVE_bext_0[$bext_key], "\x00"); 309 $thisfile_riff_WAVE_bext_0[$bext_key] = substr($thisfile_riff_WAVE_bext_0[$bext_key], 0, $null_terminator_offset); 310 } 311 312 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10); 313 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8); 314 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8)); 315 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1)); 316 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254); 317 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601))); 318 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) { 319 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) { 320 $bext_timestamp = array(); 321 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date; 322 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; 323 $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']); 324 } else { 325 $this->warning('RIFF.WAVE.BEXT.origin_time is invalid'); 326 } 327 } else { 328 $this->warning('RIFF.WAVE.BEXT.origin_date is invalid'); 329 } 330 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author']; 331 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title']; 332 } 333 334 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) { 335 // shortcut 336 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0]; 337 338 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2)); 339 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001); 340 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) { 341 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true; 342 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004); 343 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008); 344 345 $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2)); 346 } 347 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2)); 348 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2)); 349 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001); 350 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002); 351 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004); 352 } 353 354 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) { 355 // shortcut 356 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0]; 357 358 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4); 359 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64)); 360 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64)); 361 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64)); 362 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64)); 363 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64)); 364 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64)); 365 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64)); 366 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10)); 367 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8)); 368 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10)); 369 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8)); 370 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64)); 371 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64)); 372 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64)); 373 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true); 374 for ($i = 0; $i < 8; $i++) { 375 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4); 376 $thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8) + 4, 4)); 377 } 378 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024)); 379 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772))); 380 $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772); 381 382 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist']; 383 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title']; 384 } 385 386 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) { 387 // SoundMiner metadata 388 389 // shortcuts 390 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0]; 391 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data']; 392 $SNDM_startoffset = 0; 393 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size']; 394 395 while ($SNDM_startoffset < $SNDM_endoffset) { 396 $SNDM_thisTagOffset = 0; 397 $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4)); 398 $SNDM_thisTagOffset += 4; 399 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4); 400 $SNDM_thisTagOffset += 4; 401 $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); 402 $SNDM_thisTagOffset += 2; 403 $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); 404 $SNDM_thisTagOffset += 2; 405 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize); 406 $SNDM_thisTagOffset += $SNDM_thisTagDataSize; 407 408 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) { 409 $this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'); 410 break; 411 } elseif ($SNDM_thisTagSize <= 0) { 412 $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'); 413 break; 414 } 415 $SNDM_startoffset += $SNDM_thisTagSize; 416 417 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText; 418 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) { 419 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText; 420 } else { 421 $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'); 422 } 423 } 424 425 $tagmapping = array( 426 'tracktitle'=>'title', 427 'category' =>'genre', 428 'cdtitle' =>'album', 429 ); 430 foreach ($tagmapping as $fromkey => $tokey) { 431 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) { 432 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey]; 433 } 434 } 435 } 436 437 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) { 438 // requires functions simplexml_load_string and get_object_vars 439 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) { 440 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML; 441 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) { 442 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']); 443 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000); 444 } 445 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) { 446 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']); 447 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000); 448 } 449 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) { 450 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0')); 451 $timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105 452 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate; 453 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600); 454 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60); 455 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60)); 456 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate']; 457 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f); 458 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f)); 459 unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f); 460 } 461 unset($parsedXML); 462 } 463 } 464 465 if (isset($thisfile_riff_WAVE['guan'][0]['data'])) { 466 // shortcut 467 $thisfile_riff_WAVE_guan_0 = &$thisfile_riff_WAVE['guan'][0]; 468 if (!empty($thisfile_riff_WAVE_guan_0['data']) && (substr($thisfile_riff_WAVE_guan_0['data'], 0, 14) == 'GUANO|Version:')) { 469 $thisfile_riff['guano'] = array(); 470 foreach (explode("\n", $thisfile_riff_WAVE_guan_0['data']) as $line) { 471 if ($line) { 472 @list($key, $value) = explode(':', $line, 2); 473 if (substr($value, 0, 3) == '[{"') { 474 if ($decoded = @json_decode($value, true)) { 475 if (!empty($decoded) && (count($decoded) == 1)) { 476 $value = $decoded[0]; 477 } else { 478 $value = $decoded; 479 } 480 } 481 } 482 $thisfile_riff['guano'] = array_merge_recursive($thisfile_riff['guano'], getid3_lib::CreateDeepArray($key, '|', $value)); 483 } 484 } 485 486 // https://www.wildlifeacoustics.com/SCHEMA/GUANO.html 487 foreach ($thisfile_riff['guano'] as $key => $value) { 488 switch ($key) { 489 case 'Loc Position': 490 if (preg_match('#^([\\+\\-]?[0-9]+\\.[0-9]+) ([\\+\\-]?[0-9]+\\.[0-9]+)$#', $value, $matches)) { 491 list($dummy, $latitude, $longitude) = $matches; 492 $thisfile_riff['comments']['gps_latitude'][0] = floatval($latitude); 493 $thisfile_riff['comments']['gps_longitude'][0] = floatval($longitude); 494 $thisfile_riff['guano'][$key] = floatval($latitude).' '.floatval($longitude); 495 } 496 break; 497 case 'Loc Elevation': // Elevation/altitude above mean sea level in meters 498 $thisfile_riff['comments']['gps_altitude'][0] = floatval($value); 499 $thisfile_riff['guano'][$key] = (float) $value; 500 break; 501 case 'Filter HP': // High-pass filter frequency in kHz 502 case 'Filter LP': // Low-pass filter frequency in kHz 503 case 'Humidity': // Relative humidity as a percentage 504 case 'Length': // Recording length in seconds 505 case 'Loc Accuracy': // Estimated Position Error in meters 506 case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing 507 case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing 508 $thisfile_riff['guano'][$key] = (float) $value; 509 break; 510 case 'Samplerate': // Recording sample rate, Hz 511 case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed. 512 $thisfile_riff['guano'][$key] = (int) $value; 513 break; 514 } 515 } 516 517 } else { 518 $this->warning('RIFF.guan data not in expected format'); 519 } 520 } 521 522 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { 523 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; 524 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); 525 } 526 527 if (!empty($info['wavpack'])) { 528 $thisfile_audio_dataformat = 'wavpack'; 529 $thisfile_audio['bitrate_mode'] = 'vbr'; 530 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version']; 531 532 // Reset to the way it was - RIFF parsing will have messed this up 533 $info['avdataend'] = $Original['avdataend']; 534 $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 535 536 $this->fseek($info['avdataoffset'] - 44); 537 $RIFFdata = $this->fread(44); 538 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8; 539 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44; 540 541 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) { 542 $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize); 543 $this->fseek($info['avdataend']); 544 $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize); 545 } 546 547 // move the data chunk after all other chunks (if any) 548 // so that the RIFF parser doesn't see EOF when trying 549 // to skip over the data chunk 550 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8); 551 $getid3_riff = new getid3_riff($this->getid3); 552 $getid3_riff->ParseRIFFdata($RIFFdata); 553 unset($getid3_riff); 554 } 555 556 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { 557 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { 558 case 0x0001: // PCM 559 if (!empty($info['ac3'])) { 560 // Dolby Digital WAV files masquerade as PCM-WAV, but they're not 561 $thisfile_audio['wformattag'] = 0x2000; 562 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); 563 $thisfile_audio['lossless'] = false; 564 $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; 565 $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate']; 566 } 567 if (!empty($info['dts'])) { 568 // Dolby DTS files masquerade as PCM-WAV, but they're not 569 $thisfile_audio['wformattag'] = 0x2001; 570 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); 571 $thisfile_audio['lossless'] = false; 572 $thisfile_audio['bitrate'] = $info['dts']['bitrate']; 573 $thisfile_audio['sample_rate'] = $info['dts']['sample_rate']; 574 } 575 break; 576 case 0x08AE: // ClearJump LiteWave 577 $thisfile_audio['bitrate_mode'] = 'vbr'; 578 $thisfile_audio_dataformat = 'litewave'; 579 580 //typedef struct tagSLwFormat { 581 // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags 582 // DWORD m_dwScale; // scale factor for lossy compression 583 // DWORD m_dwBlockSize; // number of samples in encoded blocks 584 // WORD m_wQuality; // alias for the scale factor 585 // WORD m_wMarkDistance; // distance between marks in bytes 586 // WORD m_wReserved; 587 // 588 // //following paramters are ignored if CF_FILESRC is not set 589 // DWORD m_dwOrgSize; // original file size in bytes 590 // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file 591 // DWORD m_dwRiffChunkSize; // riff chunk size in the original file 592 // 593 // PCMWAVEFORMAT m_OrgWf; // original wave format 594 // }SLwFormat, *PSLwFormat; 595 596 // shortcut 597 $thisfile_riff['litewave']['raw'] = array(); 598 $riff_litewave = &$thisfile_riff['litewave']; 599 $riff_litewave_raw = &$riff_litewave['raw']; 600 601 $flags = array( 602 'compression_method' => 1, 603 'compression_flags' => 1, 604 'm_dwScale' => 4, 605 'm_dwBlockSize' => 4, 606 'm_wQuality' => 2, 607 'm_wMarkDistance' => 2, 608 'm_wReserved' => 2, 609 'm_dwOrgSize' => 4, 610 'm_bFactExists' => 2, 611 'm_dwRiffChunkSize' => 4, 612 ); 613 $litewave_offset = 18; 614 foreach ($flags as $flag => $length) { 615 $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length)); 616 $litewave_offset += $length; 617 } 618 619 //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20)); 620 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality']; 621 622 $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true; 623 $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true; 624 $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04); 625 626 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false); 627 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor']; 628 break; 629 630 default: 631 break; 632 } 633 } 634 if ($info['avdataend'] > $info['filesize']) { 635 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') { 636 case 'wavpack': // WavPack 637 case 'lpac': // LPAC 638 case 'ofr': // OptimFROG 639 case 'ofs': // OptimFROG DualStream 640 // lossless compressed audio formats that keep original RIFF headers - skip warning 641 break; 642 643 case 'litewave': 644 if (($info['avdataend'] - $info['filesize']) == 1) { 645 // LiteWave appears to incorrectly *not* pad actual output file 646 // to nearest WORD boundary so may appear to be short by one 647 // byte, in which case - skip warning 648 } else { 649 // Short by more than one byte, throw warning 650 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'); 651 $info['avdataend'] = $info['filesize']; 652 } 653 break; 654 655 default: 656 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) { 657 // output file appears to be incorrectly *not* padded to nearest WORD boundary 658 // Output less severe warning 659 $this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'); 660 $info['avdataend'] = $info['filesize']; 661 } else { 662 // Short by more than one byte, throw warning 663 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'); 664 $info['avdataend'] = $info['filesize']; 665 } 666 break; 667 } 668 } 669 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) { 670 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) { 671 $info['avdataend']--; 672 $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'); 673 } 674 } 675 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) { 676 unset($thisfile_audio['bits_per_sample']); 677 if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) { 678 $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; 679 } 680 } 681 break; 682 683 // http://en.wikipedia.org/wiki/Audio_Video_Interleave 684 case 'AVI ': 685 $info['fileformat'] = 'avi'; 686 $info['mime_type'] = 'video/avi'; 687 688 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably 689 $thisfile_video['dataformat'] = 'avi'; 690 691 $thisfile_riff_video_current = array(); 692 693 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { 694 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8; 695 if (isset($thisfile_riff['AVIX'])) { 696 $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size']; 697 } else { 698 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size']; 699 } 700 if ($info['avdataend'] > $info['filesize']) { 701 $this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)'); 702 $info['avdataend'] = $info['filesize']; 703 } 704 } 705 706 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) { 707 //$bIndexType = array( 708 // 0x00 => 'AVI_INDEX_OF_INDEXES', 709 // 0x01 => 'AVI_INDEX_OF_CHUNKS', 710 // 0x80 => 'AVI_INDEX_IS_DATA', 711 //); 712 //$bIndexSubtype = array( 713 // 0x01 => array( 714 // 0x01 => 'AVI_INDEX_2FIELD', 715 // ), 716 //); 717 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) { 718 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data']; 719 720 $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2)); 721 $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1)); 722 $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1)); 723 $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4)); 724 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4); 725 $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4)); 726 727 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']]; 728 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']]; 729 730 unset($ahsisd); 731 } 732 } 733 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) { 734 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data']; 735 736 // shortcut 737 $thisfile_riff_raw['avih'] = array(); 738 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih']; 739 740 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) 741 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) { 742 $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero'); 743 return false; 744 } 745 746 $flags = array( 747 'dwMaxBytesPerSec', // max. transfer rate 748 'dwPaddingGranularity', // pad to multiples of this size; normally 2K. 749 'dwFlags', // the ever-present flags 750 'dwTotalFrames', // # frames in file 751 'dwInitialFrames', // 752 'dwStreams', // 753 'dwSuggestedBufferSize', // 754 'dwWidth', // 755 'dwHeight', // 756 'dwScale', // 757 'dwRate', // 758 'dwStart', // 759 'dwLength', // 760 ); 761 $avih_offset = 4; 762 foreach ($flags as $flag) { 763 $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4)); 764 $avih_offset += 4; 765 } 766 767 $flags = array( 768 'hasindex' => 0x00000010, 769 'mustuseindex' => 0x00000020, 770 'interleaved' => 0x00000100, 771 'trustcktype' => 0x00000800, 772 'capturedfile' => 0x00010000, 773 'copyrighted' => 0x00020010, 774 ); 775 foreach ($flags as $flag => $value) { 776 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value); 777 } 778 779 // shortcut 780 $thisfile_riff_video[$streamindex] = array(); 781 /** @var array $thisfile_riff_video_current */ 782 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex]; 783 784 if ($thisfile_riff_raw_avih['dwWidth'] > 0) { 785 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth']; 786 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width']; 787 } 788 if ($thisfile_riff_raw_avih['dwHeight'] > 0) { 789 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight']; 790 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height']; 791 } 792 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { 793 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames']; 794 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames']; 795 } 796 797 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3); 798 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate']; 799 } 800 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) { 801 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) { 802 $thisfile_riff_raw_strf_strhfccType_streamindex = null; 803 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) { 804 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { 805 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data']; 806 $strhfccType = substr($strhData, 0, 4); 807 808 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) { 809 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data']; 810 811 // shortcut 812 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex]; 813 814 switch ($strhfccType) { 815 case 'auds': 816 $thisfile_audio['bitrate_mode'] = 'cbr'; 817 $thisfile_audio_dataformat = 'wav'; 818 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) { 819 $streamindex = count($thisfile_riff_audio); 820 } 821 822 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData); 823 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 824 825 // shortcut 826 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; 827 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex]; 828 829 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) { 830 unset($thisfile_audio_streams_currentstream['bits_per_sample']); 831 } 832 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag']; 833 unset($thisfile_audio_streams_currentstream['raw']); 834 835 // shortcut 836 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw']; 837 838 unset($thisfile_riff_audio[$streamindex]['raw']); 839 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 840 841 $thisfile_audio['lossless'] = false; 842 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) { 843 case 0x0001: // PCM 844 $thisfile_audio_dataformat = 'wav'; 845 $thisfile_audio['lossless'] = true; 846 break; 847 848 case 0x0050: // MPEG Layer 2 or Layer 1 849 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2 850 break; 851 852 case 0x0055: // MPEG Layer 3 853 $thisfile_audio_dataformat = 'mp3'; 854 break; 855 856 case 0x00FF: // AAC 857 $thisfile_audio_dataformat = 'aac'; 858 break; 859 860 case 0x0161: // Windows Media v7 / v8 / v9 861 case 0x0162: // Windows Media Professional v9 862 case 0x0163: // Windows Media Lossess v9 863 $thisfile_audio_dataformat = 'wma'; 864 break; 865 866 case 0x2000: // AC-3 867 $thisfile_audio_dataformat = 'ac3'; 868 break; 869 870 case 0x2001: // DTS 871 $thisfile_audio_dataformat = 'dts'; 872 break; 873 874 default: 875 $thisfile_audio_dataformat = 'wav'; 876 break; 877 } 878 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat; 879 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless']; 880 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 881 break; 882 883 884 case 'iavs': 885 case 'vids': 886 // shortcut 887 $thisfile_riff_raw['strh'][$i] = array(); 888 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i]; 889 890 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType; 891 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4); 892 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags 893 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2)); 894 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2)); 895 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4)); 896 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4)); 897 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4)); 898 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4)); 899 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4)); 900 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4)); 901 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4)); 902 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4)); 903 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4)); 904 905 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']); 906 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler']; 907 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 908 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']); 909 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 910 } 911 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 912 $thisfile_video['pixel_aspect_ratio'] = (float) 1; 913 switch ($thisfile_riff_raw_strh_current['fccHandler']) { 914 case 'HFYU': // Huffman Lossless Codec 915 case 'IRAW': // Intel YUV Uncompressed 916 case 'YUY2': // Uncompressed YUV 4:2:2 917 $thisfile_video['lossless'] = true; 918 break; 919 920 default: 921 $thisfile_video['lossless'] = false; 922 break; 923 } 924 925 switch ($strhfccType) { 926 case 'vids': 927 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff')); 928 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; 929 930 if ($thisfile_riff_video_current['codec'] == 'DV') { 931 $thisfile_riff_video_current['dv_type'] = 2; 932 } 933 break; 934 935 case 'iavs': 936 $thisfile_riff_video_current['dv_type'] = 1; 937 break; 938 } 939 break; 940 941 default: 942 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"'); 943 break; 944 945 } 946 } 947 } 948 949 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 950 951 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 952 if (self::fourccLookup($thisfile_video['fourcc'])) { 953 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']); 954 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 955 } 956 957 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) { 958 case 'HFYU': // Huffman Lossless Codec 959 case 'IRAW': // Intel YUV Uncompressed 960 case 'YUY2': // Uncompressed YUV 4:2:2 961 $thisfile_video['lossless'] = true; 962 //$thisfile_video['bits_per_sample'] = 24; 963 break; 964 965 default: 966 $thisfile_video['lossless'] = false; 967 //$thisfile_video['bits_per_sample'] = 24; 968 break; 969 } 970 971 } 972 } 973 } 974 } 975 break; 976 977 978 case 'AMV ': 979 $info['fileformat'] = 'amv'; 980 $info['mime_type'] = 'video/amv'; 981 982 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR 983 $thisfile_video['dataformat'] = 'mjpeg'; 984 $thisfile_video['codec'] = 'mjpeg'; 985 $thisfile_video['lossless'] = false; 986 $thisfile_video['bits_per_sample'] = 24; 987 988 $thisfile_audio['dataformat'] = 'adpcm'; 989 $thisfile_audio['lossless'] = false; 990 break; 991 992 993 // http://en.wikipedia.org/wiki/CD-DA 994 case 'CDDA': 995 $info['fileformat'] = 'cda'; 996 unset($info['mime_type']); 997 998 $thisfile_audio_dataformat = 'cda'; 999 1000 $info['avdataoffset'] = 44; 1001 1002 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) { 1003 // shortcut 1004 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0]; 1005 1006 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2)); 1007 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2)); 1008 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4)); 1009 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4)); 1010 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4)); 1011 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4)); 1012 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4)); 1013 1014 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75; 1015 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75; 1016 $info['comments']['track_number'] = $thisfile_riff_CDDA_fmt_0['track_num']; 1017 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds']; 1018 1019 // hardcoded data for CD-audio 1020 $thisfile_audio['lossless'] = true; 1021 $thisfile_audio['sample_rate'] = 44100; 1022 $thisfile_audio['channels'] = 2; 1023 $thisfile_audio['bits_per_sample'] = 16; 1024 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample']; 1025 $thisfile_audio['bitrate_mode'] = 'cbr'; 1026 } 1027 break; 1028 1029 // http://en.wikipedia.org/wiki/AIFF 1030 case 'AIFF': 1031 case 'AIFC': 1032 $info['fileformat'] = 'aiff'; 1033 $info['mime_type'] = 'audio/x-aiff'; 1034 1035 $thisfile_audio['bitrate_mode'] = 'cbr'; 1036 $thisfile_audio_dataformat = 'aiff'; 1037 $thisfile_audio['lossless'] = true; 1038 1039 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { 1040 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8; 1041 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size']; 1042 if ($info['avdataend'] > $info['filesize']) { 1043 if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) { 1044 // structures rounded to 2-byte boundary, but dumb encoders 1045 // forget to pad end of file to make this actually work 1046 } else { 1047 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 1048 } 1049 $info['avdataend'] = $info['filesize']; 1050 } 1051 } 1052 1053 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) { 1054 1055 // shortcut 1056 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data']; 1057 1058 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true); 1059 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false); 1060 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true); 1061 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10)); 1062 1063 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) { 1064 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4); 1065 $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false); 1066 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize); 1067 switch ($thisfile_riff_audio['codec_name']) { 1068 case 'NONE': 1069 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 1070 $thisfile_audio['lossless'] = true; 1071 break; 1072 1073 case '': 1074 switch ($thisfile_riff_audio['codec_fourcc']) { 1075 // http://developer.apple.com/qa/snd/snd07.html 1076 case 'sowt': 1077 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM'; 1078 $thisfile_audio['lossless'] = true; 1079 break; 1080 1081 case 'twos': 1082 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM'; 1083 $thisfile_audio['lossless'] = true; 1084 break; 1085 1086 default: 1087 break; 1088 } 1089 break; 1090 1091 default: 1092 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name']; 1093 $thisfile_audio['lossless'] = false; 1094 break; 1095 } 1096 } 1097 1098 $thisfile_audio['channels'] = $thisfile_riff_audio['channels']; 1099 if ($thisfile_riff_audio['bits_per_sample'] > 0) { 1100 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample']; 1101 } 1102 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate']; 1103 if ($thisfile_audio['sample_rate'] == 0) { 1104 $this->error('Corrupted AIFF file: sample_rate == zero'); 1105 return false; 1106 } 1107 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate']; 1108 } 1109 1110 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) { 1111 $offset = 0; 1112 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1113 $offset += 2; 1114 for ($i = 0; $i < $CommentCount; $i++) { 1115 $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false); 1116 $offset += 4; 1117 $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true); 1118 $offset += 2; 1119 $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1120 $offset += 2; 1121 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength); 1122 $offset += $CommentLength; 1123 1124 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']); 1125 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment']; 1126 } 1127 } 1128 1129 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1130 foreach ($CommentsChunkNames as $key => $value) { 1131 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1132 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1133 } 1134 } 1135 /* 1136 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) { 1137 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1138 $getid3_temp = new getID3(); 1139 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1140 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1141 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; 1142 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1143 $info['id3v2'] = $getid3_temp->info['id3v2']; 1144 } 1145 unset($getid3_temp, $getid3_id3v2); 1146 } 1147 */ 1148 break; 1149 1150 // http://en.wikipedia.org/wiki/8SVX 1151 case '8SVX': 1152 $info['fileformat'] = '8svx'; 1153 $info['mime_type'] = 'audio/8svx'; 1154 1155 $thisfile_audio['bitrate_mode'] = 'cbr'; 1156 $thisfile_audio_dataformat = '8svx'; 1157 $thisfile_audio['bits_per_sample'] = 8; 1158 $thisfile_audio['channels'] = 1; // overridden below, if need be 1159 $ActualBitsPerSample = 0; 1160 1161 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { 1162 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; 1163 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size']; 1164 if ($info['avdataend'] > $info['filesize']) { 1165 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 1166 } 1167 } 1168 1169 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) { 1170 // shortcut 1171 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0]; 1172 1173 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4)); 1174 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4)); 1175 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4)); 1176 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2)); 1177 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1)); 1178 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1)); 1179 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4)); 1180 1181 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec']; 1182 1183 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) { 1184 case 0: 1185 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 1186 $thisfile_audio['lossless'] = true; 1187 $ActualBitsPerSample = 8; 1188 break; 1189 1190 case 1: 1191 $thisfile_audio['codec'] = 'Fibonacci-delta encoding'; 1192 $thisfile_audio['lossless'] = false; 1193 $ActualBitsPerSample = 4; 1194 break; 1195 1196 default: 1197 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"'); 1198 break; 1199 } 1200 } 1201 1202 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) { 1203 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4)); 1204 switch ($ChannelsIndex) { 1205 case 6: // Stereo 1206 $thisfile_audio['channels'] = 2; 1207 break; 1208 1209 case 2: // Left channel only 1210 case 4: // Right channel only 1211 $thisfile_audio['channels'] = 1; 1212 break; 1213 1214 default: 1215 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"'); 1216 break; 1217 } 1218 1219 } 1220 1221 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1222 foreach ($CommentsChunkNames as $key => $value) { 1223 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1224 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1225 } 1226 } 1227 1228 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels']; 1229 if (!empty($thisfile_audio['bitrate'])) { 1230 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8); 1231 } 1232 break; 1233 1234 case 'CDXA': 1235 $info['fileformat'] = 'vcd'; // Asume Video CD 1236 $info['mime_type'] = 'video/mpeg'; 1237 1238 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { 1239 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true); 1240 1241 $getid3_temp = new getID3(); 1242 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1243 $getid3_mpeg = new getid3_mpeg($getid3_temp); 1244 $getid3_mpeg->Analyze(); 1245 if (empty($getid3_temp->info['error'])) { 1246 $info['audio'] = $getid3_temp->info['audio']; 1247 $info['video'] = $getid3_temp->info['video']; 1248 $info['mpeg'] = $getid3_temp->info['mpeg']; 1249 $info['warning'] = $getid3_temp->info['warning']; 1250 } 1251 unset($getid3_temp, $getid3_mpeg); 1252 } 1253 break; 1254 1255 case 'WEBP': 1256 // https://developers.google.com/speed/webp/docs/riff_container 1257 // https://tools.ietf.org/html/rfc6386 1258 // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt 1259 $info['fileformat'] = 'webp'; 1260 $info['mime_type'] = 'image/webp'; 1261 1262 if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) { 1263 $old_offset = $this->ftell(); 1264 $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size 1265 $WEBP_VP8_header = $this->fread(10); 1266 $this->fseek($old_offset); 1267 if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") { 1268 $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000); 1269 $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20; 1270 $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000); 1271 $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0; 1272 1273 $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14; 1274 $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF); 1275 $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14; 1276 $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF); 1277 1278 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width']; 1279 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height']; 1280 } else { 1281 $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"'); 1282 } 1283 1284 } 1285 if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) { 1286 $old_offset = $this->ftell(); 1287 $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size 1288 $WEBP_VP8L_header = $this->fread(10); 1289 $this->fseek($old_offset); 1290 if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") { 1291 $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4)); 1292 $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1; 1293 $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1; 1294 $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1)); 1295 $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3)); 1296 1297 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width']; 1298 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height']; 1299 } else { 1300 $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"'); 1301 } 1302 1303 } 1304 break; 1305 1306 default: 1307 $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead'); 1308 //unset($info['fileformat']); 1309 } 1310 1311 switch ($RIFFsubtype) { 1312 case 'WAVE': 1313 case 'AIFF': 1314 case 'AIFC': 1315 $ID3v2_key_good = 'id3 '; 1316 $ID3v2_keys_bad = array('ID3 ', 'tag '); 1317 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) { 1318 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) { 1319 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]; 1320 $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"'); 1321 } 1322 } 1323 1324 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { 1325 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1326 1327 $getid3_temp = new getID3(); 1328 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1329 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1330 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; 1331 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1332 $info['id3v2'] = $getid3_temp->info['id3v2']; 1333 } 1334 unset($getid3_temp, $getid3_id3v2); 1335 } 1336 break; 1337 } 1338 1339 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) { 1340 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4)); 1341 } 1342 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) { 1343 self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']); 1344 } 1345 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) { 1346 self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']); 1347 } 1348 1349 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) { 1350 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version']; 1351 } 1352 1353 if (!isset($info['playtime_seconds'])) { 1354 $info['playtime_seconds'] = 0; 1355 } 1356 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { 1357 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie 1358 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1359 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { 1360 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1361 } 1362 1363 if ($info['playtime_seconds'] > 0) { 1364 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1365 1366 if (!isset($info['bitrate'])) { 1367 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1368 } 1369 1370 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) { 1371 1372 if (!isset($thisfile_audio['bitrate'])) { 1373 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1374 } 1375 1376 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1377 1378 if (!isset($thisfile_video['bitrate'])) { 1379 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1380 } 1381 1382 } 1383 } 1384 1385 1386 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) { 1387 1388 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1389 $thisfile_audio['bitrate'] = 0; 1390 $thisfile_video['bitrate'] = $info['bitrate']; 1391 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) { 1392 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate']; 1393 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate']; 1394 } 1395 if ($thisfile_video['bitrate'] <= 0) { 1396 unset($thisfile_video['bitrate']); 1397 } 1398 if ($thisfile_audio['bitrate'] <= 0) { 1399 unset($thisfile_audio['bitrate']); 1400 } 1401 } 1402 1403 if (isset($info['mpeg']['audio'])) { 1404 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer']; 1405 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1406 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels']; 1407 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate']; 1408 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1409 if (!empty($info['mpeg']['audio']['codec'])) { 1410 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec']; 1411 } 1412 if (!empty($thisfile_audio['streams'])) { 1413 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) { 1414 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) { 1415 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate']; 1416 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels']; 1417 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; 1418 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 1419 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec']; 1420 } 1421 } 1422 } 1423 $getid3_mp3 = new getid3_mp3($this->getid3); 1424 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions(); 1425 unset($getid3_mp3); 1426 } 1427 1428 1429 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) { 1430 switch ($thisfile_audio_dataformat) { 1431 case 'ac3': 1432 // ignore bits_per_sample 1433 break; 1434 1435 default: 1436 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample']; 1437 break; 1438 } 1439 } 1440 1441 1442 if (empty($thisfile_riff_raw)) { 1443 unset($thisfile_riff['raw']); 1444 } 1445 if (empty($thisfile_riff_audio)) { 1446 unset($thisfile_riff['audio']); 1447 } 1448 if (empty($thisfile_riff_video)) { 1449 unset($thisfile_riff['video']); 1450 } 1451 1452 return true; 1453 } 1454 1455 /** 1456 * @param int $startoffset 1457 * @param int $maxoffset 1458 * 1459 * @return array|false 1460 * 1461 * @throws Exception 1462 * @throws getid3_exception 1463 */ 1464 public function ParseRIFFAMV($startoffset, $maxoffset) { 1465 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size 1466 1467 // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation 1468 //typedef struct _amvmainheader { 1469 //FOURCC fcc; // 'amvh' 1470 //DWORD cb; 1471 //DWORD dwMicroSecPerFrame; 1472 //BYTE reserve[28]; 1473 //DWORD dwWidth; 1474 //DWORD dwHeight; 1475 //DWORD dwSpeed; 1476 //DWORD reserve0; 1477 //DWORD reserve1; 1478 //BYTE bTimeSec; 1479 //BYTE bTimeMin; 1480 //WORD wTimeHour; 1481 //} AMVMAINHEADER; 1482 1483 $info = &$this->getid3->info; 1484 $RIFFchunk = false; 1485 1486 try { 1487 1488 $this->fseek($startoffset); 1489 $maxoffset = min($maxoffset, $info['avdataend']); 1490 $AMVheader = $this->fread(284); 1491 if (substr($AMVheader, 0, 8) != 'hdrlamvh') { 1492 throw new Exception('expecting "hdrlamv" at offset '.($startoffset + 0).', found "'.substr($AMVheader, 0, 8).'"'); 1493 } 1494 if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes 1495 throw new Exception('expecting "0x38000000" at offset '.($startoffset + 8).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 8, 4)).'"'); 1496 } 1497 $RIFFchunk = array(); 1498 $RIFFchunk['amvh']['us_per_frame'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 12, 4)); 1499 $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved? 1500 $RIFFchunk['amvh']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 44, 4)); 1501 $RIFFchunk['amvh']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 48, 4)); 1502 $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 52, 4)); 1503 $RIFFchunk['amvh']['reserved0'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved? 1504 $RIFFchunk['amvh']['reserved1'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved? 1505 $RIFFchunk['amvh']['runtime_sec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 64, 1)); 1506 $RIFFchunk['amvh']['runtime_min'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 65, 1)); 1507 $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 66, 2)); 1508 1509 $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame']; 1510 $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x']; 1511 $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y']; 1512 $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) + ($RIFFchunk['amvh']['runtime_min'] * 60) + $RIFFchunk['amvh']['runtime_sec']; 1513 1514 // the rest is all hardcoded(?) and does not appear to be useful until you get to audio info at offset 256, even then everything is probably hardcoded 1515 1516 if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") { 1517 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).'"'); 1518 } 1519 // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144 1520 if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") { 1521 throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset + 144).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 144, 8)).'"'); 1522 } 1523 // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180 1524 1525 if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") { 1526 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).'"'); 1527 } 1528 // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256 1529 if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") { 1530 throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset + 256).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 256, 8)).'"'); 1531 } 1532 // followed by 20 bytes of a modified WAVEFORMATEX: 1533 // typedef struct { 1534 // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code) 1535 // WORD nChannels; //(Fixme: this is always 1) 1536 // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050) 1537 // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100) 1538 // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?) 1539 // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4) 1540 // WORD cbSize; //(Fixme: this seems to be 0 in AMV files) 1541 // WORD reserved; 1542 // } WAVEFORMATEX; 1543 $RIFFchunk['strf']['wformattag'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 264, 2)); 1544 $RIFFchunk['strf']['nchannels'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 266, 2)); 1545 $RIFFchunk['strf']['nsamplespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 268, 4)); 1546 $RIFFchunk['strf']['navgbytespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 272, 4)); 1547 $RIFFchunk['strf']['nblockalign'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 276, 2)); 1548 $RIFFchunk['strf']['wbitspersample'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 278, 2)); 1549 $RIFFchunk['strf']['cbsize'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 280, 2)); 1550 $RIFFchunk['strf']['reserved'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 282, 2)); 1551 1552 1553 $info['audio']['lossless'] = false; 1554 $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec']; 1555 $info['audio']['channels'] = $RIFFchunk['strf']['nchannels']; 1556 $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample']; 1557 $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample']; 1558 $info['audio']['bitrate_mode'] = 'cbr'; 1559 1560 1561 } catch (getid3_exception $e) { 1562 if ($e->getCode() == 10) { 1563 $this->warning('RIFFAMV parser: '.$e->getMessage()); 1564 } else { 1565 throw $e; 1566 } 1567 } 1568 1569 return $RIFFchunk; 1570 } 1571 1572 /** 1573 * @param int $startoffset 1574 * @param int $maxoffset 1575 * 1576 * @return array|false 1577 * @throws getid3_exception 1578 */ 1579 public function ParseRIFF($startoffset, $maxoffset) { 1580 $info = &$this->getid3->info; 1581 1582 $RIFFchunk = false; 1583 $FoundAllChunksWeNeed = false; 1584 $LISTchunkParent = null; 1585 $LISTchunkMaxOffset = null; 1586 $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77" 1587 1588 try { 1589 $this->fseek($startoffset); 1590 $maxoffset = min($maxoffset, $info['avdataend']); 1591 while ($this->ftell() < $maxoffset) { 1592 $chunknamesize = $this->fread(8); 1593 //$chunkname = substr($chunknamesize, 0, 4); 1594 $chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4)); // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult 1595 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4)); 1596 //if (strlen(trim($chunkname, "\x00")) < 4) { 1597 if (strlen($chunkname) < 4) { 1598 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.'); 1599 break; 1600 } 1601 if (($chunksize == 0) && ($chunkname != 'JUNK')) { 1602 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.'); 1603 break; 1604 } 1605 if (($chunksize % 2) != 0) { 1606 // all structures are packed on word boundaries 1607 $chunksize++; 1608 } 1609 1610 switch ($chunkname) { 1611 case 'LIST': 1612 $listname = $this->fread(4); 1613 if (preg_match('#^(movi|rec )$#i', $listname)) { 1614 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4; 1615 $RIFFchunk[$listname]['size'] = $chunksize; 1616 1617 if (!$FoundAllChunksWeNeed) { 1618 $WhereWeWere = $this->ftell(); 1619 $AudioChunkHeader = $this->fread(12); 1620 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2); 1621 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2); 1622 $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4)); 1623 1624 if ($AudioChunkStreamType == 'wb') { 1625 $FirstFourBytes = substr($AudioChunkHeader, 8, 4); 1626 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) { 1627 // MP3 1628 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { 1629 $getid3_temp = new getID3(); 1630 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1631 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1632 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1633 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1634 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); 1635 if (isset($getid3_temp->info['mpeg']['audio'])) { 1636 $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio']; 1637 $info['audio'] = $getid3_temp->info['audio']; 1638 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer']; 1639 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1640 $info['audio']['channels'] = $info['mpeg']['audio']['channels']; 1641 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; 1642 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1643 //$info['bitrate'] = $info['audio']['bitrate']; 1644 } 1645 unset($getid3_temp, $getid3_mp3); 1646 } 1647 1648 } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) { 1649 // AC3 1650 $getid3_temp = new getID3(); 1651 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1652 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1653 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1654 $getid3_ac3 = new getid3_ac3($getid3_temp); 1655 $getid3_ac3->Analyze(); 1656 if (empty($getid3_temp->info['error'])) { 1657 $info['audio'] = $getid3_temp->info['audio']; 1658 $info['ac3'] = $getid3_temp->info['ac3']; 1659 if (!empty($getid3_temp->info['warning'])) { 1660 foreach ($getid3_temp->info['warning'] as $key => $value) { 1661 $this->warning($value); 1662 } 1663 } 1664 } 1665 unset($getid3_temp, $getid3_ac3); 1666 } 1667 } 1668 $FoundAllChunksWeNeed = true; 1669 $this->fseek($WhereWeWere); 1670 } 1671 $this->fseek($chunksize - 4, SEEK_CUR); 1672 1673 } else { 1674 1675 if (!isset($RIFFchunk[$listname])) { 1676 $RIFFchunk[$listname] = array(); 1677 } 1678 $LISTchunkParent = $listname; 1679 $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize; 1680 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) { 1681 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk); 1682 } 1683 1684 } 1685 break; 1686 1687 default: 1688 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) { 1689 $this->fseek($chunksize, SEEK_CUR); 1690 break; 1691 } 1692 $thisindex = 0; 1693 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) { 1694 $thisindex = count($RIFFchunk[$chunkname]); 1695 } 1696 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8; 1697 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize; 1698 switch ($chunkname) { 1699 case 'data': 1700 $info['avdataoffset'] = $this->ftell(); 1701 $info['avdataend'] = $info['avdataoffset'] + $chunksize; 1702 1703 $testData = $this->fread(36); 1704 if ($testData === '') { 1705 break; 1706 } 1707 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) { 1708 1709 // Probably is MP3 data 1710 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { 1711 $getid3_temp = new getID3(); 1712 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1713 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1714 $getid3_temp->info['avdataend'] = $info['avdataend']; 1715 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1716 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); 1717 if (empty($getid3_temp->info['error'])) { 1718 $info['audio'] = $getid3_temp->info['audio']; 1719 $info['mpeg'] = $getid3_temp->info['mpeg']; 1720 } 1721 unset($getid3_temp, $getid3_mp3); 1722 } 1723 1724 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) { 1725 1726 // This is probably AC-3 data 1727 $getid3_temp = new getID3(); 1728 if ($isRegularAC3) { 1729 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1730 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1731 $getid3_temp->info['avdataend'] = $info['avdataend']; 1732 } 1733 $getid3_ac3 = new getid3_ac3($getid3_temp); 1734 if ($isRegularAC3) { 1735 $getid3_ac3->Analyze(); 1736 } else { 1737 // Dolby Digital WAV 1738 // AC-3 content, but not encoded in same format as normal AC-3 file 1739 // For one thing, byte order is swapped 1740 $ac3_data = ''; 1741 for ($i = 0; $i < 28; $i += 2) { 1742 $ac3_data .= substr($testData, 8 + $i + 1, 1); 1743 $ac3_data .= substr($testData, 8 + $i + 0, 1); 1744 } 1745 $getid3_ac3->getid3->info['avdataoffset'] = 0; 1746 $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data); 1747 $getid3_ac3->AnalyzeString($ac3_data); 1748 } 1749 1750 if (empty($getid3_temp->info['error'])) { 1751 $info['audio'] = $getid3_temp->info['audio']; 1752 $info['ac3'] = $getid3_temp->info['ac3']; 1753 if (!empty($getid3_temp->info['warning'])) { 1754 foreach ($getid3_temp->info['warning'] as $newerror) { 1755 $this->warning('getid3_ac3() says: ['.$newerror.']'); 1756 } 1757 } 1758 } 1759 unset($getid3_temp, $getid3_ac3); 1760 1761 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) { 1762 1763 // This is probably DTS data 1764 $getid3_temp = new getID3(); 1765 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1766 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1767 $getid3_dts = new getid3_dts($getid3_temp); 1768 $getid3_dts->Analyze(); 1769 if (empty($getid3_temp->info['error'])) { 1770 $info['audio'] = $getid3_temp->info['audio']; 1771 $info['dts'] = $getid3_temp->info['dts']; 1772 $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing 1773 if (!empty($getid3_temp->info['warning'])) { 1774 foreach ($getid3_temp->info['warning'] as $newerror) { 1775 $this->warning('getid3_dts() says: ['.$newerror.']'); 1776 } 1777 } 1778 } 1779 1780 unset($getid3_temp, $getid3_dts); 1781 1782 } elseif (substr($testData, 0, 4) == 'wvpk') { 1783 1784 // This is WavPack data 1785 $info['wavpack']['offset'] = $info['avdataoffset']; 1786 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4)); 1787 $this->parseWavPackHeader(substr($testData, 8, 28)); 1788 1789 } else { 1790 // This is some other kind of data (quite possibly just PCM) 1791 // do nothing special, just skip it 1792 } 1793 $nextoffset = $info['avdataend']; 1794 $this->fseek($nextoffset); 1795 break; 1796 1797 case 'iXML': 1798 case 'bext': 1799 case 'cart': 1800 case 'fmt ': 1801 case 'strh': 1802 case 'strf': 1803 case 'indx': 1804 case 'MEXT': 1805 case 'DISP': 1806 case 'wamd': 1807 case 'guan': 1808 // always read data in 1809 case 'JUNK': 1810 // should be: never read data in 1811 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc) 1812 if ($chunksize < 1048576) { 1813 if ($chunksize > 0) { 1814 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1815 if ($chunkname == 'JUNK') { 1816 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) { 1817 // only keep text characters [chr(32)-chr(127)] 1818 $info['riff']['comments']['junk'][] = trim($matches[1]); 1819 } 1820 // but if nothing there, ignore 1821 // remove the key in either case 1822 unset($RIFFchunk[$chunkname][$thisindex]['data']); 1823 } 1824 } 1825 } else { 1826 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data'); 1827 $this->fseek($chunksize, SEEK_CUR); 1828 } 1829 break; 1830 1831 //case 'IDVX': 1832 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize)); 1833 // break; 1834 1835 case 'scot': 1836 // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html 1837 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1838 $RIFFchunk[$chunkname][$thisindex]['parsed']['alter'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 0, 1); 1839 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 1, 1); 1840 $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 2, 2)); 1841 $RIFFchunk[$chunkname][$thisindex]['parsed']['title'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 4, 43); // "name" in other documentation 1842 $RIFFchunk[$chunkname][$thisindex]['parsed']['copy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 47, 4); 1843 $RIFFchunk[$chunkname][$thisindex]['parsed']['padd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 51, 1); 1844 $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 52, 5); 1845 $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 57, 2)); 1846 $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 59, 2)); 1847 $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 61, 2)); 1848 $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 63, 2)); 1849 $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 65, 6); 1850 $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 71, 6); 1851 $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 77, 1); 1852 $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 78, 1); 1853 $RIFFchunk[$chunkname][$thisindex]['parsed']['digital'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 79, 1); 1854 $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 80, 2)); 1855 $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 82, 1); 1856 $RIFFchunk[$chunkname][$thisindex]['parsed']['compress'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 83, 1); 1857 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 84, 4)); 1858 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 88, 2)); 1859 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 90, 4)); 1860 $RIFFchunk[$chunkname][$thisindex]['parsed']['future1'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 94, 12); 1861 $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106, 4)); 1862 $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110, 4)); 1863 $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114, 4)); 1864 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118, 2)); 1865 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120, 2)); 1866 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 122, 3); 1867 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 125, 4); 1868 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 129, 1); 1869 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 130, 3); 1870 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 133, 4); 1871 $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 137, 1); 1872 $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 138, 21); 1873 $RIFFchunk[$chunkname][$thisindex]['parsed']['future2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108); 1874 $RIFFchunk[$chunkname][$thisindex]['parsed']['artist'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 267, 34); 1875 $RIFFchunk[$chunkname][$thisindex]['parsed']['comment'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 301, 34); // "trivia" in other documentation 1876 $RIFFchunk[$chunkname][$thisindex]['parsed']['intro'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 335, 2); 1877 $RIFFchunk[$chunkname][$thisindex]['parsed']['end'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 337, 1); 1878 $RIFFchunk[$chunkname][$thisindex]['parsed']['year'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 338, 4); 1879 $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 342, 1); 1880 $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 343, 1); 1881 $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 344, 6); 1882 $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350, 2)); 1883 $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352, 2)); 1884 $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354, 2)); 1885 $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 356, 1); 1886 $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357, 4)); 1887 $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361, 2)); 1888 $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363, 4)); 1889 $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367, 4)); 1890 $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371, 4)); 1891 $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375, 4)); 1892 $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 379, 33); 1893 1894 foreach (array('title', 'artist', 'comment') as $key) { 1895 if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) { 1896 $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]); 1897 } 1898 } 1899 if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) { 1900 $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')'); 1901 } 1902 break; 1903 1904 default: 1905 if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { 1906 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset']; 1907 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size']; 1908 unset($RIFFchunk[$chunkname][$thisindex]['offset']); 1909 unset($RIFFchunk[$chunkname][$thisindex]['size']); 1910 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) { 1911 unset($RIFFchunk[$chunkname][$thisindex]); 1912 } 1913 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) { 1914 unset($RIFFchunk[$chunkname]); 1915 } 1916 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1917 } elseif ($chunksize < 2048) { 1918 // only read data in if smaller than 2kB 1919 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1920 } else { 1921 $this->fseek($chunksize, SEEK_CUR); 1922 } 1923 break; 1924 } 1925 break; 1926 } 1927 } 1928 1929 } catch (getid3_exception $e) { 1930 if ($e->getCode() == 10) { 1931 $this->warning('RIFF parser: '.$e->getMessage()); 1932 } else { 1933 throw $e; 1934 } 1935 } 1936 1937 return $RIFFchunk; 1938 } 1939 1940 /** 1941 * @param string $RIFFdata 1942 * 1943 * @return bool 1944 */ 1945 public function ParseRIFFdata(&$RIFFdata) { 1946 $info = &$this->getid3->info; 1947 if ($RIFFdata) { 1948 $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); 1949 $fp_temp = fopen($tempfile, 'wb'); 1950 $RIFFdataLength = strlen($RIFFdata); 1951 $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4); 1952 for ($i = 0; $i < 4; $i++) { 1953 $RIFFdata[($i + 4)] = $NewLengthString[$i]; 1954 } 1955 fwrite($fp_temp, $RIFFdata); 1956 fclose($fp_temp); 1957 1958 $getid3_temp = new getID3(); 1959 $getid3_temp->openfile($tempfile); 1960 $getid3_temp->info['filesize'] = $RIFFdataLength; 1961 $getid3_temp->info['filenamepath'] = $info['filenamepath']; 1962 $getid3_temp->info['tags'] = $info['tags']; 1963 $getid3_temp->info['warning'] = $info['warning']; 1964 $getid3_temp->info['error'] = $info['error']; 1965 $getid3_temp->info['comments'] = $info['comments']; 1966 $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array()); 1967 $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array()); 1968 $getid3_riff = new getid3_riff($getid3_temp); 1969 $getid3_riff->Analyze(); 1970 1971 $info['riff'] = $getid3_temp->info['riff']; 1972 $info['warning'] = $getid3_temp->info['warning']; 1973 $info['error'] = $getid3_temp->info['error']; 1974 $info['tags'] = $getid3_temp->info['tags']; 1975 $info['comments'] = $getid3_temp->info['comments']; 1976 unset($getid3_riff, $getid3_temp); 1977 unlink($tempfile); 1978 } 1979 return false; 1980 } 1981 1982 /** 1983 * @param array $RIFFinfoArray 1984 * @param array $CommentsTargetArray 1985 * 1986 * @return bool 1987 */ 1988 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) { 1989 $RIFFinfoKeyLookup = array( 1990 'IARL'=>'archivallocation', 1991 'IART'=>'artist', 1992 'ICDS'=>'costumedesigner', 1993 'ICMS'=>'commissionedby', 1994 'ICMT'=>'comment', 1995 'ICNT'=>'country', 1996 'ICOP'=>'copyright', 1997 'ICRD'=>'creationdate', 1998 'IDIM'=>'dimensions', 1999 'IDIT'=>'digitizationdate', 2000 'IDPI'=>'resolution', 2001 'IDST'=>'distributor', 2002 'IEDT'=>'editor', 2003 'IENG'=>'engineers', 2004 'IFRM'=>'accountofparts', 2005 'IGNR'=>'genre', 2006 'IKEY'=>'keywords', 2007 'ILGT'=>'lightness', 2008 'ILNG'=>'language', 2009 'IMED'=>'orignalmedium', 2010 'IMUS'=>'composer', 2011 'INAM'=>'title', 2012 'IPDS'=>'productiondesigner', 2013 'IPLT'=>'palette', 2014 'IPRD'=>'product', 2015 'IPRO'=>'producer', 2016 'IPRT'=>'part', 2017 'IRTD'=>'rating', 2018 'ISBJ'=>'subject', 2019 'ISFT'=>'software', 2020 'ISGN'=>'secondarygenre', 2021 'ISHP'=>'sharpness', 2022 'ISRC'=>'sourcesupplier', 2023 'ISRF'=>'digitizationsource', 2024 'ISTD'=>'productionstudio', 2025 'ISTR'=>'starring', 2026 'ITCH'=>'encoded_by', 2027 'IWEB'=>'url', 2028 'IWRI'=>'writer', 2029 '____'=>'comment', 2030 ); 2031 foreach ($RIFFinfoKeyLookup as $key => $value) { 2032 if (isset($RIFFinfoArray[$key])) { 2033 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) { 2034 if (trim($commentdata['data']) != '') { 2035 if (isset($CommentsTargetArray[$value])) { 2036 $CommentsTargetArray[$value][] = trim($commentdata['data']); 2037 } else { 2038 $CommentsTargetArray[$value] = array(trim($commentdata['data'])); 2039 } 2040 } 2041 } 2042 } 2043 } 2044 return true; 2045 } 2046 2047 /** 2048 * @param string $WaveFormatExData 2049 * 2050 * @return array 2051 */ 2052 public static function parseWAVEFORMATex($WaveFormatExData) { 2053 // shortcut 2054 $WaveFormatEx = array(); 2055 $WaveFormatEx['raw'] = array(); 2056 $WaveFormatEx_raw = &$WaveFormatEx['raw']; 2057 2058 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2); 2059 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2); 2060 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4); 2061 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4); 2062 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2); 2063 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2); 2064 if (strlen($WaveFormatExData) > 16) { 2065 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2); 2066 } 2067 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw); 2068 2069 $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']); 2070 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels']; 2071 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec']; 2072 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8; 2073 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample']; 2074 2075 return $WaveFormatEx; 2076 } 2077 2078 /** 2079 * @param string $WavPackChunkData 2080 * 2081 * @return bool 2082 */ 2083 public function parseWavPackHeader($WavPackChunkData) { 2084 // typedef struct { 2085 // char ckID [4]; 2086 // long ckSize; 2087 // short version; 2088 // short bits; // added for version 2.00 2089 // short flags, shift; // added for version 3.00 2090 // long total_samples, crc, crc2; 2091 // char extension [4], extra_bc, extras [3]; 2092 // } WavpackHeader; 2093 2094 // shortcut 2095 $info = &$this->getid3->info; 2096 $info['wavpack'] = array(); 2097 $thisfile_wavpack = &$info['wavpack']; 2098 2099 $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2)); 2100 if ($thisfile_wavpack['version'] >= 2) { 2101 $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2)); 2102 } 2103 if ($thisfile_wavpack['version'] >= 3) { 2104 $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2)); 2105 $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2)); 2106 $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4)); 2107 $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4)); 2108 $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4)); 2109 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4); 2110 $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1)); 2111 for ($i = 0; $i <= 2; $i++) { 2112 $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1)); 2113 } 2114 2115 // shortcut 2116 $thisfile_wavpack['flags'] = array(); 2117 $thisfile_wavpack_flags = &$thisfile_wavpack['flags']; 2118 2119 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001); 2120 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002); 2121 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004); 2122 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008); 2123 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010); 2124 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020); 2125 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040); 2126 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080); 2127 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100); 2128 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200); 2129 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400); 2130 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800); 2131 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000); 2132 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000); 2133 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000); 2134 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000); 2135 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000); 2136 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000); 2137 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000); 2138 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000); 2139 } 2140 2141 return true; 2142 } 2143 2144 /** 2145 * @param string $BITMAPINFOHEADER 2146 * @param bool $littleEndian 2147 * 2148 * @return array 2149 */ 2150 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { 2151 2152 $parsed = array(); 2153 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure 2154 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels 2155 $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 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 2156 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1 2157 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels 2158 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures) 2159 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device 2160 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device 2161 $parsed['biClrUsed'] = substr($BITMAPINFOHEADER, 32, 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 2162 $parsed['biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important 2163 $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed); 2164 2165 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier 2166 2167 return $parsed; 2168 } 2169 2170 /** 2171 * @param string $DIVXTAG 2172 * @param bool $raw 2173 * 2174 * @return array 2175 */ 2176 public static function ParseDIVXTAG($DIVXTAG, $raw=false) { 2177 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/ 2178 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip 2179 // 'Byte Layout: '1111111111111111 2180 // '32 for Movie - 1 '1111111111111111 2181 // '28 for Author - 6 '6666666666666666 2182 // '4 for year - 2 '6666666666662222 2183 // '3 for genre - 3 '7777777777777777 2184 // '48 for Comments - 7 '7777777777777777 2185 // '1 for Rating - 4 '7777777777777777 2186 // '5 for Future Additions - 0 '333400000DIVXTAG 2187 // '128 bytes total 2188 2189 static $DIVXTAGgenre = array( 2190 0 => 'Action', 2191 1 => 'Action/Adventure', 2192 2 => 'Adventure', 2193 3 => 'Adult', 2194 4 => 'Anime', 2195 5 => 'Cartoon', 2196 6 => 'Claymation', 2197 7 => 'Comedy', 2198 8 => 'Commercial', 2199 9 => 'Documentary', 2200 10 => 'Drama', 2201 11 => 'Home Video', 2202 12 => 'Horror', 2203 13 => 'Infomercial', 2204 14 => 'Interactive', 2205 15 => 'Mystery', 2206 16 => 'Music Video', 2207 17 => 'Other', 2208 18 => 'Religion', 2209 19 => 'Sci Fi', 2210 20 => 'Thriller', 2211 21 => 'Western', 2212 ), 2213 $DIVXTAGrating = array( 2214 0 => 'Unrated', 2215 1 => 'G', 2216 2 => 'PG', 2217 3 => 'PG-13', 2218 4 => 'R', 2219 5 => 'NC-17', 2220 ); 2221 2222 $parsed = array(); 2223 $parsed['title'] = trim(substr($DIVXTAG, 0, 32)); 2224 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28)); 2225 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4))); 2226 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48)); 2227 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3))); 2228 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1)); 2229 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null 2230 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG" 2231 2232 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']); 2233 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']); 2234 2235 if (!$raw) { 2236 unset($parsed['genre_id'], $parsed['rating_id']); 2237 foreach ($parsed as $key => $value) { 2238 if (empty($value)) { 2239 unset($parsed[$key]); 2240 } 2241 } 2242 } 2243 2244 foreach ($parsed as $tag => $value) { 2245 $parsed[$tag] = array($value); 2246 } 2247 2248 return $parsed; 2249 } 2250 2251 /** 2252 * @param string $tagshortname 2253 * 2254 * @return string 2255 */ 2256 public static function waveSNDMtagLookup($tagshortname) { 2257 $begin = __LINE__; 2258 2259 /** This is not a comment! 2260 2261 ©kwd keywords 2262 ©BPM bpm 2263 ©trt tracktitle 2264 ©des description 2265 ©gen category 2266 ©fin featuredinstrument 2267 ©LID longid 2268 ©bex bwdescription 2269 ©pub publisher 2270 ©cdt cdtitle 2271 ©alb library 2272 ©com composer 2273 2274 */ 2275 2276 return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm'); 2277 } 2278 2279 /** 2280 * @param int $wFormatTag 2281 * 2282 * @return string 2283 */ 2284 public static function wFormatTagLookup($wFormatTag) { 2285 2286 $begin = __LINE__; 2287 2288 /** This is not a comment! 2289 2290 0x0000 Microsoft Unknown Wave Format 2291 0x0001 Pulse Code Modulation (PCM) 2292 0x0002 Microsoft ADPCM 2293 0x0003 IEEE Float 2294 0x0004 Compaq Computer VSELP 2295 0x0005 IBM CVSD 2296 0x0006 Microsoft A-Law 2297 0x0007 Microsoft mu-Law 2298 0x0008 Microsoft DTS 2299 0x0010 OKI ADPCM 2300 0x0011 Intel DVI/IMA ADPCM 2301 0x0012 Videologic MediaSpace ADPCM 2302 0x0013 Sierra Semiconductor ADPCM 2303 0x0014 Antex Electronics G.723 ADPCM 2304 0x0015 DSP Solutions DigiSTD 2305 0x0016 DSP Solutions DigiFIX 2306 0x0017 Dialogic OKI ADPCM 2307 0x0018 MediaVision ADPCM 2308 0x0019 Hewlett-Packard CU 2309 0x0020 Yamaha ADPCM 2310 0x0021 Speech Compression Sonarc 2311 0x0022 DSP Group TrueSpeech 2312 0x0023 Echo Speech EchoSC1 2313 0x0024 Audiofile AF36 2314 0x0025 Audio Processing Technology APTX 2315 0x0026 AudioFile AF10 2316 0x0027 Prosody 1612 2317 0x0028 LRC 2318 0x0030 Dolby AC2 2319 0x0031 Microsoft GSM 6.10 2320 0x0032 MSNAudio 2321 0x0033 Antex Electronics ADPCME 2322 0x0034 Control Resources VQLPC 2323 0x0035 DSP Solutions DigiREAL 2324 0x0036 DSP Solutions DigiADPCM 2325 0x0037 Control Resources CR10 2326 0x0038 Natural MicroSystems VBXADPCM 2327 0x0039 Crystal Semiconductor IMA ADPCM 2328 0x003A EchoSC3 2329 0x003B Rockwell ADPCM 2330 0x003C Rockwell Digit LK 2331 0x003D Xebec 2332 0x0040 Antex Electronics G.721 ADPCM 2333 0x0041 G.728 CELP 2334 0x0042 MSG723 2335 0x0050 MPEG Layer-2 or Layer-1 2336 0x0052 RT24 2337 0x0053 PAC 2338 0x0055 MPEG Layer-3 2339 0x0059 Lucent G.723 2340 0x0060 Cirrus 2341 0x0061 ESPCM 2342 0x0062 Voxware 2343 0x0063 Canopus Atrac 2344 0x0064 G.726 ADPCM 2345 0x0065 G.722 ADPCM 2346 0x0066 DSAT 2347 0x0067 DSAT Display 2348 0x0069 Voxware Byte Aligned 2349 0x0070 Voxware AC8 2350 0x0071 Voxware AC10 2351 0x0072 Voxware AC16 2352 0x0073 Voxware AC20 2353 0x0074 Voxware MetaVoice 2354 0x0075 Voxware MetaSound 2355 0x0076 Voxware RT29HW 2356 0x0077 Voxware VR12 2357 0x0078 Voxware VR18 2358 0x0079 Voxware TQ40 2359 0x0080 Softsound 2360 0x0081 Voxware TQ60 2361 0x0082 MSRT24 2362 0x0083 G.729A 2363 0x0084 MVI MV12 2364 0x0085 DF G.726 2365 0x0086 DF GSM610 2366 0x0088 ISIAudio 2367 0x0089 Onlive 2368 0x0091 SBC24 2369 0x0092 Dolby AC3 SPDIF 2370 0x0093 MediaSonic G.723 2371 0x0094 Aculab PLC Prosody 8kbps 2372 0x0097 ZyXEL ADPCM 2373 0x0098 Philips LPCBB 2374 0x0099 Packed 2375 0x00FF AAC 2376 0x0100 Rhetorex ADPCM 2377 0x0101 IBM mu-law 2378 0x0102 IBM A-law 2379 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM) 2380 0x0111 Vivo G.723 2381 0x0112 Vivo Siren 2382 0x0123 Digital G.723 2383 0x0125 Sanyo LD ADPCM 2384 0x0130 Sipro Lab Telecom ACELP NET 2385 0x0131 Sipro Lab Telecom ACELP 4800 2386 0x0132 Sipro Lab Telecom ACELP 8V3 2387 0x0133 Sipro Lab Telecom G.729 2388 0x0134 Sipro Lab Telecom G.729A 2389 0x0135 Sipro Lab Telecom Kelvin 2390 0x0140 Windows Media Video V8 2391 0x0150 Qualcomm PureVoice 2392 0x0151 Qualcomm HalfRate 2393 0x0155 Ring Zero Systems TUB GSM 2394 0x0160 Microsoft Audio 1 2395 0x0161 Windows Media Audio V7 / V8 / V9 2396 0x0162 Windows Media Audio Professional V9 2397 0x0163 Windows Media Audio Lossless V9 2398 0x0200 Creative Labs ADPCM 2399 0x0202 Creative Labs Fastspeech8 2400 0x0203 Creative Labs Fastspeech10 2401 0x0210 UHER Informatic GmbH ADPCM 2402 0x0220 Quarterdeck 2403 0x0230 I-link Worldwide VC 2404 0x0240 Aureal RAW Sport 2405 0x0250 Interactive Products HSX 2406 0x0251 Interactive Products RPELP 2407 0x0260 Consistent Software CS2 2408 0x0270 Sony SCX 2409 0x0300 Fujitsu FM Towns Snd 2410 0x0400 BTV Digital 2411 0x0401 Intel Music Coder 2412 0x0450 QDesign Music 2413 0x0680 VME VMPCM 2414 0x0681 AT&T Labs TPC 2415 0x08AE ClearJump LiteWave 2416 0x1000 Olivetti GSM 2417 0x1001 Olivetti ADPCM 2418 0x1002 Olivetti CELP 2419 0x1003 Olivetti SBC 2420 0x1004 Olivetti OPR 2421 0x1100 Lernout & Hauspie Codec (0x1100) 2422 0x1101 Lernout & Hauspie CELP Codec (0x1101) 2423 0x1102 Lernout & Hauspie SBC Codec (0x1102) 2424 0x1103 Lernout & Hauspie SBC Codec (0x1103) 2425 0x1104 Lernout & Hauspie SBC Codec (0x1104) 2426 0x1400 Norris 2427 0x1401 AT&T ISIAudio 2428 0x1500 Soundspace Music Compression 2429 0x181C VoxWare RT24 Speech 2430 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com) 2431 0x2000 Dolby AC3 2432 0x2001 Dolby DTS 2433 0x2002 WAVE_FORMAT_14_4 2434 0x2003 WAVE_FORMAT_28_8 2435 0x2004 WAVE_FORMAT_COOK 2436 0x2005 WAVE_FORMAT_DNET 2437 0x674F Ogg Vorbis 1 2438 0x6750 Ogg Vorbis 2 2439 0x6751 Ogg Vorbis 3 2440 0x676F Ogg Vorbis 1+ 2441 0x6770 Ogg Vorbis 2+ 2442 0x6771 Ogg Vorbis 3+ 2443 0x7A21 GSM-AMR (CBR, no SID) 2444 0x7A22 GSM-AMR (VBR, including SID) 2445 0xFFFE WAVE_FORMAT_EXTENSIBLE 2446 0xFFFF WAVE_FORMAT_DEVELOPMENT 2447 2448 */ 2449 2450 return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag'); 2451 } 2452 2453 /** 2454 * @param string $fourcc 2455 * 2456 * @return string 2457 */ 2458 public static function fourccLookup($fourcc) { 2459 2460 $begin = __LINE__; 2461 2462 /** This is not a comment! 2463 2464 swot http://developer.apple.com/qa/snd/snd07.html 2465 ____ No Codec (____) 2466 _BIT BI_BITFIELDS (Raw RGB) 2467 _JPG JPEG compressed 2468 _PNG PNG compressed W3C/ISO/IEC (RFC-2083) 2469 _RAW Full Frames (Uncompressed) 2470 _RGB Raw RGB Bitmap 2471 _RL4 RLE 4bpp RGB 2472 _RL8 RLE 8bpp RGB 2473 3IV1 3ivx MPEG-4 v1 2474 3IV2 3ivx MPEG-4 v2 2475 3IVX 3ivx MPEG-4 2476 AASC Autodesk Animator 2477 ABYR Kensington ?ABYR? 2478 AEMI Array Microsystems VideoONE MPEG1-I Capture 2479 AFLC Autodesk Animator FLC 2480 AFLI Autodesk Animator FLI 2481 AMPG Array Microsystems VideoONE MPEG 2482 ANIM Intel RDX (ANIM) 2483 AP41 AngelPotion Definitive 2484 ASV1 Asus Video v1 2485 ASV2 Asus Video v2 2486 ASVX Asus Video 2.0 (audio) 2487 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2 2488 AURA AuraVision Aura 1 Codec - YUV 4:1:1 2489 AVDJ Independent JPEG Group\'s codec (AVDJ) 2490 AVRN Independent JPEG Group\'s codec (AVRN) 2491 AYUV 4:4:4 YUV (AYUV) 2492 AZPR Quicktime Apple Video (AZPR) 2493 BGR Raw RGB32 2494 BLZ0 Blizzard DivX MPEG-4 2495 BTVC Conexant Composite Video 2496 BINK RAD Game Tools Bink Video 2497 BT20 Conexant Prosumer Video 2498 BTCV Conexant Composite Video Codec 2499 BW10 Data Translation Broadway MPEG Capture 2500 CC12 Intel YUV12 2501 CDVC Canopus DV 2502 CFCC Digital Processing Systems DPS Perception 2503 CGDI Microsoft Office 97 Camcorder Video 2504 CHAM Winnov Caviara Champagne 2505 CJPG Creative WebCam JPEG 2506 CLJR Cirrus Logic YUV 4:1:1 2507 CMYK Common Data Format in Printing (Colorgraph) 2508 CPLA Weitek 4:2:0 YUV Planar 2509 CRAM Microsoft Video 1 (CRAM) 2510 cvid Radius Cinepak 2511 CVID Radius Cinepak 2512 CWLT Microsoft Color WLT DIB 2513 CYUV Creative Labs YUV 2514 CYUY ATI YUV 2515 D261 H.261 2516 D263 H.263 2517 DIB Device Independent Bitmap 2518 DIV1 FFmpeg OpenDivX 2519 DIV2 Microsoft MPEG-4 v1/v2 2520 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion 2521 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion 2522 DIV5 DivX MPEG-4 v5.x 2523 DIV6 DivX ;-) (MS MPEG-4 v3.x) 2524 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo) 2525 divx DivX MPEG-4 2526 DMB1 Matrox Rainbow Runner hardware MJPEG 2527 DMB2 Paradigm MJPEG 2528 DSVD ?DSVD? 2529 DUCK Duck TrueMotion 1.0 2530 DPS0 DPS/Leitch Reality Motion JPEG 2531 DPSC DPS/Leitch PAR Motion JPEG 2532 DV25 Matrox DVCPRO codec 2533 DV50 Matrox DVCPRO50 codec 2534 DVC IEC 61834 and SMPTE 314M (DVC/DV Video) 2535 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video) 2536 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps 2537 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com) 2538 DVSL IEC Standard DV compressed in SD (SDL) 2539 DVAN ?DVAN? 2540 DVE2 InSoft DVE-2 Videoconferencing 2541 dvsd IEC 61834 and SMPTE 314M DVC/DV Video 2542 DVSD IEC 61834 and SMPTE 314M DVC/DV Video 2543 DVX1 Lucent DVX1000SP Video Decoder 2544 DVX2 Lucent DVX2000S Video Decoder 2545 DVX3 Lucent DVX3000S Video Decoder 2546 DX50 DivX v5 2547 DXT1 Microsoft DirectX Compressed Texture (DXT1) 2548 DXT2 Microsoft DirectX Compressed Texture (DXT2) 2549 DXT3 Microsoft DirectX Compressed Texture (DXT3) 2550 DXT4 Microsoft DirectX Compressed Texture (DXT4) 2551 DXT5 Microsoft DirectX Compressed Texture (DXT5) 2552 DXTC Microsoft DirectX Compressed Texture (DXTC) 2553 DXTn Microsoft DirectX Compressed Texture (DXTn) 2554 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com) 2555 EKQ0 Elsa ?EKQ0? 2556 ELK0 Elsa ?ELK0? 2557 ESCP Eidos Escape 2558 ETV1 eTreppid Video ETV1 2559 ETV2 eTreppid Video ETV2 2560 ETVC eTreppid Video ETVC 2561 FLIC Autodesk FLI/FLC Animation 2562 FLV1 Sorenson Spark 2563 FLV4 On2 TrueMotion VP6 2564 FRWT Darim Vision Forward Motion JPEG (www.darvision.com) 2565 FRWU Darim Vision Forward Uncompressed (www.darvision.com) 2566 FLJP D-Vision Field Encoded Motion JPEG 2567 FPS1 FRAPS v1 2568 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel 2569 FRWD SoftLab-Nsk Forward Motion JPEG 2570 FVF1 Iterated Systems Fractal Video Frame 2571 GLZW Motion LZW (gabest@freemail.hu) 2572 GPEG Motion JPEG (gabest@freemail.hu) 2573 GWLT Microsoft Greyscale WLT DIB 2574 H260 Intel ITU H.260 Videoconferencing 2575 H261 Intel ITU H.261 Videoconferencing 2576 H262 Intel ITU H.262 Videoconferencing 2577 H263 Intel ITU H.263 Videoconferencing 2578 H264 Intel ITU H.264 Videoconferencing 2579 H265 Intel ITU H.265 Videoconferencing 2580 H266 Intel ITU H.266 Videoconferencing 2581 H267 Intel ITU H.267 Videoconferencing 2582 H268 Intel ITU H.268 Videoconferencing 2583 H269 Intel ITU H.269 Videoconferencing 2584 HFYU Huffman Lossless Codec 2585 HMCR Rendition Motion Compensation Format (HMCR) 2586 HMRR Rendition Motion Compensation Format (HMRR) 2587 I263 FFmpeg I263 decoder 2588 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane") 2589 IUYV Interlaced version of UYVY (www.leadtools.com) 2590 IY41 Interlaced version of Y41P (www.leadtools.com) 2591 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2592 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2593 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes) 2594 i263 Intel ITU H.263 Videoconferencing (i263) 2595 I420 Intel Indeo 4 2596 IAN Intel Indeo 4 (RDX) 2597 ICLB InSoft CellB Videoconferencing 2598 IGOR Power DVD 2599 IJPG Intergraph JPEG 2600 ILVC Intel Layered Video 2601 ILVR ITU-T H.263+ 2602 IPDV I-O Data Device Giga AVI DV Codec 2603 IR21 Intel Indeo 2.1 2604 IRAW Intel YUV Uncompressed 2605 IV30 Intel Indeo 3.0 2606 IV31 Intel Indeo 3.1 2607 IV32 Ligos Indeo 3.2 2608 IV33 Ligos Indeo 3.3 2609 IV34 Ligos Indeo 3.4 2610 IV35 Ligos Indeo 3.5 2611 IV36 Ligos Indeo 3.6 2612 IV37 Ligos Indeo 3.7 2613 IV38 Ligos Indeo 3.8 2614 IV39 Ligos Indeo 3.9 2615 IV40 Ligos Indeo Interactive 4.0 2616 IV41 Ligos Indeo Interactive 4.1 2617 IV42 Ligos Indeo Interactive 4.2 2618 IV43 Ligos Indeo Interactive 4.3 2619 IV44 Ligos Indeo Interactive 4.4 2620 IV45 Ligos Indeo Interactive 4.5 2621 IV46 Ligos Indeo Interactive 4.6 2622 IV47 Ligos Indeo Interactive 4.7 2623 IV48 Ligos Indeo Interactive 4.8 2624 IV49 Ligos Indeo Interactive 4.9 2625 IV50 Ligos Indeo Interactive 5.0 2626 JBYR Kensington ?JBYR? 2627 JPEG Still Image JPEG DIB 2628 JPGL Pegasus Lossless Motion JPEG 2629 KMVC Team17 Software Karl Morton\'s Video Codec 2630 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com) 2631 LEAD LEAD Video Codec 2632 Ljpg LEAD MJPEG Codec 2633 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de) 2634 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com) 2635 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com) 2636 MMES Matrox MPEG-2 I-frame 2637 MP2v Microsoft S-Mpeg 4 version 1 (MP2v) 2638 MP42 Microsoft S-Mpeg 4 version 2 (MP42) 2639 MP43 Microsoft S-Mpeg 4 version 3 (MP43) 2640 MP4S Microsoft S-Mpeg 4 version 3 (MP4S) 2641 MP4V FFmpeg MPEG-4 2642 MPG1 FFmpeg MPEG 1/2 2643 MPG2 FFmpeg MPEG 1/2 2644 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3) 2645 MPG4 Microsoft MPEG-4 2646 MPGI Sigma Designs MPEG 2647 MPNG PNG images decoder 2648 MSS1 Microsoft Windows Screen Video 2649 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2650 M261 Microsoft H.261 2651 M263 Microsoft H.263 2652 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2) 2653 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2) 2654 MC12 ATI Motion Compensation Format (MC12) 2655 MCAM ATI Motion Compensation Format (MCAM) 2656 MJ2C Morgan Multimedia Motion JPEG2000 2657 mJPG IBM Motion JPEG w/ Huffman Tables 2658 MJPG Microsoft Motion JPEG DIB 2659 MP42 Microsoft MPEG-4 (low-motion) 2660 MP43 Microsoft MPEG-4 (fast-motion) 2661 MP4S Microsoft MPEG-4 (MP4S) 2662 mp4s Microsoft MPEG-4 (mp4s) 2663 MPEG Chromatic Research MPEG-1 Video I-Frame 2664 MPG4 Microsoft MPEG-4 Video High Speed Compressor 2665 MPGI Sigma Designs MPEG 2666 MRCA FAST Multimedia Martin Regen Codec 2667 MRLE Microsoft Run Length Encoding 2668 MSVC Microsoft Video 1 2669 MTX1 Matrox ?MTX1? 2670 MTX2 Matrox ?MTX2? 2671 MTX3 Matrox ?MTX3? 2672 MTX4 Matrox ?MTX4? 2673 MTX5 Matrox ?MTX5? 2674 MTX6 Matrox ?MTX6? 2675 MTX7 Matrox ?MTX7? 2676 MTX8 Matrox ?MTX8? 2677 MTX9 Matrox ?MTX9? 2678 MV12 Motion Pixels Codec (old) 2679 MWV1 Aware Motion Wavelets 2680 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm) 2681 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com) 2682 NUV1 NuppelVideo 2683 NTN1 Nogatech Video Compression 1 2684 NVS0 nVidia GeForce Texture (NVS0) 2685 NVS1 nVidia GeForce Texture (NVS1) 2686 NVS2 nVidia GeForce Texture (NVS2) 2687 NVS3 nVidia GeForce Texture (NVS3) 2688 NVS4 nVidia GeForce Texture (NVS4) 2689 NVS5 nVidia GeForce Texture (NVS5) 2690 NVT0 nVidia GeForce Texture (NVT0) 2691 NVT1 nVidia GeForce Texture (NVT1) 2692 NVT2 nVidia GeForce Texture (NVT2) 2693 NVT3 nVidia GeForce Texture (NVT3) 2694 NVT4 nVidia GeForce Texture (NVT4) 2695 NVT5 nVidia GeForce Texture (NVT5) 2696 PIXL MiroXL, Pinnacle PCTV 2697 PDVC I-O Data Device Digital Video Capture DV codec 2698 PGVV Radius Video Vision 2699 PHMO IBM Photomotion 2700 PIM1 MPEG Realtime (Pinnacle Cards) 2701 PIM2 Pegasus Imaging ?PIM2? 2702 PIMJ Pegasus Imaging Lossless JPEG 2703 PVEZ Horizons Technology PowerEZ 2704 PVMM PacketVideo Corporation MPEG-4 2705 PVW2 Pegasus Imaging Wavelet Compression 2706 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de) 2707 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de) 2708 QPEG Q-Team QPEG 1.0 2709 qpeq Q-Team QPEG 1.1 2710 RGB Raw BGR32 2711 RGBA Raw RGB w/ Alpha 2712 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com) 2713 ROQV Id RoQ File Video Decoder 2714 RPZA Quicktime Apple Video (RPZA) 2715 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/) 2716 RV10 RealVideo 1.0 (aka RealVideo 5.0) 2717 RV13 RealVideo 1.0 (RV13) 2718 RV20 RealVideo G2 2719 RV30 RealVideo 8 2720 RV40 RealVideo 9 2721 RGBT Raw RGB w/ Transparency 2722 RLE Microsoft Run Length Encoder 2723 RLE4 Run Length Encoded (4bpp, 16-color) 2724 RLE8 Run Length Encoded (8bpp, 256-color) 2725 RT21 Intel Indeo RealTime Video 2.1 2726 rv20 RealVideo G2 2727 rv30 RealVideo 8 2728 RVX Intel RDX (RVX ) 2729 SMC Apple Graphics (SMC ) 2730 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2 2731 SPIG Radius Spigot 2732 SVQ3 Sorenson Video 3 (Apple Quicktime 5) 2733 s422 Tekram VideoCap C210 YUV 4:2:2 2734 SDCC Sun Communication Digital Camera Codec 2735 SFMC CrystalNet Surface Fitting Method 2736 SMSC Radius SMSC 2737 SMSD Radius SMSD 2738 smsv WorldConnect Wavelet Video 2739 SPIG Radius Spigot 2740 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net) 2741 SQZ2 Microsoft VXTreme Video Codec V2 2742 STVA ST Microelectronics CMOS Imager Data (Bayer) 2743 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer) 2744 STVC ST Microelectronics CMOS Imager Data (Bunched) 2745 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format) 2746 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data) 2747 SV10 Sorenson Video R1 2748 SVQ1 Sorenson Video 2749 T420 Toshiba YUV 4:2:0 2750 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com) 2751 TVJP Pinnacle/Truevision Targa 2000 board (TVJP) 2752 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ) 2753 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com) 2754 TY2C Trident Decompression Driver 2755 TLMS TeraLogic Motion Intraframe Codec (TLMS) 2756 TLST TeraLogic Motion Intraframe Codec (TLST) 2757 TM20 Duck TrueMotion 2.0 2758 TM2X Duck TrueMotion 2X 2759 TMIC TeraLogic Motion Intraframe Codec (TMIC) 2760 TMOT Horizons Technology TrueMotion S 2761 tmot Horizons TrueMotion Video Compression 2762 TR20 Duck TrueMotion RealTime 2.0 2763 TSCC TechSmith Screen Capture Codec 2764 TV10 Tecomac Low-Bit Rate Codec 2765 TY2N Trident ?TY2N? 2766 U263 UB Video H.263/H.263+/H.263++ Decoder 2767 UMP4 UB Video MPEG 4 (www.ubvideo.com) 2768 UYNV Nvidia UYVY packed 4:2:2 2769 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision 2770 UCOD eMajix.com ClearVideo 2771 ULTI IBM Ultimotion 2772 UYVY UYVY packed 4:2:2 2773 V261 Lucent VX2000S 2774 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/) 2775 VIV1 FFmpeg H263+ decoder 2776 VIV2 Vivo H.263 2777 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf) 2778 VTLP Alaris VideoGramPiX 2779 VYU9 ATI YUV (VYU9) 2780 VYUY ATI YUV (VYUY) 2781 V261 Lucent VX2000S 2782 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format 2783 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format 2784 VCR1 ATI Video Codec 1 2785 VCR2 ATI Video Codec 2 2786 VCR3 ATI VCR 3.0 2787 VCR4 ATI VCR 4.0 2788 VCR5 ATI VCR 5.0 2789 VCR6 ATI VCR 6.0 2790 VCR7 ATI VCR 7.0 2791 VCR8 ATI VCR 8.0 2792 VCR9 ATI VCR 9.0 2793 VDCT Vitec Multimedia Video Maker Pro DIB 2794 VDOM VDOnet VDOWave 2795 VDOW VDOnet VDOLive (H.263) 2796 VDTZ Darim Vison VideoTizer YUV 2797 VGPX Alaris VideoGramPiX 2798 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422 2799 VIVO Vivo H.263 v2.00 2800 vivo Vivo H.263 2801 VIXL Miro/Pinnacle Video XL 2802 VLV1 VideoLogic/PURE Digital Videologic Capture 2803 VP30 On2 VP3.0 2804 VP31 On2 VP3.1 2805 VP6F On2 TrueMotion VP6 2806 VX1K Lucent VX1000S Video Codec 2807 VX2K Lucent VX2000S Video Codec 2808 VXSP Lucent VX1000SP Video Codec 2809 WBVC Winbond W9960 2810 WHAM Microsoft Video 1 (WHAM) 2811 WINX Winnov Software Compression 2812 WJPG AverMedia Winbond JPEG 2813 WMV1 Windows Media Video V7 2814 WMV2 Windows Media Video V8 2815 WMV3 Windows Media Video V9 2816 WNV1 Winnov Hardware Compression 2817 XYZP Extended PAL format XYZ palette (www.riff.org) 2818 x263 Xirlink H.263 2819 XLV0 NetXL Video Decoder 2820 XMPG Xing MPEG (I-Frame only) 2821 XVID XviD MPEG-4 (www.xvid.org) 2822 XXAN ?XXAN? 2823 YU92 Intel YUV (YU92) 2824 YUNV Nvidia Uncompressed YUV 4:2:2 2825 YUVP Extended PAL format YUV palette (www.riff.org) 2826 Y211 YUV 2:1:1 Packed 2827 Y411 YUV 4:1:1 Packed 2828 Y41B Weitek YUV 4:1:1 Planar 2829 Y41P Brooktree PC1 YUV 4:1:1 Packed 2830 Y41T Brooktree PC1 YUV 4:1:1 with transparency 2831 Y42B Weitek YUV 4:2:2 Planar 2832 Y42T Brooktree UYUV 4:2:2 with transparency 2833 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera 2834 Y800 Simple, single Y plane for monochrome images 2835 Y8 Grayscale video 2836 YC12 Intel YUV 12 codec 2837 YUV8 Winnov Caviar YUV8 2838 YUV9 Intel YUV9 2839 YUY2 Uncompressed YUV 4:2:2 2840 YUYV Canopus YUV 2841 YV12 YVU12 Planar 2842 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes) 2843 YVYU YVYU 4:2:2 Packed 2844 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2845 ZPEG Metheus Video Zipper 2846 2847 */ 2848 2849 return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc'); 2850 } 2851 2852 /** 2853 * @param string $byteword 2854 * @param bool $signed 2855 * 2856 * @return int|float|false 2857 */ 2858 private function EitherEndian2Int($byteword, $signed=false) { 2859 if ($this->container == 'riff') { 2860 return getid3_lib::LittleEndian2Int($byteword, $signed); 2861 } 2862 return getid3_lib::BigEndian2Int($byteword, false, $signed); 2863 } 2864 2865 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 4 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |