예제 #1
0
 function getid3_riff(&$fd, &$ThisFileInfo)
 {
     // initialize these values to an empty array, otherwise they default to NULL
     // and you can't append array values to a NULL value
     $ThisFileInfo['riff'] = array('raw' => array());
     // Shortcuts
     $thisfile_riff =& $ThisFileInfo['riff'];
     $thisfile_riff_raw =& $thisfile_riff['raw'];
     $thisfile_audio =& $ThisFileInfo['audio'];
     $thisfile_video =& $ThisFileInfo['video'];
     $thisfile_avdataoffset =& $ThisFileInfo['avdataoffset'];
     $thisfile_avdataend =& $ThisFileInfo['avdataend'];
     $thisfile_audio_dataformat =& $thisfile_audio['dataformat'];
     $thisfile_riff_audio =& $thisfile_riff['audio'];
     $thisfile_riff_video =& $thisfile_riff['video'];
     $Original['avdataoffset'] = $thisfile_avdataoffset;
     $Original['avdataend'] = $thisfile_avdataend;
     fseek($fd, $thisfile_avdataoffset, SEEK_SET);
     $RIFFheader = fread($fd, 12);
     $RIFFsubtype = substr($RIFFheader, 8, 4);
     switch (substr($RIFFheader, 0, 4)) {
         case 'FORM':
             $ThisFileInfo['fileformat'] = 'aiff';
             $RIFFheaderSize = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($RIFFheader, 4, 4));
             $thisfile_riff[$RIFFsubtype] = getid3_riff::ParseRIFF($fd, $thisfile_avdataoffset + 12, $thisfile_avdataoffset + $RIFFheaderSize, $ThisFileInfo);
             $thisfile_riff['header_size'] = $RIFFheaderSize;
             break;
         case 'RIFF':
         case 'SDSS':
             // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         case 'RMP3':
             // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
             if ($RIFFsubtype == 'RMP3') {
                 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
                 $RIFFsubtype = 'WAVE';
             }
             $ThisFileInfo['fileformat'] = 'riff';
             $RIFFheaderSize = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($RIFFheader, 4, 4));
             $thisfile_riff[$RIFFsubtype] = getid3_riff::ParseRIFF($fd, $thisfile_avdataoffset + 12, $thisfile_avdataoffset + $RIFFheaderSize, $ThisFileInfo);
             $thisfile_riff['header_size'] = $RIFFheaderSize;
             if ($RIFFsubtype == 'WAVE') {
                 $thisfile_riff_WAVE =& $thisfile_riff['WAVE'];
             }
             break;
         default:
             $ThisFileInfo['error'][] = 'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "' . $RIFFsubtype . '" instead';
             unset($ThisFileInfo['fileformat']);
             return false;
             break;
     }
     $streamindex = 0;
     switch ($RIFFsubtype) {
         case 'WAVE':
             if (empty($thisfile_audio['bitrate_mode'])) {
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             if (empty($thisfile_audio_dataformat)) {
                 $thisfile_audio_dataformat = 'wav';
             }
             if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
                 $thisfile_avdataoffset = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
                 $thisfile_avdataend = $thisfile_avdataoffset + $thisfile_riff_WAVE['data'][0]['size'];
             }
             if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
                 $thisfile_riff_audio[$streamindex] = getid3_riff::RIFFparseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
                 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                 if (@$thisfile_riff_audio[$streamindex]['bitrate'] == 0) {
                     $ThisFileInfo['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
                     return false;
                 }
                 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
                 unset($thisfile_riff_audio[$streamindex]['raw']);
                 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
                     $ThisFileInfo['warning'][] = 'Audio codec = ' . $thisfile_audio['codec'];
                 }
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 $ThisFileInfo['playtime_seconds'] = (double) (($thisfile_avdataend - $thisfile_avdataoffset) * 8 / $thisfile_audio['bitrate']);
                 $thisfile_audio['lossless'] = false;
                 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                     switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                         case 0x1:
                             // PCM
                             $thisfile_audio['lossless'] = true;
                             break;
                         case 0x2000:
                             // AC-3
                             $thisfile_audio_dataformat = 'ac3';
                             break;
                         default:
                             // do nothing
                             break;
                     }
                 }
                 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
                 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
                 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
             }
             if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
                 // shortcuts
                 $rgadData =& $thisfile_riff_WAVE['rgad'][0]['data'];
                 $thisfile_riff_raw['rgad'] = array('track' => array(), 'album' => array());
                 $thisfile_riff_raw_rgad =& $thisfile_riff_raw['rgad'];
                 $thisfile_riff_raw_rgad_track =& $thisfile_riff_raw_rgad['track'];
                 $thisfile_riff_raw_rgad_album =& $thisfile_riff_raw_rgad['album'];
                 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
                 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($rgadData, 4, 2));
                 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($rgadData, 6, 2));
                 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
                 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
                 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
                 if ($thisfile_riff_raw_rgad_track['name'] != 0 && $thisfile_riff_raw_rgad_track['originator'] != 0) {
                     $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
                     $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
                     $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
                 }
                 if ($thisfile_riff_raw_rgad_album['name'] != 0 && $thisfile_riff_raw_rgad_album['originator'] != 0) {
                     $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
                     $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
                     $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
                 }
             }
             if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
                 $thisfile_riff_raw['fact']['NumberOfSamples'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
                 // This should be a good way of calculating exact playtime,
                 // but some sample files have had incorrect number of samples,
                 // so cannot use this method
                 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
                 //     $ThisFileInfo['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
                 // }
             }
             if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
                 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
             }
             if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_bext_0 =& $thisfile_riff_WAVE['bext'][0];
                 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
                 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
                 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
                 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
                 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
                 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
                 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
                 $thisfile_riff_WAVE_bext_0['reserved'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 347, 254));
                 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
                 $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime(substr($thisfile_riff_WAVE_bext_0['origin_time'], 0, 2), substr($thisfile_riff_WAVE_bext_0['origin_time'], 3, 2), substr($thisfile_riff_WAVE_bext_0['origin_time'], 6, 2), substr($thisfile_riff_WAVE_bext_0['origin_date'], 5, 2), substr($thisfile_riff_WAVE_bext_0['origin_date'], 8, 2), substr($thisfile_riff_WAVE_bext_0['origin_date'], 0, 4));
                 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
             }
             if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_MEXT_0 =& $thisfile_riff_WAVE['MEXT'][0];
                 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x1);
                 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
                     $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x2 ? false : true;
                     $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x4);
                     $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x8);
                     $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
                 }
                 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
                 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x1);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x2);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x4);
             }
             if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_cart_0 =& $thisfile_riff_WAVE['cart'][0];
                 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
                 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
                 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
                 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
                 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
                 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
                 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
                 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
                 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
                 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
                 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
                 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
                 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
                 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
                 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
                 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
                 for ($i = 0; $i < 8; $i++) {
                     $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + $i * 8, 4);
                     $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));
                 }
                 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
                 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
                 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
             }
             if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 $ThisFileInfo['playtime_seconds'] = (double) (($thisfile_avdataend - $thisfile_avdataoffset) * 8 / $thisfile_audio['bitrate']);
             }
             if (!empty($ThisFileInfo['wavpack'])) {
                 $thisfile_audio_dataformat = 'wavpack';
                 $thisfile_audio['bitrate_mode'] = 'vbr';
                 $thisfile_audio['encoder'] = 'WavPack v' . $ThisFileInfo['wavpack']['version'];
                 // Reset to the way it was - RIFF parsing will have messed this up
                 $thisfile_avdataend = $Original['avdataend'];
                 $thisfile_audio['bitrate'] = ($thisfile_avdataend - $thisfile_avdataoffset) * 8 / $ThisFileInfo['playtime_seconds'];
                 fseek($fd, $thisfile_avdataoffset - 44, SEEK_SET);
                 $RIFFdata = fread($fd, 44);
                 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
                 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
                 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
                     $thisfile_avdataend -= $OrignalRIFFheaderSize - $OrignalRIFFdataSize;
                     fseek($fd, $thisfile_avdataend, SEEK_SET);
                     $RIFFdata .= fread($fd, $OrignalRIFFheaderSize - $OrignalRIFFdataSize);
                 }
                 // move the data chunk after all other chunks (if any)
                 // so that the RIFF parser doesn't see EOF when trying
                 // to skip over the data chunk
                 $RIFFdata = substr($RIFFdata, 0, 36) . substr($RIFFdata, 44) . substr($RIFFdata, 36, 8);
                 getid3_riff::ParseRIFFdata($RIFFdata, $ThisFileInfo);
             }
             if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                     case 0x8ae:
                         // ClearJump LiteWave
                         $thisfile_audio['bitrate_mode'] = 'vbr';
                         $thisfile_audio_dataformat = 'litewave';
                         //typedef struct tagSLwFormat {
                         //  WORD    m_wCompFormat;     // low byte defines compression method, high byte is compression flags
                         //  DWORD   m_dwScale;         // scale factor for lossy compression
                         //  DWORD   m_dwBlockSize;     // number of samples in encoded blocks
                         //  WORD    m_wQuality;        // alias for the scale factor
                         //  WORD    m_wMarkDistance;   // distance between marks in bytes
                         //  WORD    m_wReserved;
                         //
                         //  //following paramters are ignored if CF_FILESRC is not set
                         //  DWORD   m_dwOrgSize;       // original file size in bytes
                         //  WORD    m_bFactExists;     // indicates if 'fact' chunk exists in the original file
                         //  DWORD   m_dwRiffChunkSize; // riff chunk size in the original file
                         //
                         //  PCMWAVEFORMAT m_OrgWf;     // original wave format
                         // }SLwFormat, *PSLwFormat;
                         // shortcut
                         $thisfile_riff['litewave']['raw'] = array();
                         $thisfile_riff_litewave =& $thisfile_riff['litewave'];
                         $thisfile_riff_litewave_raw =& $thisfile_riff_litewave['raw'];
                         $thisfile_riff_litewave_raw['compression_method'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 18, 1));
                         $thisfile_riff_litewave_raw['compression_flags'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 19, 1));
                         $thisfile_riff_litewave_raw['m_dwScale'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 20, 4));
                         $thisfile_riff_litewave_raw['m_dwBlockSize'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 24, 4));
                         $thisfile_riff_litewave_raw['m_wQuality'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 28, 2));
                         $thisfile_riff_litewave_raw['m_wMarkDistance'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 30, 2));
                         $thisfile_riff_litewave_raw['m_wReserved'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 32, 2));
                         $thisfile_riff_litewave_raw['m_dwOrgSize'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 34, 4));
                         $thisfile_riff_litewave_raw['m_bFactExists'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 38, 2));
                         $thisfile_riff_litewave_raw['m_dwRiffChunkSize'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], 40, 4));
                         //$thisfile_riff_litewave['quality_factor'] = intval(round((2000 - $thisfile_riff_litewave_raw['m_dwScale']) / 20));
                         $thisfile_riff_litewave['quality_factor'] = $thisfile_riff_litewave_raw['m_wQuality'];
                         $thisfile_riff_litewave['flags']['raw_source'] = $thisfile_riff_litewave_raw['compression_flags'] & 0x1 ? false : true;
                         $thisfile_riff_litewave['flags']['vbr_blocksize'] = $thisfile_riff_litewave_raw['compression_flags'] & 0x2 ? false : true;
                         $thisfile_riff_litewave['flags']['seekpoints'] = (bool) ($thisfile_riff_litewave_raw['compression_flags'] & 0x4);
                         $thisfile_audio['lossless'] = $thisfile_riff_litewave_raw['m_wQuality'] == 100 ? true : false;
                         $thisfile_audio['encoder_options'] = '-q' . $thisfile_riff_litewave['quality_factor'];
                         break;
                     default:
                         break;
                 }
             }
             if ($thisfile_avdataend > $ThisFileInfo['filesize']) {
                 switch (@$thisfile_audio_dataformat) {
                     case 'wavpack':
                         // WavPack
                     // WavPack
                     case 'lpac':
                         // LPAC
                     // LPAC
                     case 'ofr':
                         // OptimFROG
                     // OptimFROG
                     case 'ofs':
                         // OptimFROG DualStream
                         // lossless compressed audio formats that keep original RIFF headers - skip warning
                         break;
                     case 'litewave':
                         if ($thisfile_avdataend - $ThisFileInfo['filesize'] == 1) {
                             // LiteWave appears to incorrectly *not* pad actual output file
                             // to nearest WORD boundary so may appear to be short by one
                             // byte, in which case - skip warning
                         } else {
                             // Short by more than one byte, throw warning
                             $ThisFileInfo['warning'][] = 'Probably truncated file - expecting ' . $thisfile_riff[$RIFFsubtype]['data'][0]['size'] . ' bytes of data, only found ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' (short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($ThisFileInfo['filesize'] - $thisfile_avdataoffset)) . ' bytes)';
                             $thisfile_avdataend = $ThisFileInfo['filesize'];
                         }
                         break;
                     default:
                         if ($thisfile_avdataend - $ThisFileInfo['filesize'] == 1 && $thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2 == 0 && ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) % 2 == 1) {
                             // output file appears to be incorrectly *not* padded to nearest WORD boundary
                             // Output less severe warning
                             $ThisFileInfo['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 ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' therefore short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($ThisFileInfo['filesize'] - $thisfile_avdataoffset)) . ' bytes)';
                             $thisfile_avdataend = $ThisFileInfo['filesize'];
                             break;
                         }
                         // Short by more than one byte, throw warning
                         $ThisFileInfo['warning'][] = 'Probably truncated file - expecting ' . $thisfile_riff[$RIFFsubtype]['data'][0]['size'] . ' bytes of data, only found ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' (short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($ThisFileInfo['filesize'] - $thisfile_avdataoffset)) . ' bytes)';
                         $thisfile_avdataend = $ThisFileInfo['filesize'];
                         break;
                 }
             }
             if (!empty($ThisFileInfo['mpeg']['audio']['LAME']['audio_bytes'])) {
                 if ($thisfile_avdataend - $thisfile_avdataoffset - $ThisFileInfo['mpeg']['audio']['LAME']['audio_bytes'] == 1) {
                     $thisfile_avdataend--;
                     $ThisFileInfo['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
                 }
             }
             if (@$thisfile_audio_dataformat == 'ac3') {
                 unset($thisfile_audio['bits_per_sample']);
                 if (!empty($ThisFileInfo['ac3']['bitrate']) && $ThisFileInfo['ac3']['bitrate'] != $thisfile_audio['bitrate']) {
                     $thisfile_audio['bitrate'] = $ThisFileInfo['ac3']['bitrate'];
                 }
             }
             break;
         case 'AVI ':
             $thisfile_video['bitrate_mode'] = 'vbr';
             // maybe not, but probably
             $thisfile_video['dataformat'] = 'avi';
             $ThisFileInfo['mime_type'] = 'video/avi';
             if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
                 $thisfile_avdataoffset = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
                 $thisfile_avdataend = $thisfile_avdataoffset + $thisfile_riff[$RIFFsubtype]['movi']['size'];
                 if ($thisfile_avdataend > $ThisFileInfo['filesize']) {
                     $ThisFileInfo['warning'][] = 'Probably truncated file - expecting ' . $thisfile_riff[$RIFFsubtype]['movi']['size'] . ' bytes of data, only found ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' (short by ' . ($thisfile_riff[$RIFFsubtype]['movi']['size'] - ($ThisFileInfo['filesize'] - $thisfile_avdataoffset)) . ' bytes)';
                     $thisfile_avdataend = $ThisFileInfo['filesize'];
                 }
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
                 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
                 // shortcut
                 $thisfile_riff_raw['avih'] = array();
                 $thisfile_riff_raw_avih =& $thisfile_riff_raw['avih'];
                 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 0, 4));
                 // frame display rate (or 0L)
                 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
                     $ThisFileInfo['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
                     return false;
                 }
                 $thisfile_riff_raw_avih['dwMaxBytesPerSec'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 4, 4));
                 // max. transfer rate
                 $thisfile_riff_raw_avih['dwPaddingGranularity'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 8, 4));
                 // pad to multiples of this size; normally 2K.
                 $thisfile_riff_raw_avih['dwFlags'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 12, 4));
                 // the ever-present flags
                 $thisfile_riff_raw_avih['dwTotalFrames'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 16, 4));
                 // # frames in file
                 $thisfile_riff_raw_avih['dwInitialFrames'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 20, 4));
                 $thisfile_riff_raw_avih['dwStreams'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 24, 4));
                 $thisfile_riff_raw_avih['dwSuggestedBufferSize'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 28, 4));
                 $thisfile_riff_raw_avih['dwWidth'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 32, 4));
                 $thisfile_riff_raw_avih['dwHeight'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 36, 4));
                 $thisfile_riff_raw_avih['dwScale'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 40, 4));
                 $thisfile_riff_raw_avih['dwRate'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 44, 4));
                 $thisfile_riff_raw_avih['dwStart'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 48, 4));
                 $thisfile_riff_raw_avih['dwLength'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($avihData, 52, 4));
                 $thisfile_riff_raw_avih['flags']['hasindex'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x10);
                 $thisfile_riff_raw_avih['flags']['mustuseindex'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x20);
                 $thisfile_riff_raw_avih['flags']['interleaved'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x100);
                 $thisfile_riff_raw_avih['flags']['trustcktype'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x800);
                 $thisfile_riff_raw_avih['flags']['capturedfile'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x10000);
                 $thisfile_riff_raw_avih['flags']['copyrighted'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x20010);
                 // shortcut
                 $thisfile_riff_video[$streamindex] = array();
                 $thisfile_riff_video_current =& $thisfile_riff_video[$streamindex];
                 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
                     $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
                     $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
                 }
                 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
                     $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
                     $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
                 }
                 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
                     $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
                     $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
                 }
                 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
                 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
                 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
                     for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
                         if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
                             $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
                             $strhfccType = substr($strhData, 0, 4);
                             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
                                 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
                                 // shortcut
                                 $thisfile_riff_raw_strf_strhfccType_streamindex =& $thisfile_riff_raw['strf'][$strhfccType][$streamindex];
                                 switch ($strhfccType) {
                                     case 'auds':
                                         $thisfile_audio['bitrate_mode'] = 'cbr';
                                         $thisfile_audio_dataformat = 'wav';
                                         if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
                                             $streamindex = count($thisfile_riff_audio);
                                         }
                                         $thisfile_riff_audio[$streamindex] = getid3_riff::RIFFparseWAVEFORMATex($strfData);
                                         $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                                         // shortcut
                                         $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                                         $thisfile_audio_streams_currentstream =& $thisfile_audio['streams'][$streamindex];
                                         if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
                                             unset($thisfile_audio_streams_currentstream['bits_per_sample']);
                                         }
                                         $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
                                         unset($thisfile_audio_streams_currentstream['raw']);
                                         // shortcut
                                         $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
                                         unset($thisfile_riff_audio[$streamindex]['raw']);
                                         $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                                         $thisfile_audio['lossless'] = false;
                                         switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
                                             case 0x1:
                                                 // PCM
                                                 $thisfile_audio_dataformat = 'wav';
                                                 $thisfile_audio['lossless'] = true;
                                                 break;
                                             case 0x50:
                                                 // MPEG Layer 2 or Layer 1
                                                 $thisfile_audio_dataformat = 'mp2';
                                                 // Assume Layer-2
                                                 break;
                                             case 0x55:
                                                 // MPEG Layer 3
                                                 $thisfile_audio_dataformat = 'mp3';
                                                 break;
                                             case 0xff:
                                                 // AAC
                                                 $thisfile_audio_dataformat = 'aac';
                                                 break;
                                             case 0x161:
                                                 // Windows Media v7 / v8 / v9
                                             // Windows Media v7 / v8 / v9
                                             case 0x162:
                                                 // Windows Media Professional v9
                                             // Windows Media Professional v9
                                             case 0x163:
                                                 // Windows Media Lossess v9
                                                 $thisfile_audio_dataformat = 'wma';
                                                 break;
                                             case 0x2000:
                                                 // AC-3
                                                 $thisfile_audio_dataformat = 'ac3';
                                                 break;
                                             case 0x2001:
                                                 // DTS
                                                 $thisfile_audio_dataformat = 'dts';
                                                 break;
                                             default:
                                                 $thisfile_audio_dataformat = 'wav';
                                                 break;
                                         }
                                         $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
                                         $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
                                         $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                                         break;
                                     case 'iavs':
                                     case 'vids':
                                         // shortcut
                                         $thisfile_riff_raw['strh'][$i] = array();
                                         $thisfile_riff_raw_strh_current =& $thisfile_riff_raw['strh'][$i];
                                         $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4);
                                         // same as $strhfccType;
                                         $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
                                         $thisfile_riff_raw_strh_current['dwFlags'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 8, 4));
                                         // Contains AVITF_* flags
                                         $thisfile_riff_raw_strh_current['wPriority'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 12, 2));
                                         $thisfile_riff_raw_strh_current['wLanguage'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 14, 2));
                                         $thisfile_riff_raw_strh_current['dwInitialFrames'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 16, 4));
                                         $thisfile_riff_raw_strh_current['dwScale'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 20, 4));
                                         $thisfile_riff_raw_strh_current['dwRate'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 24, 4));
                                         $thisfile_riff_raw_strh_current['dwStart'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 28, 4));
                                         $thisfile_riff_raw_strh_current['dwLength'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 32, 4));
                                         $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 36, 4));
                                         $thisfile_riff_raw_strh_current['dwQuality'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 40, 4));
                                         $thisfile_riff_raw_strh_current['dwSampleSize'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 44, 4));
                                         $thisfile_riff_raw_strh_current['rcFrame'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strhData, 48, 4));
                                         $thisfile_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
                                         $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
                                         if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && getid3_riff::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                                             $thisfile_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
                                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                                         }
                                         $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                                         $thisfile_video['pixel_aspect_ratio'] = (double) 1;
                                         switch ($thisfile_riff_raw_strh_current['fccHandler']) {
                                             case 'HFYU':
                                                 // Huffman Lossless Codec
                                             // Huffman Lossless Codec
                                             case 'IRAW':
                                                 // Intel YUV Uncompressed
                                             // Intel YUV Uncompressed
                                             case 'YUY2':
                                                 // Uncompressed YUV 4:2:2
                                                 $thisfile_video['lossless'] = true;
                                                 break;
                                             default:
                                                 $thisfile_video['lossless'] = false;
                                                 break;
                                         }
                                         switch ($strhfccType) {
                                             case 'vids':
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biSize'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 0, 4));
                                                 // number of bytes required by the BITMAPINFOHEADER structure
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biWidth'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 4, 4));
                                                 // width of the bitmap in pixels
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biHeight'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 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
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biPlanes'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 12, 2));
                                                 // number of color planes on the target device. In most cases this value must be set to 1
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 14, 2));
                                                 // Specifies the number of bits per pixels
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'] = substr($strfData, 16, 4);
                                                 //
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biSizeImage'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 20, 4));
                                                 // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biXPelsPerMeter'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 24, 4));
                                                 // horizontal resolution, in pixels per metre, of the target device
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biYPelsPerMeter'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 28, 4));
                                                 // vertical resolution, in pixels per metre, of the target device
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biClrUsed'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 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
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex['biClrImportant'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($strfData, 36, 4));
                                                 // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
                                                 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
                                                 if ($thisfile_riff_video_current['codec'] == 'DV') {
                                                     $thisfile_riff_video_current['dv_type'] = 2;
                                                 }
                                                 break;
                                             case 'iavs':
                                                 $thisfile_riff_video_current['dv_type'] = 1;
                                                 break;
                                         }
                                         break;
                                     default:
                                         $ThisFileInfo['warning'][] = 'Unhandled fccType for stream (' . $i . '): "' . $strhfccType . '"';
                                         break;
                                 }
                             }
                         }
                         if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && getid3_riff::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                             $thisfile_riff_video_current['codec'] = getid3_riff::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
                             $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                             switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
                                 case 'HFYU':
                                     // Huffman Lossless Codec
                                 // Huffman Lossless Codec
                                 case 'IRAW':
                                     // Intel YUV Uncompressed
                                 // Intel YUV Uncompressed
                                 case 'YUY2':
                                     // Uncompressed YUV 4:2:2
                                     $thisfile_video['lossless'] = true;
                                     $thisfile_video['bits_per_sample'] = 24;
                                     break;
                                 default:
                                     $thisfile_video['lossless'] = false;
                                     $thisfile_video['bits_per_sample'] = 24;
                                     break;
                             }
                         }
                     }
                 }
             }
             break;
         case 'CDDA':
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = 'cda';
             $thisfile_audio['lossless'] = true;
             unset($ThisFileInfo['mime_type']);
             $thisfile_avdataoffset = 44;
             if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
                 // shortcut
                 $thisfile_riff_CDDA_fmt_0 =& $thisfile_riff['CDDA']['fmt '][0];
                 $thisfile_riff_CDDA_fmt_0['unknown1'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
                 $thisfile_riff_CDDA_fmt_0['track_num'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
                 $thisfile_riff_CDDA_fmt_0['disc_id'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
                 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown6'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown7'] = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
                 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
                 $ThisFileInfo['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
                 $ThisFileInfo['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
                 // hardcoded data for CD-audio
                 $thisfile_audio['sample_rate'] = 44100;
                 $thisfile_audio['channels'] = 2;
                 $thisfile_audio['bits_per_sample'] = 16;
                 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             break;
         case 'AIFF':
         case 'AIFC':
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = 'aiff';
             $thisfile_audio['lossless'] = true;
             $ThisFileInfo['mime_type'] = 'audio/x-aiff';
             if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
                 $thisfile_avdataoffset = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
                 $thisfile_avdataend = $thisfile_avdataoffset + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
                 if ($thisfile_avdataend > $ThisFileInfo['filesize']) {
                     if ($thisfile_avdataend == $ThisFileInfo['filesize'] + 1 && $ThisFileInfo['filesize'] % 2 == 1) {
                         // structures rounded to 2-byte boundary, but dumb encoders
                         // forget to pad end of file to make this actually work
                     } else {
                         $ThisFileInfo['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'] . ' bytes of audio data, only ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' bytes found';
                     }
                     $thisfile_avdataend = $ThisFileInfo['filesize'];
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_COMM_0_data =& $thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
                 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
                 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
                 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
                 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
                 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
                     $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
                     $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
                     $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
                     switch ($thisfile_riff_audio['codec_name']) {
                         case 'NONE':
                             $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                             $thisfile_audio['lossless'] = true;
                             break;
                         case '':
                             switch ($thisfile_riff_audio['codec_fourcc']) {
                                 // http://developer.apple.com/qa/snd/snd07.html
                                 case 'sowt':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 case 'twos':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 default:
                                     break;
                             }
                             break;
                         default:
                             $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
                             $thisfile_audio['lossless'] = false;
                             break;
                     }
                 }
                 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
                 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
                     $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
                 }
                 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
                 if ($thisfile_audio['sample_rate'] == 0) {
                     $ThisFileInfo['error'][] = 'Corrupted AIFF file: sample_rate == zero';
                     return false;
                 }
                 $ThisFileInfo['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
                 $offset = 0;
                 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                 $offset += 2;
                 for ($i = 0; $i < $CommentCount; $i++) {
                     $ThisFileInfo['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
                     $offset += 4;
                     $ThisFileInfo['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
                     $offset += 2;
                     $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                     $offset += 2;
                     $ThisFileInfo['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
                     $offset += $CommentLength;
                     $ThisFileInfo['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($ThisFileInfo['comments_raw'][$i]['timestamp']);
                     $thisfile_riff['comments']['comment'][] = $ThisFileInfo['comments_raw'][$i]['comment'];
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             break;
         case '8SVX':
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = '8svx';
             $thisfile_audio['bits_per_sample'] = 8;
             $thisfile_audio['channels'] = 1;
             // overridden below, if need be
             $ThisFileInfo['mime_type'] = 'audio/x-aiff';
             if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
                 $thisfile_avdataoffset = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
                 $thisfile_avdataend = $thisfile_avdataoffset + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
                 if ($thisfile_avdataend > $ThisFileInfo['filesize']) {
                     $ThisFileInfo['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'] . ' bytes of audio data, only ' . ($ThisFileInfo['filesize'] - $thisfile_avdataoffset) . ' bytes found';
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_VHDR_0 =& $thisfile_riff[$RIFFsubtype]['VHDR'][0];
                 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
                 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
                 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
                 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
                     case 0:
                         $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                         $thisfile_audio['lossless'] = true;
                         $ActualBitsPerSample = 8;
                         break;
                     case 1:
                         $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
                         $thisfile_audio['lossless'] = false;
                         $ActualBitsPerSample = 4;
                         break;
                     default:
                         $ThisFileInfo['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "' . sCompression . '"';
                         break;
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
                 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
                 switch ($ChannelsIndex) {
                     case 6:
                         // Stereo
                         $thisfile_audio['channels'] = 2;
                         break;
                     case 2:
                         // Left channel only
                     // Left channel only
                     case 4:
                         // Right channel only
                         $thisfile_audio['channels'] = 1;
                         break;
                     default:
                         $ThisFileInfo['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "' . $ChannelsIndex . '"';
                         break;
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
             if (!empty($thisfile_audio['bitrate'])) {
                 $ThisFileInfo['playtime_seconds'] = ($thisfile_avdataend - $thisfile_avdataoffset) / ($thisfile_audio['bitrate'] / 8);
             }
             break;
         case 'CDXA':
             $ThisFileInfo['mime_type'] = 'video/mpeg';
             if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
                 $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                 if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.mpeg.php', __FILE__, false)) {
                     $dummy = $ThisFileInfo;
                     $dummy['error'] = array();
                     $mpeg_scanner = new getid3_mpeg($fd, $dummy);
                     if (empty($dummy['error'])) {
                         $ThisFileInfo['audio'] = $dummy['audio'];
                         $ThisFileInfo['video'] = $dummy['video'];
                         $ThisFileInfo['mpeg'] = $dummy['mpeg'];
                         $ThisFileInfo['warning'] = $dummy['warning'];
                     }
                 }
             }
             break;
         default:
             $ThisFileInfo['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "' . $RIFFsubtype . '" instead';
             unset($ThisFileInfo['fileformat']);
             break;
     }
     if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
         $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
     }
     if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
         $this->RIFFcommentsParse($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
     }
     if (empty($thisfile_audio['encoder']) && !empty($ThisFileInfo['mpeg']['audio']['LAME']['short_version'])) {
         $thisfile_audio['encoder'] = $ThisFileInfo['mpeg']['audio']['LAME']['short_version'];
     }
     if (!isset($ThisFileInfo['playtime_seconds'])) {
         $ThisFileInfo['playtime_seconds'] = 0;
     }
     if (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
         $ThisFileInfo['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
     }
     if ($ThisFileInfo['playtime_seconds'] > 0) {
         if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($ThisFileInfo['bitrate'])) {
                 $ThisFileInfo['bitrate'] = ($thisfile_avdataend - $thisfile_avdataoffset) / $ThisFileInfo['playtime_seconds'] * 8;
             }
         } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
             if (!isset($thisfile_audio['bitrate'])) {
                 $thisfile_audio['bitrate'] = ($thisfile_avdataend - $thisfile_avdataoffset) / $ThisFileInfo['playtime_seconds'] * 8;
             }
         } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($thisfile_video['bitrate'])) {
                 $thisfile_video['bitrate'] = ($thisfile_avdataend - $thisfile_avdataoffset) / $ThisFileInfo['playtime_seconds'] * 8;
             }
         }
     }
     if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && $thisfile_audio['bitrate'] > 0 && $ThisFileInfo['playtime_seconds'] > 0) {
         $ThisFileInfo['bitrate'] = ($thisfile_avdataend - $thisfile_avdataoffset) / $ThisFileInfo['playtime_seconds'] * 8;
         $thisfile_audio['bitrate'] = 0;
         $thisfile_video['bitrate'] = $ThisFileInfo['bitrate'];
         foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
             $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
             $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
         }
         if ($thisfile_video['bitrate'] <= 0) {
             unset($thisfile_video['bitrate']);
         }
         if ($thisfile_audio['bitrate'] <= 0) {
             unset($thisfile_audio['bitrate']);
         }
     }
     if (isset($ThisFileInfo['mpeg']['audio'])) {
         $thisfile_audio_dataformat = 'mp' . $ThisFileInfo['mpeg']['audio']['layer'];
         $thisfile_audio['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
         $thisfile_audio['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
         $thisfile_audio['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
         $thisfile_audio['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
         if (!empty($ThisFileInfo['mpeg']['audio']['codec'])) {
             $thisfile_audio['codec'] = $ThisFileInfo['mpeg']['audio']['codec'] . ' ' . $thisfile_audio['codec'];
         }
         if (!empty($thisfile_audio['streams'])) {
             foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
                 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
                     $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
                     $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                     $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
                 }
             }
         }
         $thisfile_audio['encoder_options'] = getid3_mp3::GuessEncoderOptions($ThisFileInfo);
     }
     if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && $thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0) {
         switch ($thisfile_audio_dataformat) {
             case 'ac3':
                 // ignore bits_per_sample
                 break;
             default:
                 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
                 break;
         }
     }
     if (empty($thisfile_riff_raw)) {
         unset($thisfile_riff['raw']);
     }
     if (empty($thisfile_riff_audio)) {
         unset($thisfile_riff['audio']);
     }
     if (empty($thisfile_riff_video)) {
         unset($thisfile_riff['video']);
     }
     return true;
 }
 public function Analyze()
 {
     $info =& $this->getid3->info;
     // initialize these values to an empty array, otherwise they default to NULL
     // and you can't append array values to a NULL value
     $info['riff'] = array('raw' => array());
     // Shortcuts
     $thisfile_riff =& $info['riff'];
     $thisfile_riff_raw =& $thisfile_riff['raw'];
     $thisfile_audio =& $info['audio'];
     $thisfile_video =& $info['video'];
     $thisfile_audio_dataformat =& $thisfile_audio['dataformat'];
     $thisfile_riff_audio =& $thisfile_riff['audio'];
     $thisfile_riff_video =& $thisfile_riff['video'];
     $Original['avdataoffset'] = $info['avdataoffset'];
     $Original['avdataend'] = $info['avdataend'];
     $this->fseek($info['avdataoffset']);
     $RIFFheader = $this->fread(12);
     $offset = $this->ftell();
     $RIFFtype = substr($RIFFheader, 0, 4);
     $RIFFsize = substr($RIFFheader, 4, 4);
     $RIFFsubtype = substr($RIFFheader, 8, 4);
     switch ($RIFFtype) {
         case 'FORM':
             // AIFF, AIFC
             //$info['fileformat']   = 'aiff';
             $this->container = 'aiff';
             $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
             $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, $offset + $thisfile_riff['header_size'] - 4);
             break;
         case 'RIFF':
             // AVI, WAV, etc
         // AVI, WAV, etc
         case 'SDSS':
             // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         case 'RMP3':
             // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
             //$info['fileformat']   = 'riff';
             $this->container = 'riff';
             $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
             if ($RIFFsubtype == 'RMP3') {
                 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
                 $RIFFsubtype = 'WAVE';
             }
             if ($RIFFsubtype != 'AMV ') {
                 // 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
                 // Handled separately in ParseRIFFAMV()
                 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, $offset + $thisfile_riff['header_size'] - 4);
             }
             if ($info['avdataend'] - $info['filesize'] == 1) {
                 // LiteWave appears to incorrectly *not* pad actual output file
                 // to nearest WORD boundary so may appear to be short by one
                 // byte, in which case - skip warning
                 $info['avdataend'] = $info['filesize'];
             }
             $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size'];
             // 8 = "RIFF" + 32-bit offset
             while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
                 try {
                     $this->fseek($nextRIFFoffset);
                 } catch (getid3_exception $e) {
                     if ($e->getCode() == 10) {
                         //$this->warning('RIFF parser: '.$e->getMessage());
                         $this->error('AVI extends beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
                         $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
                         break;
                     } else {
                         throw $e;
                     }
                 }
                 $nextRIFFheader = $this->fread(12);
                 if ($nextRIFFoffset == $info['avdataend'] - 1) {
                     if (substr($nextRIFFheader, 0, 1) == "") {
                         // RIFF padded to WORD boundary, we're actually already at the end
                         break;
                     }
                 }
                 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
                 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
                 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
                 $chunkdata = array();
                 $chunkdata['offset'] = $nextRIFFoffset + 8;
                 $chunkdata['size'] = $nextRIFFsize;
                 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
                 switch ($nextRIFFheaderID) {
                     case 'RIFF':
                         $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
                         if (!isset($thisfile_riff[$nextRIFFtype])) {
                             $thisfile_riff[$nextRIFFtype] = array();
                         }
                         $thisfile_riff[$nextRIFFtype][] = $chunkdata;
                         break;
                     case 'AMV ':
                         unset($info['riff']);
                         $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset);
                         break;
                     case 'JUNK':
                         // ignore
                         $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
                         break;
                     case 'IDVX':
                         $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
                         break;
                     default:
                         if ($info['filesize'] == $chunkdata['offset'] - 8 + 128) {
                             $DIVXTAG = $nextRIFFheader . $this->fread(128 - 12);
                             if (substr($DIVXTAG, -7) == 'DIVXTAG') {
                                 // 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
                                 $this->warning('Found wrongly-structured DIVXTAG at offset ' . ($this->ftell() - 128) . ', parsing anyway');
                                 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
                                 break 2;
                             }
                         }
                         $this->warning('Expecting "RIFF|JUNK|IDVX" at ' . $nextRIFFoffset . ', found "' . $nextRIFFheaderID . '" (' . getid3_lib::PrintHexBytes($nextRIFFheaderID) . ') - skipping rest of file');
                         break 2;
                 }
             }
             if ($RIFFsubtype == 'WAVE') {
                 $thisfile_riff_WAVE =& $thisfile_riff['WAVE'];
             }
             break;
         default:
             $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "' . $RIFFsubtype . '" instead');
             //unset($info['fileformat']);
             return false;
     }
     $streamindex = 0;
     switch ($RIFFsubtype) {
         // http://en.wikipedia.org/wiki/Wav
         case 'WAVE':
             $info['fileformat'] = 'wav';
             if (empty($thisfile_audio['bitrate_mode'])) {
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             if (empty($thisfile_audio_dataformat)) {
                 $thisfile_audio_dataformat = 'wav';
             }
             if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
             }
             if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
                 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
                 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || $thisfile_riff_audio[$streamindex]['bitrate'] == 0) {
                     $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
                     return false;
                 }
                 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
                 unset($thisfile_riff_audio[$streamindex]['raw']);
                 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
                     $info['warning'][] = 'Audio codec = ' . $thisfile_audio['codec'];
                 }
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 if (empty($info['playtime_seconds'])) {
                     // may already be set (e.g. DTS-WAV)
                     $info['playtime_seconds'] = (double) (($info['avdataend'] - $info['avdataoffset']) * 8 / $thisfile_audio['bitrate']);
                 }
                 $thisfile_audio['lossless'] = false;
                 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                     switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                         case 0x1:
                             // PCM
                             $thisfile_audio['lossless'] = true;
                             break;
                         case 0x2000:
                             // AC-3
                             $thisfile_audio_dataformat = 'ac3';
                             break;
                         default:
                             // do nothing
                             break;
                     }
                 }
                 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
                 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
                 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
             }
             if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
                 // shortcuts
                 $rgadData =& $thisfile_riff_WAVE['rgad'][0]['data'];
                 $thisfile_riff_raw['rgad'] = array('track' => array(), 'album' => array());
                 $thisfile_riff_raw_rgad =& $thisfile_riff_raw['rgad'];
                 $thisfile_riff_raw_rgad_track =& $thisfile_riff_raw_rgad['track'];
                 $thisfile_riff_raw_rgad_album =& $thisfile_riff_raw_rgad['album'];
                 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
                 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
                 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
                 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
                 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
                 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
                 if ($thisfile_riff_raw_rgad_track['name'] != 0 && $thisfile_riff_raw_rgad_track['originator'] != 0) {
                     $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
                     $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
                     $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
                 }
                 if ($thisfile_riff_raw_rgad_album['name'] != 0 && $thisfile_riff_raw_rgad_album['originator'] != 0) {
                     $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
                     $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
                     $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
                 }
             }
             if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
                 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
                 // This should be a good way of calculating exact playtime,
                 // but some sample files have had incorrect number of samples,
                 // so cannot use this method
                 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
                 //     $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
                 // }
             }
             if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
                 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
             }
             if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_bext_0 =& $thisfile_riff_WAVE['bext'][0];
                 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
                 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
                 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
                 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
                 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
                 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
                 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
                 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
                 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
                 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
                     if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
                         list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
                         list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
                         $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']);
                     } else {
                         $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
                     }
                 } else {
                     $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
                 }
                 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
             }
             if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_MEXT_0 =& $thisfile_riff_WAVE['MEXT'][0];
                 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x1);
                 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
                     $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x2 ? false : true;
                     $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x4);
                     $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x8);
                     $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
                 }
                 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
                 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x1);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x2);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x4);
             }
             if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_cart_0 =& $thisfile_riff_WAVE['cart'][0];
                 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
                 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
                 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
                 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
                 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
                 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
                 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
                 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
                 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
                 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
                 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
                 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
                 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
                 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
                 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
                 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
                 for ($i = 0; $i < 8; $i++) {
                     $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + $i * 8, 4);
                     $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));
                 }
                 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
                 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
                 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
             }
             if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
                 // SoundMiner metadata
                 // shortcuts
                 $thisfile_riff_WAVE_SNDM_0 =& $thisfile_riff_WAVE['SNDM'][0];
                 $thisfile_riff_WAVE_SNDM_0_data =& $thisfile_riff_WAVE_SNDM_0['data'];
                 $SNDM_startoffset = 0;
                 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
                 while ($SNDM_startoffset < $SNDM_endoffset) {
                     $SNDM_thisTagOffset = 0;
                     $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
                     $SNDM_thisTagOffset += 4;
                     $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
                     $SNDM_thisTagOffset += 4;
                     $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
                     $SNDM_thisTagOffset += 2;
                     $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
                     $SNDM_thisTagOffset += 2;
                     $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
                     $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
                     if ($SNDM_thisTagSize != 4 + 4 + 2 + 2 + $SNDM_thisTagDataSize) {
                         $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) . ')';
                         break;
                     } elseif ($SNDM_thisTagSize <= 0) {
                         $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset ' . $SNDM_startoffset . ' (file offset ' . ($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset) . ')';
                         break;
                     }
                     $SNDM_startoffset += $SNDM_thisTagSize;
                     $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
                     if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
                         $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
                     } else {
                         $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "' . $SNDM_thisTagKey . '" at offset ' . $SNDM_startoffset . ' (file offset ' . ($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset) . ')';
                     }
                 }
                 $tagmapping = array('tracktitle' => 'title', 'category' => 'genre', 'cdtitle' => 'album', 'tracktitle' => 'title');
                 foreach ($tagmapping as $fromkey => $tokey) {
                     if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
                         $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
                     }
                 }
             }
             if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
                 // requires functions simplexml_load_string and get_object_vars
                 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
                     $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
                     if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
                         @(list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']));
                         $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
                     }
                     if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
                         @(list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']));
                         $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
                     }
                     if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
                         $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'] . $parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
                         $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
                         $h = floor($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
                         $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600) / 60);
                         $s = floor($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600 - $m * 60);
                         $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600 - $m * 60 - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
                         $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
                         $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
                     }
                     unset($parsedXML);
                 }
             }
             if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 $info['playtime_seconds'] = (double) (($info['avdataend'] - $info['avdataoffset']) * 8 / $thisfile_audio['bitrate']);
             }
             if (!empty($info['wavpack'])) {
                 $thisfile_audio_dataformat = 'wavpack';
                 $thisfile_audio['bitrate_mode'] = 'vbr';
                 $thisfile_audio['encoder'] = 'WavPack v' . $info['wavpack']['version'];
                 // Reset to the way it was - RIFF parsing will have messed this up
                 $info['avdataend'] = $Original['avdataend'];
                 $thisfile_audio['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['playtime_seconds'];
                 $this->fseek($info['avdataoffset'] - 44);
                 $RIFFdata = $this->fread(44);
                 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
                 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
                 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
                     $info['avdataend'] -= $OrignalRIFFheaderSize - $OrignalRIFFdataSize;
                     $this->fseek($info['avdataend']);
                     $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
                 }
                 // move the data chunk after all other chunks (if any)
                 // so that the RIFF parser doesn't see EOF when trying
                 // to skip over the data chunk
                 $RIFFdata = substr($RIFFdata, 0, 36) . substr($RIFFdata, 44) . substr($RIFFdata, 36, 8);
                 $getid3_riff = new getid3_riff($this->getid3);
                 $getid3_riff->ParseRIFFdata($RIFFdata);
                 unset($getid3_riff);
             }
             if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                     case 0x1:
                         // PCM
                         if (!empty($info['ac3'])) {
                             // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
                             $thisfile_audio['wformattag'] = 0x2000;
                             $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
                             $thisfile_audio['lossless'] = false;
                             $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
                             $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
                         }
                         if (!empty($info['dts'])) {
                             // Dolby DTS files masquerade as PCM-WAV, but they're not
                             $thisfile_audio['wformattag'] = 0x2001;
                             $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
                             $thisfile_audio['lossless'] = false;
                             $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
                             $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
                         }
                         break;
                     case 0x8ae:
                         // ClearJump LiteWave
                         $thisfile_audio['bitrate_mode'] = 'vbr';
                         $thisfile_audio_dataformat = 'litewave';
                         //typedef struct tagSLwFormat {
                         //  WORD    m_wCompFormat;     // low byte defines compression method, high byte is compression flags
                         //  DWORD   m_dwScale;         // scale factor for lossy compression
                         //  DWORD   m_dwBlockSize;     // number of samples in encoded blocks
                         //  WORD    m_wQuality;        // alias for the scale factor
                         //  WORD    m_wMarkDistance;   // distance between marks in bytes
                         //  WORD    m_wReserved;
                         //
                         //  //following paramters are ignored if CF_FILESRC is not set
                         //  DWORD   m_dwOrgSize;       // original file size in bytes
                         //  WORD    m_bFactExists;     // indicates if 'fact' chunk exists in the original file
                         //  DWORD   m_dwRiffChunkSize; // riff chunk size in the original file
                         //
                         //  PCMWAVEFORMAT m_OrgWf;     // original wave format
                         // }SLwFormat, *PSLwFormat;
                         // shortcut
                         $thisfile_riff['litewave']['raw'] = array();
                         $riff_litewave =& $thisfile_riff['litewave'];
                         $riff_litewave_raw =& $riff_litewave['raw'];
                         $flags = array('compression_method' => 1, 'compression_flags' => 1, 'm_dwScale' => 4, 'm_dwBlockSize' => 4, 'm_wQuality' => 2, 'm_wMarkDistance' => 2, 'm_wReserved' => 2, 'm_dwOrgSize' => 4, 'm_bFactExists' => 2, 'm_dwRiffChunkSize' => 4);
                         $litewave_offset = 18;
                         foreach ($flags as $flag => $length) {
                             $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
                             $litewave_offset += $length;
                         }
                         //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
                         $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
                         $riff_litewave['flags']['raw_source'] = $riff_litewave_raw['compression_flags'] & 0x1 ? false : true;
                         $riff_litewave['flags']['vbr_blocksize'] = $riff_litewave_raw['compression_flags'] & 0x2 ? false : true;
                         $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x4);
                         $thisfile_audio['lossless'] = $riff_litewave_raw['m_wQuality'] == 100 ? true : false;
                         $thisfile_audio['encoder_options'] = '-q' . $riff_litewave['quality_factor'];
                         break;
                     default:
                         break;
                 }
             }
             if ($info['avdataend'] > $info['filesize']) {
                 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
                     case 'wavpack':
                         // WavPack
                     // WavPack
                     case 'lpac':
                         // LPAC
                     // LPAC
                     case 'ofr':
                         // OptimFROG
                     // OptimFROG
                     case 'ofs':
                         // OptimFROG DualStream
                         // lossless compressed audio formats that keep original RIFF headers - skip warning
                         break;
                     case 'litewave':
                         if ($info['avdataend'] - $info['filesize'] == 1) {
                             // LiteWave appears to incorrectly *not* pad actual output file
                             // to nearest WORD boundary so may appear to be short by one
                             // byte, in which case - skip warning
                         } else {
                             // Short by more than one byte, throw warning
                             $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)';
                             $info['avdataend'] = $info['filesize'];
                         }
                         break;
                     default:
                         if ($info['avdataend'] - $info['filesize'] == 1 && $thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2 == 0 && ($info['filesize'] - $info['avdataoffset']) % 2 == 1) {
                             // output file appears to be incorrectly *not* padded to nearest WORD boundary
                             // Output less severe warning
                             $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)';
                             $info['avdataend'] = $info['filesize'];
                         } else {
                             // Short by more than one byte, throw warning
                             $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)';
                             $info['avdataend'] = $info['filesize'];
                         }
                         break;
                 }
             }
             if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
                 if ($info['avdataend'] - $info['avdataoffset'] - $info['mpeg']['audio']['LAME']['audio_bytes'] == 1) {
                     $info['avdataend']--;
                     $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
                 }
             }
             if (isset($thisfile_audio_dataformat) && $thisfile_audio_dataformat == 'ac3') {
                 unset($thisfile_audio['bits_per_sample']);
                 if (!empty($info['ac3']['bitrate']) && $info['ac3']['bitrate'] != $thisfile_audio['bitrate']) {
                     $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
                 }
             }
             break;
             // http://en.wikipedia.org/wiki/Audio_Video_Interleave
         // http://en.wikipedia.org/wiki/Audio_Video_Interleave
         case 'AVI ':
             $info['fileformat'] = 'avi';
             $info['mime_type'] = 'video/avi';
             $thisfile_video['bitrate_mode'] = 'vbr';
             // maybe not, but probably
             $thisfile_video['dataformat'] = 'avi';
             if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
                 if (isset($thisfile_riff['AVIX'])) {
                     $info['avdataend'] = $thisfile_riff['AVIX'][count($thisfile_riff['AVIX']) - 1]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][count($thisfile_riff['AVIX']) - 1]['chunks']['movi']['size'];
                 } else {
                     $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
                 }
                 if ($info['avdataend'] > $info['filesize']) {
                     $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)';
                     $info['avdataend'] = $info['filesize'];
                 }
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
                 //$bIndexType = array(
                 //	0x00 => 'AVI_INDEX_OF_INDEXES',
                 //	0x01 => 'AVI_INDEX_OF_CHUNKS',
                 //	0x80 => 'AVI_INDEX_IS_DATA',
                 //);
                 //$bIndexSubtype = array(
                 //	0x01 => array(
                 //		0x01 => 'AVI_INDEX_2FIELD',
                 //	),
                 //);
                 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
                     $ahsisd =& $thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
                     $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
                     $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
                     $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
                     $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
                     $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
                     $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
                     //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name']    =    $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
                     //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
                     unset($ahsisd);
                 }
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
                 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
                 // shortcut
                 $thisfile_riff_raw['avih'] = array();
                 $thisfile_riff_raw_avih =& $thisfile_riff_raw['avih'];
                 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4));
                 // frame display rate (or 0L)
                 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
                     $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
                     return false;
                 }
                 $flags = array('dwMaxBytesPerSec', 'dwPaddingGranularity', 'dwFlags', 'dwTotalFrames', 'dwInitialFrames', 'dwStreams', 'dwSuggestedBufferSize', 'dwWidth', 'dwHeight', 'dwScale', 'dwRate', 'dwStart', 'dwLength');
                 $avih_offset = 4;
                 foreach ($flags as $flag) {
                     $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
                     $avih_offset += 4;
                 }
                 $flags = array('hasindex' => 0x10, 'mustuseindex' => 0x20, 'interleaved' => 0x100, 'trustcktype' => 0x800, 'capturedfile' => 0x10000, 'copyrighted' => 0x20010);
                 foreach ($flags as $flag => $value) {
                     $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
                 }
                 // shortcut
                 $thisfile_riff_video[$streamindex] = array();
                 $thisfile_riff_video_current =& $thisfile_riff_video[$streamindex];
                 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
                     $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
                     $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
                 }
                 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
                     $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
                     $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
                 }
                 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
                     $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
                     $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
                 }
                 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
                 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
                 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
                     for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
                         if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
                             $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
                             $strhfccType = substr($strhData, 0, 4);
                             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
                                 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
                                 // shortcut
                                 $thisfile_riff_raw_strf_strhfccType_streamindex =& $thisfile_riff_raw['strf'][$strhfccType][$streamindex];
                                 switch ($strhfccType) {
                                     case 'auds':
                                         $thisfile_audio['bitrate_mode'] = 'cbr';
                                         $thisfile_audio_dataformat = 'wav';
                                         if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
                                             $streamindex = count($thisfile_riff_audio);
                                         }
                                         $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
                                         $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                                         // shortcut
                                         $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                                         $thisfile_audio_streams_currentstream =& $thisfile_audio['streams'][$streamindex];
                                         if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
                                             unset($thisfile_audio_streams_currentstream['bits_per_sample']);
                                         }
                                         $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
                                         unset($thisfile_audio_streams_currentstream['raw']);
                                         // shortcut
                                         $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
                                         unset($thisfile_riff_audio[$streamindex]['raw']);
                                         $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                                         $thisfile_audio['lossless'] = false;
                                         switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
                                             case 0x1:
                                                 // PCM
                                                 $thisfile_audio_dataformat = 'wav';
                                                 $thisfile_audio['lossless'] = true;
                                                 break;
                                             case 0x50:
                                                 // MPEG Layer 2 or Layer 1
                                                 $thisfile_audio_dataformat = 'mp2';
                                                 // Assume Layer-2
                                                 break;
                                             case 0x55:
                                                 // MPEG Layer 3
                                                 $thisfile_audio_dataformat = 'mp3';
                                                 break;
                                             case 0xff:
                                                 // AAC
                                                 $thisfile_audio_dataformat = 'aac';
                                                 break;
                                             case 0x161:
                                                 // Windows Media v7 / v8 / v9
                                             // Windows Media v7 / v8 / v9
                                             case 0x162:
                                                 // Windows Media Professional v9
                                             // Windows Media Professional v9
                                             case 0x163:
                                                 // Windows Media Lossess v9
                                                 $thisfile_audio_dataformat = 'wma';
                                                 break;
                                             case 0x2000:
                                                 // AC-3
                                                 $thisfile_audio_dataformat = 'ac3';
                                                 break;
                                             case 0x2001:
                                                 // DTS
                                                 $thisfile_audio_dataformat = 'dts';
                                                 break;
                                             default:
                                                 $thisfile_audio_dataformat = 'wav';
                                                 break;
                                         }
                                         $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
                                         $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
                                         $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                                         break;
                                     case 'iavs':
                                     case 'vids':
                                         // shortcut
                                         $thisfile_riff_raw['strh'][$i] = array();
                                         $thisfile_riff_raw_strh_current =& $thisfile_riff_raw['strh'][$i];
                                         $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4);
                                         // same as $strhfccType;
                                         $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
                                         $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4));
                                         // Contains AVITF_* flags
                                         $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
                                         $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
                                         $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
                                         $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
                                         $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
                                         $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
                                         $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
                                         $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
                                         $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
                                         $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
                                         $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
                                         $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
                                         $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
                                         if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                                             $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
                                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                                         }
                                         $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                                         $thisfile_video['pixel_aspect_ratio'] = (double) 1;
                                         switch ($thisfile_riff_raw_strh_current['fccHandler']) {
                                             case 'HFYU':
                                                 // Huffman Lossless Codec
                                             // Huffman Lossless Codec
                                             case 'IRAW':
                                                 // Intel YUV Uncompressed
                                             // Intel YUV Uncompressed
                                             case 'YUY2':
                                                 // Uncompressed YUV 4:2:2
                                                 $thisfile_video['lossless'] = true;
                                                 break;
                                             default:
                                                 $thisfile_video['lossless'] = false;
                                                 break;
                                         }
                                         switch ($strhfccType) {
                                             case 'vids':
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), $this->container == 'riff');
                                                 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
                                                 if ($thisfile_riff_video_current['codec'] == 'DV') {
                                                     $thisfile_riff_video_current['dv_type'] = 2;
                                                 }
                                                 break;
                                             case 'iavs':
                                                 $thisfile_riff_video_current['dv_type'] = 1;
                                                 break;
                                         }
                                         break;
                                     default:
                                         $info['warning'][] = 'Unhandled fccType for stream (' . $i . '): "' . $strhfccType . '"';
                                         break;
                                 }
                             }
                         }
                         if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                             if (self::fourccLookup($thisfile_video['fourcc'])) {
                                 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
                                 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                             }
                             switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
                                 case 'HFYU':
                                     // Huffman Lossless Codec
                                 // Huffman Lossless Codec
                                 case 'IRAW':
                                     // Intel YUV Uncompressed
                                 // Intel YUV Uncompressed
                                 case 'YUY2':
                                     // Uncompressed YUV 4:2:2
                                     $thisfile_video['lossless'] = true;
                                     //$thisfile_video['bits_per_sample'] = 24;
                                     break;
                                 default:
                                     $thisfile_video['lossless'] = false;
                                     //$thisfile_video['bits_per_sample'] = 24;
                                     break;
                             }
                         }
                     }
                 }
             }
             break;
         case 'AMV ':
             $info['fileformat'] = 'amv';
             $info['mime_type'] = 'video/amv';
             $thisfile_video['bitrate_mode'] = 'vbr';
             // it's MJPEG, presumably contant-quality encoding, thereby VBR
             $thisfile_video['dataformat'] = 'mjpeg';
             $thisfile_video['codec'] = 'mjpeg';
             $thisfile_video['lossless'] = false;
             $thisfile_video['bits_per_sample'] = 24;
             $thisfile_audio['dataformat'] = 'adpcm';
             $thisfile_audio['lossless'] = false;
             break;
             // http://en.wikipedia.org/wiki/CD-DA
         // http://en.wikipedia.org/wiki/CD-DA
         case 'CDDA':
             $info['fileformat'] = 'cda';
             unset($info['mime_type']);
             $thisfile_audio_dataformat = 'cda';
             $info['avdataoffset'] = 44;
             if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
                 // shortcut
                 $thisfile_riff_CDDA_fmt_0 =& $thisfile_riff['CDDA']['fmt '][0];
                 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
                 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
                 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
                 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
                 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
                 $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
                 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
                 // hardcoded data for CD-audio
                 $thisfile_audio['lossless'] = true;
                 $thisfile_audio['sample_rate'] = 44100;
                 $thisfile_audio['channels'] = 2;
                 $thisfile_audio['bits_per_sample'] = 16;
                 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             break;
             // http://en.wikipedia.org/wiki/AIFF
         // http://en.wikipedia.org/wiki/AIFF
         case 'AIFF':
         case 'AIFC':
             $info['fileformat'] = 'aiff';
             $info['mime_type'] = 'audio/x-aiff';
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = 'aiff';
             $thisfile_audio['lossless'] = true;
             if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
                 if ($info['avdataend'] > $info['filesize']) {
                     if ($info['avdataend'] == $info['filesize'] + 1 && $info['filesize'] % 2 == 1) {
                         // structures rounded to 2-byte boundary, but dumb encoders
                         // forget to pad end of file to make this actually work
                     } else {
                         $info['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'] . ' bytes of audio data, only ' . ($info['filesize'] - $info['avdataoffset']) . ' bytes found';
                     }
                     $info['avdataend'] = $info['filesize'];
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_COMM_0_data =& $thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
                 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
                 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
                 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
                 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
                 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
                     $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
                     $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
                     $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
                     switch ($thisfile_riff_audio['codec_name']) {
                         case 'NONE':
                             $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                             $thisfile_audio['lossless'] = true;
                             break;
                         case '':
                             switch ($thisfile_riff_audio['codec_fourcc']) {
                                 // http://developer.apple.com/qa/snd/snd07.html
                                 case 'sowt':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 case 'twos':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 default:
                                     break;
                             }
                             break;
                         default:
                             $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
                             $thisfile_audio['lossless'] = false;
                             break;
                     }
                 }
                 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
                 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
                     $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
                 }
                 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
                 if ($thisfile_audio['sample_rate'] == 0) {
                     $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
                     return false;
                 }
                 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
                 $offset = 0;
                 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                 $offset += 2;
                 for ($i = 0; $i < $CommentCount; $i++) {
                     $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
                     $offset += 4;
                     $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
                     $offset += 2;
                     $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                     $offset += 2;
                     $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
                     $offset += $CommentLength;
                     $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
                     $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             /*
             				if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
             					getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
             					$getid3_temp = new getID3();
             					$getid3_temp->openfile($this->getid3->filename);
             					$getid3_id3v2 = new getid3_id3v2($getid3_temp);
             					$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
             					if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
             						$info['id3v2'] = $getid3_temp->info['id3v2'];
             					}
             					unset($getid3_temp, $getid3_id3v2);
             				}
             */
             break;
             // http://en.wikipedia.org/wiki/8SVX
         // http://en.wikipedia.org/wiki/8SVX
         case '8SVX':
             $info['fileformat'] = '8svx';
             $info['mime_type'] = 'audio/8svx';
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = '8svx';
             $thisfile_audio['bits_per_sample'] = 8;
             $thisfile_audio['channels'] = 1;
             // overridden below, if need be
             if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
                 if ($info['avdataend'] > $info['filesize']) {
                     $info['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'] . ' bytes of audio data, only ' . ($info['filesize'] - $info['avdataoffset']) . ' bytes found';
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_VHDR_0 =& $thisfile_riff[$RIFFsubtype]['VHDR'][0];
                 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
                 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
                 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
                 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
                     case 0:
                         $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                         $thisfile_audio['lossless'] = true;
                         $ActualBitsPerSample = 8;
                         break;
                     case 1:
                         $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
                         $thisfile_audio['lossless'] = false;
                         $ActualBitsPerSample = 4;
                         break;
                     default:
                         $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "' . sCompression . '"';
                         break;
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
                 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
                 switch ($ChannelsIndex) {
                     case 6:
                         // Stereo
                         $thisfile_audio['channels'] = 2;
                         break;
                     case 2:
                         // Left channel only
                     // Left channel only
                     case 4:
                         // Right channel only
                         $thisfile_audio['channels'] = 1;
                         break;
                     default:
                         $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "' . $ChannelsIndex . '"';
                         break;
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
             if (!empty($thisfile_audio['bitrate'])) {
                 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
             }
             break;
         case 'CDXA':
             $info['fileformat'] = 'vcd';
             // Asume Video CD
             $info['mime_type'] = 'video/mpeg';
             if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.mpeg.php', __FILE__, true);
                 $getid3_temp = new getID3();
                 $getid3_temp->openfile($this->getid3->filename);
                 $getid3_mpeg = new getid3_mpeg($getid3_temp);
                 $getid3_mpeg->Analyze();
                 if (empty($getid3_temp->info['error'])) {
                     $info['audio'] = $getid3_temp->info['audio'];
                     $info['video'] = $getid3_temp->info['video'];
                     $info['mpeg'] = $getid3_temp->info['mpeg'];
                     $info['warning'] = $getid3_temp->info['warning'];
                 }
                 unset($getid3_temp, $getid3_mpeg);
             }
             break;
         default:
             $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "' . $RIFFsubtype . '" instead';
             //unset($info['fileformat']);
     }
     switch ($RIFFsubtype) {
         case 'WAVE':
         case 'AIFF':
         case 'AIFC':
             $ID3v2_key_good = 'id3 ';
             $ID3v2_keys_bad = array('ID3 ', 'tag ');
             foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
                 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
                     $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
                     $info['warning'][] = 'mapping "' . $ID3v2_key_bad . '" chunk to "' . $ID3v2_key_good . '"';
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, true);
                 $getid3_temp = new getID3();
                 $getid3_temp->openfile($this->getid3->filename);
                 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
                 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
                 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
                     $info['id3v2'] = $getid3_temp->info['id3v2'];
                 }
                 unset($getid3_temp, $getid3_id3v2);
             }
             break;
     }
     if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
         $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
     }
     if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
         self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
     }
     if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
         self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
     }
     if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
         $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
     }
     if (!isset($info['playtime_seconds'])) {
         $info['playtime_seconds'] = 0;
     }
     if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
         // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
         $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
     } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
         $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
     }
     if ($info['playtime_seconds'] > 0) {
         if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($info['bitrate'])) {
                 $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
             if (!isset($thisfile_audio['bitrate'])) {
                 $thisfile_audio['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($thisfile_video['bitrate'])) {
                 $thisfile_video['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         }
     }
     if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && $thisfile_audio['bitrate'] > 0 && $info['playtime_seconds'] > 0) {
         $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
         $thisfile_audio['bitrate'] = 0;
         $thisfile_video['bitrate'] = $info['bitrate'];
         foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
             $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
             $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
         }
         if ($thisfile_video['bitrate'] <= 0) {
             unset($thisfile_video['bitrate']);
         }
         if ($thisfile_audio['bitrate'] <= 0) {
             unset($thisfile_audio['bitrate']);
         }
     }
     if (isset($info['mpeg']['audio'])) {
         $thisfile_audio_dataformat = 'mp' . $info['mpeg']['audio']['layer'];
         $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
         $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
         $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
         $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
         if (!empty($info['mpeg']['audio']['codec'])) {
             $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'] . ' ' . $thisfile_audio['codec'];
         }
         if (!empty($thisfile_audio['streams'])) {
             foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
                 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
                     $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
                     $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                     $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
                 }
             }
         }
         $getid3_mp3 = new getid3_mp3($this->getid3);
         $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
         unset($getid3_mp3);
     }
     if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && $thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0) {
         switch ($thisfile_audio_dataformat) {
             case 'ac3':
                 // ignore bits_per_sample
                 break;
             default:
                 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
                 break;
         }
     }
     if (empty($thisfile_riff_raw)) {
         unset($thisfile_riff['raw']);
     }
     if (empty($thisfile_riff_audio)) {
         unset($thisfile_riff['audio']);
     }
     if (empty($thisfile_riff_video)) {
         unset($thisfile_riff['video']);
     }
     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
         // MOVie container atom
         case 'trak':
             // TRAcK container atom
         // TRAcK container atom
         case 'clip':
             // CLIPping container atom
         // CLIPping container atom
         case 'matt':
             // track MATTe container atom
         // track MATTe container atom
         case 'edts':
             // EDiTS container atom
         // EDiTS container atom
         case 'tref':
             // Track REFerence container atom
         // Track REFerence container atom
         case 'mdia':
             // MeDIA container atom
         // MeDIA container atom
         case 'minf':
             // Media INFormation container atom
         // Media INFormation container atom
         case 'dinf':
             // Data INFormation container atom
         // Data INFormation container atom
         case 'udta':
             // User DaTA container atom
         // User DaTA container atom
         case 'cmov':
             // Compressed MOVie container atom
         // Compressed MOVie container atom
         case 'rmra':
             // Reference Movie Record Atom
         // Reference Movie Record Atom
         case 'rmda':
             // Reference Movie Descriptor Atom
         // 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 'stbl':
             // Sample TaBLe container atom
             $atomstructure['subatoms'] = $this->QuicktimeParseContainerAtom($atomdata, $ThisFileInfo, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
             $isVideo = false;
             $framerate = 0;
             $framecount = 0;
             foreach ($atomstructure['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'])) {
                             $framerate = round($ThisFileInfo['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
                             $framecount = $value_array2['sample_count'];
                         }
                     }
                 }
             }
             if ($isVideo && $framerate) {
                 $ThisFileInfo['quicktime']['video']['frame_rate'] = $framerate;
                 $ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['quicktime']['video']['frame_rate'];
             }
             if ($isVideo && $framecount) {
                 $ThisFileInfo['quicktime']['video']['frame_count'] = $framecount;
             }
             break;
         case '�cpy':
         case '�day':
         case '�dir':
         case '�ed1':
         case '�ed2':
         case '�ed3':
         case '�ed4':
         case '�ed5':
         case '�ed6':
         case '�ed7':
         case '�ed8':
         case '�ed9':
         case '�fmt':
         case '�inf':
         case '�prd':
         case '�prf':
         case '�req':
         case '�src':
         case '�wrt':
         case '�nam':
         case '�cmt':
         case '�wrn':
         case '�hst':
         case '�mak':
         case '�mod':
         case '�PRD':
         case '�swr':
         case '�aut':
         case '�ART':
         case '�trk':
         case '�alb':
         case '�com':
         case '�gen':
         case '�ope':
         case '�url':
         case '�enc':
             $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
         // LOOPing atom
         case 'SelO':
             // play SELection Only atom
         // play SELection Only atom
         case 'AllF':
             // play ALL Frames atom
             $atomstructure['data'] = getid3_lib::BigEndian2Int($atomdata);
             break;
         case 'name':
             //
         //
         case 'MCPS':
             // Media Cleaner PRo
         // Media Cleaner PRo
         case '@PRM':
             // adobe PReMiere version
         // adobe PReMiere version
         case '@PRQ':
             // adobe PRemiere Quicktime version
             $atomstructure['data'] = $atomdata;
             break;
         case 'cmvd':
             // Compressed MooV Data atom
             // Code by ubergeek�ubergeek*tv based on information from
             // http://developer.apple.com/quicktime/icefloe/dispatch012.html
             $atomstructure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             $CompressedFileData = substr($atomdata, 4);
             if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
                 $atomstructure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, $ThisFileInfo, 0, $atomHierarchy, $ParseAllPossibleAtoms);
             } else {
                 $ThisFileInfo['warning'][] = 'Error decompressing compressed MOV atom at offset ' . $atomstructure['offset'];
             }
             break;
         case 'dcom':
             // Data COMpression atom
             $atomstructure['compression_id'] = $atomdata;
             $atomstructure['compression_text'] = $this->QuicktimeDCOMLookup($atomdata);
             break;
         case 'rdrf':
             // Reference movie Data ReFerence atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             $atomstructure['flags']['internal_data'] = (bool) ($atomstructure['flags_raw'] & 0x1);
             $atomstructure['reference_type_name'] = substr($atomdata, 4, 4);
             $atomstructure['reference_length'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             switch ($atomstructure['reference_type_name']) {
                 case 'url ':
                     $atomstructure['url'] = $this->NoNullString(substr($atomdata, 12));
                     break;
                 case 'alis':
                     $atomstructure['file_alias'] = substr($atomdata, 12);
                     break;
                 case 'rsrc':
                     $atomstructure['resource_alias'] = substr($atomdata, 12);
                     break;
                 default:
                     $atomstructure['data'] = substr($atomdata, 12);
                     break;
             }
             break;
         case 'rmqu':
             // Reference Movie QUality atom
             $atomstructure['movie_quality'] = getid3_lib::BigEndian2Int($atomdata);
             break;
         case 'rmcs':
             // Reference Movie Cpu Speed atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             break;
         case 'rmvc':
             // Reference Movie Version Check atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['gestalt_selector'] = substr($atomdata, 4, 4);
             $atomstructure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             $atomstructure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 4));
             $atomstructure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atomdata, 14, 2));
             break;
         case 'rmcd':
             // Reference Movie Component check atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['component_type'] = substr($atomdata, 4, 4);
             $atomstructure['component_subtype'] = substr($atomdata, 8, 4);
             $atomstructure['component_manufacturer'] = substr($atomdata, 12, 4);
             $atomstructure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 16, 4));
             $atomstructure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atomdata, 20, 4));
             $atomstructure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atomdata, 24, 4));
             break;
         case 'rmdr':
             // Reference Movie Data Rate atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['data_rate'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['data_rate_bps'] = $atomstructure['data_rate'] * 10;
             break;
         case 'rmla':
             // Reference Movie Language Atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['language_id'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             $atomstructure['language'] = $this->QuicktimeLanguageLookup($atomstructure['language_id']);
             if (empty($ThisFileInfo['comments']['language']) || !in_array($atomstructure['language'], $ThisFileInfo['comments']['language'])) {
                 $ThisFileInfo['comments']['language'][] = $atomstructure['language'];
             }
             break;
         case 'rmla':
             // Reference Movie Language Atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['track_id'] = getid3_lib::BigEndian2Int(substr($atomdata, 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
             $atomstructure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 2));
             $atomstructure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atomdata, 2, 2));
             // hardcoded: 0x0000
             $atomstructure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             // hardcoded: 0x0000
             $atomstructure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atomdata, 6, 1));
             $atomstructure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atomdata, 7, 1));
             $atomstructure['flags']['play_on_open'] = (bool) $atomstructure['play_on_open_flag'];
             $atomstructure['flags']['slide_show'] = (bool) $atomstructure['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[$atomstructure['display_size_raw']])) {
                 $atomstructure['display_size'] = $ptv_lookup[$atomstructure['display_size_raw']];
             } else {
                 $ThisFileInfo['warning'][] = 'unknown "ptv " display constant (' . $atomstructure['display_size_raw'] . ')';
             }
             break;
         case 'stsd':
             // Sample Table Sample Description atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $stsdEntriesDataOffset = 8;
             for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                 $atomstructure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atomdata, $stsdEntriesDataOffset, 4));
                 $stsdEntriesDataOffset += 4;
                 $atomstructure['sample_description_table'][$i]['data_format'] = substr($atomdata, $stsdEntriesDataOffset, 4);
                 $stsdEntriesDataOffset += 4;
                 $atomstructure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atomdata, $stsdEntriesDataOffset, 6));
                 $stsdEntriesDataOffset += 6;
                 $atomstructure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atomdata, $stsdEntriesDataOffset, 2));
                 $stsdEntriesDataOffset += 2;
                 $atomstructure['sample_description_table'][$i]['data'] = substr($atomdata, $stsdEntriesDataOffset, $atomstructure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
                 $stsdEntriesDataOffset += $atomstructure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2;
                 $atomstructure['sample_description_table'][$i]['encoder_version'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 0, 2));
                 $atomstructure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 2, 2));
                 $atomstructure['sample_description_table'][$i]['encoder_vendor'] = substr($atomstructure['sample_description_table'][$i]['data'], 4, 4);
                 switch ($atomstructure['sample_description_table'][$i]['encoder_vendor']) {
                     case "":
                         // audio atom
                         $atomstructure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 8, 2));
                         $atomstructure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 10, 2));
                         $atomstructure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 12, 2));
                         $atomstructure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 14, 2));
                         $atomstructure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atomstructure['sample_description_table'][$i]['data'], 16, 4));
                         switch ($atomstructure['sample_description_table'][$i]['data_format']) {
                             case 'avc1':
                             case 'mp4v':
                                 $ThisFileInfo['fileformat'] = 'mp4';
                                 $ThisFileInfo['video']['fourcc'] = $atomstructure['sample_description_table'][$i]['data_format'];
                                 $ThisFileInfo['warning'][] = 'This version (' . GETID3_VERSION . ') of getID3() does not fully support MPEG-4 audio/video streams';
                                 break;
                             case 'qtvr':
                                 $ThisFileInfo['video']['dataformat'] = 'quicktimevr';
                                 break;
                             case 'mp4a':
                             default:
                                 $ThisFileInfo['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atomstructure['sample_description_table'][$i]['data_format']);
                                 $ThisFileInfo['quicktime']['audio']['sample_rate'] = $atomstructure['sample_description_table'][$i]['audio_sample_rate'];
                                 $ThisFileInfo['quicktime']['audio']['channels'] = $atomstructure['sample_description_table'][$i]['audio_channels'];
                                 $ThisFileInfo['quicktime']['audio']['bit_depth'] = $atomstructure['sample_description_table'][$i]['audio_bit_depth'];
                                 $ThisFileInfo['audio']['codec'] = $ThisFileInfo['quicktime']['audio']['codec'];
                                 $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['quicktime']['audio']['sample_rate'];
                                 $ThisFileInfo['audio']['channels'] = $ThisFileInfo['quicktime']['audio']['channels'];
                                 $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['quicktime']['audio']['bit_depth'];
                                 switch ($atomstructure['sample_description_table'][$i]['data_format']) {
                                     case 'raw ':
                                         // PCM
                                     // PCM
                                     case 'alac':
                                         // Apple Lossless Audio Codec
                                         $ThisFileInfo['audio']['lossless'] = true;
                                         break;
                                     default:
                                         $ThisFileInfo['audio']['lossless'] = false;
                                         break;
                                 }
                                 break;
                         }
                         break;
                     default:
                         switch ($atomstructure['sample_description_table'][$i]['data_format']) {
                             case 'mp4s':
                                 $ThisFileInfo['fileformat'] = 'mp4';
                                 break;
                             default:
                                 // video atom
                                 $atomstructure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 8, 4));
                                 $atomstructure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 12, 4));
                                 $atomstructure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 16, 2));
                                 $atomstructure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 18, 2));
                                 $atomstructure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atomstructure['sample_description_table'][$i]['data'], 20, 4));
                                 $atomstructure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atomstructure['sample_description_table'][$i]['data'], 24, 4));
                                 $atomstructure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 28, 4));
                                 $atomstructure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 32, 2));
                                 $atomstructure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 34, 1));
                                 $atomstructure['sample_description_table'][$i]['video_encoder_name'] = substr($atomstructure['sample_description_table'][$i]['data'], 35, $atomstructure['sample_description_table'][$i]['video_encoder_name_len']);
                                 $atomstructure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 66, 2));
                                 $atomstructure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atomstructure['sample_description_table'][$i]['data'], 68, 2));
                                 $atomstructure['sample_description_table'][$i]['video_pixel_color_type'] = $atomstructure['sample_description_table'][$i]['video_pixel_color_depth'] > 32 ? 'grayscale' : 'color';
                                 $atomstructure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atomstructure['sample_description_table'][$i]['video_pixel_color_depth']);
                                 if ($atomstructure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
                                     $ThisFileInfo['quicktime']['video']['codec_fourcc'] = $atomstructure['sample_description_table'][$i]['data_format'];
                                     $ThisFileInfo['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atomstructure['sample_description_table'][$i]['data_format']);
                                     $ThisFileInfo['quicktime']['video']['codec'] = $atomstructure['sample_description_table'][$i]['video_encoder_name'];
                                     $ThisFileInfo['quicktime']['video']['color_depth'] = $atomstructure['sample_description_table'][$i]['video_pixel_color_depth'];
                                     $ThisFileInfo['quicktime']['video']['color_depth_name'] = $atomstructure['sample_description_table'][$i]['video_pixel_color_name'];
                                     $ThisFileInfo['video']['codec'] = $ThisFileInfo['quicktime']['video']['codec'];
                                     $ThisFileInfo['video']['bits_per_sample'] = $ThisFileInfo['quicktime']['video']['color_depth'];
                                 }
                                 $ThisFileInfo['video']['lossless'] = false;
                                 $ThisFileInfo['video']['pixel_aspect_ratio'] = (double) 1;
                                 break;
                         }
                         break;
                 }
                 switch (strtolower($atomstructure['sample_description_table'][$i]['data_format'])) {
                     case 'mp4a':
                         $ThisFileInfo['audio']['dataformat'] = 'mp4';
                         $ThisFileInfo['quicktime']['audio']['codec'] = 'mp4';
                         break;
                     case '3ivx':
                     case '3iv1':
                     case '3iv2':
                         $ThisFileInfo['video']['dataformat'] = '3ivx';
                         break;
                     case 'xvid':
                         $ThisFileInfo['video']['dataformat'] = 'xvid';
                         break;
                     case 'mp4v':
                         $ThisFileInfo['video']['dataformat'] = 'mpeg4';
                         break;
                     case 'divx':
                     case 'div1':
                     case 'div2':
                     case 'div3':
                     case 'div4':
                     case 'div5':
                     case 'div6':
                         $TDIVXileInfo['video']['dataformat'] = 'divx';
                         break;
                     default:
                         // do nothing
                         break;
                 }
                 unset($atomstructure['sample_description_table'][$i]['data']);
             }
             break;
         case 'stts':
             // Sample Table Time-to-Sample atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $sttsEntriesDataOffset = 8;
             //$FrameRateCalculatorArray = array();
             $frames_count = 0;
             for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                 $atomstructure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atomdata, $sttsEntriesDataOffset, 4));
                 $sttsEntriesDataOffset += 4;
                 $atomstructure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atomdata, $sttsEntriesDataOffset, 4));
                 $sttsEntriesDataOffset += 4;
                 $frames_count += $atomstructure['time_to_sample_table'][$i]['sample_count'];
                 // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
                 //if (!empty($ThisFileInfo['quicktime']['time_scale']) && (@$atomstructure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
                 //	$stts_new_framerate = $ThisFileInfo['quicktime']['time_scale'] / $atomstructure['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
                 //		$ThisFileInfo['video']['frame_rate'] = max(@$ThisFileInfo['video']['frame_rate'], $stts_new_framerate);
                 //	}
                 //}
                 //
                 //@$FrameRateCalculatorArray[($ThisFileInfo['quicktime']['time_scale'] / $atomstructure['time_to_sample_table'][$i]['sample_duration'])] += $atomstructure['time_to_sample_table'][$i]['sample_count'];
             }
             $ThisFileInfo['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) > @$ThisFileInfo['video']['frame_rate']) {
             //		$ThisFileInfo['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
             //	}
             //}
             break;
         case 'stss':
             // Sample Table Sync Sample (key frames) atom
             if ($ParseAllPossibleAtoms) {
                 $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
                 $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
                 // hardcoded: 0x0000
                 $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
                 $stssEntriesDataOffset = 8;
                 for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                     $atomstructure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atomdata, $stssEntriesDataOffset, 4));
                     $stssEntriesDataOffset += 4;
                 }
             }
             break;
         case 'stsc':
             // Sample Table Sample-to-Chunk atom
             if ($ParseAllPossibleAtoms) {
                 $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
                 $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
                 // hardcoded: 0x0000
                 $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
                 $stscEntriesDataOffset = 8;
                 for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                     $atomstructure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atomdata, $stscEntriesDataOffset, 4));
                     $stscEntriesDataOffset += 4;
                     $atomstructure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atomdata, $stscEntriesDataOffset, 4));
                     $stscEntriesDataOffset += 4;
                     $atomstructure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atomdata, $stscEntriesDataOffset, 4));
                     $stscEntriesDataOffset += 4;
                 }
             }
             break;
         case 'stsz':
             // Sample Table SiZe atom
             if ($ParseAllPossibleAtoms) {
                 $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
                 $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
                 // hardcoded: 0x0000
                 $atomstructure['sample_size'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
                 $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
                 $stszEntriesDataOffset = 12;
                 if ($atomstructure['sample_size'] == 0) {
                     for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                         $atomstructure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atomdata, $stszEntriesDataOffset, 4));
                         $stszEntriesDataOffset += 4;
                     }
                 }
             }
             break;
         case 'stco':
             // Sample Table Chunk Offset atom
             if ($ParseAllPossibleAtoms) {
                 $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
                 $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
                 // hardcoded: 0x0000
                 $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
                 $stcoEntriesDataOffset = 8;
                 for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                     $atomstructure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atomdata, $stcoEntriesDataOffset, 4));
                     $stcoEntriesDataOffset += 4;
                 }
             }
             break;
         case 'co64':
             // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
             if ($ParseAllPossibleAtoms) {
                 $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
                 $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
                 // hardcoded: 0x0000
                 $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
                 $stcoEntriesDataOffset = 8;
                 for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                     $atomstructure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atomdata, $stcoEntriesDataOffset, 8));
                     $stcoEntriesDataOffset += 8;
                 }
             }
             break;
         case 'dref':
             // Data REFerence atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $drefDataOffset = 8;
             for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                 $atomstructure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atomdata, $drefDataOffset, 4));
                 $drefDataOffset += 4;
                 $atomstructure['data_references'][$i]['type'] = substr($atomdata, $drefDataOffset, 4);
                 $drefDataOffset += 4;
                 $atomstructure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atomdata, $drefDataOffset, 1));
                 $drefDataOffset += 1;
                 $atomstructure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, $drefDataOffset, 3));
                 // hardcoded: 0x0000
                 $drefDataOffset += 3;
                 $atomstructure['data_references'][$i]['data'] = substr($atomdata, $drefDataOffset, $atomstructure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
                 $drefDataOffset += $atomstructure['data_references'][$i]['size'] - 4 - 4 - 1 - 3;
                 $atomstructure['data_references'][$i]['flags']['self_reference'] = (bool) ($atomstructure['data_references'][$i]['flags_raw'] & 0x1);
             }
             break;
         case 'gmin':
             // base Media INformation atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             $atomstructure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atomdata, 6, 2));
             $atomstructure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 2));
             $atomstructure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atomdata, 10, 2));
             $atomstructure['balance'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 2));
             $atomstructure['reserved'] = getid3_lib::BigEndian2Int(substr($atomdata, 14, 2));
             break;
         case 'smhd':
             // Sound Media information HeaDer atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['balance'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             $atomstructure['reserved'] = getid3_lib::BigEndian2Int(substr($atomdata, 6, 2));
             break;
         case 'vmhd':
             // Video Media information HeaDer atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             $atomstructure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             $atomstructure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atomdata, 6, 2));
             $atomstructure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 2));
             $atomstructure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atomdata, 10, 2));
             $atomstructure['flags']['no_lean_ahead'] = (bool) ($atomstructure['flags_raw'] & 0x1);
             break;
         case 'hdlr':
             // HanDLeR reference atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['component_type'] = substr($atomdata, 4, 4);
             $atomstructure['component_subtype'] = substr($atomdata, 8, 4);
             $atomstructure['component_manufacturer'] = substr($atomdata, 12, 4);
             $atomstructure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 16, 4));
             $atomstructure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atomdata, 20, 4));
             $atomstructure['component_name'] = $this->Pascal2String(substr($atomdata, 24));
             if ($atomstructure['component_subtype'] == 'STpn' && $atomstructure['component_manufacturer'] == 'zzzz') {
                 $ThisFileInfo['video']['dataformat'] = 'quicktimevr';
             }
             break;
         case 'mdhd':
             // MeDia HeaDer atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['creation_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['modify_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             $atomstructure['time_scale'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 4));
             $atomstructure['duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 16, 4));
             $atomstructure['language_id'] = getid3_lib::BigEndian2Int(substr($atomdata, 20, 2));
             $atomstructure['quality'] = getid3_lib::BigEndian2Int(substr($atomdata, 22, 2));
             if ($atomstructure['time_scale'] == 0) {
                 $ThisFileInfo['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
                 return false;
             }
             $ThisFileInfo['quicktime']['time_scale'] = max(@$ThisFileInfo['quicktime']['time_scale'], $atomstructure['time_scale']);
             $atomstructure['creation_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['creation_time']);
             $atomstructure['modify_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['modify_time']);
             $atomstructure['playtime_seconds'] = $atomstructure['duration'] / $atomstructure['time_scale'];
             $atomstructure['language'] = $this->QuicktimeLanguageLookup($atomstructure['language_id']);
             if (empty($ThisFileInfo['comments']['language']) || !in_array($atomstructure['language'], $ThisFileInfo['comments']['language'])) {
                 $ThisFileInfo['comments']['language'][] = $atomstructure['language'];
             }
             break;
         case 'pnot':
             // Preview atom
             $atomstructure['modification_date'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             // "standard Macintosh format"
             $atomstructure['version_number'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             // hardcoded: 0x00
             $atomstructure['atom_type'] = substr($atomdata, 6, 4);
             // usually: 'PICT'
             $atomstructure['atom_index'] = getid3_lib::BigEndian2Int(substr($atomdata, 10, 2));
             // usually: 0x01
             $atomstructure['modification_date_unix'] = getid3_lib::DateMac2Unix($atomstructure['modification_date']);
             break;
         case 'crgn':
             // Clipping ReGioN atom
             $atomstructure['region_size'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 2));
             // The Region size, Region boundary box,
             $atomstructure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atomdata, 2, 8));
             // and Clipping region data fields
             $atomstructure['clipping_data'] = substr($atomdata, 10);
             // constitute a QuickDraw region.
             break;
         case 'load':
             // track LOAD settings atom
             $atomstructure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             $atomstructure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             $atomstructure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 4));
             $atomstructure['default_hints']['double_buffer'] = (bool) ($atomstructure['default_hints_raw'] & 0x20);
             $atomstructure['default_hints']['high_quality'] = (bool) ($atomstructure['default_hints_raw'] & 0x100);
             break;
         case 'tmcd':
             // TiMe CoDe atom
         // TiMe CoDe atom
         case 'chap':
             // CHAPter list atom
         // CHAPter list atom
         case 'sync':
             // SYNChronization atom
         // SYNChronization atom
         case 'scpt':
             // tranSCriPT atom
         // tranSCriPT atom
         case 'ssrc':
             // non-primary SouRCe atom
             for ($i = 0; $i < strlen($atomdata) % 4; $i++) {
                 $atomstructure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atomdata, $i * 4, 4));
             }
             break;
         case 'elst':
             // Edit LiST atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['number_entries'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             for ($i = 0; $i < $atomstructure['number_entries']; $i++) {
                 $atomstructure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $i * 12 + 0, 4));
                 $atomstructure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $i * 12 + 4, 4));
                 $atomstructure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atomdata, 8 + $i * 12 + 8, 4));
             }
             break;
         case 'kmat':
             // compressed MATte atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             // hardcoded: 0x0000
             $atomstructure['matte_data_raw'] = substr($atomdata, 4);
             break;
         case 'ctab':
             // Color TABle atom
             $atomstructure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             // hardcoded: 0x00000000
             $atomstructure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 2));
             // hardcoded: 0x8000
             $atomstructure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atomdata, 6, 2)) + 1;
             for ($colortableentry = 0; $colortableentry < $atomstructure['color_table_size']; $colortableentry++) {
                 $atomstructure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $colortableentry * 8 + 0, 2));
                 $atomstructure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $colortableentry * 8 + 2, 2));
                 $atomstructure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $colortableentry * 8 + 4, 2));
                 $atomstructure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atomdata, 8 + $colortableentry * 8 + 6, 2));
             }
             break;
         case 'mvhd':
             // MoVie HeaDer atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             $atomstructure['creation_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['modify_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             $atomstructure['time_scale'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 4));
             $atomstructure['duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 16, 4));
             $atomstructure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atomdata, 20, 4));
             $atomstructure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atomdata, 24, 2));
             $atomstructure['reserved'] = substr($atomdata, 26, 10);
             $atomstructure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atomdata, 36, 4));
             $atomstructure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atomdata, 40, 4));
             $atomstructure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atomdata, 44, 4));
             $atomstructure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atomdata, 48, 4));
             $atomstructure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atomdata, 52, 4));
             $atomstructure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atomdata, 56, 4));
             $atomstructure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atomdata, 60, 4));
             $atomstructure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atomdata, 64, 4));
             $atomstructure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atomdata, 68, 4));
             $atomstructure['preview_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 72, 4));
             $atomstructure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 76, 4));
             $atomstructure['poster_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 80, 4));
             $atomstructure['selection_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 84, 4));
             $atomstructure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 88, 4));
             $atomstructure['current_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 92, 4));
             $atomstructure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atomdata, 96, 4));
             if ($atomstructure['time_scale'] == 0) {
                 $ThisFileInfo['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
                 return false;
             }
             $atomstructure['creation_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['creation_time']);
             $atomstructure['modify_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['modify_time']);
             $ThisFileInfo['quicktime']['time_scale'] = max(@$ThisFileInfo['quicktime']['time_scale'], $atomstructure['time_scale']);
             $ThisFileInfo['quicktime']['display_scale'] = $atomstructure['matrix_a'];
             $ThisFileInfo['playtime_seconds'] = $atomstructure['duration'] / $atomstructure['time_scale'];
             break;
         case 'tkhd':
             // TracK HeaDer atom
             $atomstructure['version'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 1));
             $atomstructure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atomdata, 1, 3));
             $atomstructure['creation_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['modify_time'] = getid3_lib::BigEndian2Int(substr($atomdata, 8, 4));
             $atomstructure['trackid'] = getid3_lib::BigEndian2Int(substr($atomdata, 12, 4));
             $atomstructure['reserved1'] = getid3_lib::BigEndian2Int(substr($atomdata, 16, 4));
             $atomstructure['duration'] = getid3_lib::BigEndian2Int(substr($atomdata, 20, 4));
             $atomstructure['reserved2'] = getid3_lib::BigEndian2Int(substr($atomdata, 24, 8));
             $atomstructure['layer'] = getid3_lib::BigEndian2Int(substr($atomdata, 32, 2));
             $atomstructure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atomdata, 34, 2));
             $atomstructure['volume'] = getid3_lib::FixedPoint8_8(substr($atomdata, 36, 2));
             $atomstructure['reserved3'] = getid3_lib::BigEndian2Int(substr($atomdata, 38, 2));
             $atomstructure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atomdata, 40, 4));
             $atomstructure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atomdata, 44, 4));
             $atomstructure['matrix_u'] = getid3_lib::FixedPoint16_16(substr($atomdata, 48, 4));
             $atomstructure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atomdata, 52, 4));
             $atomstructure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atomdata, 56, 4));
             $atomstructure['matrix_v'] = getid3_lib::FixedPoint16_16(substr($atomdata, 60, 4));
             $atomstructure['matrix_x'] = getid3_lib::FixedPoint2_30(substr($atomdata, 64, 4));
             $atomstructure['matrix_y'] = getid3_lib::FixedPoint2_30(substr($atomdata, 68, 4));
             $atomstructure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atomdata, 72, 4));
             $atomstructure['width'] = getid3_lib::FixedPoint16_16(substr($atomdata, 76, 4));
             $atomstructure['height'] = getid3_lib::FixedPoint16_16(substr($atomdata, 80, 4));
             $atomstructure['flags']['enabled'] = (bool) ($atomstructure['flags_raw'] & 0x1);
             $atomstructure['flags']['in_movie'] = (bool) ($atomstructure['flags_raw'] & 0x2);
             $atomstructure['flags']['in_preview'] = (bool) ($atomstructure['flags_raw'] & 0x4);
             $atomstructure['flags']['in_poster'] = (bool) ($atomstructure['flags_raw'] & 0x8);
             $atomstructure['creation_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['creation_time']);
             $atomstructure['modify_time_unix'] = getid3_lib::DateMac2Unix($atomstructure['modify_time']);
             if (!isset($ThisFileInfo['video']['resolution_x']) || !isset($ThisFileInfo['video']['resolution_y'])) {
                 $ThisFileInfo['video']['resolution_x'] = $atomstructure['width'];
                 $ThisFileInfo['video']['resolution_y'] = $atomstructure['height'];
             }
             if ($atomstructure['flags']['enabled'] == 1) {
                 $ThisFileInfo['video']['resolution_x'] = max($ThisFileInfo['video']['resolution_x'], $atomstructure['width']);
                 $ThisFileInfo['video']['resolution_y'] = max($ThisFileInfo['video']['resolution_y'], $atomstructure['height']);
             }
             if (!empty($ThisFileInfo['video']['resolution_x']) && !empty($ThisFileInfo['video']['resolution_y'])) {
                 $ThisFileInfo['quicktime']['video']['resolution_x'] = $ThisFileInfo['video']['resolution_x'];
                 $ThisFileInfo['quicktime']['video']['resolution_y'] = $ThisFileInfo['video']['resolution_y'];
             } else {
                 unset($ThisFileInfo['video']['resolution_x']);
                 unset($ThisFileInfo['video']['resolution_y']);
                 unset($ThisFileInfo['quicktime']['video']);
             }
             break;
         case 'meta':
             // METAdata atom
             // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
             $NextTagPosition = strpos($atomdata, '�');
             while ($NextTagPosition < strlen($atomdata)) {
                 $metaItemSize = getid3_lib::BigEndian2Int(substr($atomdata, $NextTagPosition - 4, 4)) - 4;
                 if ($metaItemSize == -4) {
                     break;
                 }
                 $metaItemRaw = substr($atomdata, $NextTagPosition, $metaItemSize);
                 $metaItemKey = substr($metaItemRaw, 0, 4);
                 $metaItemData = substr($metaItemRaw, 20);
                 $NextTagPosition += $metaItemSize + 4;
                 $this->CopyToAppropriateCommentsSection($metaItemKey, $metaItemData, $ThisFileInfo);
             }
             break;
         case 'ftyp':
             // FileTYPe (?) atom (for MP4 it seems)
             $atomstructure['signature'] = substr($atomdata, 0, 4);
             $atomstructure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atomdata, 4, 4));
             $atomstructure['fourcc'] = substr($atomdata, 8, 4);
             break;
         case 'mdat':
             // Media DATa atom
         // Media DATa atom
         case 'free':
             // FREE space atom
         // FREE space atom
         case 'skip':
             // SKIP atom
         // SKIP atom
         case 'wide':
             // 64-bit expansion placeholder atom
             // 'mdat' data is too big to deal with, contains no useful metadata
             // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
             // When writing QuickTime files, it is sometimes necessary to update an atom's size.
             // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
             // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
             // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
             // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
             // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
             // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
             break;
         case 'nsav':
             // NoSAVe atom
             // http://developer.apple.com/technotes/tn/tn2038.html
             $atomstructure['data'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             break;
         case 'ctyp':
             // Controller TYPe atom (seen on QTVR)
             // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
             // some controller names are:
             //   0x00 + 'std' for linear movie
             //   'none' for no controls
             $atomstructure['ctyp'] = substr($atomdata, 0, 4);
             switch ($atomstructure['ctyp']) {
                 case 'qtvr':
                     $ThisFileInfo['video']['dataformat'] = 'quicktimevr';
                     break;
             }
             break;
         case 'pano':
             // PANOrama track (seen on QTVR)
             $atomstructure['pano'] = getid3_lib::BigEndian2Int(substr($atomdata, 0, 4));
             break;
         case 'hint':
             // HINT track
         // HINT track
         case 'hinf':
             //
         //
         case 'hinv':
             //
         //
         case 'hnti':
             //
             $ThisFileInfo['quicktime']['hinting'] = true;
             break;
         case 'imgt':
             // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
             for ($i = 0; $i < $atomstructure['size'] - 8; $i += 4) {
                 $atomstructure['imgt'][] = getid3_lib::BigEndian2Int(substr($atomdata, $i, 4));
             }
             break;
         case 'FXTC':
             // Something to do with Adobe After Effects (?)
         // Something to do with Adobe After Effects (?)
         case 'PrmA':
         case 'code':
         case 'FIEL':
             // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
             // Observed-but-not-handled atom types are just listed here
             // to prevent warnings being generated
             $atomstructure['data'] = $atomdata;
             break;
         default:
             $ThisFileInfo['warning'][] = 'Unknown QuickTime atom type: "' . $atomname . '" at offset ' . $baseoffset;
             $atomstructure['data'] = $atomdata;
             break;
     }
     array_pop($atomHierarchy);
     return $atomstructure;
 }
 public 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 = end($atomHierarchy);
     // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
     array_push($atomHierarchy, $atomname);
     $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
     $atom_structure['name'] = $atomname;
     $atom_structure['size'] = $atomsize;
     $atom_structure['offset'] = $baseoffset;
     switch ($atomname) {
         case 'moov':
             // MOVie container atom
         // MOVie container atom
         case 'trak':
             // TRAcK container atom
         // TRAcK container atom
         case 'clip':
             // CLIPping container atom
         // CLIPping container atom
         case 'matt':
             // track MATTe container atom
         // track MATTe container atom
         case 'edts':
             // EDiTS container atom
         // EDiTS container atom
         case 'tref':
             // Track REFerence container atom
         // Track REFerence container atom
         case 'mdia':
             // MeDIA container atom
         // MeDIA container atom
         case 'minf':
             // Media INFormation container atom
         // Media INFormation container atom
         case 'dinf':
             // Data INFormation container atom
         // Data INFormation container atom
         case 'udta':
             // User DaTA container atom
         // User DaTA container atom
         case 'cmov':
             // Compressed MOVie container atom
         // Compressed MOVie container atom
         case 'rmra':
             // Reference Movie Record Atom
         // Reference Movie Record Atom
         case 'rmda':
             // Reference Movie Descriptor Atom
         // 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
             if ($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 "":
         case "":
         case "":
         case "":
         case "":
             $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
         // Album ARTist
         case 'catg':
             // CaTeGory
         // CaTeGory
         case 'covr':
             // COVeR artwork
         // COVeR artwork
         case 'cpil':
             // ComPILation
         // ComPILation
         case 'cprt':
             // CoPyRighT
         // CoPyRighT
         case 'desc':
             // DESCription
         // DESCription
         case 'disk':
             // DISK number
         // DISK number
         case 'egid':
             // Episode Global ID
         // Episode Global ID
         case 'gnre':
             // GeNRE
         // GeNRE
         case 'keyw':
             // KEYWord
         // KEYWord
         case 'ldes':
         case 'pcst':
             // PodCaST
         // PodCaST
         case 'pgap':
             // GAPless Playback
         // GAPless Playback
         case 'purd':
             // PURchase Date
         // PURchase Date
         case 'purl':
             // Podcast URL
         // Podcast URL
         case 'rati':
         case 'rndu':
         case 'rpdu':
         case 'rtng':
             // RaTiNG
         // RaTiNG
         case 'stik':
         case 'tmpo':
             // TeMPO (BPM)
         // TeMPO (BPM)
         case 'trkn':
             // TRacK Number
         // TRacK Number
         case 'tves':
             // TV EpiSode
         // TV EpiSode
         case 'tvnn':
             // TV Network Name
         // TV Network Name
         case 'tvsh':
             // TV SHow Name
         // TV SHow Name
         case 'tvsn':
             // TV SeasoN
         // TV SeasoN
         case 'akID':
             // iTunes store account type
         // iTunes store account type
         case 'apID':
         case 'atID':
         case 'cmID':
         case 'cnID':
         case 'geID':
         case 'plID':
         case 'sfID':
             // iTunes store country
         // iTunes store country
         case "©" . 'alb':
             // ALBum
         // ALBum
         case "©" . 'art':
             // ARTist
         // ARTist
         case "©" . 'ART':
         case "©" . 'aut':
         case "©" . 'cmt':
             // CoMmenT
         // CoMmenT
         case "©" . 'com':
             // COMposer
         // COMposer
         case "©" . 'cpy':
         case "©" . 'day':
             // content created year
         // 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
         // GENre
         case "©" . 'grp':
             // GRouPing
         // GRouPing
         case "©" . 'hst':
         case "©" . 'inf':
         case "©" . 'lyr':
             // LYRics
         // LYRics
         case "©" . 'mak':
         case "©" . 'mod':
         case "©" . 'nam':
             // full NAMe
         // full NAMe
         case "©" . 'ope':
         case "©" . 'PRD':
         case "©" . 'prd':
         case "©" . 'prf':
         case "©" . 'req':
         case "©" . 'src':
         case "©" . 'swr':
         case "©" . 'too':
             // encoder
         // encoder
         case "©" . 'trk':
             // TRacK
         // TRacK
         case "©" . 'url':
         case "©" . 'wrn':
         case "©" . 'wrt':
             // WRiTer
         // 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) == "µ") {
                     // 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);
                         if ($boxsmallsize <= 1) {
                             $info['warning'][] = 'Invalid QuickTime atom smallbox size "' . $boxsmallsize . '" in atom "' . $atomname . '" at offset: ' . ($atom_structure['offset'] + $atomoffset);
                             $atom_structure['data'] = null;
                             $atomoffset = strlen($atom_data);
                             break;
                         }
                         switch ($boxsmalltype) {
                             case "µ":
                                 $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);
                         if ($boxsize <= 1) {
                             $info['warning'][] = 'Invalid QuickTime atom box size "' . $boxsize . '" in atom "' . $atomname . '" at offset: ' . ($atom_structure['offset'] + $atomoffset);
                             $atom_structure['data'] = null;
                             $atomoffset = strlen($atom_data);
                             break;
                         }
                         $atomoffset += $boxsize;
                         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
                                     // 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
                                     // text flag
                                     case 13:
                                         // image flag
                                     // image flag
                                     default:
                                         $atom_structure['data'] = substr($boxdata, 8);
                                         if ($atomname == 'covr') {
                                             // not a foolproof check, but better than nothing
                                             if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
                                                 $atom_structure['image_mime'] = 'image/jpeg';
                                             } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
                                                 $atom_structure['image_mime'] = 'image/png';
                                             } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
                                                 $atom_structure['image_mime'] = 'image/gif';
                                             }
                                         }
                                         break;
                                 }
                                 break;
                             default:
                                 $info['warning'][] = 'Unknown QuickTime box type: "' . getid3_lib::PrintHexBytes($boxtype) . '" at offset ' . $baseoffset;
                                 $atom_structure['data'] = $atom_data;
                         }
                     }
                 }
             }
             $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
         // LOOPing atom
         case 'SelO':
             // play SELection Only atom
         // 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
         // Media Cleaner PRo
         case '@PRM':
             // adobe PReMiere version
         // 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)) {
                 $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'] & 0x1);
             $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 "":
                         // audio tracks
                         $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));
                         // video tracks
                         // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
                         $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4));
                         $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4));
                         $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2));
                         $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2));
                         $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4));
                         $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4));
                         $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4));
                         $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2));
                         $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4);
                         $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2));
                         $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2));
                         switch ($atom_structure['sample_description_table'][$i]['data_format']) {
                             case '2vuY':
                             case 'avc1':
                             case 'cvid':
                             case 'dvc ':
                             case 'dvcp':
                             case 'gif ':
                             case 'h263':
                             case 'jpeg':
                             case 'kpcd':
                             case 'mjpa':
                             case 'mjpb':
                             case 'mp4v':
                             case 'png ':
                             case 'raw ':
                             case 'rle ':
                             case 'rpza':
                             case 'smc ':
                             case 'SVQ1':
                             case 'SVQ3':
                             case 'tiff':
                             case 'v210':
                             case 'v216':
                             case 'v308':
                             case 'v408':
                             case 'v410':
                             case 'yuv2':
                                 $info['fileformat'] = 'mp4';
                                 $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
                                 // http://www.getid3.org/phpBB3/viewtopic.php?t=1550
                                 //if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
                                 if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
                                     // assume that values stored here are more important than values stored in [tkhd] atom
                                     $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
                                     $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
                                     $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
                                     $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
                                 }
                                 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
                                     // 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'] = (double) 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'] & 0x1);
             }
             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'] & 0x1);
             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 Macintosh format"
             $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
             // hardcoded: 0x00
             $atom_structure['atom_type'] = substr($atom_data, 6, 4);
             // usually: 'PICT'
             $atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
             // usually: 0x01
             $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
             break;
         case 'crgn':
             // Clipping ReGioN atom
             $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
             // The Region size, Region boundary box,
             $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8));
             // and Clipping region data fields
             $atom_structure['clipping_data'] = substr($atom_data, 10);
             // constitute a QuickDraw region.
             break;
         case 'load':
             // track LOAD settings atom
             $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
             $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
             $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x20);
             $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x100);
             break;
         case 'tmcd':
             // TiMe CoDe atom
         // TiMe CoDe atom
         case 'chap':
             // CHAPter list atom
         // CHAPter list atom
         case 'sync':
             // SYNChronization atom
         // SYNChronization atom
         case 'scpt':
             // tranSCriPT atom
         // tranSCriPT atom
         case 'ssrc':
             // non-primary SouRCe atom
             for ($i = 0; $i < strlen($atom_data); $i += 4) {
                 @($atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)));
             }
             break;
         case 'elst':
             // Edit LiST 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));
             for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
                 $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $i * 12 + 0, 4));
                 $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $i * 12 + 4, 4));
                 $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + $i * 12 + 8, 4));
             }
             break;
         case 'kmat':
             // compressed MATte 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['matte_data_raw'] = substr($atom_data, 4);
             break;
         case 'ctab':
             // Color TABle atom
             $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             // hardcoded: 0x00000000
             $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
             // hardcoded: 0x8000
             $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1;
             for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
                 $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 0, 2));
                 $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 2, 2));
                 $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 4, 2));
                 $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 6, 2));
             }
             break;
         case 'mvhd':
             // MoVie 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['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['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
             $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
             $atom_structure['reserved'] = substr($atom_data, 26, 10);
             $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
             $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
             $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
             $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
             $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
             $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
             $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
             $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
             $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
             $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
             $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
             $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
             $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
             $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
             $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
             $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
             if ($atom_structure['time_scale'] == 0) {
                 $info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
                 return false;
             }
             $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
             $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
             $info['quicktime']['time_scale'] = isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale'];
             $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
             $info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
             break;
         case 'tkhd':
             // TracK 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['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
             $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
             $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
             $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
             $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
             $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
             $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
             $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
             $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
             // http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
             // http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
             $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
             $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
             $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
             $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
             $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
             $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
             $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
             $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
             $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
             $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
             $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
             $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x1);
             $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x2);
             $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x4);
             $atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x8);
             $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
             $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
             if ($atom_structure['flags']['enabled'] == 1) {
                 if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
                     $info['video']['resolution_x'] = $atom_structure['width'];
                     $info['video']['resolution_y'] = $atom_structure['height'];
                 }
                 $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
                 $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
                 $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
                 $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
             } else {
                 // see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295
                 //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
                 //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
                 //if (isset($info['quicktime']['video']))    { unset($info['quicktime']['video']);    }
             }
             break;
         case 'iods':
             // Initial Object DeScriptor atom
             // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
             // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
             $offset = 0;
             $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
             $offset += 3;
             $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
             //$offset already adjusted by quicktime_read_mp4_descr_length()
             $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
             $offset += 2;
             $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6;
             // 6 bytes would only be right if all tracks use 1-byte length fields
             for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
                 $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
                 $offset += 1;
                 $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
                 //$offset already adjusted by quicktime_read_mp4_descr_length()
                 $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
                 $offset += 4;
             }
             $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
             $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
             break;
         case 'ftyp':
             // FileTYPe (?) atom (for MP4 it seems)
             $atom_structure['signature'] = substr($atom_data, 0, 4);
             $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['fourcc'] = substr($atom_data, 8, 4);
             break;
         case 'mdat':
             // Media DATa atom
             // 'mdat' contains the actual data for the audio/video, possibly also subtitles
             /* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
             // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
             $mdat_offset = 0;
             while (true) {
                 if (substr($atom_data, $mdat_offset, 8) == "" . 'wide') {
                     $mdat_offset += 8;
                 } elseif (substr($atom_data, $mdat_offset, 8) == "" . 'mdat') {
                     $mdat_offset += 8;
                 } else {
                     break;
                 }
             }
             // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
             while (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) && $chapter_string_length < 1000 && $chapter_string_length <= strlen($atom_data) - $mdat_offset - 2 && preg_match('#^[\\x20-\\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
                 $mdat_offset += 2 + $chapter_string_length;
                 @($info['quicktime']['comments']['chapters'][] = $chapter_matches[0]);
             }
             if ($atomsize > 8 && (!isset($info['avdataend_tmp']) || $info['quicktime'][$atomname]['size'] > $info['avdataend_tmp'] - $info['avdataoffset'])) {
                 $info['avdataoffset'] = $atom_structure['offset'] + 8;
                 // $info['quicktime'][$atomname]['offset'] + 8;
                 $OldAVDataEnd = $info['avdataend'];
                 $info['avdataend'] = $atom_structure['offset'] + $atom_structure['size'];
                 // $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($this->fread(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);
             }
             unset($mdat_offset, $chapter_string_length, $chapter_matches);
             break;
         case 'free':
             // FREE space atom
         // FREE space atom
         case 'skip':
             // SKIP atom
         // SKIP atom
         case 'wide':
             // 64-bit expansion placeholder atom
             // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
             // When writing QuickTime files, it is sometimes necessary to update an atom's size.
             // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
             // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
             // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
             // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
             // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
             // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
             break;
         case 'nsav':
             // NoSAVe atom
             // http://developer.apple.com/technotes/tn/tn2038.html
             $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             break;
         case 'ctyp':
             // Controller TYPe atom (seen on QTVR)
             // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
             // some controller names are:
             //   0x00 + 'std' for linear movie
             //   'none' for no controls
             $atom_structure['ctyp'] = substr($atom_data, 0, 4);
             $info['quicktime']['controller'] = $atom_structure['ctyp'];
             switch ($atom_structure['ctyp']) {
                 case 'qtvr':
                     $info['video']['dataformat'] = 'quicktimevr';
                     break;
             }
             break;
         case 'pano':
             // PANOrama track (seen on QTVR)
             $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             break;
         case 'hint':
             // HINT track
         // HINT track
         case 'hinf':
             //
         //
         case 'hinv':
             //
         //
         case 'hnti':
             //
             $info['quicktime']['hinting'] = true;
             break;
         case 'imgt':
             // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
             for ($i = 0; $i < $atom_structure['size'] - 8; $i += 4) {
                 $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
             }
             break;
             // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
         // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
         case 'FXTC':
             // Something to do with Adobe After Effects (?)
         // Something to do with Adobe After Effects (?)
         case 'PrmA':
         case 'code':
         case 'FIEL':
             // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
         // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
         case 'tapt':
             // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
             // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
             // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
             // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
         // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
         // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
         // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
         // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
         case 'ctts':
             //  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'cslg':
             //  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'sdtp':
             //  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'stps':
             //  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
             //$atom_structure['data'] = $atom_data;
             break;
         case "©" . 'xyz':
             // GPS latitude+longitude+altitude
             $atom_structure['data'] = $atom_data;
             if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
                 @(list($all, $latitude, $longitude, $altitude) = $matches);
                 $info['quicktime']['comments']['gps_latitude'][] = floatval($latitude);
                 $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
                 if (!empty($altitude)) {
                     $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
                 }
             } else {
                 $info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset ' . $baseoffset . '. Please report as getID3() bug.';
             }
             break;
         case 'NCDT':
             // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
             // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
             $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
             break;
         case 'NCTH':
             // Nikon Camera THumbnail image
         // Nikon Camera THumbnail image
         case 'NCVW':
             // Nikon Camera preVieW image
             // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
             if (preg_match('/^\\xFF\\xD8\\xFF/', $atom_data)) {
                 $atom_structure['data'] = $atom_data;
                 $atom_structure['image_mime'] = 'image/jpeg';
                 $atom_structure['description'] = $atomname == 'NCTH' ? 'Nikon Camera Thumbnail Image' : ($atomname == 'NCVW' ? 'Nikon Camera Preview Image' : 'Nikon preview image');
                 $info['quicktime']['comments']['picture'][] = array('image_mime' => $atom_structure['image_mime'], 'data' => $atom_data, 'description' => $atom_structure['description']);
             }
             break;
         case 'NCTG':
             // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
             $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
             break;
         case 'NCHD':
             // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
         // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
         case 'NCDB':
             // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
         // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
         case 'CNCV':
             // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
             $atom_structure['data'] = $atom_data;
             break;
         case "":
         case 'meta':
             // METAdata atom
             // some kind of metacontainer, may contain a big data dump such as:
             // mdta keys  mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst   data DEApple 0  (data DE2011-05-11T17:54:04+0200 2  *data DE+52.4936+013.3897+040.247/   data DE4.3.1  data DEiPhone 4
             // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
             $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['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
             //$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
             break;
         case 'data':
             // metaDATA atom
             // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
             $atom_structure['language'] = substr($atom_data, 4 + 0, 2);
             $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
             $atom_structure['data'] = substr($atom_data, 4 + 4);
             break;
         default:
             $info['warning'][] = 'Unknown QuickTime atom type: "' . $atomname . '" (' . trim(getid3_lib::PrintHexBytes($atomname)) . ') at offset ' . $baseoffset;
             $atom_structure['data'] = $atom_data;
             break;
     }
     array_pop($atomHierarchy);
     return $atom_structure;
 }
 function QuicktimeParseAtom($atomname, $atomsize, $atom_data, &$ThisFileInfo, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms)
 {
     // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
     $atomparent = array_pop($atomHierarchy);
     array_push($atomHierarchy, $atomname);
     $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
     $atom_structure['name'] = $atomname;
     $atom_structure['size'] = $atomsize;
     $atom_structure['offset'] = $baseoffset;
     switch ($atomname) {
         case 'moov':
             // MOVie container atom
         // MOVie container atom
         case 'trak':
             // TRAcK container atom
         // TRAcK container atom
         case 'clip':
             // CLIPping container atom
         // CLIPping container atom
         case 'matt':
             // track MATTe container atom
         // track MATTe container atom
         case 'edts':
             // EDiTS container atom
         // EDiTS container atom
         case 'tref':
             // Track REFerence container atom
         // Track REFerence container atom
         case 'mdia':
             // MeDIA container atom
         // MeDIA container atom
         case 'minf':
             // Media INFormation container atom
         // Media INFormation container atom
         case 'dinf':
             // Data INFormation container atom
         // Data INFormation container atom
         case 'udta':
             // User DaTA container atom
         // User DaTA container atom
         case 'cmov':
             // Compressed MOVie container atom
         // Compressed MOVie container atom
         case 'rmra':
             // Reference Movie Record Atom
         // Reference Movie Record Atom
         case 'rmda':
             // Reference Movie Descriptor Atom
         // Reference Movie Descriptor Atom
         case 'gmhd':
             // Generic Media info HeaDer atom (seen on QTVR)
         // Generic Media info HeaDer atom (seen on QTVR)
         case 'ilst':
             // Item LiST container atom
             $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $ThisFileInfo, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
             break;
         case 'stbl':
             // Sample TaBLe container atom
             $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $ThisFileInfo, $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($ThisFileInfo['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
                             $framecount = $value_array2['sample_count'];
                         }
                     }
                 }
             }
             if ($isVideo && $framerate) {
                 $ThisFileInfo['quicktime']['video']['frame_rate'] = $framerate;
                 $ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['quicktime']['video']['frame_rate'];
             }
             if ($isVideo && $framecount) {
                 $ThisFileInfo['quicktime']['video']['frame_count'] = $framecount;
             }
             break;
         case 'aART':
             // Album ARTist
         // Album ARTist
         case 'catg':
             // CaTeGory
         // CaTeGory
         case 'covr':
             // COVeR artwork
         // COVeR artwork
         case 'cpil':
             // ComPILation
         // ComPILation
         case 'cprt':
             // CoPyRighT
         // CoPyRighT
         case 'desc':
             // DESCription
         // DESCription
         case 'disk':
             // DISK number
         // DISK number
         case 'egid':
             // Episode Global ID
         // Episode Global ID
         case 'gnre':
             // GeNRE
         // GeNRE
         case 'keyw':
             // KEYWord
         // KEYWord
         case 'ldes':
         case 'pcst':
             // PodCaST
         // PodCaST
         case 'pgap':
             // GAPless Playback
         // GAPless Playback
         case 'purd':
             // PURchase Date
         // PURchase Date
         case 'purl':
             // Podcast URL
         // Podcast URL
         case 'rati':
         case 'rndu':
         case 'rpdu':
         case 'rtng':
             // RaTiNG
         // RaTiNG
         case 'stik':
         case 'tmpo':
             // TeMPO (BPM)
         // TeMPO (BPM)
         case 'trkn':
             // TRacK Number
         // TRacK Number
         case 'tves':
             // TV EpiSode
         // TV EpiSode
         case 'tvnn':
             // TV Network Name
         // TV Network Name
         case 'tvsh':
             // TV SHow Name
         // TV SHow Name
         case 'tvsn':
             // TV SeasoN
         // TV SeasoN
         case 'akID':
             // iTunes store account type
         // iTunes store account type
         case 'apID':
         case 'atID':
         case 'cmID':
         case 'cnID':
         case 'geID':
         case 'plID':
         case 'sfID':
             // iTunes store country
         // iTunes store country
         case '©alb':
             // ALBum
         // ALBum
         case '©art':
             // ARTist
         // ARTist
         case '©ART':
         case '©aut':
         case '©cmt':
             // CoMmenT
         // CoMmenT
         case '©com':
             // COMposer
         // COMposer
         case '©cpy':
         case '©day':
             // content created year
         // 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
         // GENre
         case '©grp':
             // GRouPing
         // GRouPing
         case '©hst':
         case '©inf':
         case '©lyr':
             // LYRics
         // LYRics
         case '©mak':
         case '©mod':
         case '©nam':
             // full NAMe
         // full NAMe
         case '©ope':
         case '©PRD':
         case '©prd':
         case '©prf':
         case '©req':
         case '©src':
         case '©swr':
         case '©too':
             // encoder
         // encoder
         case '©trk':
             // TRacK
         // TRacK
         case '©url':
         case '©wrn':
         case '©wrt':
             // WRiTer
         // WRiTer
         case '----':
             // itunes specific
             if ($atomparent == '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($ThisFileInfo['comments']['language']) || !in_array($atom_structure['language'], $ThisFileInfo['comments']['language'])) {
                     $ThisFileInfo['comments']['language'][] = $atom_structure['language'];
                 }
             } else {
                 // Apple item list box atom handler
                 $atomoffset = 0;
                 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
                                 // 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
                                 // text flag
                                 case 13:
                                     // image flag
                                 // image flag
                                 default:
                                     $atom_structure['data'] = substr($boxdata, 8);
                                     break;
                             }
                             break;
                         default:
                             $ThisFileInfo['warning'][] = 'Unknown QuickTime box type: "' . $boxtype . '" at offset ' . $baseoffset;
                             $atom_structure['data'] = $atom_data;
                     }
                     $atomoffset += $boxsize;
                 }
             }
             $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $ThisFileInfo, $atom_structure['name']);
             break;
         case 'play':
             // auto-PLAY atom
             $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
             $ThisFileInfo['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
         // LOOPing atom
         case 'SelO':
             // play SELection Only atom
         // 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
         // Media Cleaner PRo
         case '@PRM':
             // adobe PReMiere version
         // 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);
             ob_start();
             if ($UncompressedHeader = gzuncompress($CompressedFileData)) {
                 ob_end_clean();
                 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, $ThisFileInfo, 0, $atomHierarchy, $ParseAllPossibleAtoms);
             } else {
                 $errormessage = ob_get_contents();
                 ob_end_clean();
                 $ThisFileInfo['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'] & 0x1);
             $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($ThisFileInfo['comments']['language']) || !in_array($atom_structure['language'], $ThisFileInfo['comments']['language'])) {
                 $ThisFileInfo['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 {
                 $ThisFileInfo['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 "":
                         // 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':
                                 $ThisFileInfo['fileformat'] = 'mp4';
                                 $ThisFileInfo['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
                                 //$ThisFileInfo['warning'][] = 'This version of getID3() [v'.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':
                                 $ThisFileInfo['video']['dataformat'] = 'quicktimevr';
                                 break;
                             case 'mp4a':
                             default:
                                 $ThisFileInfo['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
                                 $ThisFileInfo['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
                                 $ThisFileInfo['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels'];
                                 $ThisFileInfo['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
                                 $ThisFileInfo['audio']['codec'] = $ThisFileInfo['quicktime']['audio']['codec'];
                                 $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['quicktime']['audio']['sample_rate'];
                                 $ThisFileInfo['audio']['channels'] = $ThisFileInfo['quicktime']['audio']['channels'];
                                 $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['quicktime']['audio']['bit_depth'];
                                 switch ($atom_structure['sample_description_table'][$i]['data_format']) {
                                     case 'raw ':
                                         // PCM
                                     // PCM
                                     case 'alac':
                                         // Apple Lossless Audio Codec
                                         $ThisFileInfo['audio']['lossless'] = true;
                                         break;
                                     default:
                                         $ThisFileInfo['audio']['lossless'] = false;
                                         break;
                                 }
                                 break;
                         }
                         break;
                     default:
                         switch ($atom_structure['sample_description_table'][$i]['data_format']) {
                             case 'mp4s':
                                 $ThisFileInfo['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') {
                                     $ThisFileInfo['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
                                     $ThisFileInfo['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
                                     $ThisFileInfo['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'];
                                     $ThisFileInfo['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
                                     $ThisFileInfo['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
                                     $ThisFileInfo['video']['codec'] = $ThisFileInfo['quicktime']['video']['codec'];
                                     $ThisFileInfo['video']['bits_per_sample'] = $ThisFileInfo['quicktime']['video']['color_depth'];
                                 }
                                 $ThisFileInfo['video']['lossless'] = false;
                                 $ThisFileInfo['video']['pixel_aspect_ratio'] = (double) 1;
                                 break;
                         }
                         break;
                 }
                 switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
                     case 'mp4a':
                         $ThisFileInfo['audio']['dataformat'] = 'mp4';
                         $ThisFileInfo['quicktime']['audio']['codec'] = 'mp4';
                         break;
                     case '3ivx':
                     case '3iv1':
                     case '3iv2':
                         $ThisFileInfo['video']['dataformat'] = '3ivx';
                         break;
                     case 'xvid':
                         $ThisFileInfo['video']['dataformat'] = 'xvid';
                         break;
                     case 'mp4v':
                         $ThisFileInfo['video']['dataformat'] = 'mpeg4';
                         break;
                     case 'divx':
                     case 'div1':
                     case 'div2':
                     case 'div3':
                     case 'div4':
                     case 'div5':
                     case 'div6':
                         $TDIVXileInfo['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($ThisFileInfo['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
                 //	$stts_new_framerate = $ThisFileInfo['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
                 //		$ThisFileInfo['video']['frame_rate'] = max($ThisFileInfo['video']['frame_rate'], $stts_new_framerate);
                 //	}
                 //}
                 //
                 //$FrameRateCalculatorArray[($ThisFileInfo['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
             }
             $ThisFileInfo['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) > $ThisFileInfo['video']['frame_rate']) {
             //		$ThisFileInfo['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'] & 0x1);
             }
             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'] & 0x1);
             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') {
                 $ThisFileInfo['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) {
                 $ThisFileInfo['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
                 return false;
             }
             $ThisFileInfo['quicktime']['time_scale'] = isset($ThisFileInfo['quicktime']['time_scale']) ? max($ThisFileInfo['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($ThisFileInfo['comments']['language']) || !in_array($atom_structure['language'], $ThisFileInfo['comments']['language'])) {
                 $ThisFileInfo['comments']['language'][] = $atom_structure['language'];
             }
             break;
         case 'pnot':
             // Preview atom
             $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             // "standard Macintosh format"
             $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
             // hardcoded: 0x00
             $atom_structure['atom_type'] = substr($atom_data, 6, 4);
             // usually: 'PICT'
             $atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
             // usually: 0x01
             $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
             break;
         case 'crgn':
             // Clipping ReGioN atom
             $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
             // The Region size, Region boundary box,
             $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8));
             // and Clipping region data fields
             $atom_structure['clipping_data'] = substr($atom_data, 10);
             // constitute a QuickDraw region.
             break;
         case 'load':
             // track LOAD settings atom
             $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
             $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
             $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x20);
             $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x100);
             break;
         case 'tmcd':
             // TiMe CoDe atom
         // TiMe CoDe atom
         case 'chap':
             // CHAPter list atom
         // CHAPter list atom
         case 'sync':
             // SYNChronization atom
         // SYNChronization atom
         case 'scpt':
             // tranSCriPT atom
         // tranSCriPT atom
         case 'ssrc':
             // non-primary SouRCe atom
             for ($i = 0; $i < strlen($atom_data) % 4; $i++) {
                 $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4));
             }
             break;
         case 'elst':
             // Edit LiST 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));
             for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
                 $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $i * 12 + 0, 4));
                 $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $i * 12 + 4, 4));
                 $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + $i * 12 + 8, 4));
             }
             break;
         case 'kmat':
             // compressed MATte 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['matte_data_raw'] = substr($atom_data, 4);
             break;
         case 'ctab':
             // Color TABle atom
             $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             // hardcoded: 0x00000000
             $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
             // hardcoded: 0x8000
             $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1;
             for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
                 $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 0, 2));
                 $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 2, 2));
                 $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 4, 2));
                 $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + $colortableentry * 8 + 6, 2));
             }
             break;
         case 'mvhd':
             // MoVie 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['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['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
             $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
             $atom_structure['reserved'] = substr($atom_data, 26, 10);
             $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
             $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
             $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
             $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
             $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
             $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
             $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
             $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
             $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
             $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
             $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
             $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
             $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
             $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
             $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
             $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
             if ($atom_structure['time_scale'] == 0) {
                 $ThisFileInfo['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
                 return false;
             }
             $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
             $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
             $ThisFileInfo['quicktime']['time_scale'] = isset($ThisFileInfo['quicktime']['time_scale']) ? max($ThisFileInfo['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale'];
             $ThisFileInfo['quicktime']['display_scale'] = $atom_structure['matrix_a'];
             $ThisFileInfo['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
             break;
         case 'tkhd':
             // TracK 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['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
             $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
             $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
             $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
             $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
             $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
             $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
             $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
             $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
             $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
             $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
             $atom_structure['matrix_u'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
             $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
             $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
             $atom_structure['matrix_v'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
             $atom_structure['matrix_x'] = getid3_lib::FixedPoint2_30(substr($atom_data, 64, 4));
             $atom_structure['matrix_y'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
             $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
             $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
             $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
             $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x1);
             $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x2);
             $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x4);
             $atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x8);
             $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
             $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
             if ($atom_structure['flags']['enabled'] == 1) {
                 if (!isset($ThisFileInfo['video']['resolution_x']) || !isset($ThisFileInfo['video']['resolution_y'])) {
                     $ThisFileInfo['video']['resolution_x'] = $atom_structure['width'];
                     $ThisFileInfo['video']['resolution_y'] = $atom_structure['height'];
                 }
                 $ThisFileInfo['video']['resolution_x'] = max($ThisFileInfo['video']['resolution_x'], $atom_structure['width']);
                 $ThisFileInfo['video']['resolution_y'] = max($ThisFileInfo['video']['resolution_y'], $atom_structure['height']);
                 $ThisFileInfo['quicktime']['video']['resolution_x'] = $ThisFileInfo['video']['resolution_x'];
                 $ThisFileInfo['quicktime']['video']['resolution_y'] = $ThisFileInfo['video']['resolution_y'];
             } else {
                 if (isset($ThisFileInfo['video']['resolution_x'])) {
                     unset($ThisFileInfo['video']['resolution_x']);
                 }
                 if (isset($ThisFileInfo['video']['resolution_y'])) {
                     unset($ThisFileInfo['video']['resolution_y']);
                 }
                 if (isset($ThisFileInfo['quicktime']['video'])) {
                     unset($ThisFileInfo['quicktime']['video']);
                 }
             }
             break;
         case 'iods':
             // Initial Object DeScriptor atom
             // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
             // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
             $offset = 0;
             $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
             $offset += 3;
             $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
             //$offset already adjusted by quicktime_read_mp4_descr_length()
             $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
             $offset += 2;
             $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
             $offset += 1;
             $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6;
             // 6 bytes would only be right if all tracks use 1-byte length fields
             for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
                 $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
                 $offset += 1;
                 $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
                 //$offset already adjusted by quicktime_read_mp4_descr_length()
                 $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
                 $offset += 4;
             }
             $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
             $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
             break;
         case 'meta':
             // METAdata atom
             // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
             /*
             $NextTagPosition = strpos($atom_data, '©');
             while ($NextTagPosition < strlen($atom_data)) {
             	$metaItemSize = getid3_lib::BigEndian2Int(substr($atom_data, $NextTagPosition - 4, 4)) - 4;
             	if ($metaItemSize == -4) {
             		break;
             	}
             	$metaItemRaw  = substr($atom_data, $NextTagPosition, $metaItemSize);
             	$metaItemKey  = substr($metaItemRaw, 0, 4);
             	$metaItemData = substr($metaItemRaw, 20);
             	$NextTagPosition += $metaItemSize + 4;
             
             	$this->CopyToAppropriateCommentsSection($metaItemKey, $metaItemData, $ThisFileInfo);
             }
             */
             $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['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $ThisFileInfo, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
             break;
         case 'ftyp':
             // FileTYPe (?) atom (for MP4 it seems)
             $atom_structure['signature'] = substr($atom_data, 0, 4);
             $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
             $atom_structure['fourcc'] = substr($atom_data, 8, 4);
             break;
         case 'mdat':
             // Media DATa atom
         // Media DATa atom
         case 'free':
             // FREE space atom
         // FREE space atom
         case 'skip':
             // SKIP atom
         // SKIP atom
         case 'wide':
             // 64-bit expansion placeholder atom
             // 'mdat' data is too big to deal with, contains no useful metadata
             // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
             // When writing QuickTime files, it is sometimes necessary to update an atom's size.
             // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
             // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
             // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
             // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
             // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
             // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
             break;
         case 'nsav':
             // NoSAVe atom
             // http://developer.apple.com/technotes/tn/tn2038.html
             $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             break;
         case 'ctyp':
             // Controller TYPe atom (seen on QTVR)
             // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
             // some controller names are:
             //   0x00 + 'std' for linear movie
             //   'none' for no controls
             $atom_structure['ctyp'] = substr($atom_data, 0, 4);
             $ThisFileInfo['quicktime']['controller'] = $atom_structure['ctyp'];
             switch ($atom_structure['ctyp']) {
                 case 'qtvr':
                     $ThisFileInfo['video']['dataformat'] = 'quicktimevr';
                     break;
             }
             break;
         case 'pano':
             // PANOrama track (seen on QTVR)
             $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
             break;
         case 'hint':
             // HINT track
         // HINT track
         case 'hinf':
             //
         //
         case 'hinv':
             //
         //
         case 'hnti':
             //
             $ThisFileInfo['quicktime']['hinting'] = true;
             break;
         case 'imgt':
             // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
             for ($i = 0; $i < $atom_structure['size'] - 8; $i += 4) {
                 $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
             }
             break;
             // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
         // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
         case 'FXTC':
             // Something to do with Adobe After Effects (?)
         // Something to do with Adobe After Effects (?)
         case 'PrmA':
         case 'code':
         case 'FIEL':
             // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
         // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
         case 'tapt':
             // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
             // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
             // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
             // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
         // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
         // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
         // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
         // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
         case 'ctts':
             //  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'cslg':
             //  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'sdtp':
             //  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         //  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
         case 'stps':
             //  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
             //$atom_structure['data'] = $atom_data;
             break;
         default:
             $ThisFileInfo['warning'][] = 'Unknown QuickTime atom type: "' . $atomname . '" at offset ' . $baseoffset;
             $atom_structure['data'] = $atom_data;
             break;
     }
     array_pop($atomHierarchy);
     return $atom_structure;
 }