File indexing completed on 2024-12-22 05:33:12
0001 <?php 0002 ///////////////////////////////////////////////////////////////// 0003 /// getID3() by James Heinrich <info@getid3.org> // 0004 // available at http://getid3.sourceforge.net // 0005 // or http://www.getid3.org // 0006 // also https://github.com/JamesHeinrich/getID3 // 0007 ///////////////////////////////////////////////////////////////// 0008 // See readme.txt for more details // 0009 ///////////////////////////////////////////////////////////////// 0010 // // 0011 // module.audio-video.riff.php // 0012 // module for analyzing RIFF files // 0013 // multiple formats supported by this module: // 0014 // Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX // 0015 // dependencies: module.audio.mp3.php // 0016 // module.audio.ac3.php // 0017 // module.audio.dts.php // 0018 // /// 0019 ///////////////////////////////////////////////////////////////// 0020 0021 /** 0022 * @todo Parse AC-3/DTS audio inside WAVE correctly 0023 * @todo Rewrite RIFF parser totally 0024 */ 0025 0026 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true); 0027 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true); 0028 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); 0029 0030 class getid3_riff extends getid3_handler { 0031 0032 protected $container = 'riff'; // default 0033 0034 public function Analyze() { 0035 $info = &$this->getid3->info; 0036 0037 // initialize these values to an empty array, otherwise they default to NULL 0038 // and you can't append array values to a NULL value 0039 $info['riff'] = array('raw'=>array()); 0040 0041 // Shortcuts 0042 $thisfile_riff = &$info['riff']; 0043 $thisfile_riff_raw = &$thisfile_riff['raw']; 0044 $thisfile_audio = &$info['audio']; 0045 $thisfile_video = &$info['video']; 0046 $thisfile_audio_dataformat = &$thisfile_audio['dataformat']; 0047 $thisfile_riff_audio = &$thisfile_riff['audio']; 0048 $thisfile_riff_video = &$thisfile_riff['video']; 0049 0050 $Original['avdataoffset'] = $info['avdataoffset']; 0051 $Original['avdataend'] = $info['avdataend']; 0052 0053 $this->fseek($info['avdataoffset']); 0054 $RIFFheader = $this->fread(12); 0055 $offset = $this->ftell(); 0056 $RIFFtype = substr($RIFFheader, 0, 4); 0057 $RIFFsize = substr($RIFFheader, 4, 4); 0058 $RIFFsubtype = substr($RIFFheader, 8, 4); 0059 0060 switch ($RIFFtype) { 0061 0062 case 'FORM': // AIFF, AIFC 0063 //$info['fileformat'] = 'aiff'; 0064 $this->container = 'aiff'; 0065 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 0066 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 0067 break; 0068 0069 case 'RIFF': // AVI, WAV, etc 0070 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) 0071 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s 0072 //$info['fileformat'] = 'riff'; 0073 $this->container = 'riff'; 0074 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 0075 if ($RIFFsubtype == 'RMP3') { 0076 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s 0077 $RIFFsubtype = 'WAVE'; 0078 } 0079 if ($RIFFsubtype != 'AMV ') { 0080 // 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 0081 // Handled separately in ParseRIFFAMV() 0082 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 0083 } 0084 if (($info['avdataend'] - $info['filesize']) == 1) { 0085 // LiteWave appears to incorrectly *not* pad actual output file 0086 // to nearest WORD boundary so may appear to be short by one 0087 // byte, in which case - skip warning 0088 $info['avdataend'] = $info['filesize']; 0089 } 0090 0091 $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset 0092 while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) { 0093 try { 0094 $this->fseek($nextRIFFoffset); 0095 } catch (getid3_exception $e) { 0096 if ($e->getCode() == 10) { 0097 //$this->warning('RIFF parser: '.$e->getMessage()); 0098 $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong'); 0099 $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present'); 0100 break; 0101 } else { 0102 throw $e; 0103 } 0104 } 0105 $nextRIFFheader = $this->fread(12); 0106 if ($nextRIFFoffset == ($info['avdataend'] - 1)) { 0107 if (substr($nextRIFFheader, 0, 1) == "\x00") { 0108 // RIFF padded to WORD boundary, we're actually already at the end 0109 break; 0110 } 0111 } 0112 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4); 0113 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4)); 0114 $nextRIFFtype = substr($nextRIFFheader, 8, 4); 0115 $chunkdata = array(); 0116 $chunkdata['offset'] = $nextRIFFoffset + 8; 0117 $chunkdata['size'] = $nextRIFFsize; 0118 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size']; 0119 0120 switch ($nextRIFFheaderID) { 0121 case 'RIFF': 0122 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset); 0123 if (!isset($thisfile_riff[$nextRIFFtype])) { 0124 $thisfile_riff[$nextRIFFtype] = array(); 0125 } 0126 $thisfile_riff[$nextRIFFtype][] = $chunkdata; 0127 break; 0128 0129 case 'AMV ': 0130 unset($info['riff']); 0131 $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset); 0132 break; 0133 0134 case 'JUNK': 0135 // ignore 0136 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata; 0137 break; 0138 0139 case 'IDVX': 0140 $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size'])); 0141 break; 0142 0143 default: 0144 if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) { 0145 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12); 0146 if (substr($DIVXTAG, -7) == 'DIVXTAG') { 0147 // 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 0148 $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway'); 0149 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG); 0150 break 2; 0151 } 0152 } 0153 $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file'); 0154 break 2; 0155 0156 } 0157 0158 } 0159 if ($RIFFsubtype == 'WAVE') { 0160 $thisfile_riff_WAVE = &$thisfile_riff['WAVE']; 0161 } 0162 break; 0163 0164 default: 0165 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead'); 0166 //unset($info['fileformat']); 0167 return false; 0168 } 0169 0170 $streamindex = 0; 0171 switch ($RIFFsubtype) { 0172 0173 // http://en.wikipedia.org/wiki/Wav 0174 case 'WAVE': 0175 $info['fileformat'] = 'wav'; 0176 0177 if (empty($thisfile_audio['bitrate_mode'])) { 0178 $thisfile_audio['bitrate_mode'] = 'cbr'; 0179 } 0180 if (empty($thisfile_audio_dataformat)) { 0181 $thisfile_audio_dataformat = 'wav'; 0182 } 0183 0184 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) { 0185 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8; 0186 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size']; 0187 } 0188 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) { 0189 0190 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']); 0191 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 0192 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) { 0193 $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero'; 0194 return false; 0195 } 0196 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw']; 0197 unset($thisfile_riff_audio[$streamindex]['raw']); 0198 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; 0199 0200 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 0201 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { 0202 $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec']; 0203 } 0204 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; 0205 0206 if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV) 0207 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); 0208 } 0209 0210 $thisfile_audio['lossless'] = false; 0211 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { 0212 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { 0213 0214 case 0x0001: // PCM 0215 $thisfile_audio['lossless'] = true; 0216 break; 0217 0218 case 0x2000: // AC-3 0219 $thisfile_audio_dataformat = 'ac3'; 0220 break; 0221 0222 default: 0223 // do nothing 0224 break; 0225 0226 } 0227 } 0228 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag']; 0229 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 0230 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless']; 0231 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat; 0232 } 0233 0234 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) { 0235 0236 // shortcuts 0237 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data']; 0238 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array()); 0239 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad']; 0240 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track']; 0241 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album']; 0242 0243 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4)); 0244 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2)); 0245 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2)); 0246 0247 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT); 0248 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT); 0249 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3)); 0250 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3)); 0251 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1)); 0252 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9)); 0253 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3)); 0254 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3)); 0255 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1)); 0256 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9)); 0257 0258 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude']; 0259 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) { 0260 $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']); 0261 $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']); 0262 $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']); 0263 } 0264 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) { 0265 $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']); 0266 $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']); 0267 $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']); 0268 } 0269 } 0270 0271 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) { 0272 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4)); 0273 0274 // This should be a good way of calculating exact playtime, 0275 // but some sample files have had incorrect number of samples, 0276 // so cannot use this method 0277 0278 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) { 0279 // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec']; 0280 // } 0281 } 0282 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) { 0283 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8); 0284 } 0285 0286 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) { 0287 // shortcut 0288 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0]; 0289 0290 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256)); 0291 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32)); 0292 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32)); 0293 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10); 0294 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8); 0295 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8)); 0296 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1)); 0297 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254); 0298 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601))); 0299 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) { 0300 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) { 0301 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date; 0302 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; 0303 $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']); 0304 } else { 0305 $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid'; 0306 } 0307 } else { 0308 $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid'; 0309 } 0310 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author']; 0311 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title']; 0312 } 0313 0314 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) { 0315 // shortcut 0316 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0]; 0317 0318 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2)); 0319 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001); 0320 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) { 0321 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true; 0322 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004); 0323 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008); 0324 0325 $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2)); 0326 } 0327 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2)); 0328 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2)); 0329 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001); 0330 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002); 0331 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004); 0332 } 0333 0334 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) { 0335 // shortcut 0336 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0]; 0337 0338 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4); 0339 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64)); 0340 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64)); 0341 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64)); 0342 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64)); 0343 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64)); 0344 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64)); 0345 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64)); 0346 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10)); 0347 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8)); 0348 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10)); 0349 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8)); 0350 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64)); 0351 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64)); 0352 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64)); 0353 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true); 0354 for ($i = 0; $i < 8; $i++) { 0355 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4); 0356 $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)); 0357 } 0358 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024)); 0359 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772))); 0360 0361 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist']; 0362 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title']; 0363 } 0364 0365 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) { 0366 // SoundMiner metadata 0367 0368 // shortcuts 0369 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0]; 0370 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data']; 0371 $SNDM_startoffset = 0; 0372 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size']; 0373 0374 while ($SNDM_startoffset < $SNDM_endoffset) { 0375 $SNDM_thisTagOffset = 0; 0376 $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4)); 0377 $SNDM_thisTagOffset += 4; 0378 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4); 0379 $SNDM_thisTagOffset += 4; 0380 $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); 0381 $SNDM_thisTagOffset += 2; 0382 $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); 0383 $SNDM_thisTagOffset += 2; 0384 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize); 0385 $SNDM_thisTagOffset += $SNDM_thisTagDataSize; 0386 0387 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) { 0388 $info['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).')'; 0389 break; 0390 } elseif ($SNDM_thisTagSize <= 0) { 0391 $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'; 0392 break; 0393 } 0394 $SNDM_startoffset += $SNDM_thisTagSize; 0395 0396 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText; 0397 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) { 0398 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText; 0399 } else { 0400 $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'; 0401 } 0402 } 0403 0404 $tagmapping = array( 0405 'tracktitle'=>'title', 0406 'category' =>'genre', 0407 'cdtitle' =>'album', 0408 'tracktitle'=>'title', 0409 ); 0410 foreach ($tagmapping as $fromkey => $tokey) { 0411 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) { 0412 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey]; 0413 } 0414 } 0415 } 0416 0417 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) { 0418 // requires functions simplexml_load_string and get_object_vars 0419 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) { 0420 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML; 0421 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) { 0422 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']); 0423 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000); 0424 } 0425 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) { 0426 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']); 0427 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000); 0428 } 0429 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) { 0430 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0')); 0431 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']; 0432 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600); 0433 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60); 0434 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60)); 0435 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate']; 0436 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f); 0437 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f)); 0438 } 0439 unset($parsedXML); 0440 } 0441 } 0442 0443 0444 0445 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { 0446 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; 0447 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); 0448 } 0449 0450 if (!empty($info['wavpack'])) { 0451 $thisfile_audio_dataformat = 'wavpack'; 0452 $thisfile_audio['bitrate_mode'] = 'vbr'; 0453 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version']; 0454 0455 // Reset to the way it was - RIFF parsing will have messed this up 0456 $info['avdataend'] = $Original['avdataend']; 0457 $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 0458 0459 $this->fseek($info['avdataoffset'] - 44); 0460 $RIFFdata = $this->fread(44); 0461 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8; 0462 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44; 0463 0464 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) { 0465 $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize); 0466 $this->fseek($info['avdataend']); 0467 $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize); 0468 } 0469 0470 // move the data chunk after all other chunks (if any) 0471 // so that the RIFF parser doesn't see EOF when trying 0472 // to skip over the data chunk 0473 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8); 0474 $getid3_riff = new getid3_riff($this->getid3); 0475 $getid3_riff->ParseRIFFdata($RIFFdata); 0476 unset($getid3_riff); 0477 } 0478 0479 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { 0480 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { 0481 case 0x0001: // PCM 0482 if (!empty($info['ac3'])) { 0483 // Dolby Digital WAV files masquerade as PCM-WAV, but they're not 0484 $thisfile_audio['wformattag'] = 0x2000; 0485 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); 0486 $thisfile_audio['lossless'] = false; 0487 $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; 0488 $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate']; 0489 } 0490 if (!empty($info['dts'])) { 0491 // Dolby DTS files masquerade as PCM-WAV, but they're not 0492 $thisfile_audio['wformattag'] = 0x2001; 0493 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); 0494 $thisfile_audio['lossless'] = false; 0495 $thisfile_audio['bitrate'] = $info['dts']['bitrate']; 0496 $thisfile_audio['sample_rate'] = $info['dts']['sample_rate']; 0497 } 0498 break; 0499 case 0x08AE: // ClearJump LiteWave 0500 $thisfile_audio['bitrate_mode'] = 'vbr'; 0501 $thisfile_audio_dataformat = 'litewave'; 0502 0503 //typedef struct tagSLwFormat { 0504 // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags 0505 // DWORD m_dwScale; // scale factor for lossy compression 0506 // DWORD m_dwBlockSize; // number of samples in encoded blocks 0507 // WORD m_wQuality; // alias for the scale factor 0508 // WORD m_wMarkDistance; // distance between marks in bytes 0509 // WORD m_wReserved; 0510 // 0511 // //following paramters are ignored if CF_FILESRC is not set 0512 // DWORD m_dwOrgSize; // original file size in bytes 0513 // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file 0514 // DWORD m_dwRiffChunkSize; // riff chunk size in the original file 0515 // 0516 // PCMWAVEFORMAT m_OrgWf; // original wave format 0517 // }SLwFormat, *PSLwFormat; 0518 0519 // shortcut 0520 $thisfile_riff['litewave']['raw'] = array(); 0521 $riff_litewave = &$thisfile_riff['litewave']; 0522 $riff_litewave_raw = &$riff_litewave['raw']; 0523 0524 $flags = array( 0525 'compression_method' => 1, 0526 'compression_flags' => 1, 0527 'm_dwScale' => 4, 0528 'm_dwBlockSize' => 4, 0529 'm_wQuality' => 2, 0530 'm_wMarkDistance' => 2, 0531 'm_wReserved' => 2, 0532 'm_dwOrgSize' => 4, 0533 'm_bFactExists' => 2, 0534 'm_dwRiffChunkSize' => 4, 0535 ); 0536 $litewave_offset = 18; 0537 foreach ($flags as $flag => $length) { 0538 $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length)); 0539 $litewave_offset += $length; 0540 } 0541 0542 //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20)); 0543 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality']; 0544 0545 $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true; 0546 $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true; 0547 $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04); 0548 0549 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false); 0550 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor']; 0551 break; 0552 0553 default: 0554 break; 0555 } 0556 } 0557 if ($info['avdataend'] > $info['filesize']) { 0558 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') { 0559 case 'wavpack': // WavPack 0560 case 'lpac': // LPAC 0561 case 'ofr': // OptimFROG 0562 case 'ofs': // OptimFROG DualStream 0563 // lossless compressed audio formats that keep original RIFF headers - skip warning 0564 break; 0565 0566 case 'litewave': 0567 if (($info['avdataend'] - $info['filesize']) == 1) { 0568 // LiteWave appears to incorrectly *not* pad actual output file 0569 // to nearest WORD boundary so may appear to be short by one 0570 // byte, in which case - skip warning 0571 } else { 0572 // Short by more than one byte, throw warning 0573 $info['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)'; 0574 $info['avdataend'] = $info['filesize']; 0575 } 0576 break; 0577 0578 default: 0579 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) { 0580 // output file appears to be incorrectly *not* padded to nearest WORD boundary 0581 // Output less severe warning 0582 $info['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)'; 0583 $info['avdataend'] = $info['filesize']; 0584 } else { 0585 // Short by more than one byte, throw warning 0586 $info['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)'; 0587 $info['avdataend'] = $info['filesize']; 0588 } 0589 break; 0590 } 0591 } 0592 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) { 0593 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) { 0594 $info['avdataend']--; 0595 $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'; 0596 } 0597 } 0598 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) { 0599 unset($thisfile_audio['bits_per_sample']); 0600 if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) { 0601 $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; 0602 } 0603 } 0604 break; 0605 0606 // http://en.wikipedia.org/wiki/Audio_Video_Interleave 0607 case 'AVI ': 0608 $info['fileformat'] = 'avi'; 0609 $info['mime_type'] = 'video/avi'; 0610 0611 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably 0612 $thisfile_video['dataformat'] = 'avi'; 0613 0614 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { 0615 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8; 0616 if (isset($thisfile_riff['AVIX'])) { 0617 $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size']; 0618 } else { 0619 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size']; 0620 } 0621 if ($info['avdataend'] > $info['filesize']) { 0622 $info['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)'; 0623 $info['avdataend'] = $info['filesize']; 0624 } 0625 } 0626 0627 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) { 0628 //$bIndexType = array( 0629 // 0x00 => 'AVI_INDEX_OF_INDEXES', 0630 // 0x01 => 'AVI_INDEX_OF_CHUNKS', 0631 // 0x80 => 'AVI_INDEX_IS_DATA', 0632 //); 0633 //$bIndexSubtype = array( 0634 // 0x01 => array( 0635 // 0x01 => 'AVI_INDEX_2FIELD', 0636 // ), 0637 //); 0638 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) { 0639 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data']; 0640 0641 $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2)); 0642 $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1)); 0643 $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1)); 0644 $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4)); 0645 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4); 0646 $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4)); 0647 0648 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']]; 0649 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']]; 0650 0651 unset($ahsisd); 0652 } 0653 } 0654 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) { 0655 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data']; 0656 0657 // shortcut 0658 $thisfile_riff_raw['avih'] = array(); 0659 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih']; 0660 0661 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) 0662 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) { 0663 $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero'; 0664 return false; 0665 } 0666 0667 $flags = array( 0668 'dwMaxBytesPerSec', // max. transfer rate 0669 'dwPaddingGranularity', // pad to multiples of this size; normally 2K. 0670 'dwFlags', // the ever-present flags 0671 'dwTotalFrames', // # frames in file 0672 'dwInitialFrames', // 0673 'dwStreams', // 0674 'dwSuggestedBufferSize', // 0675 'dwWidth', // 0676 'dwHeight', // 0677 'dwScale', // 0678 'dwRate', // 0679 'dwStart', // 0680 'dwLength', // 0681 ); 0682 $avih_offset = 4; 0683 foreach ($flags as $flag) { 0684 $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4)); 0685 $avih_offset += 4; 0686 } 0687 0688 $flags = array( 0689 'hasindex' => 0x00000010, 0690 'mustuseindex' => 0x00000020, 0691 'interleaved' => 0x00000100, 0692 'trustcktype' => 0x00000800, 0693 'capturedfile' => 0x00010000, 0694 'copyrighted' => 0x00020010, 0695 ); 0696 foreach ($flags as $flag => $value) { 0697 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value); 0698 } 0699 0700 // shortcut 0701 $thisfile_riff_video[$streamindex] = array(); 0702 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex]; 0703 0704 if ($thisfile_riff_raw_avih['dwWidth'] > 0) { 0705 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth']; 0706 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width']; 0707 } 0708 if ($thisfile_riff_raw_avih['dwHeight'] > 0) { 0709 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight']; 0710 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height']; 0711 } 0712 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { 0713 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames']; 0714 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames']; 0715 } 0716 0717 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3); 0718 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate']; 0719 } 0720 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) { 0721 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) { 0722 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) { 0723 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { 0724 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data']; 0725 $strhfccType = substr($strhData, 0, 4); 0726 0727 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) { 0728 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data']; 0729 0730 // shortcut 0731 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex]; 0732 0733 switch ($strhfccType) { 0734 case 'auds': 0735 $thisfile_audio['bitrate_mode'] = 'cbr'; 0736 $thisfile_audio_dataformat = 'wav'; 0737 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) { 0738 $streamindex = count($thisfile_riff_audio); 0739 } 0740 0741 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData); 0742 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 0743 0744 // shortcut 0745 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; 0746 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex]; 0747 0748 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) { 0749 unset($thisfile_audio_streams_currentstream['bits_per_sample']); 0750 } 0751 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag']; 0752 unset($thisfile_audio_streams_currentstream['raw']); 0753 0754 // shortcut 0755 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw']; 0756 0757 unset($thisfile_riff_audio[$streamindex]['raw']); 0758 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 0759 0760 $thisfile_audio['lossless'] = false; 0761 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) { 0762 case 0x0001: // PCM 0763 $thisfile_audio_dataformat = 'wav'; 0764 $thisfile_audio['lossless'] = true; 0765 break; 0766 0767 case 0x0050: // MPEG Layer 2 or Layer 1 0768 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2 0769 break; 0770 0771 case 0x0055: // MPEG Layer 3 0772 $thisfile_audio_dataformat = 'mp3'; 0773 break; 0774 0775 case 0x00FF: // AAC 0776 $thisfile_audio_dataformat = 'aac'; 0777 break; 0778 0779 case 0x0161: // Windows Media v7 / v8 / v9 0780 case 0x0162: // Windows Media Professional v9 0781 case 0x0163: // Windows Media Lossess v9 0782 $thisfile_audio_dataformat = 'wma'; 0783 break; 0784 0785 case 0x2000: // AC-3 0786 $thisfile_audio_dataformat = 'ac3'; 0787 break; 0788 0789 case 0x2001: // DTS 0790 $thisfile_audio_dataformat = 'dts'; 0791 break; 0792 0793 default: 0794 $thisfile_audio_dataformat = 'wav'; 0795 break; 0796 } 0797 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat; 0798 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless']; 0799 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 0800 break; 0801 0802 0803 case 'iavs': 0804 case 'vids': 0805 // shortcut 0806 $thisfile_riff_raw['strh'][$i] = array(); 0807 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i]; 0808 0809 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType; 0810 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4); 0811 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags 0812 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2)); 0813 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2)); 0814 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4)); 0815 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4)); 0816 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4)); 0817 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4)); 0818 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4)); 0819 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4)); 0820 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4)); 0821 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4)); 0822 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4)); 0823 0824 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']); 0825 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler']; 0826 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 0827 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']); 0828 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 0829 } 0830 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 0831 $thisfile_video['pixel_aspect_ratio'] = (float) 1; 0832 switch ($thisfile_riff_raw_strh_current['fccHandler']) { 0833 case 'HFYU': // Huffman Lossless Codec 0834 case 'IRAW': // Intel YUV Uncompressed 0835 case 'YUY2': // Uncompressed YUV 4:2:2 0836 $thisfile_video['lossless'] = true; 0837 break; 0838 0839 default: 0840 $thisfile_video['lossless'] = false; 0841 break; 0842 } 0843 0844 switch ($strhfccType) { 0845 case 'vids': 0846 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff')); 0847 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; 0848 0849 if ($thisfile_riff_video_current['codec'] == 'DV') { 0850 $thisfile_riff_video_current['dv_type'] = 2; 0851 } 0852 break; 0853 0854 case 'iavs': 0855 $thisfile_riff_video_current['dv_type'] = 1; 0856 break; 0857 } 0858 break; 0859 0860 default: 0861 $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"'; 0862 break; 0863 0864 } 0865 } 0866 } 0867 0868 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { 0869 0870 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; 0871 if (self::fourccLookup($thisfile_video['fourcc'])) { 0872 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']); 0873 $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; 0874 } 0875 0876 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) { 0877 case 'HFYU': // Huffman Lossless Codec 0878 case 'IRAW': // Intel YUV Uncompressed 0879 case 'YUY2': // Uncompressed YUV 4:2:2 0880 $thisfile_video['lossless'] = true; 0881 //$thisfile_video['bits_per_sample'] = 24; 0882 break; 0883 0884 default: 0885 $thisfile_video['lossless'] = false; 0886 //$thisfile_video['bits_per_sample'] = 24; 0887 break; 0888 } 0889 0890 } 0891 } 0892 } 0893 } 0894 break; 0895 0896 0897 case 'AMV ': 0898 $info['fileformat'] = 'amv'; 0899 $info['mime_type'] = 'video/amv'; 0900 0901 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR 0902 $thisfile_video['dataformat'] = 'mjpeg'; 0903 $thisfile_video['codec'] = 'mjpeg'; 0904 $thisfile_video['lossless'] = false; 0905 $thisfile_video['bits_per_sample'] = 24; 0906 0907 $thisfile_audio['dataformat'] = 'adpcm'; 0908 $thisfile_audio['lossless'] = false; 0909 break; 0910 0911 0912 // http://en.wikipedia.org/wiki/CD-DA 0913 case 'CDDA': 0914 $info['fileformat'] = 'cda'; 0915 unset($info['mime_type']); 0916 0917 $thisfile_audio_dataformat = 'cda'; 0918 0919 $info['avdataoffset'] = 44; 0920 0921 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) { 0922 // shortcut 0923 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0]; 0924 0925 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2)); 0926 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2)); 0927 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4)); 0928 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4)); 0929 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4)); 0930 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4)); 0931 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4)); 0932 0933 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75; 0934 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75; 0935 $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num']; 0936 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds']; 0937 0938 // hardcoded data for CD-audio 0939 $thisfile_audio['lossless'] = true; 0940 $thisfile_audio['sample_rate'] = 44100; 0941 $thisfile_audio['channels'] = 2; 0942 $thisfile_audio['bits_per_sample'] = 16; 0943 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample']; 0944 $thisfile_audio['bitrate_mode'] = 'cbr'; 0945 } 0946 break; 0947 0948 // http://en.wikipedia.org/wiki/AIFF 0949 case 'AIFF': 0950 case 'AIFC': 0951 $info['fileformat'] = 'aiff'; 0952 $info['mime_type'] = 'audio/x-aiff'; 0953 0954 $thisfile_audio['bitrate_mode'] = 'cbr'; 0955 $thisfile_audio_dataformat = 'aiff'; 0956 $thisfile_audio['lossless'] = true; 0957 0958 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { 0959 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8; 0960 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size']; 0961 if ($info['avdataend'] > $info['filesize']) { 0962 if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) { 0963 // structures rounded to 2-byte boundary, but dumb encoders 0964 // forget to pad end of file to make this actually work 0965 } else { 0966 $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'; 0967 } 0968 $info['avdataend'] = $info['filesize']; 0969 } 0970 } 0971 0972 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) { 0973 0974 // shortcut 0975 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data']; 0976 0977 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true); 0978 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false); 0979 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true); 0980 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10)); 0981 0982 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) { 0983 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4); 0984 $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false); 0985 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize); 0986 switch ($thisfile_riff_audio['codec_name']) { 0987 case 'NONE': 0988 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 0989 $thisfile_audio['lossless'] = true; 0990 break; 0991 0992 case '': 0993 switch ($thisfile_riff_audio['codec_fourcc']) { 0994 // http://developer.apple.com/qa/snd/snd07.html 0995 case 'sowt': 0996 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM'; 0997 $thisfile_audio['lossless'] = true; 0998 break; 0999 1000 case 'twos': 1001 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM'; 1002 $thisfile_audio['lossless'] = true; 1003 break; 1004 1005 default: 1006 break; 1007 } 1008 break; 1009 1010 default: 1011 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name']; 1012 $thisfile_audio['lossless'] = false; 1013 break; 1014 } 1015 } 1016 1017 $thisfile_audio['channels'] = $thisfile_riff_audio['channels']; 1018 if ($thisfile_riff_audio['bits_per_sample'] > 0) { 1019 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample']; 1020 } 1021 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate']; 1022 if ($thisfile_audio['sample_rate'] == 0) { 1023 $info['error'][] = 'Corrupted AIFF file: sample_rate == zero'; 1024 return false; 1025 } 1026 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate']; 1027 } 1028 1029 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) { 1030 $offset = 0; 1031 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1032 $offset += 2; 1033 for ($i = 0; $i < $CommentCount; $i++) { 1034 $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false); 1035 $offset += 4; 1036 $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true); 1037 $offset += 2; 1038 $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); 1039 $offset += 2; 1040 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength); 1041 $offset += $CommentLength; 1042 1043 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']); 1044 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment']; 1045 } 1046 } 1047 1048 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1049 foreach ($CommentsChunkNames as $key => $value) { 1050 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1051 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1052 } 1053 } 1054 /* 1055 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) { 1056 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1057 $getid3_temp = new getID3(); 1058 $getid3_temp->openfile($this->getid3->filename); 1059 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1060 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; 1061 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1062 $info['id3v2'] = $getid3_temp->info['id3v2']; 1063 } 1064 unset($getid3_temp, $getid3_id3v2); 1065 } 1066 */ 1067 break; 1068 1069 // http://en.wikipedia.org/wiki/8SVX 1070 case '8SVX': 1071 $info['fileformat'] = '8svx'; 1072 $info['mime_type'] = 'audio/8svx'; 1073 1074 $thisfile_audio['bitrate_mode'] = 'cbr'; 1075 $thisfile_audio_dataformat = '8svx'; 1076 $thisfile_audio['bits_per_sample'] = 8; 1077 $thisfile_audio['channels'] = 1; // overridden below, if need be 1078 1079 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { 1080 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; 1081 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size']; 1082 if ($info['avdataend'] > $info['filesize']) { 1083 $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'; 1084 } 1085 } 1086 1087 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) { 1088 // shortcut 1089 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0]; 1090 1091 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4)); 1092 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4)); 1093 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4)); 1094 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2)); 1095 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1)); 1096 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1)); 1097 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4)); 1098 1099 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec']; 1100 1101 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) { 1102 case 0: 1103 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; 1104 $thisfile_audio['lossless'] = true; 1105 $ActualBitsPerSample = 8; 1106 break; 1107 1108 case 1: 1109 $thisfile_audio['codec'] = 'Fibonacci-delta encoding'; 1110 $thisfile_audio['lossless'] = false; 1111 $ActualBitsPerSample = 4; 1112 break; 1113 1114 default: 1115 $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"'; 1116 break; 1117 } 1118 } 1119 1120 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) { 1121 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4)); 1122 switch ($ChannelsIndex) { 1123 case 6: // Stereo 1124 $thisfile_audio['channels'] = 2; 1125 break; 1126 1127 case 2: // Left channel only 1128 case 4: // Right channel only 1129 $thisfile_audio['channels'] = 1; 1130 break; 1131 1132 default: 1133 $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"'; 1134 break; 1135 } 1136 1137 } 1138 1139 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); 1140 foreach ($CommentsChunkNames as $key => $value) { 1141 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { 1142 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; 1143 } 1144 } 1145 1146 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels']; 1147 if (!empty($thisfile_audio['bitrate'])) { 1148 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8); 1149 } 1150 break; 1151 1152 case 'CDXA': 1153 $info['fileformat'] = 'vcd'; // Asume Video CD 1154 $info['mime_type'] = 'video/mpeg'; 1155 1156 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { 1157 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true); 1158 1159 $getid3_temp = new getID3(); 1160 $getid3_temp->openfile($this->getid3->filename); 1161 $getid3_mpeg = new getid3_mpeg($getid3_temp); 1162 $getid3_mpeg->Analyze(); 1163 if (empty($getid3_temp->info['error'])) { 1164 $info['audio'] = $getid3_temp->info['audio']; 1165 $info['video'] = $getid3_temp->info['video']; 1166 $info['mpeg'] = $getid3_temp->info['mpeg']; 1167 $info['warning'] = $getid3_temp->info['warning']; 1168 } 1169 unset($getid3_temp, $getid3_mpeg); 1170 } 1171 break; 1172 1173 1174 default: 1175 $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead'; 1176 //unset($info['fileformat']); 1177 } 1178 1179 switch ($RIFFsubtype) { 1180 case 'WAVE': 1181 case 'AIFF': 1182 case 'AIFC': 1183 $ID3v2_key_good = 'id3 '; 1184 $ID3v2_keys_bad = array('ID3 ', 'tag '); 1185 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) { 1186 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) { 1187 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]; 1188 $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"'; 1189 } 1190 } 1191 1192 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { 1193 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1194 1195 $getid3_temp = new getID3(); 1196 $getid3_temp->openfile($this->getid3->filename); 1197 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1198 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; 1199 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) { 1200 $info['id3v2'] = $getid3_temp->info['id3v2']; 1201 } 1202 unset($getid3_temp, $getid3_id3v2); 1203 } 1204 break; 1205 } 1206 1207 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) { 1208 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4)); 1209 } 1210 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) { 1211 self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']); 1212 } 1213 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) { 1214 self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']); 1215 } 1216 1217 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) { 1218 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version']; 1219 } 1220 1221 if (!isset($info['playtime_seconds'])) { 1222 $info['playtime_seconds'] = 0; 1223 } 1224 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { 1225 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie 1226 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1227 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { 1228 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); 1229 } 1230 1231 if ($info['playtime_seconds'] > 0) { 1232 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1233 1234 if (!isset($info['bitrate'])) { 1235 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1236 } 1237 1238 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) { 1239 1240 if (!isset($thisfile_audio['bitrate'])) { 1241 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1242 } 1243 1244 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { 1245 1246 if (!isset($thisfile_video['bitrate'])) { 1247 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1248 } 1249 1250 } 1251 } 1252 1253 1254 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) { 1255 1256 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); 1257 $thisfile_audio['bitrate'] = 0; 1258 $thisfile_video['bitrate'] = $info['bitrate']; 1259 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) { 1260 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate']; 1261 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate']; 1262 } 1263 if ($thisfile_video['bitrate'] <= 0) { 1264 unset($thisfile_video['bitrate']); 1265 } 1266 if ($thisfile_audio['bitrate'] <= 0) { 1267 unset($thisfile_audio['bitrate']); 1268 } 1269 } 1270 1271 if (isset($info['mpeg']['audio'])) { 1272 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer']; 1273 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1274 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels']; 1275 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate']; 1276 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1277 if (!empty($info['mpeg']['audio']['codec'])) { 1278 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec']; 1279 } 1280 if (!empty($thisfile_audio['streams'])) { 1281 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) { 1282 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) { 1283 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate']; 1284 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels']; 1285 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; 1286 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; 1287 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec']; 1288 } 1289 } 1290 } 1291 $getid3_mp3 = new getid3_mp3($this->getid3); 1292 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions(); 1293 unset($getid3_mp3); 1294 } 1295 1296 1297 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) { 1298 switch ($thisfile_audio_dataformat) { 1299 case 'ac3': 1300 // ignore bits_per_sample 1301 break; 1302 1303 default: 1304 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample']; 1305 break; 1306 } 1307 } 1308 1309 1310 if (empty($thisfile_riff_raw)) { 1311 unset($thisfile_riff['raw']); 1312 } 1313 if (empty($thisfile_riff_audio)) { 1314 unset($thisfile_riff['audio']); 1315 } 1316 if (empty($thisfile_riff_video)) { 1317 unset($thisfile_riff['video']); 1318 } 1319 1320 return true; 1321 } 1322 1323 public function ParseRIFFAMV($startoffset, $maxoffset) { 1324 // 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 1325 1326 // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation 1327 //typedef struct _amvmainheader { 1328 //FOURCC fcc; // 'amvh' 1329 //DWORD cb; 1330 //DWORD dwMicroSecPerFrame; 1331 //BYTE reserve[28]; 1332 //DWORD dwWidth; 1333 //DWORD dwHeight; 1334 //DWORD dwSpeed; 1335 //DWORD reserve0; 1336 //DWORD reserve1; 1337 //BYTE bTimeSec; 1338 //BYTE bTimeMin; 1339 //WORD wTimeHour; 1340 //} AMVMAINHEADER; 1341 1342 $info = &$this->getid3->info; 1343 $RIFFchunk = false; 1344 1345 try { 1346 1347 $this->fseek($startoffset); 1348 $maxoffset = min($maxoffset, $info['avdataend']); 1349 $AMVheader = $this->fread(284); 1350 if (substr($AMVheader, 0, 8) != 'hdrlamvh') { 1351 throw new Exception('expecting "hdrlamv" at offset '.($startoffset + 0).', found "'.substr($AMVheader, 0, 8).'"'); 1352 } 1353 if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes 1354 throw new Exception('expecting "0x38000000" at offset '.($startoffset + 8).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 8, 4)).'"'); 1355 } 1356 $RIFFchunk = array(); 1357 $RIFFchunk['amvh']['us_per_frame'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 12, 4)); 1358 $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved? 1359 $RIFFchunk['amvh']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 44, 4)); 1360 $RIFFchunk['amvh']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 48, 4)); 1361 $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 52, 4)); 1362 $RIFFchunk['amvh']['reserved0'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved? 1363 $RIFFchunk['amvh']['reserved1'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved? 1364 $RIFFchunk['amvh']['runtime_sec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 64, 1)); 1365 $RIFFchunk['amvh']['runtime_min'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 65, 1)); 1366 $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 66, 2)); 1367 1368 $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame']; 1369 $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x']; 1370 $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y']; 1371 $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) + ($RIFFchunk['amvh']['runtime_min'] * 60) + $RIFFchunk['amvh']['runtime_sec']; 1372 1373 // 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 1374 1375 if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") { 1376 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).'"'); 1377 } 1378 // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144 1379 if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") { 1380 throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset + 144).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 144, 8)).'"'); 1381 } 1382 // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180 1383 1384 if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") { 1385 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).'"'); 1386 } 1387 // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256 1388 if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") { 1389 throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset + 256).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 256, 8)).'"'); 1390 } 1391 // followed by 20 bytes of a modified WAVEFORMATEX: 1392 // typedef struct { 1393 // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code) 1394 // WORD nChannels; //(Fixme: this is always 1) 1395 // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050) 1396 // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100) 1397 // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?) 1398 // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4) 1399 // WORD cbSize; //(Fixme: this seems to be 0 in AMV files) 1400 // WORD reserved; 1401 // } WAVEFORMATEX; 1402 $RIFFchunk['strf']['wformattag'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 264, 2)); 1403 $RIFFchunk['strf']['nchannels'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 266, 2)); 1404 $RIFFchunk['strf']['nsamplespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 268, 4)); 1405 $RIFFchunk['strf']['navgbytespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 272, 4)); 1406 $RIFFchunk['strf']['nblockalign'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 276, 2)); 1407 $RIFFchunk['strf']['wbitspersample'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 278, 2)); 1408 $RIFFchunk['strf']['cbsize'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 280, 2)); 1409 $RIFFchunk['strf']['reserved'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 282, 2)); 1410 1411 1412 $info['audio']['lossless'] = false; 1413 $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec']; 1414 $info['audio']['channels'] = $RIFFchunk['strf']['nchannels']; 1415 $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample']; 1416 $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample']; 1417 $info['audio']['bitrate_mode'] = 'cbr'; 1418 1419 1420 } catch (getid3_exception $e) { 1421 if ($e->getCode() == 10) { 1422 $this->warning('RIFFAMV parser: '.$e->getMessage()); 1423 } else { 1424 throw $e; 1425 } 1426 } 1427 1428 return $RIFFchunk; 1429 } 1430 1431 1432 public function ParseRIFF($startoffset, $maxoffset) { 1433 $info = &$this->getid3->info; 1434 1435 $RIFFchunk = false; 1436 $FoundAllChunksWeNeed = false; 1437 1438 try { 1439 $this->fseek($startoffset); 1440 $maxoffset = min($maxoffset, $info['avdataend']); 1441 while ($this->ftell() < $maxoffset) { 1442 $chunknamesize = $this->fread(8); 1443 //$chunkname = substr($chunknamesize, 0, 4); 1444 $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 1445 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4)); 1446 //if (strlen(trim($chunkname, "\x00")) < 4) { 1447 if (strlen($chunkname) < 4) { 1448 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.'); 1449 break; 1450 } 1451 if (($chunksize == 0) && ($chunkname != 'JUNK')) { 1452 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.'); 1453 break; 1454 } 1455 if (($chunksize % 2) != 0) { 1456 // all structures are packed on word boundaries 1457 $chunksize++; 1458 } 1459 1460 switch ($chunkname) { 1461 case 'LIST': 1462 $listname = $this->fread(4); 1463 if (preg_match('#^(movi|rec )$#i', $listname)) { 1464 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4; 1465 $RIFFchunk[$listname]['size'] = $chunksize; 1466 1467 if (!$FoundAllChunksWeNeed) { 1468 $WhereWeWere = $this->ftell(); 1469 $AudioChunkHeader = $this->fread(12); 1470 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2); 1471 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2); 1472 $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4)); 1473 1474 if ($AudioChunkStreamType == 'wb') { 1475 $FirstFourBytes = substr($AudioChunkHeader, 8, 4); 1476 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) { 1477 // MP3 1478 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { 1479 $getid3_temp = new getID3(); 1480 $getid3_temp->openfile($this->getid3->filename); 1481 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1482 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1483 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1484 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); 1485 if (isset($getid3_temp->info['mpeg']['audio'])) { 1486 $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio']; 1487 $info['audio'] = $getid3_temp->info['audio']; 1488 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer']; 1489 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1490 $info['audio']['channels'] = $info['mpeg']['audio']['channels']; 1491 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; 1492 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1493 //$info['bitrate'] = $info['audio']['bitrate']; 1494 } 1495 unset($getid3_temp, $getid3_mp3); 1496 } 1497 1498 } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) { 1499 1500 // AC3 1501 $getid3_temp = new getID3(); 1502 $getid3_temp->openfile($this->getid3->filename); 1503 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1504 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1505 $getid3_ac3 = new getid3_ac3($getid3_temp); 1506 $getid3_ac3->Analyze(); 1507 if (empty($getid3_temp->info['error'])) { 1508 $info['audio'] = $getid3_temp->info['audio']; 1509 $info['ac3'] = $getid3_temp->info['ac3']; 1510 if (!empty($getid3_temp->info['warning'])) { 1511 foreach ($getid3_temp->info['warning'] as $key => $value) { 1512 $info['warning'][] = $value; 1513 } 1514 } 1515 } 1516 unset($getid3_temp, $getid3_ac3); 1517 } 1518 } 1519 $FoundAllChunksWeNeed = true; 1520 $this->fseek($WhereWeWere); 1521 } 1522 $this->fseek($chunksize - 4, SEEK_CUR); 1523 1524 } else { 1525 1526 if (!isset($RIFFchunk[$listname])) { 1527 $RIFFchunk[$listname] = array(); 1528 } 1529 $LISTchunkParent = $listname; 1530 $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize; 1531 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) { 1532 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk); 1533 } 1534 1535 } 1536 break; 1537 1538 default: 1539 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) { 1540 $this->fseek($chunksize, SEEK_CUR); 1541 break; 1542 } 1543 $thisindex = 0; 1544 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) { 1545 $thisindex = count($RIFFchunk[$chunkname]); 1546 } 1547 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8; 1548 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize; 1549 switch ($chunkname) { 1550 case 'data': 1551 $info['avdataoffset'] = $this->ftell(); 1552 $info['avdataend'] = $info['avdataoffset'] + $chunksize; 1553 1554 $testData = $this->fread(36); 1555 if ($testData === '') { 1556 break; 1557 } 1558 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) { 1559 1560 // Probably is MP3 data 1561 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { 1562 $getid3_temp = new getID3(); 1563 $getid3_temp->openfile($this->getid3->filename); 1564 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1565 $getid3_temp->info['avdataend'] = $info['avdataend']; 1566 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1567 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); 1568 if (empty($getid3_temp->info['error'])) { 1569 $info['audio'] = $getid3_temp->info['audio']; 1570 $info['mpeg'] = $getid3_temp->info['mpeg']; 1571 } 1572 unset($getid3_temp, $getid3_mp3); 1573 } 1574 1575 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) { 1576 1577 // This is probably AC-3 data 1578 $getid3_temp = new getID3(); 1579 if ($isRegularAC3) { 1580 $getid3_temp->openfile($this->getid3->filename); 1581 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1582 $getid3_temp->info['avdataend'] = $info['avdataend']; 1583 } 1584 $getid3_ac3 = new getid3_ac3($getid3_temp); 1585 if ($isRegularAC3) { 1586 $getid3_ac3->Analyze(); 1587 } else { 1588 // Dolby Digital WAV 1589 // AC-3 content, but not encoded in same format as normal AC-3 file 1590 // For one thing, byte order is swapped 1591 $ac3_data = ''; 1592 for ($i = 0; $i < 28; $i += 2) { 1593 $ac3_data .= substr($testData, 8 + $i + 1, 1); 1594 $ac3_data .= substr($testData, 8 + $i + 0, 1); 1595 } 1596 $getid3_ac3->AnalyzeString($ac3_data); 1597 } 1598 1599 if (empty($getid3_temp->info['error'])) { 1600 $info['audio'] = $getid3_temp->info['audio']; 1601 $info['ac3'] = $getid3_temp->info['ac3']; 1602 if (!empty($getid3_temp->info['warning'])) { 1603 foreach ($getid3_temp->info['warning'] as $newerror) { 1604 $this->warning('getid3_ac3() says: ['.$newerror.']'); 1605 } 1606 } 1607 } 1608 unset($getid3_temp, $getid3_ac3); 1609 1610 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) { 1611 1612 // This is probably DTS data 1613 $getid3_temp = new getID3(); 1614 $getid3_temp->openfile($this->getid3->filename); 1615 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1616 $getid3_dts = new getid3_dts($getid3_temp); 1617 $getid3_dts->Analyze(); 1618 if (empty($getid3_temp->info['error'])) { 1619 $info['audio'] = $getid3_temp->info['audio']; 1620 $info['dts'] = $getid3_temp->info['dts']; 1621 $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing 1622 if (!empty($getid3_temp->info['warning'])) { 1623 foreach ($getid3_temp->info['warning'] as $newerror) { 1624 $this->warning('getid3_dts() says: ['.$newerror.']'); 1625 } 1626 } 1627 } 1628 1629 unset($getid3_temp, $getid3_dts); 1630 1631 } elseif (substr($testData, 0, 4) == 'wvpk') { 1632 1633 // This is WavPack data 1634 $info['wavpack']['offset'] = $info['avdataoffset']; 1635 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4)); 1636 $this->parseWavPackHeader(substr($testData, 8, 28)); 1637 1638 } else { 1639 // This is some other kind of data (quite possibly just PCM) 1640 // do nothing special, just skip it 1641 } 1642 $nextoffset = $info['avdataend']; 1643 $this->fseek($nextoffset); 1644 break; 1645 1646 case 'iXML': 1647 case 'bext': 1648 case 'cart': 1649 case 'fmt ': 1650 case 'strh': 1651 case 'strf': 1652 case 'indx': 1653 case 'MEXT': 1654 case 'DISP': 1655 // always read data in 1656 case 'JUNK': 1657 // should be: never read data in 1658 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc) 1659 if ($chunksize < 1048576) { 1660 if ($chunksize > 0) { 1661 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1662 if ($chunkname == 'JUNK') { 1663 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) { 1664 // only keep text characters [chr(32)-chr(127)] 1665 $info['riff']['comments']['junk'][] = trim($matches[1]); 1666 } 1667 // but if nothing there, ignore 1668 // remove the key in either case 1669 unset($RIFFchunk[$chunkname][$thisindex]['data']); 1670 } 1671 } 1672 } else { 1673 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data'); 1674 $this->fseek($chunksize, SEEK_CUR); 1675 } 1676 break; 1677 1678 //case 'IDVX': 1679 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize)); 1680 // break; 1681 1682 default: 1683 if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { 1684 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset']; 1685 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size']; 1686 unset($RIFFchunk[$chunkname][$thisindex]['offset']); 1687 unset($RIFFchunk[$chunkname][$thisindex]['size']); 1688 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) { 1689 unset($RIFFchunk[$chunkname][$thisindex]); 1690 } 1691 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) { 1692 unset($RIFFchunk[$chunkname]); 1693 } 1694 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1695 } elseif ($chunksize < 2048) { 1696 // only read data in if smaller than 2kB 1697 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); 1698 } else { 1699 $this->fseek($chunksize, SEEK_CUR); 1700 } 1701 break; 1702 } 1703 break; 1704 } 1705 } 1706 1707 } catch (getid3_exception $e) { 1708 if ($e->getCode() == 10) { 1709 $this->warning('RIFF parser: '.$e->getMessage()); 1710 } else { 1711 throw $e; 1712 } 1713 } 1714 1715 return $RIFFchunk; 1716 } 1717 1718 public function ParseRIFFdata(&$RIFFdata) { 1719 $info = &$this->getid3->info; 1720 if ($RIFFdata) { 1721 $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); 1722 $fp_temp = fopen($tempfile, 'wb'); 1723 $RIFFdataLength = strlen($RIFFdata); 1724 $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4); 1725 for ($i = 0; $i < 4; $i++) { 1726 $RIFFdata[($i + 4)] = $NewLengthString[$i]; 1727 } 1728 fwrite($fp_temp, $RIFFdata); 1729 fclose($fp_temp); 1730 1731 $getid3_temp = new getID3(); 1732 $getid3_temp->openfile($tempfile); 1733 $getid3_temp->info['filesize'] = $RIFFdataLength; 1734 $getid3_temp->info['filenamepath'] = $info['filenamepath']; 1735 $getid3_temp->info['tags'] = $info['tags']; 1736 $getid3_temp->info['warning'] = $info['warning']; 1737 $getid3_temp->info['error'] = $info['error']; 1738 $getid3_temp->info['comments'] = $info['comments']; 1739 $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array()); 1740 $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array()); 1741 $getid3_riff = new getid3_riff($getid3_temp); 1742 $getid3_riff->Analyze(); 1743 1744 $info['riff'] = $getid3_temp->info['riff']; 1745 $info['warning'] = $getid3_temp->info['warning']; 1746 $info['error'] = $getid3_temp->info['error']; 1747 $info['tags'] = $getid3_temp->info['tags']; 1748 $info['comments'] = $getid3_temp->info['comments']; 1749 unset($getid3_riff, $getid3_temp); 1750 unlink($tempfile); 1751 } 1752 return false; 1753 } 1754 1755 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) { 1756 $RIFFinfoKeyLookup = array( 1757 'IARL'=>'archivallocation', 1758 'IART'=>'artist', 1759 'ICDS'=>'costumedesigner', 1760 'ICMS'=>'commissionedby', 1761 'ICMT'=>'comment', 1762 'ICNT'=>'country', 1763 'ICOP'=>'copyright', 1764 'ICRD'=>'creationdate', 1765 'IDIM'=>'dimensions', 1766 'IDIT'=>'digitizationdate', 1767 'IDPI'=>'resolution', 1768 'IDST'=>'distributor', 1769 'IEDT'=>'editor', 1770 'IENG'=>'engineers', 1771 'IFRM'=>'accountofparts', 1772 'IGNR'=>'genre', 1773 'IKEY'=>'keywords', 1774 'ILGT'=>'lightness', 1775 'ILNG'=>'language', 1776 'IMED'=>'orignalmedium', 1777 'IMUS'=>'composer', 1778 'INAM'=>'title', 1779 'IPDS'=>'productiondesigner', 1780 'IPLT'=>'palette', 1781 'IPRD'=>'product', 1782 'IPRO'=>'producer', 1783 'IPRT'=>'part', 1784 'IRTD'=>'rating', 1785 'ISBJ'=>'subject', 1786 'ISFT'=>'software', 1787 'ISGN'=>'secondarygenre', 1788 'ISHP'=>'sharpness', 1789 'ISRC'=>'sourcesupplier', 1790 'ISRF'=>'digitizationsource', 1791 'ISTD'=>'productionstudio', 1792 'ISTR'=>'starring', 1793 'ITCH'=>'encoded_by', 1794 'IWEB'=>'url', 1795 'IWRI'=>'writer', 1796 '____'=>'comment', 1797 ); 1798 foreach ($RIFFinfoKeyLookup as $key => $value) { 1799 if (isset($RIFFinfoArray[$key])) { 1800 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) { 1801 if (trim($commentdata['data']) != '') { 1802 if (isset($CommentsTargetArray[$value])) { 1803 $CommentsTargetArray[$value][] = trim($commentdata['data']); 1804 } else { 1805 $CommentsTargetArray[$value] = array(trim($commentdata['data'])); 1806 } 1807 } 1808 } 1809 } 1810 } 1811 return true; 1812 } 1813 1814 public static function parseWAVEFORMATex($WaveFormatExData) { 1815 // shortcut 1816 $WaveFormatEx['raw'] = array(); 1817 $WaveFormatEx_raw = &$WaveFormatEx['raw']; 1818 1819 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2); 1820 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2); 1821 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4); 1822 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4); 1823 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2); 1824 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2); 1825 if (strlen($WaveFormatExData) > 16) { 1826 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2); 1827 } 1828 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw); 1829 1830 $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']); 1831 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels']; 1832 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec']; 1833 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8; 1834 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample']; 1835 1836 return $WaveFormatEx; 1837 } 1838 1839 public function parseWavPackHeader($WavPackChunkData) { 1840 // typedef struct { 1841 // char ckID [4]; 1842 // long ckSize; 1843 // short version; 1844 // short bits; // added for version 2.00 1845 // short flags, shift; // added for version 3.00 1846 // long total_samples, crc, crc2; 1847 // char extension [4], extra_bc, extras [3]; 1848 // } WavpackHeader; 1849 1850 // shortcut 1851 $info = &$this->getid3->info; 1852 $info['wavpack'] = array(); 1853 $thisfile_wavpack = &$info['wavpack']; 1854 1855 $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2)); 1856 if ($thisfile_wavpack['version'] >= 2) { 1857 $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2)); 1858 } 1859 if ($thisfile_wavpack['version'] >= 3) { 1860 $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2)); 1861 $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2)); 1862 $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4)); 1863 $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4)); 1864 $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4)); 1865 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4); 1866 $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1)); 1867 for ($i = 0; $i <= 2; $i++) { 1868 $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1)); 1869 } 1870 1871 // shortcut 1872 $thisfile_wavpack['flags'] = array(); 1873 $thisfile_wavpack_flags = &$thisfile_wavpack['flags']; 1874 1875 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001); 1876 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002); 1877 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004); 1878 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008); 1879 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010); 1880 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020); 1881 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040); 1882 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080); 1883 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100); 1884 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200); 1885 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400); 1886 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800); 1887 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000); 1888 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000); 1889 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000); 1890 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000); 1891 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000); 1892 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000); 1893 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000); 1894 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000); 1895 } 1896 1897 return true; 1898 } 1899 1900 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { 1901 1902 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure 1903 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels 1904 $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 1905 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1 1906 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels 1907 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures) 1908 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device 1909 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device 1910 $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 1911 $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 1912 $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed); 1913 1914 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier 1915 1916 return $parsed; 1917 } 1918 1919 public static function ParseDIVXTAG($DIVXTAG, $raw=false) { 1920 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/ 1921 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip 1922 // 'Byte Layout: '1111111111111111 1923 // '32 for Movie - 1 '1111111111111111 1924 // '28 for Author - 6 '6666666666666666 1925 // '4 for year - 2 '6666666666662222 1926 // '3 for genre - 3 '7777777777777777 1927 // '48 for Comments - 7 '7777777777777777 1928 // '1 for Rating - 4 '7777777777777777 1929 // '5 for Future Additions - 0 '333400000DIVXTAG 1930 // '128 bytes total 1931 1932 static $DIVXTAGgenre = array( 1933 0 => 'Action', 1934 1 => 'Action/Adventure', 1935 2 => 'Adventure', 1936 3 => 'Adult', 1937 4 => 'Anime', 1938 5 => 'Cartoon', 1939 6 => 'Claymation', 1940 7 => 'Comedy', 1941 8 => 'Commercial', 1942 9 => 'Documentary', 1943 10 => 'Drama', 1944 11 => 'Home Video', 1945 12 => 'Horror', 1946 13 => 'Infomercial', 1947 14 => 'Interactive', 1948 15 => 'Mystery', 1949 16 => 'Music Video', 1950 17 => 'Other', 1951 18 => 'Religion', 1952 19 => 'Sci Fi', 1953 20 => 'Thriller', 1954 21 => 'Western', 1955 ), 1956 $DIVXTAGrating = array( 1957 0 => 'Unrated', 1958 1 => 'G', 1959 2 => 'PG', 1960 3 => 'PG-13', 1961 4 => 'R', 1962 5 => 'NC-17', 1963 ); 1964 1965 $parsed['title'] = trim(substr($DIVXTAG, 0, 32)); 1966 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28)); 1967 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4))); 1968 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48)); 1969 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3))); 1970 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1)); 1971 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null 1972 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG" 1973 1974 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']); 1975 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']); 1976 1977 if (!$raw) { 1978 unset($parsed['genre_id'], $parsed['rating_id']); 1979 foreach ($parsed as $key => $value) { 1980 if (!$value === '') { 1981 unset($parsed['key']); 1982 } 1983 } 1984 } 1985 1986 foreach ($parsed as $tag => $value) { 1987 $parsed[$tag] = array($value); 1988 } 1989 1990 return $parsed; 1991 } 1992 1993 public static function waveSNDMtagLookup($tagshortname) { 1994 $begin = __LINE__; 1995 1996 /** This is not a comment! 1997 1998 ©kwd keywords 1999 ©BPM bpm 2000 ©trt tracktitle 2001 ©des description 2002 ©gen category 2003 ©fin featuredinstrument 2004 ©LID longid 2005 ©bex bwdescription 2006 ©pub publisher 2007 ©cdt cdtitle 2008 ©alb library 2009 ©com composer 2010 2011 */ 2012 2013 return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm'); 2014 } 2015 2016 public static function wFormatTagLookup($wFormatTag) { 2017 2018 $begin = __LINE__; 2019 2020 /** This is not a comment! 2021 2022 0x0000 Microsoft Unknown Wave Format 2023 0x0001 Pulse Code Modulation (PCM) 2024 0x0002 Microsoft ADPCM 2025 0x0003 IEEE Float 2026 0x0004 Compaq Computer VSELP 2027 0x0005 IBM CVSD 2028 0x0006 Microsoft A-Law 2029 0x0007 Microsoft mu-Law 2030 0x0008 Microsoft DTS 2031 0x0010 OKI ADPCM 2032 0x0011 Intel DVI/IMA ADPCM 2033 0x0012 Videologic MediaSpace ADPCM 2034 0x0013 Sierra Semiconductor ADPCM 2035 0x0014 Antex Electronics G.723 ADPCM 2036 0x0015 DSP Solutions DigiSTD 2037 0x0016 DSP Solutions DigiFIX 2038 0x0017 Dialogic OKI ADPCM 2039 0x0018 MediaVision ADPCM 2040 0x0019 Hewlett-Packard CU 2041 0x0020 Yamaha ADPCM 2042 0x0021 Speech Compression Sonarc 2043 0x0022 DSP Group TrueSpeech 2044 0x0023 Echo Speech EchoSC1 2045 0x0024 Audiofile AF36 2046 0x0025 Audio Processing Technology APTX 2047 0x0026 AudioFile AF10 2048 0x0027 Prosody 1612 2049 0x0028 LRC 2050 0x0030 Dolby AC2 2051 0x0031 Microsoft GSM 6.10 2052 0x0032 MSNAudio 2053 0x0033 Antex Electronics ADPCME 2054 0x0034 Control Resources VQLPC 2055 0x0035 DSP Solutions DigiREAL 2056 0x0036 DSP Solutions DigiADPCM 2057 0x0037 Control Resources CR10 2058 0x0038 Natural MicroSystems VBXADPCM 2059 0x0039 Crystal Semiconductor IMA ADPCM 2060 0x003A EchoSC3 2061 0x003B Rockwell ADPCM 2062 0x003C Rockwell Digit LK 2063 0x003D Xebec 2064 0x0040 Antex Electronics G.721 ADPCM 2065 0x0041 G.728 CELP 2066 0x0042 MSG723 2067 0x0050 MPEG Layer-2 or Layer-1 2068 0x0052 RT24 2069 0x0053 PAC 2070 0x0055 MPEG Layer-3 2071 0x0059 Lucent G.723 2072 0x0060 Cirrus 2073 0x0061 ESPCM 2074 0x0062 Voxware 2075 0x0063 Canopus Atrac 2076 0x0064 G.726 ADPCM 2077 0x0065 G.722 ADPCM 2078 0x0066 DSAT 2079 0x0067 DSAT Display 2080 0x0069 Voxware Byte Aligned 2081 0x0070 Voxware AC8 2082 0x0071 Voxware AC10 2083 0x0072 Voxware AC16 2084 0x0073 Voxware AC20 2085 0x0074 Voxware MetaVoice 2086 0x0075 Voxware MetaSound 2087 0x0076 Voxware RT29HW 2088 0x0077 Voxware VR12 2089 0x0078 Voxware VR18 2090 0x0079 Voxware TQ40 2091 0x0080 Softsound 2092 0x0081 Voxware TQ60 2093 0x0082 MSRT24 2094 0x0083 G.729A 2095 0x0084 MVI MV12 2096 0x0085 DF G.726 2097 0x0086 DF GSM610 2098 0x0088 ISIAudio 2099 0x0089 Onlive 2100 0x0091 SBC24 2101 0x0092 Dolby AC3 SPDIF 2102 0x0093 MediaSonic G.723 2103 0x0094 Aculab PLC Prosody 8kbps 2104 0x0097 ZyXEL ADPCM 2105 0x0098 Philips LPCBB 2106 0x0099 Packed 2107 0x00FF AAC 2108 0x0100 Rhetorex ADPCM 2109 0x0101 IBM mu-law 2110 0x0102 IBM A-law 2111 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM) 2112 0x0111 Vivo G.723 2113 0x0112 Vivo Siren 2114 0x0123 Digital G.723 2115 0x0125 Sanyo LD ADPCM 2116 0x0130 Sipro Lab Telecom ACELP NET 2117 0x0131 Sipro Lab Telecom ACELP 4800 2118 0x0132 Sipro Lab Telecom ACELP 8V3 2119 0x0133 Sipro Lab Telecom G.729 2120 0x0134 Sipro Lab Telecom G.729A 2121 0x0135 Sipro Lab Telecom Kelvin 2122 0x0140 Windows Media Video V8 2123 0x0150 Qualcomm PureVoice 2124 0x0151 Qualcomm HalfRate 2125 0x0155 Ring Zero Systems TUB GSM 2126 0x0160 Microsoft Audio 1 2127 0x0161 Windows Media Audio V7 / V8 / V9 2128 0x0162 Windows Media Audio Professional V9 2129 0x0163 Windows Media Audio Lossless V9 2130 0x0200 Creative Labs ADPCM 2131 0x0202 Creative Labs Fastspeech8 2132 0x0203 Creative Labs Fastspeech10 2133 0x0210 UHER Informatic GmbH ADPCM 2134 0x0220 Quarterdeck 2135 0x0230 I-link Worldwide VC 2136 0x0240 Aureal RAW Sport 2137 0x0250 Interactive Products HSX 2138 0x0251 Interactive Products RPELP 2139 0x0260 Consistent Software CS2 2140 0x0270 Sony SCX 2141 0x0300 Fujitsu FM Towns Snd 2142 0x0400 BTV Digital 2143 0x0401 Intel Music Coder 2144 0x0450 QDesign Music 2145 0x0680 VME VMPCM 2146 0x0681 AT&T Labs TPC 2147 0x08AE ClearJump LiteWave 2148 0x1000 Olivetti GSM 2149 0x1001 Olivetti ADPCM 2150 0x1002 Olivetti CELP 2151 0x1003 Olivetti SBC 2152 0x1004 Olivetti OPR 2153 0x1100 Lernout & Hauspie Codec (0x1100) 2154 0x1101 Lernout & Hauspie CELP Codec (0x1101) 2155 0x1102 Lernout & Hauspie SBC Codec (0x1102) 2156 0x1103 Lernout & Hauspie SBC Codec (0x1103) 2157 0x1104 Lernout & Hauspie SBC Codec (0x1104) 2158 0x1400 Norris 2159 0x1401 AT&T ISIAudio 2160 0x1500 Soundspace Music Compression 2161 0x181C VoxWare RT24 Speech 2162 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com) 2163 0x2000 Dolby AC3 2164 0x2001 Dolby DTS 2165 0x2002 WAVE_FORMAT_14_4 2166 0x2003 WAVE_FORMAT_28_8 2167 0x2004 WAVE_FORMAT_COOK 2168 0x2005 WAVE_FORMAT_DNET 2169 0x674F Ogg Vorbis 1 2170 0x6750 Ogg Vorbis 2 2171 0x6751 Ogg Vorbis 3 2172 0x676F Ogg Vorbis 1+ 2173 0x6770 Ogg Vorbis 2+ 2174 0x6771 Ogg Vorbis 3+ 2175 0x7A21 GSM-AMR (CBR, no SID) 2176 0x7A22 GSM-AMR (VBR, including SID) 2177 0xFFFE WAVE_FORMAT_EXTENSIBLE 2178 0xFFFF WAVE_FORMAT_DEVELOPMENT 2179 2180 */ 2181 2182 return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag'); 2183 } 2184 2185 public static function fourccLookup($fourcc) { 2186 2187 $begin = __LINE__; 2188 2189 /** This is not a comment! 2190 2191 swot http://developer.apple.com/qa/snd/snd07.html 2192 ____ No Codec (____) 2193 _BIT BI_BITFIELDS (Raw RGB) 2194 _JPG JPEG compressed 2195 _PNG PNG compressed W3C/ISO/IEC (RFC-2083) 2196 _RAW Full Frames (Uncompressed) 2197 _RGB Raw RGB Bitmap 2198 _RL4 RLE 4bpp RGB 2199 _RL8 RLE 8bpp RGB 2200 3IV1 3ivx MPEG-4 v1 2201 3IV2 3ivx MPEG-4 v2 2202 3IVX 3ivx MPEG-4 2203 AASC Autodesk Animator 2204 ABYR Kensington ?ABYR? 2205 AEMI Array Microsystems VideoONE MPEG1-I Capture 2206 AFLC Autodesk Animator FLC 2207 AFLI Autodesk Animator FLI 2208 AMPG Array Microsystems VideoONE MPEG 2209 ANIM Intel RDX (ANIM) 2210 AP41 AngelPotion Definitive 2211 ASV1 Asus Video v1 2212 ASV2 Asus Video v2 2213 ASVX Asus Video 2.0 (audio) 2214 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2 2215 AURA AuraVision Aura 1 Codec - YUV 4:1:1 2216 AVDJ Independent JPEG Group\'s codec (AVDJ) 2217 AVRN Independent JPEG Group\'s codec (AVRN) 2218 AYUV 4:4:4 YUV (AYUV) 2219 AZPR Quicktime Apple Video (AZPR) 2220 BGR Raw RGB32 2221 BLZ0 Blizzard DivX MPEG-4 2222 BTVC Conexant Composite Video 2223 BINK RAD Game Tools Bink Video 2224 BT20 Conexant Prosumer Video 2225 BTCV Conexant Composite Video Codec 2226 BW10 Data Translation Broadway MPEG Capture 2227 CC12 Intel YUV12 2228 CDVC Canopus DV 2229 CFCC Digital Processing Systems DPS Perception 2230 CGDI Microsoft Office 97 Camcorder Video 2231 CHAM Winnov Caviara Champagne 2232 CJPG Creative WebCam JPEG 2233 CLJR Cirrus Logic YUV 4:1:1 2234 CMYK Common Data Format in Printing (Colorgraph) 2235 CPLA Weitek 4:2:0 YUV Planar 2236 CRAM Microsoft Video 1 (CRAM) 2237 cvid Radius Cinepak 2238 CVID Radius Cinepak 2239 CWLT Microsoft Color WLT DIB 2240 CYUV Creative Labs YUV 2241 CYUY ATI YUV 2242 D261 H.261 2243 D263 H.263 2244 DIB Device Independent Bitmap 2245 DIV1 FFmpeg OpenDivX 2246 DIV2 Microsoft MPEG-4 v1/v2 2247 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion 2248 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion 2249 DIV5 DivX MPEG-4 v5.x 2250 DIV6 DivX ;-) (MS MPEG-4 v3.x) 2251 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo) 2252 divx DivX MPEG-4 2253 DMB1 Matrox Rainbow Runner hardware MJPEG 2254 DMB2 Paradigm MJPEG 2255 DSVD ?DSVD? 2256 DUCK Duck TrueMotion 1.0 2257 DPS0 DPS/Leitch Reality Motion JPEG 2258 DPSC DPS/Leitch PAR Motion JPEG 2259 DV25 Matrox DVCPRO codec 2260 DV50 Matrox DVCPRO50 codec 2261 DVC IEC 61834 and SMPTE 314M (DVC/DV Video) 2262 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video) 2263 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps 2264 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com) 2265 DVSL IEC Standard DV compressed in SD (SDL) 2266 DVAN ?DVAN? 2267 DVE2 InSoft DVE-2 Videoconferencing 2268 dvsd IEC 61834 and SMPTE 314M DVC/DV Video 2269 DVSD IEC 61834 and SMPTE 314M DVC/DV Video 2270 DVX1 Lucent DVX1000SP Video Decoder 2271 DVX2 Lucent DVX2000S Video Decoder 2272 DVX3 Lucent DVX3000S Video Decoder 2273 DX50 DivX v5 2274 DXT1 Microsoft DirectX Compressed Texture (DXT1) 2275 DXT2 Microsoft DirectX Compressed Texture (DXT2) 2276 DXT3 Microsoft DirectX Compressed Texture (DXT3) 2277 DXT4 Microsoft DirectX Compressed Texture (DXT4) 2278 DXT5 Microsoft DirectX Compressed Texture (DXT5) 2279 DXTC Microsoft DirectX Compressed Texture (DXTC) 2280 DXTn Microsoft DirectX Compressed Texture (DXTn) 2281 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com) 2282 EKQ0 Elsa ?EKQ0? 2283 ELK0 Elsa ?ELK0? 2284 ESCP Eidos Escape 2285 ETV1 eTreppid Video ETV1 2286 ETV2 eTreppid Video ETV2 2287 ETVC eTreppid Video ETVC 2288 FLIC Autodesk FLI/FLC Animation 2289 FLV1 Sorenson Spark 2290 FLV4 On2 TrueMotion VP6 2291 FRWT Darim Vision Forward Motion JPEG (www.darvision.com) 2292 FRWU Darim Vision Forward Uncompressed (www.darvision.com) 2293 FLJP D-Vision Field Encoded Motion JPEG 2294 FPS1 FRAPS v1 2295 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel 2296 FRWD SoftLab-Nsk Forward Motion JPEG 2297 FVF1 Iterated Systems Fractal Video Frame 2298 GLZW Motion LZW (gabest@freemail.hu) 2299 GPEG Motion JPEG (gabest@freemail.hu) 2300 GWLT Microsoft Greyscale WLT DIB 2301 H260 Intel ITU H.260 Videoconferencing 2302 H261 Intel ITU H.261 Videoconferencing 2303 H262 Intel ITU H.262 Videoconferencing 2304 H263 Intel ITU H.263 Videoconferencing 2305 H264 Intel ITU H.264 Videoconferencing 2306 H265 Intel ITU H.265 Videoconferencing 2307 H266 Intel ITU H.266 Videoconferencing 2308 H267 Intel ITU H.267 Videoconferencing 2309 H268 Intel ITU H.268 Videoconferencing 2310 H269 Intel ITU H.269 Videoconferencing 2311 HFYU Huffman Lossless Codec 2312 HMCR Rendition Motion Compensation Format (HMCR) 2313 HMRR Rendition Motion Compensation Format (HMRR) 2314 I263 FFmpeg I263 decoder 2315 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane") 2316 IUYV Interlaced version of UYVY (www.leadtools.com) 2317 IY41 Interlaced version of Y41P (www.leadtools.com) 2318 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2319 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard 2320 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes) 2321 i263 Intel ITU H.263 Videoconferencing (i263) 2322 I420 Intel Indeo 4 2323 IAN Intel Indeo 4 (RDX) 2324 ICLB InSoft CellB Videoconferencing 2325 IGOR Power DVD 2326 IJPG Intergraph JPEG 2327 ILVC Intel Layered Video 2328 ILVR ITU-T H.263+ 2329 IPDV I-O Data Device Giga AVI DV Codec 2330 IR21 Intel Indeo 2.1 2331 IRAW Intel YUV Uncompressed 2332 IV30 Intel Indeo 3.0 2333 IV31 Intel Indeo 3.1 2334 IV32 Ligos Indeo 3.2 2335 IV33 Ligos Indeo 3.3 2336 IV34 Ligos Indeo 3.4 2337 IV35 Ligos Indeo 3.5 2338 IV36 Ligos Indeo 3.6 2339 IV37 Ligos Indeo 3.7 2340 IV38 Ligos Indeo 3.8 2341 IV39 Ligos Indeo 3.9 2342 IV40 Ligos Indeo Interactive 4.0 2343 IV41 Ligos Indeo Interactive 4.1 2344 IV42 Ligos Indeo Interactive 4.2 2345 IV43 Ligos Indeo Interactive 4.3 2346 IV44 Ligos Indeo Interactive 4.4 2347 IV45 Ligos Indeo Interactive 4.5 2348 IV46 Ligos Indeo Interactive 4.6 2349 IV47 Ligos Indeo Interactive 4.7 2350 IV48 Ligos Indeo Interactive 4.8 2351 IV49 Ligos Indeo Interactive 4.9 2352 IV50 Ligos Indeo Interactive 5.0 2353 JBYR Kensington ?JBYR? 2354 JPEG Still Image JPEG DIB 2355 JPGL Pegasus Lossless Motion JPEG 2356 KMVC Team17 Software Karl Morton\'s Video Codec 2357 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com) 2358 LEAD LEAD Video Codec 2359 Ljpg LEAD MJPEG Codec 2360 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de) 2361 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com) 2362 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com) 2363 MMES Matrox MPEG-2 I-frame 2364 MP2v Microsoft S-Mpeg 4 version 1 (MP2v) 2365 MP42 Microsoft S-Mpeg 4 version 2 (MP42) 2366 MP43 Microsoft S-Mpeg 4 version 3 (MP43) 2367 MP4S Microsoft S-Mpeg 4 version 3 (MP4S) 2368 MP4V FFmpeg MPEG-4 2369 MPG1 FFmpeg MPEG 1/2 2370 MPG2 FFmpeg MPEG 1/2 2371 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3) 2372 MPG4 Microsoft MPEG-4 2373 MPGI Sigma Designs MPEG 2374 MPNG PNG images decoder 2375 MSS1 Microsoft Windows Screen Video 2376 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2377 M261 Microsoft H.261 2378 M263 Microsoft H.263 2379 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2) 2380 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2) 2381 MC12 ATI Motion Compensation Format (MC12) 2382 MCAM ATI Motion Compensation Format (MCAM) 2383 MJ2C Morgan Multimedia Motion JPEG2000 2384 mJPG IBM Motion JPEG w/ Huffman Tables 2385 MJPG Microsoft Motion JPEG DIB 2386 MP42 Microsoft MPEG-4 (low-motion) 2387 MP43 Microsoft MPEG-4 (fast-motion) 2388 MP4S Microsoft MPEG-4 (MP4S) 2389 mp4s Microsoft MPEG-4 (mp4s) 2390 MPEG Chromatic Research MPEG-1 Video I-Frame 2391 MPG4 Microsoft MPEG-4 Video High Speed Compressor 2392 MPGI Sigma Designs MPEG 2393 MRCA FAST Multimedia Martin Regen Codec 2394 MRLE Microsoft Run Length Encoding 2395 MSVC Microsoft Video 1 2396 MTX1 Matrox ?MTX1? 2397 MTX2 Matrox ?MTX2? 2398 MTX3 Matrox ?MTX3? 2399 MTX4 Matrox ?MTX4? 2400 MTX5 Matrox ?MTX5? 2401 MTX6 Matrox ?MTX6? 2402 MTX7 Matrox ?MTX7? 2403 MTX8 Matrox ?MTX8? 2404 MTX9 Matrox ?MTX9? 2405 MV12 Motion Pixels Codec (old) 2406 MWV1 Aware Motion Wavelets 2407 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm) 2408 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com) 2409 NUV1 NuppelVideo 2410 NTN1 Nogatech Video Compression 1 2411 NVS0 nVidia GeForce Texture (NVS0) 2412 NVS1 nVidia GeForce Texture (NVS1) 2413 NVS2 nVidia GeForce Texture (NVS2) 2414 NVS3 nVidia GeForce Texture (NVS3) 2415 NVS4 nVidia GeForce Texture (NVS4) 2416 NVS5 nVidia GeForce Texture (NVS5) 2417 NVT0 nVidia GeForce Texture (NVT0) 2418 NVT1 nVidia GeForce Texture (NVT1) 2419 NVT2 nVidia GeForce Texture (NVT2) 2420 NVT3 nVidia GeForce Texture (NVT3) 2421 NVT4 nVidia GeForce Texture (NVT4) 2422 NVT5 nVidia GeForce Texture (NVT5) 2423 PIXL MiroXL, Pinnacle PCTV 2424 PDVC I-O Data Device Digital Video Capture DV codec 2425 PGVV Radius Video Vision 2426 PHMO IBM Photomotion 2427 PIM1 MPEG Realtime (Pinnacle Cards) 2428 PIM2 Pegasus Imaging ?PIM2? 2429 PIMJ Pegasus Imaging Lossless JPEG 2430 PVEZ Horizons Technology PowerEZ 2431 PVMM PacketVideo Corporation MPEG-4 2432 PVW2 Pegasus Imaging Wavelet Compression 2433 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de) 2434 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de) 2435 QPEG Q-Team QPEG 1.0 2436 qpeq Q-Team QPEG 1.1 2437 RGB Raw BGR32 2438 RGBA Raw RGB w/ Alpha 2439 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com) 2440 ROQV Id RoQ File Video Decoder 2441 RPZA Quicktime Apple Video (RPZA) 2442 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/) 2443 RV10 RealVideo 1.0 (aka RealVideo 5.0) 2444 RV13 RealVideo 1.0 (RV13) 2445 RV20 RealVideo G2 2446 RV30 RealVideo 8 2447 RV40 RealVideo 9 2448 RGBT Raw RGB w/ Transparency 2449 RLE Microsoft Run Length Encoder 2450 RLE4 Run Length Encoded (4bpp, 16-color) 2451 RLE8 Run Length Encoded (8bpp, 256-color) 2452 RT21 Intel Indeo RealTime Video 2.1 2453 rv20 RealVideo G2 2454 rv30 RealVideo 8 2455 RVX Intel RDX (RVX ) 2456 SMC Apple Graphics (SMC ) 2457 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2 2458 SPIG Radius Spigot 2459 SVQ3 Sorenson Video 3 (Apple Quicktime 5) 2460 s422 Tekram VideoCap C210 YUV 4:2:2 2461 SDCC Sun Communication Digital Camera Codec 2462 SFMC CrystalNet Surface Fitting Method 2463 SMSC Radius SMSC 2464 SMSD Radius SMSD 2465 smsv WorldConnect Wavelet Video 2466 SPIG Radius Spigot 2467 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net) 2468 SQZ2 Microsoft VXTreme Video Codec V2 2469 STVA ST Microelectronics CMOS Imager Data (Bayer) 2470 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer) 2471 STVC ST Microelectronics CMOS Imager Data (Bunched) 2472 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format) 2473 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data) 2474 SV10 Sorenson Video R1 2475 SVQ1 Sorenson Video 2476 T420 Toshiba YUV 4:2:0 2477 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com) 2478 TVJP Pinnacle/Truevision Targa 2000 board (TVJP) 2479 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ) 2480 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com) 2481 TY2C Trident Decompression Driver 2482 TLMS TeraLogic Motion Intraframe Codec (TLMS) 2483 TLST TeraLogic Motion Intraframe Codec (TLST) 2484 TM20 Duck TrueMotion 2.0 2485 TM2X Duck TrueMotion 2X 2486 TMIC TeraLogic Motion Intraframe Codec (TMIC) 2487 TMOT Horizons Technology TrueMotion S 2488 tmot Horizons TrueMotion Video Compression 2489 TR20 Duck TrueMotion RealTime 2.0 2490 TSCC TechSmith Screen Capture Codec 2491 TV10 Tecomac Low-Bit Rate Codec 2492 TY2N Trident ?TY2N? 2493 U263 UB Video H.263/H.263+/H.263++ Decoder 2494 UMP4 UB Video MPEG 4 (www.ubvideo.com) 2495 UYNV Nvidia UYVY packed 4:2:2 2496 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision 2497 UCOD eMajix.com ClearVideo 2498 ULTI IBM Ultimotion 2499 UYVY UYVY packed 4:2:2 2500 V261 Lucent VX2000S 2501 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/) 2502 VIV1 FFmpeg H263+ decoder 2503 VIV2 Vivo H.263 2504 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf) 2505 VTLP Alaris VideoGramPiX 2506 VYU9 ATI YUV (VYU9) 2507 VYUY ATI YUV (VYUY) 2508 V261 Lucent VX2000S 2509 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format 2510 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format 2511 VCR1 ATI Video Codec 1 2512 VCR2 ATI Video Codec 2 2513 VCR3 ATI VCR 3.0 2514 VCR4 ATI VCR 4.0 2515 VCR5 ATI VCR 5.0 2516 VCR6 ATI VCR 6.0 2517 VCR7 ATI VCR 7.0 2518 VCR8 ATI VCR 8.0 2519 VCR9 ATI VCR 9.0 2520 VDCT Vitec Multimedia Video Maker Pro DIB 2521 VDOM VDOnet VDOWave 2522 VDOW VDOnet VDOLive (H.263) 2523 VDTZ Darim Vison VideoTizer YUV 2524 VGPX Alaris VideoGramPiX 2525 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422 2526 VIVO Vivo H.263 v2.00 2527 vivo Vivo H.263 2528 VIXL Miro/Pinnacle Video XL 2529 VLV1 VideoLogic/PURE Digital Videologic Capture 2530 VP30 On2 VP3.0 2531 VP31 On2 VP3.1 2532 VP6F On2 TrueMotion VP6 2533 VX1K Lucent VX1000S Video Codec 2534 VX2K Lucent VX2000S Video Codec 2535 VXSP Lucent VX1000SP Video Codec 2536 WBVC Winbond W9960 2537 WHAM Microsoft Video 1 (WHAM) 2538 WINX Winnov Software Compression 2539 WJPG AverMedia Winbond JPEG 2540 WMV1 Windows Media Video V7 2541 WMV2 Windows Media Video V8 2542 WMV3 Windows Media Video V9 2543 WNV1 Winnov Hardware Compression 2544 XYZP Extended PAL format XYZ palette (www.riff.org) 2545 x263 Xirlink H.263 2546 XLV0 NetXL Video Decoder 2547 XMPG Xing MPEG (I-Frame only) 2548 XVID XviD MPEG-4 (www.xvid.org) 2549 XXAN ?XXAN? 2550 YU92 Intel YUV (YU92) 2551 YUNV Nvidia Uncompressed YUV 4:2:2 2552 YUVP Extended PAL format YUV palette (www.riff.org) 2553 Y211 YUV 2:1:1 Packed 2554 Y411 YUV 4:1:1 Packed 2555 Y41B Weitek YUV 4:1:1 Planar 2556 Y41P Brooktree PC1 YUV 4:1:1 Packed 2557 Y41T Brooktree PC1 YUV 4:1:1 with transparency 2558 Y42B Weitek YUV 4:2:2 Planar 2559 Y42T Brooktree UYUV 4:2:2 with transparency 2560 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera 2561 Y800 Simple, single Y plane for monochrome images 2562 Y8 Grayscale video 2563 YC12 Intel YUV 12 codec 2564 YUV8 Winnov Caviar YUV8 2565 YUV9 Intel YUV9 2566 YUY2 Uncompressed YUV 4:2:2 2567 YUYV Canopus YUV 2568 YV12 YVU12 Planar 2569 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes) 2570 YVYU YVYU 4:2:2 Packed 2571 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) 2572 ZPEG Metheus Video Zipper 2573 2574 */ 2575 2576 return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc'); 2577 } 2578 2579 private function EitherEndian2Int($byteword, $signed=false) { 2580 if ($this->container == 'riff') { 2581 return getid3_lib::LittleEndian2Int($byteword, $signed); 2582 } 2583 return getid3_lib::BigEndian2Int($byteword, false, $signed); 2584 } 2585 2586 }