Changeset 29734 for trunk/src/wp-includes/ID3/module.audio-video.riff.php
- Timestamp:
- 09/11/2014 07:06:33 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/module.audio-video.riff.php
r23766 r29734 4 4 // available at http://getid3.sourceforge.net // 5 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 6 7 ///////////////////////////////////////////////////////////////// 7 8 // See readme.txt for more details // … … 27 28 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); 28 29 29 class getid3_riff extends getid3_handler 30 { 30 class getid3_riff extends getid3_handler { 31 32 protected $container = 'riff'; // default 31 33 32 34 public function Analyze() { … … 59 61 60 62 case 'FORM': // AIFF, AIFC 61 $info['fileformat'] = 'aiff'; 63 //$info['fileformat'] = 'aiff'; 64 $this->container = 'aiff'; 62 65 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 63 66 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); … … 67 70 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) 68 71 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s 69 $info['fileformat'] = 'riff'; 72 //$info['fileformat'] = 'riff'; 73 $this->container = 'riff'; 70 74 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); 71 75 if ($RIFFsubtype == 'RMP3') { … … 73 77 $RIFFsubtype = 'WAVE'; 74 78 } 75 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 79 if ($RIFFsubtype != 'AMV ') { 80 // 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 81 // Handled separately in ParseRIFFAMV() 82 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); 83 } 76 84 if (($info['avdataend'] - $info['filesize']) == 1) { 77 85 // LiteWave appears to incorrectly *not* pad actual output file … … 111 119 112 120 switch ($nextRIFFheaderID) { 113 114 121 case 'RIFF': 115 122 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset); 116 117 123 if (!isset($thisfile_riff[$nextRIFFtype])) { 118 124 $thisfile_riff[$nextRIFFtype] = array(); 119 125 } 120 126 $thisfile_riff[$nextRIFFtype][] = $chunkdata; 127 break; 128 129 case 'AMV ': 130 unset($info['riff']); 131 $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset); 121 132 break; 122 133 … … 153 164 default: 154 165 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead'); 155 unset($info['fileformat']);166 //unset($info['fileformat']); 156 167 return false; 157 168 } … … 159 170 $streamindex = 0; 160 171 switch ($RIFFsubtype) { 172 173 // http://en.wikipedia.org/wiki/Wav 161 174 case 'WAVE': 175 $info['fileformat'] = 'wav'; 176 162 177 if (empty($thisfile_audio['bitrate_mode'])) { 163 178 $thisfile_audio['bitrate_mode'] = 'cbr'; … … 589 604 break; 590 605 606 // http://en.wikipedia.org/wiki/Audio_Video_Interleave 591 607 case 'AVI ': 608 $info['fileformat'] = 'avi'; 609 $info['mime_type'] = 'video/avi'; 610 592 611 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably 593 612 $thisfile_video['dataformat'] = 'avi'; 594 $info['mime_type'] = 'video/avi';595 613 596 614 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { … … 826 844 switch ($strhfccType) { 827 845 case 'vids': 828 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($ info['fileformat']== 'riff'));846 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff')); 829 847 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; 830 848 … … 876 894 break; 877 895 896 897 case 'AMV ': 898 $info['fileformat'] = 'amv'; 899 $info['mime_type'] = 'video/amv'; 900 901 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR 902 $thisfile_video['dataformat'] = 'mjpeg'; 903 $thisfile_video['codec'] = 'mjpeg'; 904 $thisfile_video['lossless'] = false; 905 $thisfile_video['bits_per_sample'] = 24; 906 907 $thisfile_audio['dataformat'] = 'adpcm'; 908 $thisfile_audio['lossless'] = false; 909 break; 910 911 912 // http://en.wikipedia.org/wiki/CD-DA 878 913 case 'CDDA': 879 $thisfile_audio['bitrate_mode'] = 'cbr'; 914 $info['fileformat'] = 'cda'; 915 unset($info['mime_type']); 916 880 917 $thisfile_audio_dataformat = 'cda'; 881 $thisfile_audio['lossless'] = true;882 unset($info['mime_type']);883 918 884 919 $info['avdataoffset'] = 44; … … 902 937 903 938 // hardcoded data for CD-audio 939 $thisfile_audio['lossless'] = true; 904 940 $thisfile_audio['sample_rate'] = 44100; 905 941 $thisfile_audio['channels'] = 2; … … 910 946 break; 911 947 912 948 // http://en.wikipedia.org/wiki/AIFF 913 949 case 'AIFF': 914 950 case 'AIFC': 951 $info['fileformat'] = 'aiff'; 952 $info['mime_type'] = 'audio/x-aiff'; 953 915 954 $thisfile_audio['bitrate_mode'] = 'cbr'; 916 955 $thisfile_audio_dataformat = 'aiff'; 917 956 $thisfile_audio['lossless'] = true; 918 $info['mime_type'] = 'audio/x-aiff';919 957 920 958 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { … … 1029 1067 break; 1030 1068 1069 // http://en.wikipedia.org/wiki/8SVX 1031 1070 case '8SVX': 1071 $info['fileformat'] = '8svx'; 1072 $info['mime_type'] = 'audio/8svx'; 1073 1032 1074 $thisfile_audio['bitrate_mode'] = 'cbr'; 1033 1075 $thisfile_audio_dataformat = '8svx'; 1034 1076 $thisfile_audio['bits_per_sample'] = 8; 1035 1077 $thisfile_audio['channels'] = 1; // overridden below, if need be 1036 $info['mime_type'] = 'audio/x-aiff';1037 1078 1038 1079 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { … … 1109 1150 break; 1110 1151 1111 1112 1152 case 'CDXA': 1113 $info['mime_type'] = 'video/mpeg'; 1153 $info['fileformat'] = 'vcd'; // Asume Video CD 1154 $info['mime_type'] = 'video/mpeg'; 1155 1114 1156 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { 1115 if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) {1116 $getid3_temp = new getID3(); 1117 $getid3_temp->openfile($this->getid3->filename);1118 $getid3_mpeg = new getid3_mpeg($getid3_temp);1119 $getid3_mpeg->Analyze();1120 if (empty($getid3_temp->info['error'])) {1121 $info['audio'] = $getid3_temp->info['audio'];1122 $info['video'] = $getid3_temp->info['video'];1123 $info['mpeg'] = $getid3_temp->info['mpeg'];1124 $info['warning'] = $getid3_temp->info['warning'];1125 }1126 unset($getid3_temp, $getid3_mpeg);1127 }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); 1128 1170 } 1129 1171 break; … … 1132 1174 default: 1133 1175 $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead'; 1134 unset($info['fileformat']); 1135 break; 1176 //unset($info['fileformat']); 1136 1177 } 1137 1178 … … 1151 1192 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { 1152 1193 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1194 1153 1195 $getid3_temp = new getID3(); 1154 1196 $getid3_temp->openfile($this->getid3->filename); … … 1279 1321 } 1280 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 1281 1432 public function ParseRIFF($startoffset, $maxoffset) { 1282 1433 $info = &$this->getid3->info; … … 1330 1481 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1331 1482 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; 1332 $getid3_mp3 = new getid3_mp3($getid3_temp );1483 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1333 1484 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); 1334 1485 if (isset($getid3_temp->info['mpeg']['audio'])) { … … 1413 1564 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1414 1565 $getid3_temp->info['avdataend'] = $info['avdataend']; 1415 $getid3_mp3 = new getid3_mp3($getid3_temp );1566 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); 1416 1567 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); 1417 1568 if (empty($getid3_temp->info['error'])) { … … 2427 2578 2428 2579 private function EitherEndian2Int($byteword, $signed=false) { 2429 if ($this-> getid3->info['fileformat']== 'riff') {2580 if ($this->container == 'riff') { 2430 2581 return getid3_lib::LittleEndian2Int($byteword, $signed); 2431 2582 }
Note: See TracChangeset
for help on using the changeset viewer.