[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[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)getid3_lib::SafeDiv(($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'] = (int) $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'] = (int) $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)getid3_lib::SafeDiv((($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'] = getid3_lib::SafeDiv(($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 ($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 ($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) { // @phpstan-ignore-line 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) { // @phpstan-ignore-line 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) { // @phpstan-ignore-line 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 if (!isset($thisfile_riff_raw['strf'][$strhfccType][$streamindex])) { 812 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = null; 813 } 814 // shortcut 815 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex]; 816 817 switch ($strhfccType) { 818 case 'auds': 819 $thisfile_audio['bitrate_mode'] = 'cbr'; 820 $thisfile_audio_dataformat = 'wav'; 821 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) { 822 $streamindex = count($thisfile_riff_audio); 823 } 824 825 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData); 826 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 827 828 // shortcut 829 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; 830 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex]; 831 832 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) { 833 unset($thisfile_audio_streams_currentstream['bits_per_sample']); 834 } 835 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag']; 836 unset($thisfile_audio_streams_currentstream['raw']); 837 838 // shortcut 839 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw']; 840 841 unset($thisfile_riff_audio[$streamindex]['raw']); 842 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 843 844 $thisfile_audio['lossless'] = false; 845 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) { 846 case 0x0001: // PCM 847 $thisfile_audio_dataformat = 'wav'; 848 $thisfile_audio['lossless'] = true; 849 break; 850 851 case 0x0050: // MPEG Layer 2 or Layer 1 852 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2 853 break; 854 855 case 0x0055: // MPEG Layer 3 856 $thisfile_audio_dataformat = 'mp3'; 857 break; 858 859 case 0x00FF: // AAC 860 $thisfile_audio_dataformat = 'aac'; 861 break; 862 863 case 0x0161: // Windows Media v7 / v8 / v9 864 case 0x0162: // Windows Media Professional v9 865 case 0x0163: // Windows Media Lossess v9 866 $thisfile_audio_dataformat = 'wma'; 867 break; 868 869 case 0x2000: // AC-3 870 $thisfile_audio_dataformat = 'ac3'; 871 break; 872 873 case 0x2001: // DTS 874 $thisfile_audio_dataformat = 'dts'; 875 break; 876 877 default: 878 $thisfile_audio_dataformat = 'wav'; 879 break; 880 } 881 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat; 882 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless']; 883 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 884 break; 885 886 887 case 'iavs': 888 case 'vids': 889 // shortcut 890 $thisfile_riff_raw['strh'][$i] = array(); 891 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i]; 892 893 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType; 894 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4); 895 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags 896 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2)); 897 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2)); 898 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4)); 899 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4)); 900 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4)); 901 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4)); 902 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4)); 903 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4)); 904 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4)); 905 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4)); 906 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4)); 907 908 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']); 909 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler']; 910 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 911 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']); 912 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 913 } 914 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 915 $thisfile_video['pixel_aspect_ratio'] = (float) 1; 916 switch ($thisfile_riff_raw_strh_current['fccHandler']) { 917 case 'HFYU': // Huffman Lossless Codec 918 case 'IRAW': // Intel YUV Uncompressed 919 case 'YUY2': // Uncompressed YUV 4:2:2 920 $thisfile_video['lossless'] = true; 921 break; 922 923 default: 924 $thisfile_video['lossless'] = false; 925 break; 926 } 927 928 switch ($strhfccType) { 929 case 'vids': 930 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff')); 931 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; 932 933 if ($thisfile_riff_video_current['codec'] == 'DV') { 934 $thisfile_riff_video_current['dv_type'] = 2; 935 } 936 break; 937 938 case 'iavs': 939 $thisfile_riff_video_current['dv_type'] = 1; 940 break; 941 } 942 break; 943 944 default: 945 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"'); 946 break; 947 948 } 949 } 950 } 951 952 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 953 954 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 955 if (self::fourccLookup($thisfile_video['fourcc'])) { 956 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']); 957 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 958 } 959 960 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) { 961 case 'HFYU': // Huffman Lossless Codec 962 case 'IRAW': // Intel YUV Uncompressed 963 case 'YUY2': // Uncompressed YUV 4:2:2 964 $thisfile_video['lossless'] = true; 965 //$thisfile_video['bits_per_sample'] = 24; 966 break; 967 968 default: 969 $thisfile_video['lossless'] = false; 970 //$thisfile_video['bits_per_sample'] = 24; 971 break; 972 } 973 974 } 975 } 976 } 977 } 978 break; 979 980 981 case 'AMV ': 982 $info['fileformat'] = 'amv'; 983 $info['mime_type'] = 'video/amv'; 984 985 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR 986 $thisfile_video['dataformat'] = 'mjpeg'; 987 $thisfile_video['codec'] = 'mjpeg'; 988 $thisfile_video['lossless'] = false; 989 $thisfile_video['bits_per_sample'] = 24; 990 991 $thisfile_audio['dataformat'] = 'adpcm'; 992 $thisfile_audio['lossless'] = false; 993 break; 994 995 996 // http://en.wikipedia.org/wiki/CD-DA 997 case 'CDDA': 998 $info['fileformat'] = 'cda'; 999 unset($info['mime_type']); 1000 1001 $thisfile_audio_dataformat = 'cda'; 1002 1003 $info['avdataoffset'] = 44; 1004 1005 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) { 1006 // shortcut 1007 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0]; 1008 1009 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2)); 1010 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2)); 1011 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4)); 1012 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4)); 1013 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4)); 1014 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4)); 1015 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4)); 1016 1017 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75; 1018 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75; 1019 $info['comments']['track_number'] = $thisfile_riff_CDDA_fmt_0['track_num']; 1020 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds']; 1021 1022 // hardcoded data for CD-audio 1023 $thisfile_audio['lossless'] = true; 1024 $thisfile_audio['sample_rate'] = 44100; 1025 $thisfile_audio['channels'] = 2; 1026 $thisfile_audio['bits_per_sample'] = 16; 1027 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample']; 1028 $thisfile_audio['bitrate_mode'] = 'cbr'; 1029 } 1030 break; 1031 1032 // http://en.wikipedia.org/wiki/AIFF 1033 case 'AIFF': 1034 case 'AIFC': 1035 $info['fileformat'] = 'aiff'; 1036 $info['mime_type'] = 'audio/x-aiff'; 1037 1038 $thisfile_audio['bitrate_mode'] = 'cbr'; 1039 $thisfile_audio_dataformat = 'aiff'; 1040 $thisfile_audio['lossless'] = true; 1041 1042 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { 1043 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8; 1044 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size']; 1045 if ($info['avdataend'] > $info['filesize']) { 1046 if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) { 1047 // structures rounded to 2-byte boundary, but dumb encoders 1048 // forget to pad end of file to make this actually work 1049 } else { 1050 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 1051 } 1052 $info['avdataend'] = $info['filesize']; 1053 } 1054 } 1055 1056 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) { 1057 1058 // shortcut 1059 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data']; 1060 1061 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true); 1062 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false); 1063 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true); 1064 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10)); 1065 1066 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) { 1067 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4); 1068 $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false); 1069 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize); 1070 switch ($thisfile_riff_audio['codec_name']) { 1071 case 'NONE': 1072 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 1073 $thisfile_audio['lossless'] = true; 1074 break; 1075 1076 case '': 1077 switch ($thisfile_riff_audio['codec_fourcc']) { 1078 // http://developer.apple.com/qa/snd/snd07.html 1079 case 'sowt': 1080 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM'; 1081 $thisfile_audio['lossless'] = true; 1082 break; 1083 1084 case 'twos': 1085 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM'; 1086 $thisfile_audio['lossless'] = true; 1087 break; 1088 1089 default: 1090 break; 1091 } 1092 break; 1093 1094 default: 1095 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name']; 1096 $thisfile_audio['lossless'] = false; 1097 break; 1098 } 1099 } 1100 1101 $thisfile_audio['channels'] = $thisfile_riff_audio['channels']; 1102 if ($thisfile_riff_audio['bits_per_sample'] > 0) { 1103 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample']; 1104 } 1105 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate']; 1106 if ($thisfile_audio['sample_rate'] == 0) { 1107 $this->error('Corrupted AIFF file: sample_rate == zero'); 1108 return false; 1109 } 1110 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate']; 1111 } 1112 1113 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) { 1114 $offset = 0; 1115 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1116 $offset += 2; 1117 for ($i = 0; $i < $CommentCount; $i++) { 1118 $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false); 1119 $offset += 4; 1120 $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true); 1121 $offset += 2; 1122 $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1123 $offset += 2; 1124 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength); 1125 $offset += $CommentLength; 1126 1127 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']); 1128 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment']; 1129 } 1130 } 1131 1132 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1133 foreach ($CommentsChunkNames as $key => $value) { 1134 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1135 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1136 } 1137 } 1138 /* 1139 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) { 1140 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1141 $getid3_temp = new getID3(); 1142 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1143 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1144 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; 1145 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1146 $info['id3v2'] = $getid3_temp->info['id3v2']; 1147 } 1148 unset($getid3_temp, $getid3_id3v2); 1149 } 1150 */ 1151 break; 1152 1153 // http://en.wikipedia.org/wiki/8SVX 1154 case '8SVX': 1155 $info['fileformat'] = '8svx'; 1156 $info['mime_type'] = 'audio/8svx'; 1157 1158 $thisfile_audio['bitrate_mode'] = 'cbr'; 1159 $thisfile_audio_dataformat = '8svx'; 1160 $thisfile_audio['bits_per_sample'] = 8; 1161 $thisfile_audio['channels'] = 1; // overridden below, if need be 1162 $ActualBitsPerSample = 0; 1163 1164 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { 1165 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; 1166 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size']; 1167 if ($info['avdataend'] > $info['filesize']) { 1168 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 1169 } 1170 } 1171 1172 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) { 1173 // shortcut 1174 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0]; 1175 1176 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4)); 1177 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4)); 1178 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4)); 1179 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2)); 1180 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1)); 1181 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1)); 1182 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4)); 1183 1184 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec']; 1185 1186 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) { 1187 case 0: 1188 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 1189 $thisfile_audio['lossless'] = true; 1190 $ActualBitsPerSample = 8; 1191 break; 1192 1193 case 1: 1194 $thisfile_audio['codec'] = 'Fibonacci-delta encoding'; 1195 $thisfile_audio['lossless'] = false; 1196 $ActualBitsPerSample = 4; 1197 break; 1198 1199 default: 1200 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"'); 1201 break; 1202 } 1203 } 1204 1205 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) { 1206 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4)); 1207 switch ($ChannelsIndex) { 1208 case 6: // Stereo 1209 $thisfile_audio['channels'] = 2; 1210 break; 1211 1212 case 2: // Left channel only 1213 case 4: // Right channel only 1214 $thisfile_audio['channels'] = 1; 1215 break; 1216 1217 default: 1218 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"'); 1219 break; 1220 } 1221 1222 } 1223 1224 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1225 foreach ($CommentsChunkNames as $key => $value) { 1226 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1227 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1228 } 1229 } 1230 1231 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels']; 1232 if (!empty($thisfile_audio['bitrate'])) { 1233 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8); 1234 } 1235 break; 1236 1237 case 'CDXA': 1238 $info['fileformat'] = 'vcd'; // Asume Video CD 1239 $info['mime_type'] = 'video/mpeg'; 1240 1241 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { 1242 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true); 1243 1244 $getid3_temp = new getID3(); 1245 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1246 $getid3_mpeg = new getid3_mpeg($getid3_temp); 1247 $getid3_mpeg->Analyze(); 1248 if (empty($getid3_temp->info['error'])) { 1249 $info['audio'] = $getid3_temp->info['audio']; 1250 $info['video'] = $getid3_temp->info['video']; 1251 $info['mpeg'] = $getid3_temp->info['mpeg']; 1252 $info['warning'] = $getid3_temp->info['warning']; 1253 } 1254 unset($getid3_temp, $getid3_mpeg); 1255 } 1256 break; 1257 1258 case 'WEBP': 1259 // https://developers.google.com/speed/webp/docs/riff_container 1260 // https://tools.ietf.org/html/rfc6386 1261 // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt 1262 $info['fileformat'] = 'webp'; 1263 $info['mime_type'] = 'image/webp'; 1264 1265 if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) { 1266 $old_offset = $this->ftell(); 1267 $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size 1268 $WEBP_VP8_header = $this->fread(10); 1269 $this->fseek($old_offset); 1270 if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") { 1271 $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000); 1272 $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20; 1273 $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000); 1274 $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0; 1275 1276 $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14; 1277 $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF); 1278 $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14; 1279 $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF); 1280 1281 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width']; 1282 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height']; 1283 } else { 1284 $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)).'"'); 1285 } 1286 1287 } 1288 if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) { 1289 $old_offset = $this->ftell(); 1290 $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size 1291 $WEBP_VP8L_header = $this->fread(10); 1292 $this->fseek($old_offset); 1293 if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") { 1294 $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4)); 1295 $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1; 1296 $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1; 1297 $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1)); 1298 $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3)); 1299 1300 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width']; 1301 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height']; 1302 } else { 1303 $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"'); 1304 } 1305 1306 } 1307 break; 1308 1309 default: 1310 $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead'); 1311 //unset($info['fileformat']); 1312 } 1313 1314 switch ($RIFFsubtype) { 1315 case 'WAVE': 1316 case 'AIFF': 1317 case 'AIFC': 1318 $ID3v2_key_good = 'id3 '; 1319 $ID3v2_keys_bad = array('ID3 ', 'tag '); 1320 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) { 1321 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) { 1322 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]; 1323 $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"'); 1324 } 1325 } 1326 1327 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { 1328 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1329 1330 $getid3_temp = new getID3(); 1331 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1332 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1333 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; 1334 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1335 $info['id3v2'] = $getid3_temp->info['id3v2']; 1336 } 1337 unset($getid3_temp, $getid3_id3v2); 1338 } 1339 break; 1340 } 1341 1342 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) { 1343 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4)); 1344 } 1345 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) { 1346 self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']); 1347 } 1348 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) { 1349 self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']); 1350 } 1351 1352 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) { 1353 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version']; 1354 } 1355 1356 if (!isset($info['playtime_seconds'])) { 1357 $info['playtime_seconds'] = 0; 1358 } 1359 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line 1360 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie 1361 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1362 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line 1363 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1364 } 1365 1366 if ($info['playtime_seconds'] > 0) { 1367 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1368 1369 if (!isset($info['bitrate'])) { 1370 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1371 } 1372 1373 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) { 1374 1375 if (!isset($thisfile_audio['bitrate'])) { 1376 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1377 } 1378 1379 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1380 1381 if (!isset($thisfile_video['bitrate'])) { 1382 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1383 } 1384 1385 } 1386 } 1387 1388 1389 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) { 1390 1391 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1392 $thisfile_audio['bitrate'] = 0; 1393 $thisfile_video['bitrate'] = $info['bitrate']; 1394 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) { 1395 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate']; 1396 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate']; 1397 } 1398 if ($thisfile_video['bitrate'] <= 0) { 1399 unset($thisfile_video['bitrate']); 1400 } 1401 if ($thisfile_audio['bitrate'] <= 0) { 1402 unset($thisfile_audio['bitrate']); 1403 } 1404 } 1405 1406 if (isset($info['mpeg']['audio'])) { 1407 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer']; 1408 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1409 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels']; 1410 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate']; 1411 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1412 if (!empty($info['mpeg']['audio']['codec'])) { 1413 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec']; 1414 } 1415 if (!empty($thisfile_audio['streams'])) { 1416 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) { 1417 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) { 1418 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate']; 1419 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels']; 1420 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; 1421 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 1422 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec']; 1423 } 1424 } 1425 } 1426 $getid3_mp3 = new getid3_mp3($this->getid3); 1427 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions(); 1428 unset($getid3_mp3); 1429 } 1430 1431 1432 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) { 1433 switch ($thisfile_audio_dataformat) { 1434 case 'ac3': 1435 // ignore bits_per_sample 1436 break; 1437 1438 default: 1439 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample']; 1440 break; 1441 } 1442 } 1443 1444 1445 if (empty($thisfile_riff_raw)) { 1446 unset($thisfile_riff['raw']); 1447 } 1448 if (empty($thisfile_riff_audio)) { 1449 unset($thisfile_riff['audio']); 1450 } 1451 if (empty($thisfile_riff_video)) { 1452 unset($thisfile_riff['video']); 1453 } 1454 1455 return true; 1456 } 1457 1458 /** 1459 * @param int $startoffset 1460 * @param int $maxoffset 1461 * 1462 * @return array|false 1463 * 1464 * @throws Exception 1465 * @throws getid3_exception 1466 */ 1467 public function ParseRIFFAMV($startoffset, $maxoffset) { 1468 // 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 1469 1470 // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation 1471 //typedef struct _amvmainheader { 1472 //FOURCC fcc; // 'amvh' 1473 //DWORD cb; 1474 //DWORD dwMicroSecPerFrame; 1475 //BYTE reserve[28]; 1476 //DWORD dwWidth; 1477 //DWORD dwHeight; 1478 //DWORD dwSpeed; 1479 //DWORD reserve0; 1480 //DWORD reserve1; 1481 //BYTE bTimeSec; 1482 //BYTE bTimeMin; 1483 //WORD wTimeHour; 1484 //} AMVMAINHEADER; 1485 1486 $info = &$this->getid3->info; 1487 $RIFFchunk = false; 1488 1489 try { 1490 1491 $this->fseek($startoffset); 1492 $maxoffset = min($maxoffset, $info['avdataend']); 1493 $AMVheader = $this->fread(284); 1494 if (substr($AMVheader, 0, 8) != 'hdrlamvh') { 1495 throw new Exception('expecting "hdrlamv" at offset '.($startoffset + 0).', found "'.substr($AMVheader, 0, 8).'"'); 1496 } 1497 if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes 1498 throw new Exception('expecting "0x38000000" at offset '.($startoffset + 8).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 8, 4)).'"'); 1499 } 1500 $RIFFchunk = array(); 1501 $RIFFchunk['amvh']['us_per_frame'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 12, 4)); 1502 $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved? 1503 $RIFFchunk['amvh']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 44, 4)); 1504 $RIFFchunk['amvh']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 48, 4)); 1505 $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 52, 4)); 1506 $RIFFchunk['amvh']['reserved0'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved? 1507 $RIFFchunk['amvh']['reserved1'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved? 1508 $RIFFchunk['amvh']['runtime_sec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 64, 1)); 1509 $RIFFchunk['amvh']['runtime_min'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 65, 1)); 1510 $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 66, 2)); 1511 1512 $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame']; 1513 $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x']; 1514 $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y']; 1515 $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) + ($RIFFchunk['amvh']['runtime_min'] * 60) + $RIFFchunk['amvh']['runtime_sec']; 1516 1517 // 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 1518 1519 if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") { 1520 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).'"'); 1521 } 1522 // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144 1523 if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") { 1524 throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset + 144).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 144, 8)).'"'); 1525 } 1526 // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180 1527 1528 if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") { 1529 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).'"'); 1530 } 1531 // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256 1532 if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") { 1533 throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset + 256).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 256, 8)).'"'); 1534 } 1535 // followed by 20 bytes of a modified WAVEFORMATEX: 1536 // typedef struct { 1537 // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code) 1538 // WORD nChannels; //(Fixme: this is always 1) 1539 // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050) 1540 // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100) 1541 // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?) 1542 // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4) 1543 // WORD cbSize; //(Fixme: this seems to be 0 in AMV files) 1544 // WORD reserved; 1545 // } WAVEFORMATEX; 1546 $RIFFchunk['strf']['wformattag'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 264, 2)); 1547 $RIFFchunk['strf']['nchannels'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 266, 2)); 1548 $RIFFchunk['strf']['nsamplespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 268, 4)); 1549 $RIFFchunk['strf']['navgbytespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 272, 4)); 1550 $RIFFchunk['strf']['nblockalign'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 276, 2)); 1551 $RIFFchunk['strf']['wbitspersample'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 278, 2)); 1552 $RIFFchunk['strf']['cbsize'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 280, 2)); 1553 $RIFFchunk['strf']['reserved'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 282, 2)); 1554 1555 1556 $info['audio']['lossless'] = false; 1557 $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec']; 1558 $info['audio']['channels'] = $RIFFchunk['strf']['nchannels']; 1559 $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample']; 1560 $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample']; 1561 $info['audio']['bitrate_mode'] = 'cbr'; 1562 1563 1564 } catch (getid3_exception $e) { 1565 if ($e->getCode() == 10) { 1566 $this->warning('RIFFAMV parser: '.$e->getMessage()); 1567 } else { 1568 throw $e; 1569 } 1570 } 1571 1572 return $RIFFchunk; 1573 } 1574 1575 /** 1576 * @param int $startoffset 1577 * @param int $maxoffset 1578 * 1579 * @return array|false 1580 * @throws getid3_exception 1581 */ 1582 public function ParseRIFF($startoffset, $maxoffset) { 1583 $info = &$this->getid3->info; 1584 1585 $RIFFchunk = array(); 1586 $FoundAllChunksWeNeed = false; 1587 $LISTchunkParent = null; 1588 $LISTchunkMaxOffset = null; 1589 $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77" 1590 1591 try { 1592 $this->fseek($startoffset); 1593 $maxoffset = min($maxoffset, $info['avdataend']); 1594 while ($this->ftell() < $maxoffset) { 1595 $chunknamesize = $this->fread(8); 1596 //$chunkname = substr($chunknamesize, 0, 4); 1597 $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 1598 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4)); 1599 //if (strlen(trim($chunkname, "\x00")) < 4) { 1600 if (strlen($chunkname) < 4) { 1601 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.'); 1602 break; 1603 } 1604 if (($chunksize == 0) && ($chunkname != 'JUNK')) { 1605 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.'); 1606 break; 1607 } 1608 if (($chunksize % 2) != 0) { 1609 // all structures are packed on word boundaries 1610 $chunksize++; 1611 } 1612 1613 switch ($chunkname) { 1614 case 'LIST': 1615 $listname = $this->fread(4); 1616 if (preg_match('#^(movi|rec )$#i', $listname)) { 1617 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4; 1618 $RIFFchunk[$listname]['size'] = $chunksize; 1619 1620 if (!$FoundAllChunksWeNeed) { 1621 $WhereWeWere = $this->ftell(); 1622 $AudioChunkHeader = $this->fread(12); 1623 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2); 1624 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2); 1625 $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4)); 1626 1627 if ($AudioChunkStreamType == 'wb') { 1628 $FirstFourBytes = substr($AudioChunkHeader, 8, 4); 1629 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) { 1630 // MP3 1631 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { 1632 $getid3_temp = new getID3(); 1633 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1634 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1635 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1636 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1637 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); 1638 if (isset($getid3_temp->info['mpeg']['audio'])) { 1639 $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio']; 1640 $info['audio'] = $getid3_temp->info['audio']; 1641 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer']; 1642 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1643 $info['audio']['channels'] = $info['mpeg']['audio']['channels']; 1644 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; 1645 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1646 //$info['bitrate'] = $info['audio']['bitrate']; 1647 } 1648 unset($getid3_temp, $getid3_mp3); 1649 } 1650 1651 } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) { 1652 // AC3 1653 $getid3_temp = new getID3(); 1654 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1655 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1656 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1657 $getid3_ac3 = new getid3_ac3($getid3_temp); 1658 $getid3_ac3->Analyze(); 1659 if (empty($getid3_temp->info['error'])) { 1660 $info['audio'] = $getid3_temp->info['audio']; 1661 $info['ac3'] = $getid3_temp->info['ac3']; 1662 if (!empty($getid3_temp->info['warning'])) { 1663 foreach ($getid3_temp->info['warning'] as $key => $value) { 1664 $this->warning($value); 1665 } 1666 } 1667 } 1668 unset($getid3_temp, $getid3_ac3); 1669 } 1670 } 1671 $FoundAllChunksWeNeed = true; 1672 $this->fseek($WhereWeWere); 1673 } 1674 $this->fseek($chunksize - 4, SEEK_CUR); 1675 1676 } else { 1677 1678 if (!isset($RIFFchunk[$listname])) { 1679 $RIFFchunk[$listname] = array(); 1680 } 1681 $LISTchunkParent = $listname; 1682 $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize; 1683 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) { 1684 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk); 1685 } 1686 1687 } 1688 break; 1689 1690 default: 1691 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) { 1692 $this->fseek($chunksize, SEEK_CUR); 1693 break; 1694 } 1695 $thisindex = 0; 1696 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) { 1697 $thisindex = count($RIFFchunk[$chunkname]); 1698 } 1699 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8; 1700 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize; 1701 switch ($chunkname) { 1702 case 'data': 1703 $info['avdataoffset'] = $this->ftell(); 1704 $info['avdataend'] = $info['avdataoffset'] + $chunksize; 1705 1706 $testData = $this->fread(36); 1707 if ($testData === '') { 1708 break; 1709 } 1710 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) { 1711 1712 // Probably is MP3 data 1713 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { 1714 $getid3_temp = new getID3(); 1715 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1716 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1717 $getid3_temp->info['avdataend'] = $info['avdataend']; 1718 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1719 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); 1720 if (empty($getid3_temp->info['error'])) { 1721 $info['audio'] = $getid3_temp->info['audio']; 1722 $info['mpeg'] = $getid3_temp->info['mpeg']; 1723 } 1724 unset($getid3_temp, $getid3_mp3); 1725 } 1726 1727 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) { 1728 1729 // This is probably AC-3 data 1730 $getid3_temp = new getID3(); 1731 if ($isRegularAC3) { 1732 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1733 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1734 $getid3_temp->info['avdataend'] = $info['avdataend']; 1735 } 1736 $getid3_ac3 = new getid3_ac3($getid3_temp); 1737 if ($isRegularAC3) { 1738 $getid3_ac3->Analyze(); 1739 } else { 1740 // Dolby Digital WAV 1741 // AC-3 content, but not encoded in same format as normal AC-3 file 1742 // For one thing, byte order is swapped 1743 $ac3_data = ''; 1744 for ($i = 0; $i < 28; $i += 2) { 1745 $ac3_data .= substr($testData, 8 + $i + 1, 1); 1746 $ac3_data .= substr($testData, 8 + $i + 0, 1); 1747 } 1748 $getid3_ac3->getid3->info['avdataoffset'] = 0; 1749 $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data); 1750 $getid3_ac3->AnalyzeString($ac3_data); 1751 } 1752 1753 if (empty($getid3_temp->info['error'])) { 1754 $info['audio'] = $getid3_temp->info['audio']; 1755 $info['ac3'] = $getid3_temp->info['ac3']; 1756 if (!empty($getid3_temp->info['warning'])) { 1757 foreach ($getid3_temp->info['warning'] as $newerror) { 1758 $this->warning('getid3_ac3() says: ['.$newerror.']'); 1759 } 1760 } 1761 } 1762 unset($getid3_temp, $getid3_ac3); 1763 1764 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) { 1765 1766 // This is probably DTS data 1767 $getid3_temp = new getID3(); 1768 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); 1769 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1770 $getid3_dts = new getid3_dts($getid3_temp); 1771 $getid3_dts->Analyze(); 1772 if (empty($getid3_temp->info['error'])) { 1773 $info['audio'] = $getid3_temp->info['audio']; 1774 $info['dts'] = $getid3_temp->info['dts']; 1775 $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing 1776 if (!empty($getid3_temp->info['warning'])) { 1777 foreach ($getid3_temp->info['warning'] as $newerror) { 1778 $this->warning('getid3_dts() says: ['.$newerror.']'); 1779 } 1780 } 1781 } 1782 1783 unset($getid3_temp, $getid3_dts); 1784 1785 } elseif (substr($testData, 0, 4) == 'wvpk') { 1786 1787 // This is WavPack data 1788 $info['wavpack']['offset'] = $info['avdataoffset']; 1789 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4)); 1790 $this->parseWavPackHeader(substr($testData, 8, 28)); 1791 1792 } else { 1793 // This is some other kind of data (quite possibly just PCM) 1794 // do nothing special, just skip it 1795 } 1796 $nextoffset = $info['avdataend']; 1797 $this->fseek($nextoffset); 1798 break; 1799 1800 case 'iXML': 1801 case 'bext': 1802 case 'cart': 1803 case 'fmt ': 1804 case 'strh': 1805 case 'strf': 1806 case 'indx': 1807 case 'MEXT': 1808 case 'DISP': 1809 case 'wamd': 1810 case 'guan': 1811 // always read data in 1812 case 'JUNK': 1813 // should be: never read data in 1814 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc) 1815 if ($chunksize < 1048576) { 1816 if ($chunksize > 0) { 1817 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1818 if ($chunkname == 'JUNK') { 1819 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) { 1820 // only keep text characters [chr(32)-chr(127)] 1821 $info['riff']['comments']['junk'][] = trim($matches[1]); 1822 } 1823 // but if nothing there, ignore 1824 // remove the key in either case 1825 unset($RIFFchunk[$chunkname][$thisindex]['data']); 1826 } 1827 } 1828 } else { 1829 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data'); 1830 $this->fseek($chunksize, SEEK_CUR); 1831 } 1832 break; 1833 1834 //case 'IDVX': 1835 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize)); 1836 // break; 1837 1838 case 'scot': 1839 // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html 1840 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1841 $RIFFchunk[$chunkname][$thisindex]['parsed']['alter'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 0, 1); 1842 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 1, 1); 1843 $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 2, 2)); 1844 $RIFFchunk[$chunkname][$thisindex]['parsed']['title'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 4, 43); // "name" in other documentation 1845 $RIFFchunk[$chunkname][$thisindex]['parsed']['copy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 47, 4); 1846 $RIFFchunk[$chunkname][$thisindex]['parsed']['padd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 51, 1); 1847 $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 52, 5); 1848 $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 57, 2)); 1849 $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 59, 2)); 1850 $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 61, 2)); 1851 $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 63, 2)); 1852 $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 65, 6); 1853 $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 71, 6); 1854 $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 77, 1); 1855 $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 78, 1); 1856 $RIFFchunk[$chunkname][$thisindex]['parsed']['digital'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 79, 1); 1857 $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 80, 2)); 1858 $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 82, 1); 1859 $RIFFchunk[$chunkname][$thisindex]['parsed']['compress'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 83, 1); 1860 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 84, 4)); 1861 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 88, 2)); 1862 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 90, 4)); 1863 $RIFFchunk[$chunkname][$thisindex]['parsed']['future1'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 94, 12); 1864 $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106, 4)); 1865 $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110, 4)); 1866 $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114, 4)); 1867 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118, 2)); 1868 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120, 2)); 1869 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 122, 3); 1870 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 125, 4); 1871 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 129, 1); 1872 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 130, 3); 1873 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 133, 4); 1874 $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 137, 1); 1875 $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 138, 21); 1876 $RIFFchunk[$chunkname][$thisindex]['parsed']['future2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108); 1877 $RIFFchunk[$chunkname][$thisindex]['parsed']['artist'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 267, 34); 1878 $RIFFchunk[$chunkname][$thisindex]['parsed']['comment'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 301, 34); // "trivia" in other documentation 1879 $RIFFchunk[$chunkname][$thisindex]['parsed']['intro'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 335, 2); 1880 $RIFFchunk[$chunkname][$thisindex]['parsed']['end'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 337, 1); 1881 $RIFFchunk[$chunkname][$thisindex]['parsed']['year'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 338, 4); 1882 $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 342, 1); 1883 $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 343, 1); 1884 $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 344, 6); 1885 $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350, 2)); 1886 $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352, 2)); 1887 $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354, 2)); 1888 $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 356, 1); 1889 $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357, 4)); 1890 $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361, 2)); 1891 $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363, 4)); 1892 $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367, 4)); 1893 $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371, 4)); 1894 $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375, 4)); 1895 $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 379, 33); 1896 1897 foreach (array('title', 'artist', 'comment') as $key) { 1898 if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) { 1899 $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]); 1900 } 1901 } 1902 if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) { 1903 $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')'); 1904 } 1905 break; 1906 1907 default: 1908 if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { 1909 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset']; 1910 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size']; 1911 unset($RIFFchunk[$chunkname][$thisindex]['offset']); 1912 unset($RIFFchunk[$chunkname][$thisindex]['size']); 1913 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) { 1914 unset($RIFFchunk[$chunkname][$thisindex]); 1915 } 1916 if (count($RIFFchunk[$chunkname]) === 0) { 1917 unset($RIFFchunk[$chunkname]); 1918 } 1919 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1920 } elseif ($chunksize < 2048) { 1921 // only read data in if smaller than 2kB 1922 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1923 } else { 1924 $this->fseek($chunksize, SEEK_CUR); 1925 } 1926 break; 1927 } 1928 break; 1929 } 1930 } 1931 1932 } catch (getid3_exception $e) { 1933 if ($e->getCode() == 10) { 1934 $this->warning('RIFF parser: '.$e->getMessage()); 1935 } else { 1936 throw $e; 1937 } 1938 } 1939 1940 return !empty($RIFFchunk) ? $RIFFchunk : false; 1941 } 1942 1943 /** 1944 * @param string $RIFFdata 1945 * 1946 * @return bool 1947 */ 1948 public function ParseRIFFdata(&$RIFFdata) { 1949 $info = &$this->getid3->info; 1950 if ($RIFFdata) { 1951 $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); 1952 $fp_temp = fopen($tempfile, 'wb'); 1953 $RIFFdataLength = strlen($RIFFdata); 1954 $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4); 1955 for ($i = 0; $i < 4; $i++) { 1956 $RIFFdata[($i + 4)] = $NewLengthString[$i]; 1957 } 1958 fwrite($fp_temp, $RIFFdata); 1959 fclose($fp_temp); 1960 1961 $getid3_temp = new getID3(); 1962 $getid3_temp->openfile($tempfile); 1963 $getid3_temp->info['filesize'] = $RIFFdataLength; 1964 $getid3_temp->info['filenamepath'] = $info['filenamepath']; 1965 $getid3_temp->info['tags'] = $info['tags']; 1966 $getid3_temp->info['warning'] = $info['warning']; 1967 $getid3_temp->info['error'] = $info['error']; 1968 $getid3_temp->info['comments'] = $info['comments']; 1969 $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array()); 1970 $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array()); 1971 $getid3_riff = new getid3_riff($getid3_temp); 1972 $getid3_riff->Analyze(); 1973 1974 $info['riff'] = $getid3_temp->info['riff']; 1975 $info['warning'] = $getid3_temp->info['warning']; 1976 $info['error'] = $getid3_temp->info['error']; 1977 $info['tags'] = $getid3_temp->info['tags']; 1978 $info['comments'] = $getid3_temp->info['comments']; 1979 unset($getid3_riff, $getid3_temp); 1980 unlink($tempfile); 1981 } 1982 return false; 1983 } 1984 1985 /** 1986 * @param array $RIFFinfoArray 1987 * @param array $CommentsTargetArray 1988 * 1989 * @return bool 1990 */ 1991 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) { 1992 $RIFFinfoKeyLookup = array( 1993 'IARL'=>'archivallocation', 1994 'IART'=>'artist', 1995 'ICDS'=>'costumedesigner', 1996 'ICMS'=>'commissionedby', 1997 'ICMT'=>'comment', 1998 'ICNT'=>'country', 1999 'ICOP'=>'copyright', 2000 'ICRD'=>'creationdate', 2001 'IDIM'=>'dimensions', 2002 'IDIT'=>'digitizationdate', 2003 'IDPI'=>'resolution', 2004 'IDST'=>'distributor', 2005 'IEDT'=>'editor', 2006 'IENG'=>'engineers', 2007 'IFRM'=>'accountofparts', 2008 'IGNR'=>'genre', 2009 'IKEY'=>'keywords', 2010 'ILGT'=>'lightness', 2011 'ILNG'=>'language', 2012 'IMED'=>'orignalmedium', 2013 'IMUS'=>'composer', 2014 'INAM'=>'title', 2015 'IPDS'=>'productiondesigner', 2016 'IPLT'=>'palette', 2017 'IPRD'=>'product', 2018 'IPRO'=>'producer', 2019 'IPRT'=>'part', 2020 'IRTD'=>'rating', 2021 'ISBJ'=>'subject', 2022 'ISFT'=>'software', 2023 'ISGN'=>'secondarygenre', 2024 'ISHP'=>'sharpness', 2025 'ISRC'=>'sourcesupplier', 2026 'ISRF'=>'digitizationsource', 2027 'ISTD'=>'productionstudio', 2028 'ISTR'=>'starring', 2029 'ITCH'=>'encoded_by', 2030 'IWEB'=>'url', 2031 'IWRI'=>'writer', 2032 '____'=>'comment', 2033 ); 2034 foreach ($RIFFinfoKeyLookup as $key => $value) { 2035 if (isset($RIFFinfoArray[$key])) { 2036 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) { 2037 if (!empty($commentdata['data']) && trim($commentdata['data']) != '') { 2038 if (isset($CommentsTargetArray[$value])) { 2039 $CommentsTargetArray[$value][] = trim($commentdata['data']); 2040 } else { 2041 $CommentsTargetArray[$value] = array(trim($commentdata['data'])); 2042 } 2043 } 2044 } 2045 } 2046 } 2047 return true; 2048 } 2049 2050 /** 2051 * @param string $WaveFormatExData 2052 * 2053 * @return array 2054 */ 2055 public static function parseWAVEFORMATex($WaveFormatExData) { 2056 // shortcut 2057 $WaveFormatEx = array(); 2058 $WaveFormatEx['raw'] = array(); 2059 $WaveFormatEx_raw = &$WaveFormatEx['raw']; 2060 2061 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2); 2062 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2); 2063 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4); 2064 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4); 2065 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2); 2066 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2); 2067 if (strlen($WaveFormatExData) > 16) { 2068 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2); 2069 } 2070 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw); 2071 2072 $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']); 2073 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels']; 2074 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec']; 2075 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8; 2076 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample']; 2077 2078 return $WaveFormatEx; 2079 } 2080 2081 /** 2082 * @param string $WavPackChunkData 2083 * 2084 * @return bool 2085 */ 2086 public function parseWavPackHeader($WavPackChunkData) { 2087 // typedef struct { 2088 // char ckID [4]; 2089 // long ckSize; 2090 // short version; 2091 // short bits; // added for version 2.00 2092 // short flags, shift; // added for version 3.00 2093 // long total_samples, crc, crc2; 2094 // char extension [4], extra_bc, extras [3]; 2095 // } WavpackHeader; 2096 2097 // shortcut 2098 $info = &$this->getid3->info; 2099 $info['wavpack'] = array(); 2100 $thisfile_wavpack = &$info['wavpack']; 2101 2102 $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2)); 2103 if ($thisfile_wavpack['version'] >= 2) { 2104 $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2)); 2105 } 2106 if ($thisfile_wavpack['version'] >= 3) { 2107 $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2)); 2108 $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2)); 2109 $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4)); 2110 $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4)); 2111 $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4)); 2112 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4); 2113 $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1)); 2114 for ($i = 0; $i <= 2; $i++) { 2115 $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1)); 2116 } 2117 2118 // shortcut 2119 $thisfile_wavpack['flags'] = array(); 2120 $thisfile_wavpack_flags = &$thisfile_wavpack['flags']; 2121 2122 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001); 2123 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002); 2124 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004); 2125 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008); 2126 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010); 2127 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020); 2128 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040); 2129 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080); 2130 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100); 2131 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200); 2132 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400); 2133 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800); 2134 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000); 2135 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000); 2136 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000); 2137 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000); 2138 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000); 2139 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000); 2140 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000); 2141 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000); 2142 } 2143 2144 return true; 2145 } 2146 2147 /** 2148 * @param string $BITMAPINFOHEADER 2149 * @param bool $littleEndian 2150 * 2151 * @return array 2152 */ 2153 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { 2154 2155 $parsed = array(); 2156 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure 2157 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels 2158 $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 2159 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1 2160 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels 2161 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures) 2162 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device 2163 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device 2164 $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 2165 $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 2166 $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed); 2167 2168 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier 2169 2170 return $parsed; 2171 } 2172 2173 /** 2174 * @param string $DIVXTAG 2175 * @param bool $raw 2176 * 2177 * @return array 2178 */ 2179 public static function ParseDIVXTAG($DIVXTAG, $raw=false) { 2180 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/ 2181 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip 2182 // 'Byte Layout: '1111111111111111 2183 // '32 for Movie - 1 '1111111111111111 2184 // '28 for Author - 6 '6666666666666666 2185 // '4 for year - 2 '6666666666662222 2186 // '3 for genre - 3 '7777777777777777 2187 // '48 for Comments - 7 '7777777777777777 2188 // '1 for Rating - 4 '7777777777777777 2189 // '5 for Future Additions - 0 '333400000DIVXTAG 2190 // '128 bytes total 2191 2192 static $DIVXTAGgenre = array( 2193 0 => 'Action', 2194 1 => 'Action/Adventure', 2195 2 => 'Adventure', 2196 3 => 'Adult', 2197 4 => 'Anime', 2198 5 => 'Cartoon', 2199 6 => 'Claymation', 2200 7 => 'Comedy', 2201 8 => 'Commercial', 2202 9 => 'Documentary', 2203 10 => 'Drama', 2204 11 => 'Home Video', 2205 12 => 'Horror', 2206 13 => 'Infomercial', 2207 14 => 'Interactive', 2208 15 => 'Mystery', 2209 16 => 'Music Video', 2210 17 => 'Other', 2211 18 => 'Religion', 2212 19 => 'Sci Fi', 2213 20 => 'Thriller', 2214 21 => 'Western', 2215 ), 2216 $DIVXTAGrating = array( 2217 0 => 'Unrated', 2218 1 => 'G', 2219 2 => 'PG', 2220 3 => 'PG-13', 2221 4 => 'R', 2222 5 => 'NC-17', 2223 ); 2224 2225 $parsed = array(); 2226 $parsed['title'] = trim(substr($DIVXTAG, 0, 32)); 2227 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28)); 2228 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4))); 2229 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48)); 2230 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3))); 2231 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1)); 2232 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null 2233 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG" 2234 2235 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']); 2236 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']); 2237 2238 if (!$raw) { 2239 unset($parsed['genre_id'], $parsed['rating_id']); 2240 foreach ($parsed as $key => $value) { 2241 if (empty($value)) { 2242 unset($parsed[$key]); 2243 } 2244 } 2245 } 2246 2247 foreach ($parsed as $tag => $value) { 2248 $parsed[$tag] = array($value); 2249 } 2250 2251 return $parsed; 2252 } 2253 2254 /** 2255 * @param string $tagshortname 2256 * 2257 * @return string 2258 */ 2259 public static function waveSNDMtagLookup($tagshortname) { 2260 $begin = __LINE__; 2261 2262 /** This is not a comment! 2263 2264 ©kwd keywords 2265 ©BPM bpm 2266 ©trt tracktitle 2267 ©des description 2268 ©gen category 2269 ©fin featuredinstrument 2270 ©LID longid 2271 ©bex bwdescription 2272 ©pub publisher 2273 ©cdt cdtitle 2274 ©alb library 2275 ©com composer 2276 2277 */ 2278 2279 return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm'); 2280 } 2281 2282 /** 2283 * @param int $wFormatTag 2284 * 2285 * @return string 2286 */ 2287 public static function wFormatTagLookup($wFormatTag) { 2288 2289 $begin = __LINE__; 2290 2291 /** This is not a comment! 2292 2293 0x0000 Microsoft Unknown Wave Format 2294 0x0001 Pulse Code Modulation (PCM) 2295 0x0002 Microsoft ADPCM 2296 0x0003 IEEE Float 2297 0x0004 Compaq Computer VSELP 2298 0x0005 IBM CVSD 2299 0x0006 Microsoft A-Law 2300 0x0007 Microsoft mu-Law 2301 0x0008 Microsoft DTS 2302 0x0010 OKI ADPCM 2303 0x0011 Intel DVI/IMA ADPCM 2304 0x0012 Videologic MediaSpace ADPCM 2305 0x0013 Sierra Semiconductor ADPCM 2306 0x0014 Antex Electronics G.723 ADPCM 2307 0x0015 DSP Solutions DigiSTD 2308 0x0016 DSP Solutions DigiFIX 2309 0x0017 Dialogic OKI ADPCM 2310 0x0018 MediaVision ADPCM 2311 0x0019 Hewlett-Packard CU 2312 0x0020 Yamaha ADPCM 2313 0x0021 Speech Compression Sonarc 2314 0x0022 DSP Group TrueSpeech 2315 0x0023 Echo Speech EchoSC1 2316 0x0024 Audiofile AF36 2317 0x0025 Audio Processing Technology APTX 2318 0x0026 AudioFile AF10 2319 0x0027 Prosody 1612 2320 0x0028 LRC 2321 0x0030 Dolby AC2 2322 0x0031 Microsoft GSM 6.10 2323 0x0032 MSNAudio 2324 0x0033 Antex Electronics ADPCME 2325 0x0034 Control Resources VQLPC 2326 0x0035 DSP Solutions DigiREAL 2327 0x0036 DSP Solutions DigiADPCM 2328 0x0037 Control Resources CR10 2329 0x0038 Natural MicroSystems VBXADPCM 2330 0x0039 Crystal Semiconductor IMA ADPCM 2331 0x003A EchoSC3 2332 0x003B Rockwell ADPCM 2333 0x003C Rockwell Digit LK 2334 0x003D Xebec 2335 0x0040 Antex Electronics G.721 ADPCM 2336 0x0041 G.728 CELP 2337 0x0042 MSG723 2338 0x0050 MPEG Layer-2 or Layer-1 2339 0x0052 RT24 2340 0x0053 PAC 2341 0x0055 MPEG Layer-3 2342 0x0059 Lucent G.723 2343 0x0060 Cirrus 2344 0x0061 ESPCM 2345 0x0062 Voxware 2346 0x0063 Canopus Atrac 2347 0x0064 G.726 ADPCM 2348 0x0065 G.722 ADPCM 2349 0x0066 DSAT 2350 0x0067 DSAT Display 2351 0x0069 Voxware Byte Aligned 2352 0x0070 Voxware AC8 2353 0x0071 Voxware AC10 2354 0x0072 Voxware AC16 2355 0x0073 Voxware AC20 2356 0x0074 Voxware MetaVoice 2357 0x0075 Voxware MetaSound 2358 0x0076 Voxware RT29HW 2359 0x0077 Voxware VR12 2360 0x0078 Voxware VR18 2361 0x0079 Voxware TQ40 2362 0x0080 Softsound 2363 0x0081 Voxware TQ60 2364 0x0082 MSRT24 2365 0x0083 G.729A 2366 0x0084 MVI MV12 2367 0x0085 DF G.726 2368 0x0086 DF GSM610 2369 0x0088 ISIAudio 2370 0x0089 Onlive 2371 0x0091 SBC24 2372 0x0092 Dolby AC3 SPDIF 2373 0x0093 MediaSonic G.723 2374 0x0094 Aculab PLC Prosody 8kbps 2375 0x0097 ZyXEL ADPCM 2376 0x0098 Philips LPCBB 2377 0x0099 Packed 2378 0x00FF AAC 2379 0x0100 Rhetorex ADPCM 2380 0x0101 IBM mu-law 2381 0x0102 IBM A-law 2382 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM) 2383 0x0111 Vivo G.723 2384 0x0112 Vivo Siren 2385 0x0123 Digital G.723 2386 0x0125 Sanyo LD ADPCM 2387 0x0130 Sipro Lab Telecom ACELP NET 2388 0x0131 Sipro Lab Telecom ACELP 4800 2389 0x0132 Sipro Lab Telecom ACELP 8V3 2390 0x0133 Sipro Lab Telecom G.729 2391 0x0134 Sipro Lab Telecom G.729A 2392 0x0135 Sipro Lab Telecom Kelvin 2393 0x0140 Windows Media Video V8 2394 0x0150 Qualcomm PureVoice 2395 0x0151 Qualcomm HalfRate 2396 0x0155 Ring Zero Systems TUB GSM 2397 0x0160 Microsoft Audio 1 2398 0x0161 Windows Media Audio V7 / V8 / V9 2399 0x0162 Windows Media Audio Professional V9 2400 0x0163 Windows Media Audio Lossless V9 2401 0x0200 Creative Labs ADPCM 2402 0x0202 Creative Labs Fastspeech8 2403 0x0203 Creative Labs Fastspeech10 2404 0x0210 UHER Informatic GmbH ADPCM 2405 0x0220 Quarterdeck 2406 0x0230 I-link Worldwide VC 2407 0x0240 Aureal RAW Sport 2408 0x0250 Interactive Products HSX 2409 0x0251 Interactive Products RPELP 2410 0x0260 Consistent Software CS2 2411 0x0270 Sony SCX 2412 0x0300 Fujitsu FM Towns Snd 2413 0x0400 BTV Digital 2414 0x0401 Intel Music Coder 2415 0x0450 QDesign Music 2416 0x0680 VME VMPCM 2417 0x0681 AT&T Labs TPC 2418 0x08AE ClearJump LiteWave 2419 0x1000 Olivetti GSM 2420 0x1001 Olivetti ADPCM 2421 0x1002 Olivetti CELP 2422 0x1003 Olivetti SBC 2423 0x1004 Olivetti OPR 2424 0x1100 Lernout & Hauspie Codec (0x1100) 2425 0x1101 Lernout & Hauspie CELP Codec (0x1101) 2426 0x1102 Lernout & Hauspie SBC Codec (0x1102) 2427 0x1103 Lernout & Hauspie SBC Codec (0x1103) 2428 0x1104 Lernout & Hauspie SBC Codec (0x1104) 2429 0x1400 Norris 2430 0x1401 AT&T ISIAudio 2431 0x1500 Soundspace Music Compression 2432 0x181C VoxWare RT24 Speech 2433 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com) 2434 0x2000 Dolby AC3 2435 0x2001 Dolby DTS 2436 0x2002 WAVE_FORMAT_14_4 2437 0x2003 WAVE_FORMAT_28_8 2438 0x2004 WAVE_FORMAT_COOK 2439 0x2005 WAVE_FORMAT_DNET 2440 0x674F Ogg Vorbis 1 2441 0x6750 Ogg Vorbis 2 2442 0x6751 Ogg Vorbis 3 2443 0x676F Ogg Vorbis 1+ 2444 0x6770 Ogg Vorbis 2+ 2445 0x6771 Ogg Vorbis 3+ 2446 0x7A21 GSM-AMR (CBR, no SID) 2447 0x7A22 GSM-AMR (VBR, including SID) 2448 0xFFFE WAVE_FORMAT_EXTENSIBLE 2449 0xFFFF WAVE_FORMAT_DEVELOPMENT 2450 2451 */ 2452 2453 return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag'); 2454 } 2455 2456 /** 2457 * @param string $fourcc 2458 * 2459 * @return string 2460 */ 2461 public static function fourccLookup($fourcc) { 2462 2463 $begin = __LINE__; 2464 2465 /** This is not a comment! 2466 2467 swot http://developer.apple.com/qa/snd/snd07.html 2468 ____ No Codec (____) 2469 _BIT BI_BITFIELDS (Raw RGB) 2470 _JPG JPEG compressed 2471 _PNG PNG compressed W3C/ISO/IEC (RFC-2083) 2472 _RAW Full Frames (Uncompressed) 2473 _RGB Raw RGB Bitmap 2474 _RL4 RLE 4bpp RGB 2475 _RL8 RLE 8bpp RGB 2476 3IV1 3ivx MPEG-4 v1 2477 3IV2 3ivx MPEG-4 v2 2478 3IVX 3ivx MPEG-4 2479 AASC Autodesk Animator 2480 ABYR Kensington ?ABYR? 2481 AEMI Array Microsystems VideoONE MPEG1-I Capture 2482 AFLC Autodesk Animator FLC 2483 AFLI Autodesk Animator FLI 2484 AMPG Array Microsystems VideoONE MPEG 2485 ANIM Intel RDX (ANIM) 2486 AP41 AngelPotion Definitive 2487 ASV1 Asus Video v1 2488 ASV2 Asus Video v2 2489 ASVX Asus Video 2.0 (audio) 2490 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2 2491 AURA AuraVision Aura 1 Codec - YUV 4:1:1 2492 AVDJ Independent JPEG Group\'s codec (AVDJ) 2493 AVRN Independent JPEG Group\'s codec (AVRN) 2494 AYUV 4:4:4 YUV (AYUV) 2495 AZPR Quicktime Apple Video (AZPR) 2496 BGR Raw RGB32 2497 BLZ0 Blizzard DivX MPEG-4 2498 BTVC Conexant Composite Video 2499 BINK RAD Game Tools Bink Video 2500 BT20 Conexant Prosumer Video 2501 BTCV Conexant Composite Video Codec 2502 BW10 Data Translation Broadway MPEG Capture 2503 CC12 Intel YUV12 2504 CDVC Canopus DV 2505 CFCC Digital Processing Systems DPS Perception 2506 CGDI Microsoft Office 97 Camcorder Video 2507 CHAM Winnov Caviara Champagne 2508 CJPG Creative WebCam JPEG 2509 CLJR Cirrus Logic YUV 4:1:1 2510 CMYK Common Data Format in Printing (Colorgraph) 2511 CPLA Weitek 4:2:0 YUV Planar 2512 CRAM Microsoft Video 1 (CRAM) 2513 cvid Radius Cinepak 2514 CVID Radius Cinepak 2515 CWLT Microsoft Color WLT DIB 2516 CYUV Creative Labs YUV 2517 CYUY ATI YUV 2518 D261 H.261 2519 D263 H.263 2520 DIB Device Independent Bitmap 2521 DIV1 FFmpeg OpenDivX 2522 DIV2 Microsoft MPEG-4 v1/v2 2523 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion 2524 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion 2525 DIV5 DivX MPEG-4 v5.x 2526 DIV6 DivX ;-) (MS MPEG-4 v3.x) 2527 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo) 2528 divx DivX MPEG-4 2529 DMB1 Matrox Rainbow Runner hardware MJPEG 2530 DMB2 Paradigm MJPEG 2531 DSVD ?DSVD? 2532 DUCK Duck TrueMotion 1.0 2533 DPS0 DPS/Leitch Reality Motion JPEG 2534 DPSC DPS/Leitch PAR Motion JPEG 2535 DV25 Matrox DVCPRO codec 2536 DV50 Matrox DVCPRO50 codec 2537 DVC IEC 61834 and SMPTE 314M (DVC/DV Video) 2538 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video) 2539 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps 2540 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com) 2541 DVSL IEC Standard DV compressed in SD (SDL) 2542 DVAN ?DVAN? 2543 DVE2 InSoft DVE-2 Videoconferencing 2544 dvsd IEC 61834 and SMPTE 314M DVC/DV Video 2545 DVSD IEC 61834 and SMPTE 314M DVC/DV Video 2546 DVX1 Lucent DVX1000SP Video Decoder 2547 DVX2 Lucent DVX2000S Video Decoder 2548 DVX3 Lucent DVX3000S Video Decoder 2549 DX50 DivX v5 2550 DXT1 Microsoft DirectX Compressed Texture (DXT1) 2551 DXT2 Microsoft DirectX Compressed Texture (DXT2) 2552 DXT3 Microsoft DirectX Compressed Texture (DXT3) 2553 DXT4 Microsoft DirectX Compressed Texture (DXT4) 2554 DXT5 Microsoft DirectX Compressed Texture (DXT5) 2555 DXTC Microsoft DirectX Compressed Texture (DXTC) 2556 DXTn Microsoft DirectX Compressed Texture (DXTn) 2557 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com) 2558 EKQ0 Elsa ?EKQ0? 2559 ELK0 Elsa ?ELK0? 2560 ESCP Eidos Escape 2561 ETV1 eTreppid Video ETV1 2562 ETV2 eTreppid Video ETV2 2563 ETVC eTreppid Video ETVC 2564 FLIC Autodesk FLI/FLC Animation 2565 FLV1 Sorenson Spark 2566 FLV4 On2 TrueMotion VP6 2567 FRWT Darim Vision Forward Motion JPEG (www.darvision.com) 2568 FRWU Darim Vision Forward Uncompressed (www.darvision.com) 2569 FLJP D-Vision Field Encoded Motion JPEG 2570 FPS1 FRAPS v1 2571 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel 2572 FRWD SoftLab-Nsk Forward Motion JPEG 2573 FVF1 Iterated Systems Fractal Video Frame 2574 GLZW Motion LZW (gabest@freemail.hu) 2575 GPEG Motion JPEG (gabest@freemail.hu) 2576 GWLT Microsoft Greyscale WLT DIB 2577 H260 Intel ITU H.260 Videoconferencing 2578 H261 Intel ITU H.261 Videoconferencing 2579 H262 Intel ITU H.262 Videoconferencing 2580 H263 Intel ITU H.263 Videoconferencing 2581 H264 Intel ITU H.264 Videoconferencing 2582 H265 Intel ITU H.265 Videoconferencing 2583 H266 Intel ITU H.266 Videoconferencing 2584 H267 Intel ITU H.267 Videoconferencing 2585 H268 Intel ITU H.268 Videoconferencing 2586 H269 Intel ITU H.269 Videoconferencing 2587 HFYU Huffman Lossless Codec 2588 HMCR Rendition Motion Compensation Format (HMCR) 2589 HMRR Rendition Motion Compensation Format (HMRR) 2590 I263 FFmpeg I263 decoder 2591 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane") 2592 IUYV Interlaced version of UYVY (www.leadtools.com) 2593 IY41 Interlaced version of Y41P (www.leadtools.com) 2594 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2595 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2596 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes) 2597 i263 Intel ITU H.263 Videoconferencing (i263) 2598 I420 Intel Indeo 4 2599 IAN Intel Indeo 4 (RDX) 2600 ICLB InSoft CellB Videoconferencing 2601 IGOR Power DVD 2602 IJPG Intergraph JPEG 2603 ILVC Intel Layered Video 2604 ILVR ITU-T H.263+ 2605 IPDV I-O Data Device Giga AVI DV Codec 2606 IR21 Intel Indeo 2.1 2607 IRAW Intel YUV Uncompressed 2608 IV30 Intel Indeo 3.0 2609 IV31 Intel Indeo 3.1 2610 IV32 Ligos Indeo 3.2 2611 IV33 Ligos Indeo 3.3 2612 IV34 Ligos Indeo 3.4 2613 IV35 Ligos Indeo 3.5 2614 IV36 Ligos Indeo 3.6 2615 IV37 Ligos Indeo 3.7 2616 IV38 Ligos Indeo 3.8 2617 IV39 Ligos Indeo 3.9 2618 IV40 Ligos Indeo Interactive 4.0 2619 IV41 Ligos Indeo Interactive 4.1 2620 IV42 Ligos Indeo Interactive 4.2 2621 IV43 Ligos Indeo Interactive 4.3 2622 IV44 Ligos Indeo Interactive 4.4 2623 IV45 Ligos Indeo Interactive 4.5 2624 IV46 Ligos Indeo Interactive 4.6 2625 IV47 Ligos Indeo Interactive 4.7 2626 IV48 Ligos Indeo Interactive 4.8 2627 IV49 Ligos Indeo Interactive 4.9 2628 IV50 Ligos Indeo Interactive 5.0 2629 JBYR Kensington ?JBYR? 2630 JPEG Still Image JPEG DIB 2631 JPGL Pegasus Lossless Motion JPEG 2632 KMVC Team17 Software Karl Morton\'s Video Codec 2633 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com) 2634 LEAD LEAD Video Codec 2635 Ljpg LEAD MJPEG Codec 2636 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de) 2637 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com) 2638 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com) 2639 MMES Matrox MPEG-2 I-frame 2640 MP2v Microsoft S-Mpeg 4 version 1 (MP2v) 2641 MP42 Microsoft S-Mpeg 4 version 2 (MP42) 2642 MP43 Microsoft S-Mpeg 4 version 3 (MP43) 2643 MP4S Microsoft S-Mpeg 4 version 3 (MP4S) 2644 MP4V FFmpeg MPEG-4 2645 MPG1 FFmpeg MPEG 1/2 2646 MPG2 FFmpeg MPEG 1/2 2647 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3) 2648 MPG4 Microsoft MPEG-4 2649 MPGI Sigma Designs MPEG 2650 MPNG PNG images decoder 2651 MSS1 Microsoft Windows Screen Video 2652 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2653 M261 Microsoft H.261 2654 M263 Microsoft H.263 2655 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2) 2656 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2) 2657 MC12 ATI Motion Compensation Format (MC12) 2658 MCAM ATI Motion Compensation Format (MCAM) 2659 MJ2C Morgan Multimedia Motion JPEG2000 2660 mJPG IBM Motion JPEG w/ Huffman Tables 2661 MJPG Microsoft Motion JPEG DIB 2662 MP42 Microsoft MPEG-4 (low-motion) 2663 MP43 Microsoft MPEG-4 (fast-motion) 2664 MP4S Microsoft MPEG-4 (MP4S) 2665 mp4s Microsoft MPEG-4 (mp4s) 2666 MPEG Chromatic Research MPEG-1 Video I-Frame 2667 MPG4 Microsoft MPEG-4 Video High Speed Compressor 2668 MPGI Sigma Designs MPEG 2669 MRCA FAST Multimedia Martin Regen Codec 2670 MRLE Microsoft Run Length Encoding 2671 MSVC Microsoft Video 1 2672 MTX1 Matrox ?MTX1? 2673 MTX2 Matrox ?MTX2? 2674 MTX3 Matrox ?MTX3? 2675 MTX4 Matrox ?MTX4? 2676 MTX5 Matrox ?MTX5? 2677 MTX6 Matrox ?MTX6? 2678 MTX7 Matrox ?MTX7? 2679 MTX8 Matrox ?MTX8? 2680 MTX9 Matrox ?MTX9? 2681 MV12 Motion Pixels Codec (old) 2682 MWV1 Aware Motion Wavelets 2683 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm) 2684 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com) 2685 NUV1 NuppelVideo 2686 NTN1 Nogatech Video Compression 1 2687 NVS0 nVidia GeForce Texture (NVS0) 2688 NVS1 nVidia GeForce Texture (NVS1) 2689 NVS2 nVidia GeForce Texture (NVS2) 2690 NVS3 nVidia GeForce Texture (NVS3) 2691 NVS4 nVidia GeForce Texture (NVS4) 2692 NVS5 nVidia GeForce Texture (NVS5) 2693 NVT0 nVidia GeForce Texture (NVT0) 2694 NVT1 nVidia GeForce Texture (NVT1) 2695 NVT2 nVidia GeForce Texture (NVT2) 2696 NVT3 nVidia GeForce Texture (NVT3) 2697 NVT4 nVidia GeForce Texture (NVT4) 2698 NVT5 nVidia GeForce Texture (NVT5) 2699 PIXL MiroXL, Pinnacle PCTV 2700 PDVC I-O Data Device Digital Video Capture DV codec 2701 PGVV Radius Video Vision 2702 PHMO IBM Photomotion 2703 PIM1 MPEG Realtime (Pinnacle Cards) 2704 PIM2 Pegasus Imaging ?PIM2? 2705 PIMJ Pegasus Imaging Lossless JPEG 2706 PVEZ Horizons Technology PowerEZ 2707 PVMM PacketVideo Corporation MPEG-4 2708 PVW2 Pegasus Imaging Wavelet Compression 2709 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de) 2710 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de) 2711 QPEG Q-Team QPEG 1.0 2712 qpeq Q-Team QPEG 1.1 2713 RGB Raw BGR32 2714 RGBA Raw RGB w/ Alpha 2715 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com) 2716 ROQV Id RoQ File Video Decoder 2717 RPZA Quicktime Apple Video (RPZA) 2718 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/) 2719 RV10 RealVideo 1.0 (aka RealVideo 5.0) 2720 RV13 RealVideo 1.0 (RV13) 2721 RV20 RealVideo G2 2722 RV30 RealVideo 8 2723 RV40 RealVideo 9 2724 RGBT Raw RGB w/ Transparency 2725 RLE Microsoft Run Length Encoder 2726 RLE4 Run Length Encoded (4bpp, 16-color) 2727 RLE8 Run Length Encoded (8bpp, 256-color) 2728 RT21 Intel Indeo RealTime Video 2.1 2729 rv20 RealVideo G2 2730 rv30 RealVideo 8 2731 RVX Intel RDX (RVX ) 2732 SMC Apple Graphics (SMC ) 2733 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2 2734 SPIG Radius Spigot 2735 SVQ3 Sorenson Video 3 (Apple Quicktime 5) 2736 s422 Tekram VideoCap C210 YUV 4:2:2 2737 SDCC Sun Communication Digital Camera Codec 2738 SFMC CrystalNet Surface Fitting Method 2739 SMSC Radius SMSC 2740 SMSD Radius SMSD 2741 smsv WorldConnect Wavelet Video 2742 SPIG Radius Spigot 2743 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net) 2744 SQZ2 Microsoft VXTreme Video Codec V2 2745 STVA ST Microelectronics CMOS Imager Data (Bayer) 2746 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer) 2747 STVC ST Microelectronics CMOS Imager Data (Bunched) 2748 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format) 2749 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data) 2750 SV10 Sorenson Video R1 2751 SVQ1 Sorenson Video 2752 T420 Toshiba YUV 4:2:0 2753 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com) 2754 TVJP Pinnacle/Truevision Targa 2000 board (TVJP) 2755 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ) 2756 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com) 2757 TY2C Trident Decompression Driver 2758 TLMS TeraLogic Motion Intraframe Codec (TLMS) 2759 TLST TeraLogic Motion Intraframe Codec (TLST) 2760 TM20 Duck TrueMotion 2.0 2761 TM2X Duck TrueMotion 2X 2762 TMIC TeraLogic Motion Intraframe Codec (TMIC) 2763 TMOT Horizons Technology TrueMotion S 2764 tmot Horizons TrueMotion Video Compression 2765 TR20 Duck TrueMotion RealTime 2.0 2766 TSCC TechSmith Screen Capture Codec 2767 TV10 Tecomac Low-Bit Rate Codec 2768 TY2N Trident ?TY2N? 2769 U263 UB Video H.263/H.263+/H.263++ Decoder 2770 UMP4 UB Video MPEG 4 (www.ubvideo.com) 2771 UYNV Nvidia UYVY packed 4:2:2 2772 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision 2773 UCOD eMajix.com ClearVideo 2774 ULTI IBM Ultimotion 2775 UYVY UYVY packed 4:2:2 2776 V261 Lucent VX2000S 2777 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/) 2778 VIV1 FFmpeg H263+ decoder 2779 VIV2 Vivo H.263 2780 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf) 2781 VTLP Alaris VideoGramPiX 2782 VYU9 ATI YUV (VYU9) 2783 VYUY ATI YUV (VYUY) 2784 V261 Lucent VX2000S 2785 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format 2786 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format 2787 VCR1 ATI Video Codec 1 2788 VCR2 ATI Video Codec 2 2789 VCR3 ATI VCR 3.0 2790 VCR4 ATI VCR 4.0 2791 VCR5 ATI VCR 5.0 2792 VCR6 ATI VCR 6.0 2793 VCR7 ATI VCR 7.0 2794 VCR8 ATI VCR 8.0 2795 VCR9 ATI VCR 9.0 2796 VDCT Vitec Multimedia Video Maker Pro DIB 2797 VDOM VDOnet VDOWave 2798 VDOW VDOnet VDOLive (H.263) 2799 VDTZ Darim Vison VideoTizer YUV 2800 VGPX Alaris VideoGramPiX 2801 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422 2802 VIVO Vivo H.263 v2.00 2803 vivo Vivo H.263 2804 VIXL Miro/Pinnacle Video XL 2805 VLV1 VideoLogic/PURE Digital Videologic Capture 2806 VP30 On2 VP3.0 2807 VP31 On2 VP3.1 2808 VP6F On2 TrueMotion VP6 2809 VX1K Lucent VX1000S Video Codec 2810 VX2K Lucent VX2000S Video Codec 2811 VXSP Lucent VX1000SP Video Codec 2812 WBVC Winbond W9960 2813 WHAM Microsoft Video 1 (WHAM) 2814 WINX Winnov Software Compression 2815 WJPG AverMedia Winbond JPEG 2816 WMV1 Windows Media Video V7 2817 WMV2 Windows Media Video V8 2818 WMV3 Windows Media Video V9 2819 WNV1 Winnov Hardware Compression 2820 XYZP Extended PAL format XYZ palette (www.riff.org) 2821 x263 Xirlink H.263 2822 XLV0 NetXL Video Decoder 2823 XMPG Xing MPEG (I-Frame only) 2824 XVID XviD MPEG-4 (www.xvid.org) 2825 XXAN ?XXAN? 2826 YU92 Intel YUV (YU92) 2827 YUNV Nvidia Uncompressed YUV 4:2:2 2828 YUVP Extended PAL format YUV palette (www.riff.org) 2829 Y211 YUV 2:1:1 Packed 2830 Y411 YUV 4:1:1 Packed 2831 Y41B Weitek YUV 4:1:1 Planar 2832 Y41P Brooktree PC1 YUV 4:1:1 Packed 2833 Y41T Brooktree PC1 YUV 4:1:1 with transparency 2834 Y42B Weitek YUV 4:2:2 Planar 2835 Y42T Brooktree UYUV 4:2:2 with transparency 2836 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera 2837 Y800 Simple, single Y plane for monochrome images 2838 Y8 Grayscale video 2839 YC12 Intel YUV 12 codec 2840 YUV8 Winnov Caviar YUV8 2841 YUV9 Intel YUV9 2842 YUY2 Uncompressed YUV 4:2:2 2843 YUYV Canopus YUV 2844 YV12 YVU12 Planar 2845 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes) 2846 YVYU YVYU 4:2:2 Packed 2847 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2848 ZPEG Metheus Video Zipper 2849 2850 */ 2851 2852 return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc'); 2853 } 2854 2855 /** 2856 * @param string $byteword 2857 * @param bool $signed 2858 * 2859 * @return int|float|false 2860 */ 2861 private function EitherEndian2Int($byteword, $signed=false) { 2862 if ($this->container == 'riff') { 2863 return getid3_lib::LittleEndian2Int($byteword, $signed); 2864 } 2865 return getid3_lib::BigEndian2Int($byteword, false, $signed); 2866 } 2867 2868 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Dec 21 08:20:01 2024 | Cross-referenced by PHPXref |