📄 module.audio-video.quicktime.php
字号:
<?php//////////////////////////////////////////////////////////////////// getID3() by James Heinrich <info@getid3.org> //// available at http://getid3.sourceforge.net //// or http://www.getid3.org ///////////////////////////////////////////////////////////////////// See readme.txt for more details ///////////////////////////////////////////////////////////////////// //// module.audio-video.quicktime.php //// module for analyzing Quicktime and MP3-in-MP4 files //// dependencies: module.audio.mp3.php //// ////////////////////////////////////////////////////////////////////getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);class getid3_quicktime{ function getid3_quicktime(&$fd, &$ThisFileInfo, $ReturnAtomData=true, $ParseAllPossibleAtoms=false) { $ThisFileInfo['fileformat'] = 'quicktime'; fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); $offset = 0; $atomcounter = 0; while ($offset < $ThisFileInfo['avdataend']) { fseek($fd, $offset, SEEK_SET); $AtomHeader = fread($fd, 8); $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); $atomname = substr($AtomHeader, 4, 4); $ThisFileInfo['quicktime'][$atomname]['name'] = $atomname; $ThisFileInfo['quicktime'][$atomname]['size'] = $atomsize; $ThisFileInfo['quicktime'][$atomname]['offset'] = $offset; if (($offset + $atomsize) > $ThisFileInfo['avdataend']) { $ThisFileInfo['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)'; return false; } if ($atomsize == 0) { // Furthermore, for historical reasons the list of atoms is optionally // terminated by a 32-bit integer set to 0. If you are writing a program // to read user data atoms, you should allow for the terminating 0. break; } switch ($atomname) { case 'mdat': // Media DATa atom // 'mdat' contains the actual data for the audio/video if (($atomsize > 8) && (!isset($ThisFileInfo['avdataend_tmp']) || ($ThisFileInfo['quicktime'][$atomname]['size'] > ($ThisFileInfo['avdataend_tmp'] - $ThisFileInfo['avdataoffset'])))) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['quicktime'][$atomname]['offset'] + 8; $OldAVDataEnd = $ThisFileInfo['avdataend']; $ThisFileInfo['avdataend'] = $ThisFileInfo['quicktime'][$atomname]['offset'] + $ThisFileInfo['quicktime'][$atomname]['size']; if (getid3_mp3::MPEGaudioHeaderValid(getid3_mp3::MPEGaudioHeaderDecode(fread($fd, 4)))) { getid3_mp3::getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset'], false); if (isset($ThisFileInfo['mpeg']['audio'])) { $ThisFileInfo['audio']['dataformat'] = 'mp3'; $ThisFileInfo['audio']['codec'] = (!empty($ThisFileInfo['mpeg']['audio']['encoder']) ? $ThisFileInfo['mpeg']['audio']['encoder'] : (!empty($ThisFileInfo['mpeg']['audio']['codec']) ? $ThisFileInfo['mpeg']['audio']['codec'] : (!empty($ThisFileInfo['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate']; $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels']; $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate']; $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']); $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate']; } } $ThisFileInfo['avdataend'] = $OldAVDataEnd; unset($OldAVDataEnd); } break; case 'free': // FREE space atom case 'skip': // SKIP atom case 'wide': // 64-bit expansion placeholder atom // 'free', 'skip' and 'wide' are just padding, contains no useful data at all break; default: $atomHierarchy = array(); $ThisFileInfo['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($fd, $atomsize), $ThisFileInfo, $offset, $atomHierarchy, $ParseAllPossibleAtoms); break; } $offset += $atomsize; $atomcounter++; } if (!empty($ThisFileInfo['avdataend_tmp'])) { // this value is assigned to a temp value and then erased because // otherwise any atoms beyond the 'mdat' atom would not get parsed $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataend_tmp']; unset($ThisFileInfo['avdataend_tmp']); } if (!isset($ThisFileInfo['bitrate']) && isset($ThisFileInfo['playtime_seconds'])) { $ThisFileInfo['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds']; } if (isset($ThisFileInfo['bitrate']) && !isset($ThisFileInfo['audio']['bitrate']) && !isset($ThisFileInfo['quicktime']['video'])) { $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['bitrate']; } if (($ThisFileInfo['audio']['dataformat'] == 'mp4') && empty($ThisFileInfo['video']['resolution_x'])) { $ThisFileInfo['fileformat'] = 'mp4'; $ThisFileInfo['mime_type'] = 'audio/mp4'; unset($ThisFileInfo['video']['dataformat']); } if (!$ReturnAtomData) { unset($ThisFileInfo['quicktime']['moov']); } if (empty($ThisFileInfo['audio']['dataformat']) && !empty($ThisFileInfo['quicktime']['audio'])) { $ThisFileInfo['audio']['dataformat'] = 'quicktime'; } if (empty($ThisFileInfo['video']['dataformat']) && !empty($ThisFileInfo['quicktime']['video'])) { $ThisFileInfo['video']['dataformat'] = 'quicktime'; } return true; } function QuicktimeParseAtom($atomname, $atomsize, $atomdata, &$ThisFileInfo, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm array_push($atomHierarchy, $atomname); $atomstructure['hierarchy'] = implode(' ', $atomHierarchy); $atomstructure['name'] = $atomname; $atomstructure['size'] = $atomsize; $atomstructure['offset'] = $baseoffset; switch ($atomname) { case 'moov': // MOVie container atom case 'trak': // TRAcK container atom case 'clip': // CLIPping container atom case 'matt': // track MATTe container atom case 'edts': // EDiTS container atom case 'tref': // Track REFerence container atom case 'mdia': // MeDIA container atom case 'minf': // Media INFormation container atom case 'dinf': // Data INFormation container atom case 'udta': // User DaTA container atom case 'stbl': // Sample TaBLe container atom case 'cmov': // Compressed MOVie container atom case 'rmra': // Reference Movie Record Atom case 'rmda': // Reference Movie Descriptor Atom case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) $atomstructure['subatoms'] = $this->QuicktimeParseContainerAtom($atomdata, $ThisFileInfo, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); break; case 'ヽpy': case 'ヾay': case 'ヾir': case '〆d1': case '〆d2': case '〆d3': case '〆d4': case '〆d5': case '〆d6': case '〆d7': case '〆d8': case '〆d9': case 'ゝmt': case '﹊nf': case '﹑rd': case '﹑rf': case '﹔eq': case '﹕rc': case '﹚rt': case '﹏am': case 'ヽmt': case '﹚rn': case '﹉st': case '﹎ak': case '﹎od': case '㏄RD': case '﹕wr': case '゛ut': case '〢RT': case '﹖rk': case '゛lb': case 'ヽom': case 'ゞen': case '﹐pe': case '﹗rl': case '〆nc': $atomstructure['data_length'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 2)); $atomstructure['language_id'] = getid3_lib::BigEndian2Int(substr($atomdata, 2, 2)); $atomstructure['data'] = substr($atomdata, 4); $atomstructure['language'] = $this->QuicktimeLanguageLookup($atomstructure['language_id']); if (empty($ThisFileInfo['comments']['language']) || (!in_array($atomstructure['language'], $ThisFileInfo['comments']['language']))) { $ThisFileInfo['comments']['language'][] = $atomstructure['language']; } $this->CopyToAppropriateCommentsSection($atomname, $atomstructure['data'], $ThisFileInfo); break; case 'play': // auto-PLAY atom $atomstructure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atomdata, 0, 1)); $ThisFileInfo['quicktime']['autoplay'] = $atomstructure['autoplay']; break; case 'WLOC': // Window LOCation atom $atomstructure['location_x'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 2)); $atomstructure['location_y'] = getid3_lib::BigEndian2Int(substr($atomdata, 2, 2)); break; case 'LOOP': // LOOPing atom
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -