/getid3/module.audio-video.quicktime.php
PHP | 2128 lines | 1817 code | 179 blank | 132 comment | 168 complexity | 39948e0652f76cc9045d7e55f51e9452 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?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 extends getid3_handler {
-
- var $ReturnAtomData = true;
- var $ParseAllPossibleAtoms = false;
-
- function Analyze() {
- $info = &$this->getid3->info;
-
- $info ['fileformat'] = 'quicktime';
- $info ['quicktime'] ['hinting'] = false;
- $info ['quicktime'] ['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
-
- fseek ( $this->getid3->fp, $info ['avdataoffset'], SEEK_SET );
-
- $offset = 0;
- $atomcounter = 0;
-
- while ( $offset < $info ['avdataend'] ) {
- if (! getid3_lib::intValueSupported ( $offset )) {
- $info ['error'] [] = 'Unable to parse atom at offset ' . $offset . ' because beyond ' . round ( PHP_INT_MAX / 1073741824 ) . 'GB limit of PHP filesystem functions';
- break;
- }
- fseek ( $this->getid3->fp, $offset, SEEK_SET );
- $AtomHeader = fread ( $this->getid3->fp, 8 );
-
- $atomsize = getid3_lib::BigEndian2Int ( substr ( $AtomHeader, 0, 4 ) );
- $atomname = substr ( $AtomHeader, 4, 4 );
-
- // 64-bit MOV patch by jlegateØktnc*com
- if ($atomsize == 1) {
- $atomsize = getid3_lib::BigEndian2Int ( fread ( $this->getid3->fp, 8 ) );
- }
-
- $info ['quicktime'] [$atomname] ['name'] = $atomname;
- $info ['quicktime'] [$atomname] ['size'] = $atomsize;
- $info ['quicktime'] [$atomname] ['offset'] = $offset;
-
- if (($offset + $atomsize) > $info ['avdataend']) {
- $info ['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 ( $info ['avdataend_tmp'] ) || ($info ['quicktime'] [$atomname] ['size'] > ($info ['avdataend_tmp'] - $info ['avdataoffset'])))) {
-
- $info ['avdataoffset'] = $info ['quicktime'] [$atomname] ['offset'] + 8;
- $OldAVDataEnd = $info ['avdataend'];
- $info ['avdataend'] = $info ['quicktime'] [$atomname] ['offset'] + $info ['quicktime'] [$atomname] ['size'];
-
- $getid3_temp = new getID3 ();
- $getid3_temp->openfile ( $this->getid3->filename );
- $getid3_temp->info ['avdataoffset'] = $info ['avdataoffset'];
- $getid3_temp->info ['avdataend'] = $info ['avdataend'];
- $getid3_mp3 = new getid3_mp3 ( $getid3_temp );
- if ($getid3_mp3->MPEGaudioHeaderValid ( $getid3_mp3->MPEGaudioHeaderDecode ( fread ( $this->getid3->fp, 4 ) ) )) {
- $getid3_mp3->getOnlyMPEGaudioInfo ( $getid3_temp->info ['avdataoffset'], false );
- if (! empty ( $getid3_temp->info ['warning'] )) {
- foreach ( $getid3_temp->info ['warning'] as $value ) {
- $info ['warning'] [] = $value;
- }
- }
- if (! empty ( $getid3_temp->info ['mpeg'] )) {
- $info ['mpeg'] = $getid3_temp->info ['mpeg'];
- if (isset ( $info ['mpeg'] ['audio'] )) {
- $info ['audio'] ['dataformat'] = 'mp3';
- $info ['audio'] ['codec'] = (! empty ( $info ['mpeg'] ['audio'] ['encoder'] ) ? $info ['mpeg'] ['audio'] ['encoder'] : (! empty ( $info ['mpeg'] ['audio'] ['codec'] ) ? $info ['mpeg'] ['audio'] ['codec'] : (! empty ( $info ['mpeg'] ['audio'] ['LAME'] ) ? 'LAME' : 'mp3')));
- $info ['audio'] ['sample_rate'] = $info ['mpeg'] ['audio'] ['sample_rate'];
- $info ['audio'] ['channels'] = $info ['mpeg'] ['audio'] ['channels'];
- $info ['audio'] ['bitrate'] = $info ['mpeg'] ['audio'] ['bitrate'];
- $info ['audio'] ['bitrate_mode'] = strtolower ( $info ['mpeg'] ['audio'] ['bitrate_mode'] );
- $info ['bitrate'] = $info ['audio'] ['bitrate'];
- }
- }
- }
- unset ( $getid3_mp3, $getid3_temp );
- $info ['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 ();
- $info ['quicktime'] [$atomname] = $this->QuicktimeParseAtom ( $atomname, $atomsize, fread ( $this->getid3->fp, $atomsize ), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms );
- break;
- }
-
- $offset += $atomsize;
- $atomcounter ++;
- }
-
- if (! empty ( $info ['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
- $info ['avdataend'] = $info ['avdataend_tmp'];
- unset ( $info ['avdataend_tmp'] );
- }
-
- if (! isset ( $info ['bitrate'] ) && isset ( $info ['playtime_seconds'] )) {
- $info ['bitrate'] = (($info ['avdataend'] - $info ['avdataoffset']) * 8) / $info ['playtime_seconds'];
- }
- if (isset ( $info ['bitrate'] ) && ! isset ( $info ['audio'] ['bitrate'] ) && ! isset ( $info ['quicktime'] ['video'] )) {
- $info ['audio'] ['bitrate'] = $info ['bitrate'];
- }
- if (! empty ( $info ['playtime_seconds'] ) && ! isset ( $info ['video'] ['frame_rate'] ) && ! empty ( $info ['quicktime'] ['stts_framecount'] )) {
- foreach ( $info ['quicktime'] ['stts_framecount'] as $key => $samples_count ) {
- $samples_per_second = $samples_count / $info ['playtime_seconds'];
- if ($samples_per_second > 240) {
- // has to be audio samples
- } else {
- $info ['video'] ['frame_rate'] = $samples_per_second;
- break;
- }
- }
- }
- if (($info ['audio'] ['dataformat'] == 'mp4') && empty ( $info ['video'] ['resolution_x'] )) {
- $info ['fileformat'] = 'mp4';
- $info ['mime_type'] = 'audio/mp4';
- unset ( $info ['video'] ['dataformat'] );
- }
-
- if (! $this->ReturnAtomData) {
- unset ( $info ['quicktime'] ['moov'] );
- }
-
- if (empty ( $info ['audio'] ['dataformat'] ) && ! empty ( $info ['quicktime'] ['audio'] )) {
- $info ['audio'] ['dataformat'] = 'quicktime';
- }
- if (empty ( $info ['video'] ['dataformat'] ) && ! empty ( $info ['quicktime'] ['video'] )) {
- $info ['video'] ['dataformat'] = 'quicktime';
- }
-
- return true;
- }
-
- function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
- // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
-
- $info = &$this->getid3->info;
-
- $atom_parent = array_pop ( $atomHierarchy );
- array_push ( $atomHierarchy, $atomname );
- $atom_structure ['hierarchy'] = implode ( ' ', $atomHierarchy );
- $atom_structure ['name'] = $atomname;
- $atom_structure ['size'] = $atomsize;
- $atom_structure ['offset'] = $baseoffset;
- //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'<br>';
- //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'<br><br>';
- 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 '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)
- $atom_structure ['subatoms'] = $this->QuicktimeParseContainerAtom ( $atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms );
- break;
-
- case 'ilst' : // Item LiST container atom
- $atom_structure ['subatoms'] = $this->QuicktimeParseContainerAtom ( $atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms );
-
- // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
- $allnumericnames = true;
- foreach ( $atom_structure ['subatoms'] as $subatomarray ) {
- if (! is_integer ( $subatomarray ['name'] ) || (count ( $subatomarray ['subatoms'] ) != 1)) {
- $allnumericnames = false;
- break;
- }
- }
- if ($allnumericnames) {
- $newData = array ();
- foreach ( $atom_structure ['subatoms'] as $subatomarray ) {
- foreach ( $subatomarray ['subatoms'] as $newData_subatomarray ) {
- unset ( $newData_subatomarray ['hierarchy'], $newData_subatomarray ['name'] );
- $newData [$subatomarray ['name']] = $newData_subatomarray;
- break;
- }
- }
- $atom_structure ['data'] = $newData;
- unset ( $atom_structure ['subatoms'] );
- }
- break;
-
- case "\x00\x00\x00\x01" :
- case "\x00\x00\x00\x02" :
- case "\x00\x00\x00\x03" :
- case "\x00\x00\x00\x04" :
- case "\x00\x00\x00\x05" :
- $atomname = getid3_lib::BigEndian2Int ( $atomname );
- $atom_structure ['name'] = $atomname;
- $atom_structure ['subatoms'] = $this->QuicktimeParseContainerAtom ( $atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms );
- break;
-
- case 'stbl' : // Sample TaBLe container atom
- $atom_structure ['subatoms'] = $this->QuicktimeParseContainerAtom ( $atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms );
- $isVideo = false;
- $framerate = 0;
- $framecount = 0;
- foreach ( $atom_structure ['subatoms'] as $key => $value_array ) {
- if (isset ( $value_array ['sample_description_table'] )) {
- foreach ( $value_array ['sample_description_table'] as $key2 => $value_array2 ) {
- if (isset ( $value_array2 ['data_format'] )) {
- switch ($value_array2 ['data_format']) {
- case 'avc1' :
- case 'mp4v' :
- // video data
- $isVideo = true;
- break;
- case 'mp4a' :
- // audio data
- break;
- }
- }
- }
- } elseif (isset ( $value_array ['time_to_sample_table'] )) {
- foreach ( $value_array ['time_to_sample_table'] as $key2 => $value_array2 ) {
- if (isset ( $value_array2 ['sample_count'] ) && isset ( $value_array2 ['sample_duration'] ) && ($value_array2 ['sample_duration'] > 0)) {
- $framerate = round ( $info ['quicktime'] ['time_scale'] / $value_array2 ['sample_duration'], 3 );
- $framecount = $value_array2 ['sample_count'];
- }
- }
- }
- }
- if ($isVideo && $framerate) {
- $info ['quicktime'] ['video'] ['frame_rate'] = $framerate;
- $info ['video'] ['frame_rate'] = $info ['quicktime'] ['video'] ['frame_rate'];
- }
- if ($isVideo && $framecount) {
- $info ['quicktime'] ['video'] ['frame_count'] = $framecount;
- }
- break;
-
- case 'aART' : // Album ARTist
- case 'catg' : // CaTeGory
- case 'covr' : // COVeR artwork
- case 'cpil' : // ComPILation
- case 'cprt' : // CoPyRighT
- case 'desc' : // DESCription
- case 'disk' : // DISK number
- case 'egid' : // Episode Global ID
- case 'gnre' : // GeNRE
- case 'keyw' : // KEYWord
- case 'ldes' :
- case 'pcst' : // PodCaST
- case 'pgap' : // GAPless Playback
- case 'purd' : // PURchase Date
- case 'purl' : // Podcast URL
- case 'rati' :
- case 'rndu' :
- case 'rpdu' :
- case 'rtng' : // RaTiNG
- case 'stik' :
- case 'tmpo' : // TeMPO (BPM)
- case 'trkn' : // TRacK Number
- case 'tves' : // TV EpiSode
- case 'tvnn' : // TV Network Name
- case 'tvsh' : // TV SHow Name
- case 'tvsn' : // TV SeasoN
- case 'akID' : // iTunes store account type
- case 'apID' :
- case 'atID' :
- case 'cmID' :
- case 'cnID' :
- case 'geID' :
- case 'plID' :
- case 'sfID' : // iTunes store country
- case '©alb' : // ALBum
- case '©art' : // ARTist
- case '©ART' :
- case '©aut' :
- case '©cmt' : // CoMmenT
- case '©com' : // COMposer
- case '©cpy' :
- case '©day' : // content created year
- case '©dir' :
- case '©ed1' :
- case '©ed2' :
- case '©ed3' :
- case '©ed4' :
- case '©ed5' :
- case '©ed6' :
- case '©ed7' :
- case '©ed8' :
- case '©ed9' :
- case '©enc' :
- case '©fmt' :
- case '©gen' : // GENre
- case '©grp' : // GRouPing
- case '©hst' :
- case '©inf' :
- case '©lyr' : // LYRics
- case '©mak' :
- case '©mod' :
- case '©nam' : // full NAMe
- case '©ope' :
- case '©PRD' :
- case '©prd' :
- case '©prf' :
- case '©req' :
- case '©src' :
- case '©swr' :
- case '©too' : // encoder
- case '©trk' : // TRacK
- case '©url' :
- case '©wrn' :
- case '©wrt' : // WRiTer
- case '----' : // itunes specific
- if ($atom_parent == 'udta') {
- // User data atom handler
- $atom_structure ['data_length'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 2 ) );
- $atom_structure ['language_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 2, 2 ) );
- $atom_structure ['data'] = substr ( $atom_data, 4 );
-
- $atom_structure ['language'] = $this->QuicktimeLanguageLookup ( $atom_structure ['language_id'] );
- if (empty ( $info ['comments'] ['language'] ) || (! in_array ( $atom_structure ['language'], $info ['comments'] ['language'] ))) {
- $info ['comments'] ['language'] [] = $atom_structure ['language'];
- }
- } else {
- // Apple item list box atom handler
- $atomoffset = 0;
- if (substr ( $atom_data, 2, 2 ) == "\x10\xB5") {
- // not sure what it means, but observed on iPhone4 data.
- // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
- while ( $atomoffset < strlen ( $atom_data ) ) {
- $boxsmallsize = getid3_lib::BigEndian2Int ( substr ( $atom_data, $atomoffset, 2 ) );
- $boxsmalltype = substr ( $atom_data, $atomoffset + 2, 2 );
- $boxsmalldata = substr ( $atom_data, $atomoffset + 4, $boxsmallsize );
- switch ($boxsmalltype) {
- case "\x10\xB5" :
- $atom_structure ['data'] = $boxsmalldata;
- break;
- default :
- $info ['warning'] [] = 'Unknown QuickTime smallbox type: "' . getid3_lib::PrintHexBytes ( $boxsmalltype ) . '" at offset ' . $baseoffset;
- $atom_structure ['data'] = $atom_data;
- break;
- }
- $atomoffset += (4 + $boxsmallsize);
- }
- } else {
- while ( $atomoffset < strlen ( $atom_data ) ) {
- $boxsize = getid3_lib::BigEndian2Int ( substr ( $atom_data, $atomoffset, 4 ) );
- $boxtype = substr ( $atom_data, $atomoffset + 4, 4 );
- $boxdata = substr ( $atom_data, $atomoffset + 8, $boxsize - 8 );
-
- switch ($boxtype) {
- case 'mean' :
- case 'name' :
- $atom_structure [$boxtype] = substr ( $boxdata, 4 );
- break;
-
- case 'data' :
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 1, 3 ) );
- switch ($atom_structure ['flags_raw']) {
- case 0 : // data flag
- case 21 : // tmpo/cpil flag
- switch ($atomname) {
- case 'cpil' :
- case 'pcst' :
- case 'pgap' :
- $atom_structure ['data'] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 1 ) );
- break;
-
- case 'tmpo' :
- $atom_structure ['data'] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 2 ) );
- break;
-
- case 'disk' :
- case 'trkn' :
- $num = getid3_lib::BigEndian2Int ( substr ( $boxdata, 10, 2 ) );
- $num_total = getid3_lib::BigEndian2Int ( substr ( $boxdata, 12, 2 ) );
- $atom_structure ['data'] = empty ( $num ) ? '' : $num;
- $atom_structure ['data'] .= empty ( $num_total ) ? '' : '/' . $num_total;
- break;
-
- case 'gnre' :
- $GenreID = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 4 ) );
- $atom_structure ['data'] = getid3_id3v1::LookupGenreName ( $GenreID - 1 );
- break;
-
- case 'rtng' :
- $atom_structure [$atomname] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 1 ) );
- $atom_structure ['data'] = $this->QuicktimeContentRatingLookup ( $atom_structure [$atomname] );
- break;
-
- case 'stik' :
- $atom_structure [$atomname] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 1 ) );
- $atom_structure ['data'] = $this->QuicktimeSTIKLookup ( $atom_structure [$atomname] );
- break;
-
- case 'sfID' :
- $atom_structure [$atomname] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 4 ) );
- $atom_structure ['data'] = $this->QuicktimeStoreFrontCodeLookup ( $atom_structure [$atomname] );
- break;
-
- case 'egid' :
- case 'purl' :
- $atom_structure ['data'] = substr ( $boxdata, 8 );
- break;
-
- default :
- $atom_structure ['data'] = getid3_lib::BigEndian2Int ( substr ( $boxdata, 8, 4 ) );
- }
- break;
-
- case 1 : // text flag
- case 13 : // image flag
- default :
- $atom_structure ['data'] = substr ( $boxdata, 8 );
- break;
-
- }
- break;
-
- default :
- $info ['warning'] [] = 'Unknown QuickTime box type: "' . getid3_lib::PrintHexBytes ( $boxtype ) . '" at offset ' . $baseoffset;
- $atom_structure ['data'] = $atom_data;
-
- }
- $atomoffset += $boxsize;
- }
- }
- }
- $this->CopyToAppropriateCommentsSection ( $atomname, $atom_structure ['data'], $atom_structure ['name'] );
- break;
-
- case 'play' : // auto-PLAY atom
- $atom_structure ['autoplay'] = ( bool ) getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
-
- $info ['quicktime'] ['autoplay'] = $atom_structure ['autoplay'];
- break;
-
- case 'WLOC' : // Window LOCation atom
- $atom_structure ['location_x'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 2 ) );
- $atom_structure ['location_y'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 2, 2 ) );
- break;
-
- case 'LOOP' : // LOOPing atom
- case 'SelO' : // play SELection Only atom
- case 'AllF' : // play ALL Frames atom
- $atom_structure ['data'] = getid3_lib::BigEndian2Int ( $atom_data );
- break;
-
- case 'name' : //
- case 'MCPS' : // Media Cleaner PRo
- case '@PRM' : // adobe PReMiere version
- case '@PRQ' : // adobe PRemiere Quicktime version
- $atom_structure ['data'] = $atom_data;
- break;
-
- case 'cmvd' : // Compressed MooV Data atom
- // Code by ubergeekØubergeek*tv based on information from
- // http://developer.apple.com/quicktime/icefloe/dispatch012.html
- $atom_structure ['unCompressedSize'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 4 ) );
-
- $CompressedFileData = substr ( $atom_data, 4 );
- if (($UncompressedHeader = @gzuncompress ( $CompressedFileData )) != false) {
- $atom_structure ['subatoms'] = $this->QuicktimeParseContainerAtom ( $UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms );
- } else {
- $info ['warning'] [] = 'Error decompressing compressed MOV atom at offset ' . $atom_structure ['offset'];
- }
- break;
-
- case 'dcom' : // Data COMpression atom
- $atom_structure ['compression_id'] = $atom_data;
- $atom_structure ['compression_text'] = $this->QuicktimeDCOMLookup ( $atom_data );
- break;
-
- case 'rdrf' : // Reference movie Data ReFerence atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) );
- $atom_structure ['flags'] ['internal_data'] = ( bool ) ($atom_structure ['flags_raw'] & 0x000001);
-
- $atom_structure ['reference_type_name'] = substr ( $atom_data, 4, 4 );
- $atom_structure ['reference_length'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 4 ) );
- switch ($atom_structure ['reference_type_name']) {
- case 'url ' :
- $atom_structure ['url'] = $this->NoNullString ( substr ( $atom_data, 12 ) );
- break;
-
- case 'alis' :
- $atom_structure ['file_alias'] = substr ( $atom_data, 12 );
- break;
-
- case 'rsrc' :
- $atom_structure ['resource_alias'] = substr ( $atom_data, 12 );
- break;
-
- default :
- $atom_structure ['data'] = substr ( $atom_data, 12 );
- break;
- }
- break;
-
- case 'rmqu' : // Reference Movie QUality atom
- $atom_structure ['movie_quality'] = getid3_lib::BigEndian2Int ( $atom_data );
- break;
-
- case 'rmcs' : // Reference Movie Cpu Speed atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['cpu_speed_rating'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
- break;
-
- case 'rmvc' : // Reference Movie Version Check atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['gestalt_selector'] = substr ( $atom_data, 4, 4 );
- $atom_structure ['gestalt_value_mask'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 4 ) );
- $atom_structure ['gestalt_value'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 12, 4 ) );
- $atom_structure ['gestalt_check_type'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 14, 2 ) );
- break;
-
- case 'rmcd' : // Reference Movie Component check atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['component_type'] = substr ( $atom_data, 4, 4 );
- $atom_structure ['component_subtype'] = substr ( $atom_data, 8, 4 );
- $atom_structure ['component_manufacturer'] = substr ( $atom_data, 12, 4 );
- $atom_structure ['component_flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 16, 4 ) );
- $atom_structure ['component_flags_mask'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 20, 4 ) );
- $atom_structure ['component_min_version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 24, 4 ) );
- break;
-
- case 'rmdr' : // Reference Movie Data Rate atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['data_rate'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
-
- $atom_structure ['data_rate_bps'] = $atom_structure ['data_rate'] * 10;
- break;
-
- case 'rmla' : // Reference Movie Language Atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['language_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
-
- $atom_structure ['language'] = $this->QuicktimeLanguageLookup ( $atom_structure ['language_id'] );
- if (empty ( $info ['comments'] ['language'] ) || (! in_array ( $atom_structure ['language'], $info ['comments'] ['language'] ))) {
- $info ['comments'] ['language'] [] = $atom_structure ['language'];
- }
- break;
-
- case 'rmla' : // Reference Movie Language Atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['track_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
- break;
-
- case 'ptv ' : // Print To Video - defines a movie's full screen mode
- // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
- $atom_structure ['display_size_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 2 ) );
- $atom_structure ['reserved_1'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 2, 2 ) ); // hardcoded: 0x0000
- $atom_structure ['reserved_2'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) ); // hardcoded: 0x0000
- $atom_structure ['slide_show_flag'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 6, 1 ) );
- $atom_structure ['play_on_open_flag'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 7, 1 ) );
-
- $atom_structure ['flags'] ['play_on_open'] = ( bool ) $atom_structure ['play_on_open_flag'];
- $atom_structure ['flags'] ['slide_show'] = ( bool ) $atom_structure ['slide_show_flag'];
-
- $ptv_lookup [0] = 'normal';
- $ptv_lookup [1] = 'double';
- $ptv_lookup [2] = 'half';
- $ptv_lookup [3] = 'full';
- $ptv_lookup [4] = 'current';
- if (isset ( $ptv_lookup [$atom_structure ['display_size_raw']] )) {
- $atom_structure ['display_size'] = $ptv_lookup [$atom_structure ['display_size_raw']];
- } else {
- $info ['warning'] [] = 'unknown "ptv " display constant (' . $atom_structure ['display_size_raw'] . ')';
- }
- break;
-
- case 'stsd' : // Sample Table Sample Description atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $stsdEntriesDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['sample_description_table'] [$i] ['size'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stsdEntriesDataOffset, 4 ) );
- $stsdEntriesDataOffset += 4;
- $atom_structure ['sample_description_table'] [$i] ['data_format'] = substr ( $atom_data, $stsdEntriesDataOffset, 4 );
- $stsdEntriesDataOffset += 4;
- $atom_structure ['sample_description_table'] [$i] ['reserved'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stsdEntriesDataOffset, 6 ) );
- $stsdEntriesDataOffset += 6;
- $atom_structure ['sample_description_table'] [$i] ['reference_index'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stsdEntriesDataOffset, 2 ) );
- $stsdEntriesDataOffset += 2;
- $atom_structure ['sample_description_table'] [$i] ['data'] = substr ( $atom_data, $stsdEntriesDataOffset, ($atom_structure ['sample_description_table'] [$i] ['size'] - 4 - 4 - 6 - 2) );
- $stsdEntriesDataOffset += ($atom_structure ['sample_description_table'] [$i] ['size'] - 4 - 4 - 6 - 2);
-
- $atom_structure ['sample_description_table'] [$i] ['encoder_version'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 0, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['encoder_revision'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 2, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['encoder_vendor'] = substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 4, 4 );
-
- switch ($atom_structure ['sample_description_table'] [$i] ['encoder_vendor']) {
-
- case "\x00\x00\x00\x00" :
- // audio atom
- $atom_structure ['sample_description_table'] [$i] ['audio_channels'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 8, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['audio_bit_depth'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 10, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['audio_compression_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 12, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['audio_packet_size'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 14, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['audio_sample_rate'] = getid3_lib::FixedPoint16_16 ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 16, 4 ) );
-
- switch ($atom_structure ['sample_description_table'] [$i] ['data_format']) {
- case 'avc1' :
- case 'mp4v' :
- $info ['fileformat'] = 'mp4';
- $info ['video'] ['fourcc'] = $atom_structure ['sample_description_table'] [$i] ['data_format'];
- //$info['warning'][] = 'This version of getID3() ['.$this->getid3->version().'] does not fully support MPEG-4 audio/video streams'; // 2011-02-18: why am I warning about this again? What's not supported?
- break;
-
- case 'qtvr' :
- $info ['video'] ['dataformat'] = 'quicktimevr';
- break;
-
- case 'mp4a' :
- default :
- $info ['quicktime'] ['audio'] ['codec'] = $this->QuicktimeAudioCodecLookup ( $atom_structure ['sample_description_table'] [$i] ['data_format'] );
- $info ['quicktime'] ['audio'] ['sample_rate'] = $atom_structure ['sample_description_table'] [$i] ['audio_sample_rate'];
- $info ['quicktime'] ['audio'] ['channels'] = $atom_structure ['sample_description_table'] [$i] ['audio_channels'];
- $info ['quicktime'] ['audio'] ['bit_depth'] = $atom_structure ['sample_description_table'] [$i] ['audio_bit_depth'];
- $info ['audio'] ['codec'] = $info ['quicktime'] ['audio'] ['codec'];
- $info ['audio'] ['sample_rate'] = $info ['quicktime'] ['audio'] ['sample_rate'];
- $info ['audio'] ['channels'] = $info ['quicktime'] ['audio'] ['channels'];
- $info ['audio'] ['bits_per_sample'] = $info ['quicktime'] ['audio'] ['bit_depth'];
- switch ($atom_structure ['sample_description_table'] [$i] ['data_format']) {
- case 'raw ' : // PCM
- case 'alac' : // Apple Lossless Audio Codec
- $info ['audio'] ['lossless'] = true;
- break;
- default :
- $info ['audio'] ['lossless'] = false;
- break;
- }
- break;
- }
- break;
-
- default :
- switch ($atom_structure ['sample_description_table'] [$i] ['data_format']) {
- case 'mp4s' :
- $info ['fileformat'] = 'mp4';
- break;
-
- default :
- // video atom
- $atom_structure ['sample_description_table'] [$i] ['video_temporal_quality'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 8, 4 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_spatial_quality'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 12, 4 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_frame_width'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 16, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_frame_height'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 18, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_resolution_x'] = getid3_lib::FixedPoint16_16 ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 20, 4 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_resolution_y'] = getid3_lib::FixedPoint16_16 ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 24, 4 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_data_size'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 28, 4 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_frame_count'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 32, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_encoder_name_len'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 34, 1 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_encoder_name'] = substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 35, $atom_structure ['sample_description_table'] [$i] ['video_encoder_name_len'] );
- $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_depth'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 66, 2 ) );
- $atom_structure ['sample_description_table'] [$i] ['video_color_table_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_structure ['sample_description_table'] [$i] ['data'], 68, 2 ) );
-
- $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_type'] = (($atom_structure ['sample_description_table'] [$i] ['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
- $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_name'] = $this->QuicktimeColorNameLookup ( $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_depth'] );
-
- if ($atom_structure ['sample_description_table'] [$i] ['video_pixel_color_name'] != 'invalid') {
- $info ['quicktime'] ['video'] ['codec_fourcc'] = $atom_structure ['sample_description_table'] [$i] ['data_format'];
- $info ['quicktime'] ['video'] ['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup ( $atom_structure ['sample_description_table'] [$i] ['data_format'] );
- $info ['quicktime'] ['video'] ['codec'] = (($atom_structure ['sample_description_table'] [$i] ['video_encoder_name_len'] > 0) ? $atom_structure ['sample_description_table'] [$i] ['video_encoder_name'] : $atom_structure ['sample_description_table'] [$i] ['data_format']);
- $info ['quicktime'] ['video'] ['color_depth'] = $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_depth'];
- $info ['quicktime'] ['video'] ['color_depth_name'] = $atom_structure ['sample_description_table'] [$i] ['video_pixel_color_name'];
-
- $info ['video'] ['codec'] = $info ['quicktime'] ['video'] ['codec'];
- $info ['video'] ['bits_per_sample'] = $info ['quicktime'] ['video'] ['color_depth'];
- }
- $info ['video'] ['lossless'] = false;
- $info ['video'] ['pixel_aspect_ratio'] = ( float ) 1;
- break;
- }
- break;
- }
- switch (strtolower ( $atom_structure ['sample_description_table'] [$i] ['data_format'] )) {
- case 'mp4a' :
- $info ['audio'] ['dataformat'] = 'mp4';
- $info ['quicktime'] ['audio'] ['codec'] = 'mp4';
- break;
-
- case '3ivx' :
- case '3iv1' :
- case '3iv2' :
- $info ['video'] ['dataformat'] = '3ivx';
- break;
-
- case 'xvid' :
- $info ['video'] ['dataformat'] = 'xvid';
- break;
-
- case 'mp4v' :
- $info ['video'] ['dataformat'] = 'mpeg4';
- break;
-
- case 'divx' :
- case 'div1' :
- case 'div2' :
- case 'div3' :
- case 'div4' :
- case 'div5' :
- case 'div6' :
- $info ['video'] ['dataformat'] = 'divx';
- break;
-
- default :
- // do nothing
- break;
- }
- unset ( $atom_structure ['sample_description_table'] [$i] ['data'] );
- }
- break;
-
- case 'stts' : // Sample Table Time-to-Sample atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $sttsEntriesDataOffset = 8;
- //$FrameRateCalculatorArray = array();
- $frames_count = 0;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['time_to_sample_table'] [$i] ['sample_count'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $sttsEntriesDataOffset, 4 ) );
- $sttsEntriesDataOffset += 4;
- $atom_structure ['time_to_sample_table'] [$i] ['sample_duration'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $sttsEntriesDataOffset, 4 ) );
- $sttsEntriesDataOffset += 4;
-
- $frames_count += $atom_structure ['time_to_sample_table'] [$i] ['sample_count'];
-
- // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
- //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
- // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
- // if ($stts_new_framerate <= 60) {
- // // some atoms have durations of "1" giving a very large framerate, which probably is not right
- // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
- // }
- //}
- //
- //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
- }
- $info ['quicktime'] ['stts_framecount'] [] = $frames_count;
- //$sttsFramesTotal = 0;
- //$sttsSecondsTotal = 0;
- //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
- // if (($frames_per_second > 60) || ($frames_per_second < 1)) {
- // // not video FPS information, probably audio information
- // $sttsFramesTotal = 0;
- // $sttsSecondsTotal = 0;
- // break;
- // }
- // $sttsFramesTotal += $frame_count;
- // $sttsSecondsTotal += $frame_count / $frames_per_second;
- //}
- //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
- // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
- // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
- // }
- //}
- break;
-
- case 'stss' : // Sample Table Sync Sample (key frames) atom
- if ($ParseAllPossibleAtoms) {
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $stssEntriesDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['time_to_sample_table'] [$i] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stssEntriesDataOffset, 4 ) );
- $stssEntriesDataOffset += 4;
- }
- }
- break;
-
- case 'stsc' : // Sample Table Sample-to-Chunk atom
- if ($ParseAllPossibleAtoms) {
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $stscEntriesDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['sample_to_chunk_table'] [$i] ['first_chunk'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stscEntriesDataOffset, 4 ) );
- $stscEntriesDataOffset += 4;
- $atom_structure ['sample_to_chunk_table'] [$i] ['samples_per_chunk'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stscEntriesDataOffset, 4 ) );
- $stscEntriesDataOffset += 4;
- $atom_structure ['sample_to_chunk_table'] [$i] ['sample_description'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stscEntriesDataOffset, 4 ) );
- $stscEntriesDataOffset += 4;
- }
- }
- break;
-
- case 'stsz' : // Sample Table SiZe atom
- if ($ParseAllPossibleAtoms) {
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['sample_size'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 4 ) );
- $stszEntriesDataOffset = 12;
- if ($atom_structure ['sample_size'] == 0) {
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['sample_size_table'] [$i] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stszEntriesDataOffset, 4 ) );
- $stszEntriesDataOffset += 4;
- }
- }
- }
- break;
-
- case 'stco' : // Sample Table Chunk Offset atom
- if ($ParseAllPossibleAtoms) {
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $stcoEntriesDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['chunk_offset_table'] [$i] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stcoEntriesDataOffset, 4 ) );
- $stcoEntriesDataOffset += 4;
- }
- }
- break;
-
- case 'co64' : // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
- if ($ParseAllPossibleAtoms) {
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $stcoEntriesDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['chunk_offset_table'] [$i] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $stcoEntriesDataOffset, 8 ) );
- $stcoEntriesDataOffset += 8;
- }
- }
- break;
-
- case 'dref' : // Data REFerence atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['number_entries'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $drefDataOffset = 8;
- for($i = 0; $i < $atom_structure ['number_entries']; $i ++) {
- $atom_structure ['data_references'] [$i] ['size'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $drefDataOffset, 4 ) );
- $drefDataOffset += 4;
- $atom_structure ['data_references'] [$i] ['type'] = substr ( $atom_data, $drefDataOffset, 4 );
- $drefDataOffset += 4;
- $atom_structure ['data_references'] [$i] ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $drefDataOffset, 1 ) );
- $drefDataOffset += 1;
- $atom_structure ['data_references'] [$i] ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, $drefDataOffset, 3 ) ); // hardcoded: 0x0000
- $drefDataOffset += 3;
- $atom_structure ['data_references'] [$i] ['data'] = substr ( $atom_data, $drefDataOffset, ($atom_structure ['data_references'] [$i] ['size'] - 4 - 4 - 1 - 3) );
- $drefDataOffset += ($atom_structure ['data_references'] [$i] ['size'] - 4 - 4 - 1 - 3);
-
- $atom_structure ['data_references'] [$i] ['flags'] ['self_reference'] = ( bool ) ($atom_structure ['data_references'] [$i] ['flags_raw'] & 0x001);
- }
- break;
-
- case 'gmin' : // base Media INformation atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['graphics_mode'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
- $atom_structure ['opcolor_red'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 6, 2 ) );
- $atom_structure ['opcolor_green'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 2 ) );
- $atom_structure ['opcolor_blue'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 10, 2 ) );
- $atom_structure ['balance'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 12, 2 ) );
- $atom_structure ['reserved'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 14, 2 ) );
- break;
-
- case 'smhd' : // Sound Media information HeaDer atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['balance'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
- $atom_structure ['reserved'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 6, 2 ) );
- break;
-
- case 'vmhd' : // Video Media information HeaDer atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) );
- $atom_structure ['graphics_mode'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 2 ) );
- $atom_structure ['opcolor_red'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 6, 2 ) );
- $atom_structure ['opcolor_green'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 2 ) );
- $atom_structure ['opcolor_blue'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 10, 2 ) );
-
- $atom_structure ['flags'] ['no_lean_ahead'] = ( bool ) ($atom_structure ['flags_raw'] & 0x001);
- break;
-
- case 'hdlr' : // HanDLeR reference atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['component_type'] = substr ( $atom_data, 4, 4 );
- $atom_structure ['component_subtype'] = substr ( $atom_data, 8, 4 );
- $atom_structure ['component_manufacturer'] = substr ( $atom_data, 12, 4 );
- $atom_structure ['component_flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 16, 4 ) );
- $atom_structure ['component_flags_mask'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 20, 4 ) );
- $atom_structure ['component_name'] = $this->Pascal2String ( substr ( $atom_data, 24 ) );
-
- if (($atom_structure ['component_subtype'] == 'STpn') && ($atom_structure ['component_manufacturer'] == 'zzzz')) {
- $info ['video'] ['dataformat'] = 'quicktimevr';
- }
- break;
-
- case 'mdhd' : // MeDia HeaDer atom
- $atom_structure ['version'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 1 ) );
- $atom_structure ['flags_raw'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 1, 3 ) ); // hardcoded: 0x0000
- $atom_structure ['creation_time'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 4, 4 ) );
- $atom_structure ['modify_time'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 8, 4 ) );
- $atom_structure ['time_scale'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 12, 4 ) );
- $atom_structure ['duration'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 16, 4 ) );
- $atom_structure ['language_id'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 20, 2 ) );
- $atom_structure ['quality'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 22, 2 ) );
-
- if ($atom_structure ['time_scale'] == 0) {
- $info ['error'] [] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
- return false;
- }
- $info ['quicktime'] ['time_scale'] = (isset ( $info ['quicktime'] ['time_scale'] ) ? max ( $info ['quicktime'] ['time_scale'], $atom_structure ['time_scale'] ) : $atom_structure ['time_scale']);
-
- $atom_structure ['creation_time_unix'] = getid3_lib::DateMac2Unix ( $atom_structure ['creation_time'] );
- $atom_structure ['modify_time_unix'] = getid3_lib::DateMac2Unix ( $atom_structure ['modify_time'] );
- $atom_structure ['playtime_seconds'] = $atom_structure ['duration'] / $atom_structure ['time_scale'];
- $atom_structure ['language'] = $this->QuicktimeLanguageLookup ( $atom_structure ['language_id'] );
- if (empty ( $info ['comments'] ['language'] ) || (! in_array ( $atom_structure ['language'], $info ['comments'] ['language'] ))) {
- $info ['comments'] ['language'] [] = $atom_structure ['language'];
- }
- break;
-
- case 'pnot' : // Preview atom
- $atom_structure ['modification_date'] = getid3_lib::BigEndian2Int ( substr ( $atom_data, 0, 4 ) ); // "standard Mac…
Large files files are truncated, but you can click here to view the full file