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