Mercurial > judyates
diff e2gallerypro/e2upload/Backend/Assets/getid3/module.audio-video.quicktime.php @ 3:3f6b44aa6b35 judyates
[svn r4] added ability to buy stuff, from a Prints page, but it doesn't work well with the css, and it also has not been fitted into the perl make system.
author | rlm |
---|---|
date | Mon, 22 Feb 2010 08:02:39 -0500 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/e2gallerypro/e2upload/Backend/Assets/getid3/module.audio-video.quicktime.php Mon Feb 22 08:02:39 2010 -0500 1.3 @@ -0,0 +1,1529 @@ 1.4 +<?php 1.5 +// +----------------------------------------------------------------------+ 1.6 +// | PHP version 5 | 1.7 +// +----------------------------------------------------------------------+ 1.8 +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | 1.9 +// +----------------------------------------------------------------------+ 1.10 +// | This source file is subject to version 2 of the GPL license, | 1.11 +// | that is bundled with this package in the file license.txt and is | 1.12 +// | available through the world-wide-web at the following url: | 1.13 +// | http://www.gnu.org/copyleft/gpl.html | 1.14 +// +----------------------------------------------------------------------+ 1.15 +// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | 1.16 +// +----------------------------------------------------------------------+ 1.17 +// | Authors: James Heinrich <infoØgetid3*org> | 1.18 +// | Allan Hansen <ahØartemis*dk> | 1.19 +// +----------------------------------------------------------------------+ 1.20 +// | module.audio-video.quicktime.php | 1.21 +// | Module for analyzing Quicktime, MP3-in-MP4 and Apple Lossless files. | 1.22 +// | dependencies: module.audio.mp3.php | 1.23 +// | zlib support in PHP (optional) | 1.24 +// +----------------------------------------------------------------------+ 1.25 +// 1.26 +// $Id: module.audio-video.quicktime.php,v 1.7 2006/11/02 16:03:28 ah Exp $ 1.27 + 1.28 + 1.29 + 1.30 +class getid3_quicktime extends getid3_handler 1.31 +{ 1.32 + 1.33 + public function Analyze() { 1.34 + 1.35 + $getid3 = $this->getid3; 1.36 + 1.37 + $info = &$getid3->info; 1.38 + 1.39 + $getid3->include_module('audio.mp3'); 1.40 + 1.41 + $info['quicktime'] = array (); 1.42 + $info_quicktime = &$info['quicktime']; 1.43 + 1.44 + $info['fileformat'] = 'quicktime'; 1.45 + $info_quicktime['hinting'] = false; 1.46 + 1.47 + fseek($getid3->fp, $info['avdataoffset'], SEEK_SET); 1.48 + 1.49 + $offset = $atom_counter = 0; 1.50 + 1.51 + while ($offset < $info['avdataend']) { 1.52 + 1.53 + fseek($getid3->fp, $offset, SEEK_SET); 1.54 + $atom_header = fread($getid3->fp, 8); 1.55 + 1.56 + $atom_size = getid3_lib::BigEndian2Int(substr($atom_header, 0, 4)); 1.57 + $atom_name = substr($atom_header, 4, 4); 1.58 + 1.59 + $info_quicktime[$atom_name]['name'] = $atom_name; 1.60 + $info_quicktime[$atom_name]['size'] = $atom_size; 1.61 + $info_quicktime[$atom_name]['offset'] = $offset; 1.62 + 1.63 + if (($offset + $atom_size) > $info['avdataend']) { 1.64 + throw new getid3_exception('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atom_size.' bytes)'); 1.65 + } 1.66 + 1.67 + if ($atom_size == 0) { 1.68 + // Furthermore, for historical reasons the list of atoms is optionally 1.69 + // terminated by a 32-bit integer set to 0. If you are writing a program 1.70 + // to read user data atoms, you should allow for the terminating 0. 1.71 + break; 1.72 + } 1.73 + 1.74 + switch ($atom_name) { 1.75 + 1.76 + case 'mdat': // Media DATa atom 1.77 + // 'mdat' contains the actual data for the audio/video 1.78 + if (($atom_size > 8) && (!isset($info['avdataend_tmp']) || ($info_quicktime[$atom_name]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { 1.79 + 1.80 + $info['avdataoffset'] = $info_quicktime[$atom_name]['offset'] + 8; 1.81 + $old_av_data_end = $info['avdataend']; 1.82 + $info['avdataend'] = $info_quicktime[$atom_name]['offset'] + $info_quicktime[$atom_name]['size']; 1.83 + 1.84 + 1.85 + //// MP3 1.86 + 1.87 + if (!$getid3->include_module_optional('audio.mp3')) { 1.88 + $getid3->warning('MP3 skipped because mpeg module is missing.'); 1.89 + } 1.90 + 1.91 + else { 1.92 + 1.93 + // Clone getid3 - messing with offsets - better safe than sorry 1.94 + $clone = clone $getid3; 1.95 + 1.96 + if (getid3_mp3::MPEGaudioHeaderValid(getid3_mp3::MPEGaudioHeaderDecode(fread($clone->fp, 4)))) { 1.97 + 1.98 + $mp3 = new getid3_mp3($clone); 1.99 + $mp3->AnalyzeMPEGaudioInfo(); 1.100 + 1.101 + // Import from clone and destroy 1.102 + if (isset($clone->info['mpeg']['audio'])) { 1.103 + 1.104 + $info['mpeg']['audio'] = $clone->info['mpeg']['audio']; 1.105 + 1.106 + $info['audio']['dataformat'] = 'mp3'; 1.107 + $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'))); 1.108 + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; 1.109 + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; 1.110 + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; 1.111 + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); 1.112 + $info['bitrate'] = $info['audio']['bitrate']; 1.113 + 1.114 + $getid3->warning($clone->warnings()); 1.115 + unset($clone); 1.116 + } 1.117 + } 1.118 + } 1.119 + 1.120 + $info['avdataend'] = $old_av_data_end; 1.121 + unset($old_av_data_end); 1.122 + 1.123 + } 1.124 + break; 1.125 + 1.126 + 1.127 + case 'free': // FREE space atom 1.128 + case 'skip': // SKIP atom 1.129 + case 'wide': // 64-bit expansion placeholder atom 1.130 + // 'free', 'skip' and 'wide' are just padding, contains no useful data at all 1.131 + break; 1.132 + 1.133 + 1.134 + default: 1.135 + $atom_hierarchy = array (); 1.136 + $info_quicktime[$atom_name] = $this->QuicktimeParseAtom($atom_name, $atom_size, fread($getid3->fp, $atom_size), $offset, $atom_hierarchy); 1.137 + break; 1.138 + } 1.139 + 1.140 + $offset += $atom_size; 1.141 + $atom_counter++; 1.142 + } 1.143 + 1.144 + if (!empty($info['avdataend_tmp'])) { 1.145 + // this value is assigned to a temp value and then erased because 1.146 + // otherwise any atoms beyond the 'mdat' atom would not get parsed 1.147 + $info['avdataend'] = $info['avdataend_tmp']; 1.148 + unset($info['avdataend_tmp']); 1.149 + } 1.150 + 1.151 + if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { 1.152 + $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 1.153 + } 1.154 + 1.155 + if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info_quicktime['video'])) { 1.156 + $info['audio']['bitrate'] = $info['bitrate']; 1.157 + } 1.158 + 1.159 + if ((@$info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) { 1.160 + $info['fileformat'] = 'mp4'; 1.161 + $info['mime_type'] = 'audio/mp4'; 1.162 + unset($info['video']['dataformat']); 1.163 + } 1.164 + 1.165 + if (!$getid3->option_extra_info) { 1.166 + unset($info_quicktime['moov']); 1.167 + } 1.168 + 1.169 + if (empty($info['audio']['dataformat']) && !empty($info_quicktime['audio'])) { 1.170 + $info['audio']['dataformat'] = 'quicktime'; 1.171 + } 1.172 + 1.173 + if (empty($info['video']['dataformat']) && !empty($info_quicktime['video'])) { 1.174 + $info['video']['dataformat'] = 'quicktime'; 1.175 + } 1.176 + 1.177 + return true; 1.178 + } 1.179 + 1.180 + 1.181 + 1.182 + private function QuicktimeParseAtom($atom_name, $atom_size, $atom_data, $base_offset, &$atom_hierarchy) { 1.183 + 1.184 + // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm 1.185 + 1.186 + $getid3 = $this->getid3; 1.187 + 1.188 + $info = &$getid3->info; 1.189 + $info_quicktime = &$info['quicktime']; 1.190 + 1.191 + array_push($atom_hierarchy, $atom_name); 1.192 + $atom_structure['hierarchy'] = implode(' ', $atom_hierarchy); 1.193 + $atom_structure['name'] = $atom_name; 1.194 + $atom_structure['size'] = $atom_size; 1.195 + $atom_structure['offset'] = $base_offset; 1.196 + 1.197 + switch ($atom_name) { 1.198 + case 'moov': // MOVie container atom 1.199 + case 'trak': // TRAcK container atom 1.200 + case 'clip': // CLIPping container atom 1.201 + case 'matt': // track MATTe container atom 1.202 + case 'edts': // EDiTS container atom 1.203 + case 'tref': // Track REFerence container atom 1.204 + case 'mdia': // MeDIA container atom 1.205 + case 'minf': // Media INFormation container atom 1.206 + case 'dinf': // Data INFormation container atom 1.207 + case 'udta': // User DaTA container atom 1.208 + case 'stbl': // Sample TaBLe container atom 1.209 + case 'cmov': // Compressed MOVie container atom 1.210 + case 'rmra': // Reference Movie Record Atom 1.211 + case 'rmda': // Reference Movie Descriptor Atom 1.212 + case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) 1.213 + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $base_offset + 8, $atom_hierarchy); 1.214 + break; 1.215 + 1.216 + 1.217 + case '©cpy': 1.218 + case '©day': 1.219 + case '©dir': 1.220 + case '©ed1': 1.221 + case '©ed2': 1.222 + case '©ed3': 1.223 + case '©ed4': 1.224 + case '©ed5': 1.225 + case '©ed6': 1.226 + case '©ed7': 1.227 + case '©ed8': 1.228 + case '©ed9': 1.229 + case '©fmt': 1.230 + case '©inf': 1.231 + case '©prd': 1.232 + case '©prf': 1.233 + case '©req': 1.234 + case '©src': 1.235 + case '©wrt': 1.236 + case '©nam': 1.237 + case '©cmt': 1.238 + case '©wrn': 1.239 + case '©hst': 1.240 + case '©mak': 1.241 + case '©mod': 1.242 + case '©PRD': 1.243 + case '©swr': 1.244 + case '©aut': 1.245 + case '©ART': 1.246 + case '©trk': 1.247 + case '©alb': 1.248 + case '©com': 1.249 + case '©gen': 1.250 + case '©ope': 1.251 + case '©url': 1.252 + case '©enc': 1.253 + $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 1.254 + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 1.255 + $atom_structure['data'] = substr($atom_data, 4); 1.256 + 1.257 + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 1.258 + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 1.259 + $info['comments']['language'][] = $atom_structure['language']; 1.260 + } 1.261 + $this->CopyToAppropriateCommentsSection($atom_name, $atom_structure['data']); 1.262 + break; 1.263 + 1.264 + 1.265 + case 'play': // auto-PLAY atom 1.266 + $atom_structure['autoplay'] = (bool)getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.267 + 1.268 + $info_quicktime['autoplay'] = $atom_structure['autoplay']; 1.269 + break; 1.270 + 1.271 + 1.272 + case 'WLOC': // Window LOCation atom 1.273 + $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 1.274 + $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 1.275 + break; 1.276 + 1.277 + 1.278 + case 'LOOP': // LOOPing atom 1.279 + case 'SelO': // play SELection Only atom 1.280 + case 'AllF': // play ALL Frames atom 1.281 + $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); 1.282 + break; 1.283 + 1.284 + 1.285 + case 'name': // 1.286 + case 'MCPS': // Media Cleaner PRo 1.287 + case '@PRM': // adobe PReMiere version 1.288 + case '@PRQ': // adobe PRemiere Quicktime version 1.289 + $atom_structure['data'] = $atom_data; 1.290 + break; 1.291 + 1.292 + 1.293 + case 'cmvd': // Compressed MooV Data atom 1.294 + // Code by ubergeekØubergeek*tv based on information from 1.295 + // http://developer.apple.com/quicktime/icefloe/dispatch012.html 1.296 + $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 1.297 + 1.298 + $compressed_file_data = substr($atom_data, 4); 1.299 + if (!function_exists('gzuncompress')) { 1.300 + $getid3->warning('PHP does not have zlib support - cannot decompress MOV atom at offset '.$atom_structure['offset']); 1.301 + } 1.302 + elseif ($uncompressed_header = @gzuncompress($compressed_file_data)) { 1.303 + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($uncompressed_header, 0, $atom_hierarchy); 1.304 + } else { 1.305 + $getid3->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); 1.306 + } 1.307 + break; 1.308 + 1.309 + 1.310 + case 'dcom': // Data COMpression atom 1.311 + $atom_structure['compression_id'] = $atom_data; 1.312 + $atom_structure['compression_text'] = getid3_quicktime::QuicktimeDCOMLookup($atom_data); 1.313 + break; 1.314 + 1.315 + 1.316 + case 'rdrf': // Reference movie Data ReFerence atom 1.317 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.318 + array ( 1.319 + 'version' => 1, 1.320 + 'flags_raw' => 3, 1.321 + 'reference_type_name' => -4, 1.322 + 'reference_length' => 4, 1.323 + ) 1.324 + ); 1.325 + 1.326 + $atom_structure['flags']['internal_data'] = (bool)($atom_structure['flags_raw'] & 0x000001); 1.327 + 1.328 + switch ($atom_structure['reference_type_name']) { 1.329 + case 'url ': 1.330 + $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); 1.331 + break; 1.332 + 1.333 + case 'alis': 1.334 + $atom_structure['file_alias'] = substr($atom_data, 12); 1.335 + break; 1.336 + 1.337 + case 'rsrc': 1.338 + $atom_structure['resource_alias'] = substr($atom_data, 12); 1.339 + break; 1.340 + 1.341 + default: 1.342 + $atom_structure['data'] = substr($atom_data, 12); 1.343 + break; 1.344 + } 1.345 + break; 1.346 + 1.347 + 1.348 + case 'rmqu': // Reference Movie QUality atom 1.349 + $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); 1.350 + break; 1.351 + 1.352 + 1.353 + case 'rmcs': // Reference Movie Cpu Speed atom 1.354 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.355 + array ( 1.356 + 'version' => 1, 1.357 + 'flags_raw' => 3, // hardcoded: 0x0000 1.358 + 'cpu_speed_rating' => 2 1.359 + ) 1.360 + ); 1.361 + break; 1.362 + 1.363 + 1.364 + case 'rmvc': // Reference Movie Version Check atom 1.365 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.366 + array ( 1.367 + 'version' => 1, 1.368 + 'flags_raw' => 3, // hardcoded: 0x0000 1.369 + 'gestalt_selector' => -4, 1.370 + 'gestalt_value_mask' => 4, 1.371 + 'gestalt_value' => 4, 1.372 + 'gestalt_check_type' => 2 1.373 + ) 1.374 + ); 1.375 + break; 1.376 + 1.377 + 1.378 + case 'rmcd': // Reference Movie Component check atom 1.379 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.380 + array ( 1.381 + 'version' => 1, 1.382 + 'flags_raw' => 3, // hardcoded: 0x0000 1.383 + 'component_type' => -4, 1.384 + 'component_subtype' => -4, 1.385 + 'component_manufacturer' => -4, 1.386 + 'component_flags_raw' => 4, 1.387 + 'component_flags_mask' => 4, 1.388 + 'component_min_version' => 4 1.389 + ) 1.390 + ); 1.391 + break; 1.392 + 1.393 + 1.394 + case 'rmdr': // Reference Movie Data Rate atom 1.395 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.396 + array ( 1.397 + 'version' => 1, 1.398 + 'flags_raw' => 3, // hardcoded: 0x0000 1.399 + 'data_rate' => 4 1.400 + ) 1.401 + ); 1.402 + 1.403 + $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; 1.404 + break; 1.405 + 1.406 + 1.407 + case 'rmla': // Reference Movie Language Atom 1.408 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.409 + array ( 1.410 + 'version' => 1, 1.411 + 'flags_raw' => 3, // hardcoded: 0x0000 1.412 + 'language_id' => 2 1.413 + ) 1.414 + ); 1.415 + 1.416 + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 1.417 + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 1.418 + $info['comments']['language'][] = $atom_structure['language']; 1.419 + } 1.420 + break; 1.421 + 1.422 + 1.423 + case 'rmla': // Reference Movie Language Atom 1.424 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.425 + array ( 1.426 + 'version' => 1, 1.427 + 'flags_raw' => 3, // hardcoded: 0x0000 1.428 + 'track_id' => 2 1.429 + ) 1.430 + ); 1.431 + break; 1.432 + 1.433 + 1.434 + case 'ptv ': // Print To Video - defines a movie's full screen mode 1.435 + // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm 1.436 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.437 + array ( 1.438 + 'display_size_raw' => 2, 1.439 + 'reserved_1' => 2, // hardcoded: 0x0000 1.440 + 'reserved_2' => 2, // hardcoded: 0x0000 1.441 + 'slide_show_flag' => 1, 1.442 + 'play_on_open_flag' => 1 1.443 + ) 1.444 + ); 1.445 + 1.446 + $atom_structure['flags']['play_on_open'] = (bool)$atom_structure['play_on_open_flag']; 1.447 + $atom_structure['flags']['slide_show'] = (bool)$atom_structure['slide_show_flag']; 1.448 + 1.449 + $ptv_lookup[0] = 'normal'; 1.450 + $ptv_lookup[1] = 'double'; 1.451 + $ptv_lookup[2] = 'half'; 1.452 + $ptv_lookup[3] = 'full'; 1.453 + $ptv_lookup[4] = 'current'; 1.454 + if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { 1.455 + $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; 1.456 + } else { 1.457 + $getid3->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); 1.458 + } 1.459 + break; 1.460 + 1.461 + 1.462 + case 'stsd': // Sample Table Sample Description atom 1.463 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.464 + array ( 1.465 + 'version' => 1, 1.466 + 'flags_raw' => 3, // hardcoded: 0x0000 1.467 + 'number_entries' => 4 1.468 + ) 1.469 + ); 1.470 + $stsd_entries_data_offset = 8; 1.471 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.472 + 1.473 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_data, $stsd_entries_data_offset, 1.474 + array ( 1.475 + 'size' => 4, 1.476 + 'data_format' => -4, 1.477 + 'reserved' => 6, 1.478 + 'reference_index' => 2 1.479 + ) 1.480 + ); 1.481 + 1.482 + $atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, 16+$stsd_entries_data_offset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2)); 1.483 + $stsd_entries_data_offset += 16 + ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2); 1.484 + 1.485 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_structure['sample_description_table'][$i]['data'], 0, 1.486 + array ( 1.487 + 'encoder_version' => 2, 1.488 + 'encoder_revision' => 2, 1.489 + 'encoder_vendor' => -4 1.490 + ) 1.491 + ); 1.492 + 1.493 + switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) { 1.494 + 1.495 + case "\x00\x00\x00\x00": 1.496 + // audio atom 1.497 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_structure['sample_description_table'][$i]['data'], 8, 1.498 + array ( 1.499 + 'audio_channels' => 2, 1.500 + 'audio_bit_depth' => 2, 1.501 + 'audio_compression_id' => 2, 1.502 + 'audio_packet_size' => 2 1.503 + ) 1.504 + ); 1.505 + 1.506 + $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); 1.507 + 1.508 + switch ($atom_structure['sample_description_table'][$i]['data_format']) { 1.509 + 1.510 + case 'mp4v': 1.511 + $info['fileformat'] = 'mp4'; 1.512 + throw new getid3_exception('This version of getID3() does not fully support MPEG-4 audio/video streams'); 1.513 + 1.514 + case 'qtvr': 1.515 + $info['video']['dataformat'] = 'quicktimevr'; 1.516 + break; 1.517 + 1.518 + case 'mp4a': 1.519 + default: 1.520 + $info_quicktime['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); 1.521 + $info_quicktime['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; 1.522 + $info_quicktime['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; 1.523 + $info_quicktime['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth']; 1.524 + $info['audio']['codec'] = $info_quicktime['audio']['codec']; 1.525 + $info['audio']['sample_rate'] = $info_quicktime['audio']['sample_rate']; 1.526 + $info['audio']['channels'] = $info_quicktime['audio']['channels']; 1.527 + $info['audio']['bits_per_sample'] = $info_quicktime['audio']['bit_depth']; 1.528 + switch ($atom_structure['sample_description_table'][$i]['data_format']) { 1.529 + case 'raw ': // PCM 1.530 + case 'alac': // Apple Lossless Audio Codec 1.531 + $info['audio']['lossless'] = true; 1.532 + break; 1.533 + default: 1.534 + $info['audio']['lossless'] = false; 1.535 + break; 1.536 + } 1.537 + break; 1.538 + } 1.539 + break; 1.540 + 1.541 + default: 1.542 + switch ($atom_structure['sample_description_table'][$i]['data_format']) { 1.543 + case 'mp4s': 1.544 + $info['fileformat'] = 'mp4'; 1.545 + break; 1.546 + 1.547 + default: 1.548 + // video atom 1.549 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_structure['sample_description_table'][$i]['data'], 8, 1.550 + array ( 1.551 + 'video_temporal_quality' => 4, 1.552 + 'video_spatial_quality' => 4, 1.553 + 'video_frame_width' => 2, 1.554 + 'video_frame_height' => 2 1.555 + ) 1.556 + ); 1.557 + $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); 1.558 + $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_quicktime::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); 1.559 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['sample_description_table'][$i], $atom_structure['sample_description_table'][$i]['data'], 28, 1.560 + array ( 1.561 + 'video_data_size' => 4, 1.562 + 'video_frame_count' => 2, 1.563 + 'video_encoder_name_len' => 1 1.564 + ) 1.565 + ); 1.566 + $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']); 1.567 + $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); 1.568 + $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); 1.569 + 1.570 + $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); 1.571 + $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); 1.572 + 1.573 + if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { 1.574 + $info_quicktime['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; 1.575 + $info_quicktime['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); 1.576 + $info_quicktime['video']['codec'] = $atom_structure['sample_description_table'][$i]['video_encoder_name']; 1.577 + $info_quicktime['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; 1.578 + $info_quicktime['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; 1.579 + 1.580 + $info['video']['codec'] = $info_quicktime['video']['codec']; 1.581 + $info['video']['bits_per_sample'] = $info_quicktime['video']['color_depth']; 1.582 + } 1.583 + $info['video']['lossless'] = false; 1.584 + $info['video']['pixel_aspect_ratio'] = (float)1; 1.585 + break; 1.586 + } 1.587 + break; 1.588 + } 1.589 + switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) { 1.590 + case 'mp4a': 1.591 + $info['audio']['dataformat'] = $info_quicktime['audio']['codec'] = 'mp4'; 1.592 + break; 1.593 + 1.594 + case '3ivx': 1.595 + case '3iv1': 1.596 + case '3iv2': 1.597 + $info['video']['dataformat'] = '3ivx'; 1.598 + break; 1.599 + 1.600 + case 'xvid': 1.601 + $info['video']['dataformat'] = 'xvid'; 1.602 + break; 1.603 + 1.604 + case 'mp4v': 1.605 + $info['video']['dataformat'] = 'mpeg4'; 1.606 + break; 1.607 + 1.608 + case 'divx': 1.609 + case 'div1': 1.610 + case 'div2': 1.611 + case 'div3': 1.612 + case 'div4': 1.613 + case 'div5': 1.614 + case 'div6': 1.615 + //$TDIVXileInfo['video']['dataformat'] = 'divx'; 1.616 + break; 1.617 + 1.618 + default: 1.619 + // do nothing 1.620 + break; 1.621 + } 1.622 + unset($atom_structure['sample_description_table'][$i]['data']); 1.623 + } 1.624 + break; 1.625 + 1.626 + 1.627 + case 'stts': // Sample Table Time-to-Sample atom 1.628 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.629 + array ( 1.630 + 'version' => 1, 1.631 + 'flags_raw' => 3, // hardcoded: 0x0000 1.632 + 'number_entries' => 4 1.633 + ) 1.634 + ); 1.635 + 1.636 + $stts_entries_data_offset = 8; 1.637 + $frame_rate_calculator_array = array (); 1.638 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.639 + 1.640 + $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $stts_entries_data_offset, 4)); 1.641 + $stts_entries_data_offset += 4; 1.642 + 1.643 + $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $stts_entries_data_offset, 4)); 1.644 + $stts_entries_data_offset += 4; 1.645 + 1.646 + if (!empty($info_quicktime['time_scale']) && (@$atoms_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { 1.647 + 1.648 + $stts_new_framerate = $info_quicktime['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; 1.649 + if ($stts_new_framerate <= 60) { 1.650 + // some atoms have durations of "1" giving a very large framerate, which probably is not right 1.651 + $info['video']['frame_rate'] = max(@$info['video']['frame_rate'], $stts_new_framerate); 1.652 + } 1.653 + } 1.654 + //@$frame_rate_calculator_array[($info_quicktime['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; 1.655 + } 1.656 + /* 1.657 + $stts_frames_total = 0; 1.658 + $stts_seconds_total = 0; 1.659 + foreach ($frame_rate_calculator_array as $frames_per_second => $frame_count) { 1.660 + if (($frames_per_second > 60) || ($frames_per_second < 1)) { 1.661 + // not video FPS information, probably audio information 1.662 + $stts_frames_total = 0; 1.663 + $stts_seconds_total = 0; 1.664 + break; 1.665 + } 1.666 + $stts_frames_total += $frame_count; 1.667 + $stts_seconds_total += $frame_count / $frames_per_second; 1.668 + } 1.669 + if (($stts_frames_total > 0) && ($stts_seconds_total > 0)) { 1.670 + if (($stts_frames_total / $stts_seconds_total) > @$info['video']['frame_rate']) { 1.671 + $info['video']['frame_rate'] = $stts_frames_total / $stts_seconds_total; 1.672 + } 1.673 + } 1.674 + */ 1.675 + break; 1.676 + 1.677 + 1.678 + case 'stss': // Sample Table Sync Sample (key frames) atom 1.679 + /* 1.680 + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.681 + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 1.682 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 1.683 + $stss_entries_data_offset = 8; 1.684 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.685 + $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stss_entries_data_offset, 4)); 1.686 + $stss_entries_data_offset += 4; 1.687 + } 1.688 + */ 1.689 + break; 1.690 + 1.691 + 1.692 + case 'stsc': // Sample Table Sample-to-Chunk atom 1.693 + /* 1.694 + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.695 + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 1.696 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 1.697 + $stsc_entries_data_offset = 8; 1.698 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.699 + $atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsc_entries_data_offset, 4)); 1.700 + $stsc_entries_data_offset += 4; 1.701 + $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsc_entries_data_offset, 4)); 1.702 + $stsc_entries_data_offset += 4; 1.703 + $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsc_entries_data_offset, 4)); 1.704 + $stsc_entries_data_offset += 4; 1.705 + } 1.706 + */ 1.707 + break; 1.708 + 1.709 + 1.710 + case 'stsz': // Sample Table SiZe atom 1.711 + /* 1.712 + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.713 + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 1.714 + $atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 1.715 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); 1.716 + $stsz_entries_data_offset = 12; 1.717 + if ($atom_structure['sample_size'] == 0) { 1.718 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.719 + $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stsz_entries_data_offset, 4)); 1.720 + $stsz_entries_data_offset += 4; 1.721 + } 1.722 + } 1.723 + */ 1.724 + break; 1.725 + 1.726 + 1.727 + case 'stco': // Sample Table Chunk Offset atom 1.728 + /* 1.729 + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.730 + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 1.731 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 1.732 + $stco_entries_data_offset = 8; 1.733 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.734 + $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stco_entries_data_offset, 4)); 1.735 + $stco_entries_data_offset += 4; 1.736 + } 1.737 + */ 1.738 + break; 1.739 + 1.740 + 1.741 + case 'dref': // Data REFerence atom 1.742 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.743 + array ( 1.744 + 'version' => 1, 1.745 + 'flags_raw' => 3, // hardcoded: 0x0000 1.746 + 'number_entries' => 4 1.747 + ) 1.748 + ); 1.749 + 1.750 + $dref_data_offset = 8; 1.751 + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 1.752 + 1.753 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure['data_references'][$i], $atom_data, $dref_data_offset, 1.754 + array ( 1.755 + 'size' => 4, 1.756 + 'type' => -4, 1.757 + 'version' => 1, 1.758 + 'flags_raw' => 3 // hardcoded: 0x0000 1.759 + ) 1.760 + ); 1.761 + $dref_data_offset += 12; 1.762 + 1.763 + $atom_structure['data_references'][$i]['data'] = substr($atom_data, $dref_data_offset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); 1.764 + $dref_data_offset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); 1.765 + 1.766 + $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool)($atom_structure['data_references'][$i]['flags_raw'] & 0x001); 1.767 + } 1.768 + break; 1.769 + 1.770 + 1.771 + case 'gmin': // base Media INformation atom 1.772 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.773 + array ( 1.774 + 'version' => 1, 1.775 + 'flags_raw' => 3, // hardcoded: 0x0000 1.776 + 'graphics_mode' => 2, 1.777 + 'opcolor_red' => 2, 1.778 + 'opcolor_green' => 2, 1.779 + 'opcolor_blue' => 2, 1.780 + 'balance' => 2, 1.781 + 'reserved' => 2 1.782 + ) 1.783 + ); 1.784 + break; 1.785 + 1.786 + 1.787 + case 'smhd': // Sound Media information HeaDer atom 1.788 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.789 + array ( 1.790 + 'version' => 1, 1.791 + 'flags_raw' => 3, // hardcoded: 0x0000 1.792 + 'balance' => 2, 1.793 + 'reserved' => 2 1.794 + ) 1.795 + ); 1.796 + break; 1.797 + 1.798 + 1.799 + case 'vmhd': // Video Media information HeaDer atom 1.800 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.801 + array ( 1.802 + 'version' => 1, 1.803 + 'flags_raw' => 3, 1.804 + 'graphics_mode' => 2, 1.805 + 'opcolor_red' => 2, 1.806 + 'opcolor_green' => 2, 1.807 + 'opcolor_blue' => 2 1.808 + ) 1.809 + ); 1.810 + $atom_structure['flags']['no_lean_ahead'] = (bool)($atom_structure['flags_raw'] & 0x001); 1.811 + break; 1.812 + 1.813 + 1.814 + case 'hdlr': // HanDLeR reference atom 1.815 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.816 + array ( 1.817 + 'version' => 1, 1.818 + 'flags_raw' => 3, // hardcoded: 0x0000 1.819 + 'component_type' => -4, 1.820 + 'component_subtype' => -4, 1.821 + 'component_manufacturer' => -4, 1.822 + 'component_flags_raw' => 4, 1.823 + 'component_flags_mask' => 4 1.824 + ) 1.825 + ); 1.826 + 1.827 + $atom_structure['component_name'] = substr(substr($atom_data, 24), 1); /// Pascal2String 1.828 + 1.829 + if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) { 1.830 + $info['video']['dataformat'] = 'quicktimevr'; 1.831 + } 1.832 + break; 1.833 + 1.834 + 1.835 + case 'mdhd': // MeDia HeaDer atom 1.836 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.837 + array ( 1.838 + 'version' => 1, 1.839 + 'flags_raw' => 3, // hardcoded: 0x0000 1.840 + 'creation_time' => 4, 1.841 + 'modify_time' => 4, 1.842 + 'time_scale' => 4, 1.843 + 'duration' => 4, 1.844 + 'language_id' => 2, 1.845 + 'quality' => 2 1.846 + ) 1.847 + ); 1.848 + 1.849 + if ($atom_structure['time_scale'] == 0) { 1.850 + throw new getid3_exception('Corrupt Quicktime file: mdhd.time_scale == zero'); 1.851 + } 1.852 + $info_quicktime['time_scale'] = max(@$info['quicktime']['time_scale'], $atom_structure['time_scale']); 1.853 + 1.854 + $atom_structure['creation_time_unix'] = (int)($atom_structure['creation_time'] - 2082844800); // DateMac2Unix() 1.855 + $atom_structure['modify_time_unix'] = (int)($atom_structure['modify_time'] - 2082844800); // DateMac2Unix() 1.856 + $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; 1.857 + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 1.858 + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 1.859 + $info['comments']['language'][] = $atom_structure['language']; 1.860 + } 1.861 + break; 1.862 + 1.863 + 1.864 + case 'pnot': // Preview atom 1.865 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.866 + array ( 1.867 + 'modification_date' => 4, // "standard Macintosh format" 1.868 + 'version_number' => 2, // hardcoded: 0x00 1.869 + 'atom_type' => -4, // usually: 'PICT' 1.870 + 'atom_index' => 2 // usually: 0x01 1.871 + ) 1.872 + ); 1.873 + $atom_structure['modification_date_unix'] = (int)($atom_structure['modification_date'] - 2082844800); // DateMac2Unix() 1.874 + break; 1.875 + 1.876 + 1.877 + case 'crgn': // Clipping ReGioN atom 1.878 + $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box, 1.879 + $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields 1.880 + $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region. 1.881 + break; 1.882 + 1.883 + 1.884 + case 'load': // track LOAD settings atom 1.885 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.886 + array ( 1.887 + 'preload_start_time' => 4, 1.888 + 'preload_duration' => 4, 1.889 + 'preload_flags_raw' => 4, 1.890 + 'default_hints_raw' => 4 1.891 + ) 1.892 + ); 1.893 + 1.894 + $atom_structure['default_hints']['double_buffer'] = (bool)($atom_structure['default_hints_raw'] & 0x0020); 1.895 + $atom_structure['default_hints']['high_quality'] = (bool)($atom_structure['default_hints_raw'] & 0x0100); 1.896 + break; 1.897 + 1.898 + 1.899 + case 'tmcd': // TiMe CoDe atom 1.900 + case 'chap': // CHAPter list atom 1.901 + case 'sync': // SYNChronization atom 1.902 + case 'scpt': // tranSCriPT atom 1.903 + case 'ssrc': // non-primary SouRCe atom 1.904 + for ($i = 0; $i < (strlen($atom_data) % 4); $i++) { 1.905 + $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4)); 1.906 + } 1.907 + break; 1.908 + 1.909 + 1.910 + case 'elst': // Edit LiST atom 1.911 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.912 + array ( 1.913 + 'version' => 1, 1.914 + 'flags_raw' => 3, // hardcoded: 0x0000 1.915 + 'number_entries' => 4 1.916 + ) 1.917 + ); 1.918 + 1.919 + for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) { 1.920 + $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4)); 1.921 + $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4)); 1.922 + $atom_structure['edit_list'][$i]['media_rate'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4)); 1.923 + } 1.924 + break; 1.925 + 1.926 + 1.927 + case 'kmat': // compressed MATte atom 1.928 + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1.929 + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 1.930 + $atom_structure['matte_data_raw'] = substr($atom_data, 4); 1.931 + break; 1.932 + 1.933 + 1.934 + case 'ctab': // Color TABle atom 1.935 + $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000 1.936 + $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000 1.937 + $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1; 1.938 + for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) { 1.939 + $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2)); 1.940 + $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2)); 1.941 + $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2)); 1.942 + $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2)); 1.943 + } 1.944 + break; 1.945 + 1.946 + 1.947 + case 'mvhd': // MoVie HeaDer atom 1.948 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.949 + array ( 1.950 + 'version' => 1, 1.951 + 'flags_raw' => 3, 1.952 + 'creation_time' => 4, 1.953 + 'modify_time' => 4, 1.954 + 'time_scale' => 4, 1.955 + 'duration' => 4 1.956 + ) 1.957 + ); 1.958 + 1.959 + $atom_structure['preferred_rate'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 20, 4)); 1.960 + $atom_structure['preferred_volume'] = getid3_quicktime::FixedPoint8_8(substr($atom_data, 24, 2)); 1.961 + $atom_structure['reserved'] = substr($atom_data, 26, 10); 1.962 + $atom_structure['matrix_a'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 36, 4)); 1.963 + $atom_structure['matrix_b'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 40, 4)); 1.964 + $atom_structure['matrix_u'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 44, 4)); 1.965 + $atom_structure['matrix_c'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 48, 4)); 1.966 + $atom_structure['matrix_d'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 52, 4)); 1.967 + $atom_structure['matrix_v'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 56, 4)); 1.968 + $atom_structure['matrix_x'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 60, 4)); 1.969 + $atom_structure['matrix_y'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 64, 4)); 1.970 + $atom_structure['matrix_w'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 68, 4)); 1.971 + 1.972 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 72, 1.973 + array ( 1.974 + 'preview_time' => 4, 1.975 + 'preview_duration' => 4, 1.976 + 'poster_time' => 4, 1.977 + 'selection_time' => 4, 1.978 + 'selection_duration' => 4, 1.979 + 'current_time' => 4, 1.980 + 'next_track_id' => 4 1.981 + ) 1.982 + ); 1.983 + 1.984 + if ($atom_structure['time_scale'] == 0) { 1.985 + throw new getid3_exception('Corrupt Quicktime file: mvhd.time_scale == zero'); 1.986 + } 1.987 + 1.988 + $atom_structure['creation_time_unix'] = (int)($atom_structure['creation_time'] - 2082844800); // DateMac2Unix() 1.989 + $atom_structure['modify_time_unix'] = (int)($atom_structure['modify_time'] - 2082844800); // DateMac2Unix() 1.990 + $info_quicktime['time_scale'] = max(@$info['quicktime']['time_scale'], $atom_structure['time_scale']); 1.991 + $info_quicktime['display_scale'] = $atom_structure['matrix_a']; 1.992 + $info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; 1.993 + break; 1.994 + 1.995 + 1.996 + case 'tkhd': // TracK HeaDer atom 1.997 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.998 + array ( 1.999 + 'version' => 1, 1.1000 + 'flags_raw' => 3, 1.1001 + 'creation_time' => 4, 1.1002 + 'modify_time' => 4, 1.1003 + 'trackid' => 4, 1.1004 + 'reserved1' => 4, 1.1005 + 'duration' => 4, 1.1006 + 'reserved2' => 8, 1.1007 + 'layer' => 2, 1.1008 + 'alternate_group' => 2 1.1009 + ) 1.1010 + ); 1.1011 + 1.1012 + $atom_structure['volume'] = getid3_quicktime::FixedPoint8_8(substr($atom_data, 36, 2)); 1.1013 + $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2)); 1.1014 + $atom_structure['matrix_a'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 40, 4)); 1.1015 + $atom_structure['matrix_b'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 44, 4)); 1.1016 + $atom_structure['matrix_u'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 48, 4)); 1.1017 + $atom_structure['matrix_c'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 52, 4)); 1.1018 + $atom_structure['matrix_v'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 56, 4)); 1.1019 + $atom_structure['matrix_d'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 60, 4)); 1.1020 + $atom_structure['matrix_x'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 64, 4)); 1.1021 + $atom_structure['matrix_y'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 68, 4)); 1.1022 + $atom_structure['matrix_w'] = getid3_quicktime::FixedPoint2_30(substr($atom_data, 72, 4)); 1.1023 + $atom_structure['width'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 76, 4)); 1.1024 + $atom_structure['height'] = getid3_quicktime::FixedPoint16_16(substr($atom_data, 80, 4)); 1.1025 + 1.1026 + $atom_structure['flags']['enabled'] = (bool)($atom_structure['flags_raw'] & 0x0001); 1.1027 + $atom_structure['flags']['in_movie'] = (bool)($atom_structure['flags_raw'] & 0x0002); 1.1028 + $atom_structure['flags']['in_preview'] = (bool)($atom_structure['flags_raw'] & 0x0004); 1.1029 + $atom_structure['flags']['in_poster'] = (bool)($atom_structure['flags_raw'] & 0x0008); 1.1030 + $atom_structure['creation_time_unix'] = (int)($atom_structure['creation_time'] - 2082844800); // DateMac2Unix() 1.1031 + $atom_structure['modify_time_unix'] = (int)($atom_structure['modify_time'] - 2082844800); // DateMac2Unix() 1.1032 + 1.1033 + if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) { 1.1034 + $info['video']['resolution_x'] = $atom_structure['width']; 1.1035 + $info['video']['resolution_y'] = $atom_structure['height']; 1.1036 + } 1.1037 + 1.1038 + if ($atom_structure['flags']['enabled'] == 1) { 1.1039 + $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']); 1.1040 + $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']); 1.1041 + } 1.1042 + 1.1043 + if (!empty($info['video']['resolution_x']) && !empty($info['video']['resolution_y'])) { 1.1044 + $info_quicktime['video']['resolution_x'] = $info['video']['resolution_x']; 1.1045 + $info_quicktime['video']['resolution_y'] = $info['video']['resolution_y']; 1.1046 + } else { 1.1047 + unset($info['video']['resolution_x']); 1.1048 + unset($info['video']['resolution_y']); 1.1049 + unset($info_quicktime['video']); 1.1050 + } 1.1051 + break; 1.1052 + 1.1053 + 1.1054 + case 'meta': // METAdata atom 1.1055 + // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt 1.1056 + $next_tag_position = strpos($atom_data, '©'); 1.1057 + while ($next_tag_position < strlen($atom_data)) { 1.1058 + $meta_item_size = getid3_lib::BigEndian2Int(substr($atom_data, $next_tag_position - 4, 4)) - 4; 1.1059 + if ($meta_item_size == -4) { 1.1060 + break; 1.1061 + } 1.1062 + $meta_item_raw = substr($atom_data, $next_tag_position, $meta_item_size); 1.1063 + $meta_item_key = substr($meta_item_raw, 0, 4); 1.1064 + $meta_item_data = substr($meta_item_raw, 20); 1.1065 + $next_tag_position += $meta_item_size + 4; 1.1066 + 1.1067 + $this->CopyToAppropriateCommentsSection($meta_item_key, $meta_item_data); 1.1068 + } 1.1069 + break; 1.1070 + 1.1071 + case 'ftyp': // FileTYPe (?) atom (for MP4 it seems) 1.1072 + getid3_lib::ReadSequence('BigEndian2Int', $atom_structure, $atom_data, 0, 1.1073 + array ( 1.1074 + 'signature' => -4, 1.1075 + 'unknown_1' => 4, 1.1076 + 'fourcc' => -4, 1.1077 + ) 1.1078 + ); 1.1079 + break; 1.1080 + 1.1081 + case 'mdat': // Media DATa atom 1.1082 + case 'free': // FREE space atom 1.1083 + case 'skip': // SKIP atom 1.1084 + case 'wide': // 64-bit expansion placeholder atom 1.1085 + // 'mdat' data is too big to deal with, contains no useful metadata 1.1086 + // 'free', 'skip' and 'wide' are just padding, contains no useful data at all 1.1087 + 1.1088 + // When writing QuickTime files, it is sometimes necessary to update an atom's size. 1.1089 + // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom 1.1090 + // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime 1.1091 + // puts an 8-byte placeholder atom before any atoms it may have to update the size of. 1.1092 + // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the 1.1093 + // placeholder atom can be overwritten to obtain the necessary 8 extra bytes. 1.1094 + // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ). 1.1095 + break; 1.1096 + 1.1097 + 1.1098 + case 'nsav': // NoSAVe atom 1.1099 + // http://developer.apple.com/technotes/tn/tn2038.html 1.1100 + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 1.1101 + break; 1.1102 + 1.1103 + case 'ctyp': // Controller TYPe atom (seen on QTVR) 1.1104 + // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt 1.1105 + // some controller names are: 1.1106 + // 0x00 + 'std' for linear movie 1.1107 + // 'none' for no controls 1.1108 + $atom_structure['ctyp'] = substr($atom_data, 0, 4); 1.1109 + switch ($atom_structure['ctyp']) { 1.1110 + case 'qtvr': 1.1111 + $info['video']['dataformat'] = 'quicktimevr'; 1.1112 + break; 1.1113 + } 1.1114 + break; 1.1115 + 1.1116 + case 'pano': // PANOrama track (seen on QTVR) 1.1117 + $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 1.1118 + break; 1.1119 + 1.1120 + case 'hint': // HINT track 1.1121 + case 'hinf': // 1.1122 + case 'hinv': // 1.1123 + case 'hnti': // 1.1124 + $info['quicktime']['hinting'] = true; 1.1125 + break; 1.1126 + 1.1127 + case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR) 1.1128 + for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) { 1.1129 + $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); 1.1130 + } 1.1131 + break; 1.1132 + 1.1133 + case 'FXTC': // Something to do with Adobe After Effects (?) 1.1134 + case 'PrmA': 1.1135 + case 'code': 1.1136 + case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html 1.1137 + // Observed-but-not-handled atom types are just listed here 1.1138 + // to prevent warnings being generated 1.1139 + $atom_structure['data'] = $atom_data; 1.1140 + break; 1.1141 + 1.1142 + default: 1.1143 + $getid3->warning('Unknown QuickTime atom type: "'.$atom_name.'" at offset '.$base_offset); 1.1144 + $atom_structure['data'] = $atom_data; 1.1145 + break; 1.1146 + } 1.1147 + array_pop($atom_hierarchy); 1.1148 + return $atom_structure; 1.1149 + } 1.1150 + 1.1151 + 1.1152 + 1.1153 + private function QuicktimeParseContainerAtom($atom_data, $base_offset, &$atom_hierarchy) { 1.1154 + 1.1155 + if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) { 1.1156 + return false; 1.1157 + } 1.1158 + 1.1159 + $atom_structure = false; 1.1160 + $subatom_offset = 0; 1.1161 + 1.1162 + while ($subatom_offset < strlen($atom_data)) { 1.1163 + 1.1164 + $subatom_size = getid3_lib::BigEndian2Int(substr($atom_data, $subatom_offset + 0, 4)); 1.1165 + $subatom_name = substr($atom_data, $subatom_offset + 4, 4); 1.1166 + $subatom_data = substr($atom_data, $subatom_offset + 8, $subatom_size - 8); 1.1167 + 1.1168 + if ($subatom_size == 0) { 1.1169 + // Furthermore, for historical reasons the list of atoms is optionally 1.1170 + // terminated by a 32-bit integer set to 0. If you are writing a program 1.1171 + // to read user data atoms, you should allow for the terminating 0. 1.1172 + return $atom_structure; 1.1173 + } 1.1174 + 1.1175 + $atom_structure[] = $this->QuicktimeParseAtom($subatom_name, $subatom_size, $subatom_data, $base_offset + $subatom_offset, $atom_hierarchy); 1.1176 + 1.1177 + $subatom_offset += $subatom_size; 1.1178 + } 1.1179 + return $atom_structure; 1.1180 + } 1.1181 + 1.1182 + 1.1183 + 1.1184 + private function CopyToAppropriateCommentsSection($key_name, $data) { 1.1185 + 1.1186 + // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt 1.1187 + 1.1188 + static $translator = array ( 1.1189 + '©cpy' => 'copyright', 1.1190 + '©day' => 'creation_date', 1.1191 + '©dir' => 'director', 1.1192 + '©ed1' => 'edit1', 1.1193 + '©ed2' => 'edit2', 1.1194 + '©ed3' => 'edit3', 1.1195 + '©ed4' => 'edit4', 1.1196 + '©ed5' => 'edit5', 1.1197 + '©ed6' => 'edit6', 1.1198 + '©ed7' => 'edit7', 1.1199 + '©ed8' => 'edit8', 1.1200 + '©ed9' => 'edit9', 1.1201 + '©fmt' => 'format', 1.1202 + '©inf' => 'information', 1.1203 + '©prd' => 'producer', 1.1204 + '©prf' => 'performers', 1.1205 + '©req' => 'system_requirements', 1.1206 + '©src' => 'source_credit', 1.1207 + '©wrt' => 'writer', 1.1208 + '©nam' => 'title', 1.1209 + '©cmt' => 'comment', 1.1210 + '©wrn' => 'warning', 1.1211 + '©hst' => 'host_computer', 1.1212 + '©mak' => 'make', 1.1213 + '©mod' => 'model', 1.1214 + '©PRD' => 'product', 1.1215 + '©swr' => 'software', 1.1216 + '©aut' => 'author', 1.1217 + '©ART' => 'artist', 1.1218 + '©trk' => 'track', 1.1219 + '©alb' => 'album', 1.1220 + '©com' => 'comment', 1.1221 + '©gen' => 'genre', 1.1222 + '©ope' => 'composer', 1.1223 + '©url' => 'url', 1.1224 + '©enc' => 'encoder' 1.1225 + ); 1.1226 + 1.1227 + if (isset($translator[$key_name])) { 1.1228 + $this->getid3->info['quicktime']['comments'][$translator[$key_name]][] = $data; 1.1229 + } 1.1230 + 1.1231 + return true; 1.1232 + } 1.1233 + 1.1234 + 1.1235 + 1.1236 + public static function QuicktimeLanguageLookup($language_id) { 1.1237 + 1.1238 + static $lookup = array ( 1.1239 + 0 => 'English', 1.1240 + 1 => 'French', 1.1241 + 2 => 'German', 1.1242 + 3 => 'Italian', 1.1243 + 4 => 'Dutch', 1.1244 + 5 => 'Swedish', 1.1245 + 6 => 'Spanish', 1.1246 + 7 => 'Danish', 1.1247 + 8 => 'Portuguese', 1.1248 + 9 => 'Norwegian', 1.1249 + 10 => 'Hebrew', 1.1250 + 11 => 'Japanese', 1.1251 + 12 => 'Arabic', 1.1252 + 13 => 'Finnish', 1.1253 + 14 => 'Greek', 1.1254 + 15 => 'Icelandic', 1.1255 + 16 => 'Maltese', 1.1256 + 17 => 'Turkish', 1.1257 + 18 => 'Croatian', 1.1258 + 19 => 'Chinese (Traditional)', 1.1259 + 20 => 'Urdu', 1.1260 + 21 => 'Hindi', 1.1261 + 22 => 'Thai', 1.1262 + 23 => 'Korean', 1.1263 + 24 => 'Lithuanian', 1.1264 + 25 => 'Polish', 1.1265 + 26 => 'Hungarian', 1.1266 + 27 => 'Estonian', 1.1267 + 28 => 'Lettish', 1.1268 + 28 => 'Latvian', 1.1269 + 29 => 'Saamisk', 1.1270 + 29 => 'Lappish', 1.1271 + 30 => 'Faeroese', 1.1272 + 31 => 'Farsi', 1.1273 + 31 => 'Persian', 1.1274 + 32 => 'Russian', 1.1275 + 33 => 'Chinese (Simplified)', 1.1276 + 34 => 'Flemish', 1.1277 + 35 => 'Irish', 1.1278 + 36 => 'Albanian', 1.1279 + 37 => 'Romanian', 1.1280 + 38 => 'Czech', 1.1281 + 39 => 'Slovak', 1.1282 + 40 => 'Slovenian', 1.1283 + 41 => 'Yiddish', 1.1284 + 42 => 'Serbian', 1.1285 + 43 => 'Macedonian', 1.1286 + 44 => 'Bulgarian', 1.1287 + 45 => 'Ukrainian', 1.1288 + 46 => 'Byelorussian', 1.1289 + 47 => 'Uzbek', 1.1290 + 48 => 'Kazakh', 1.1291 + 49 => 'Azerbaijani', 1.1292 + 50 => 'AzerbaijanAr', 1.1293 + 51 => 'Armenian', 1.1294 + 52 => 'Georgian', 1.1295 + 53 => 'Moldavian', 1.1296 + 54 => 'Kirghiz', 1.1297 + 55 => 'Tajiki', 1.1298 + 56 => 'Turkmen', 1.1299 + 57 => 'Mongolian', 1.1300 + 58 => 'MongolianCyr', 1.1301 + 59 => 'Pashto', 1.1302 + 60 => 'Kurdish', 1.1303 + 61 => 'Kashmiri', 1.1304 + 62 => 'Sindhi', 1.1305 + 63 => 'Tibetan', 1.1306 + 64 => 'Nepali', 1.1307 + 65 => 'Sanskrit', 1.1308 + 66 => 'Marathi', 1.1309 + 67 => 'Bengali', 1.1310 + 68 => 'Assamese', 1.1311 + 69 => 'Gujarati', 1.1312 + 70 => 'Punjabi', 1.1313 + 71 => 'Oriya', 1.1314 + 72 => 'Malayalam', 1.1315 + 73 => 'Kannada', 1.1316 + 74 => 'Tamil', 1.1317 + 75 => 'Telugu', 1.1318 + 76 => 'Sinhalese', 1.1319 + 77 => 'Burmese', 1.1320 + 78 => 'Khmer', 1.1321 + 79 => 'Lao', 1.1322 + 80 => 'Vietnamese', 1.1323 + 81 => 'Indonesian', 1.1324 + 82 => 'Tagalog', 1.1325 + 83 => 'MalayRoman', 1.1326 + 84 => 'MalayArabic', 1.1327 + 85 => 'Amharic', 1.1328 + 86 => 'Tigrinya', 1.1329 + 87 => 'Galla', 1.1330 + 87 => 'Oromo', 1.1331 + 88 => 'Somali', 1.1332 + 89 => 'Swahili', 1.1333 + 90 => 'Ruanda', 1.1334 + 91 => 'Rundi', 1.1335 + 92 => 'Chewa', 1.1336 + 93 => 'Malagasy', 1.1337 + 94 => 'Esperanto', 1.1338 + 128 => 'Welsh', 1.1339 + 129 => 'Basque', 1.1340 + 130 => 'Catalan', 1.1341 + 131 => 'Latin', 1.1342 + 132 => 'Quechua', 1.1343 + 133 => 'Guarani', 1.1344 + 134 => 'Aymara', 1.1345 + 135 => 'Tatar', 1.1346 + 136 => 'Uighur', 1.1347 + 137 => 'Dzongkha', 1.1348 + 138 => 'JavaneseRom' 1.1349 + ); 1.1350 + 1.1351 + return (isset($lookup[$language_id]) ? $lookup[$language_id] : 'invalid'); 1.1352 + } 1.1353 + 1.1354 + 1.1355 + 1.1356 + public static function QuicktimeVideoCodecLookup($codec_id) { 1.1357 + 1.1358 + static $lookup = array ( 1.1359 + '3IVX' => '3ivx MPEG-4', 1.1360 + '3IV1' => '3ivx MPEG-4 v1', 1.1361 + '3IV2' => '3ivx MPEG-4 v2', 1.1362 + 'avr ' => 'AVR-JPEG', 1.1363 + 'base' => 'Base', 1.1364 + 'WRLE' => 'BMP', 1.1365 + 'cvid' => 'Cinepak', 1.1366 + 'clou' => 'Cloud', 1.1367 + 'cmyk' => 'CMYK', 1.1368 + 'yuv2' => 'ComponentVideo', 1.1369 + 'yuvu' => 'ComponentVideoSigned', 1.1370 + 'yuvs' => 'ComponentVideoUnsigned', 1.1371 + 'dvc ' => 'DVC-NTSC', 1.1372 + 'dvcp' => 'DVC-PAL', 1.1373 + 'dvpn' => 'DVCPro-NTSC', 1.1374 + 'dvpp' => 'DVCPro-PAL', 1.1375 + 'fire' => 'Fire', 1.1376 + 'flic' => 'FLC', 1.1377 + 'b48r' => '48RGB', 1.1378 + 'gif ' => 'GIF', 1.1379 + 'smc ' => 'Graphics', 1.1380 + 'h261' => 'H261', 1.1381 + 'h263' => 'H263', 1.1382 + 'IV41' => 'Indeo4', 1.1383 + 'jpeg' => 'JPEG', 1.1384 + 'PNTG' => 'MacPaint', 1.1385 + 'msvc' => 'Microsoft Video1', 1.1386 + 'mjpa' => 'Motion JPEG-A', 1.1387 + 'mjpb' => 'Motion JPEG-B', 1.1388 + 'myuv' => 'MPEG YUV420', 1.1389 + 'dmb1' => 'OpenDML JPEG', 1.1390 + 'kpcd' => 'PhotoCD', 1.1391 + '8BPS' => 'Planar RGB', 1.1392 + 'png ' => 'PNG', 1.1393 + 'qdrw' => 'QuickDraw', 1.1394 + 'qdgx' => 'QuickDrawGX', 1.1395 + 'raw ' => 'RAW', 1.1396 + '.SGI' => 'SGI', 1.1397 + 'b16g' => '16Gray', 1.1398 + 'b64a' => '64ARGB', 1.1399 + 'SVQ1' => 'Sorenson Video 1', 1.1400 + 'SVQ1' => 'Sorenson Video 3', 1.1401 + 'syv9' => 'Sorenson YUV9', 1.1402 + 'tga ' => 'Targa', 1.1403 + 'b32a' => '32AlphaGray', 1.1404 + 'tiff' => 'TIFF', 1.1405 + 'path' => 'Vector', 1.1406 + 'rpza' => 'Video', 1.1407 + 'ripl' => 'WaterRipple', 1.1408 + 'WRAW' => 'Windows RAW', 1.1409 + 'y420' => 'YUV420' 1.1410 + ); 1.1411 + 1.1412 + return (isset($lookup[$codec_id]) ? $lookup[$codec_id] : ''); 1.1413 + } 1.1414 + 1.1415 + 1.1416 + 1.1417 + public static function QuicktimeAudioCodecLookup($codec_id) { 1.1418 + 1.1419 + static $lookup = array ( 1.1420 + '.mp3' => 'Fraunhofer MPEG Layer-III alias', 1.1421 + 'aac ' => 'ISO/IEC 14496-3 AAC', 1.1422 + 'agsm' => 'Apple GSM 10:1', 1.1423 + 'alac' => 'Apple Lossless Audio Codec', 1.1424 + 'alaw' => 'A-law 2:1', 1.1425 + 'conv' => 'Sample Format', 1.1426 + 'dvca' => 'DV', 1.1427 + 'dvi ' => 'DV 4:1', 1.1428 + 'eqal' => 'Frequency Equalizer', 1.1429 + 'fl32' => '32-bit Floating Point', 1.1430 + 'fl64' => '64-bit Floating Point', 1.1431 + 'ima4' => 'Interactive Multimedia Association 4:1', 1.1432 + 'in24' => '24-bit Integer', 1.1433 + 'in32' => '32-bit Integer', 1.1434 + 'lpc ' => 'LPC 23:1', 1.1435 + 'MAC3' => 'Macintosh Audio Compression/Expansion (MACE) 3:1', 1.1436 + 'MAC6' => 'Macintosh Audio Compression/Expansion (MACE) 6:1', 1.1437 + 'mixb' => '8-bit Mixer', 1.1438 + 'mixw' => '16-bit Mixer', 1.1439 + 'mp4a' => 'ISO/IEC 14496-3 AAC', 1.1440 + "MS'\x00\x02" => 'Microsoft ADPCM', 1.1441 + "MS'\x00\x11" => 'DV IMA', 1.1442 + "MS\x00\x55" => 'Fraunhofer MPEG Layer III', 1.1443 + 'NONE' => 'No Encoding', 1.1444 + 'Qclp' => 'Qualcomm PureVoice', 1.1445 + 'QDM2' => 'QDesign Music 2', 1.1446 + 'QDMC' => 'QDesign Music 1', 1.1447 + 'ratb' => '8-bit Rate', 1.1448 + 'ratw' => '16-bit Rate', 1.1449 + 'raw ' => 'raw PCM', 1.1450 + 'sour' => 'Sound Source', 1.1451 + 'sowt' => 'signed/two\'s complement (Little Endian)', 1.1452 + 'str1' => 'Iomega MPEG layer II', 1.1453 + 'str2' => 'Iomega MPEG *layer II', 1.1454 + 'str3' => 'Iomega MPEG **layer II', 1.1455 + 'str4' => 'Iomega MPEG ***layer II', 1.1456 + 'twos' => 'signed/two\'s complement (Big Endian)', 1.1457 + 'ulaw' => 'mu-law 2:1', 1.1458 + ); 1.1459 + 1.1460 + return (isset($lookup[$codec_id]) ? $lookup[$codec_id] : ''); 1.1461 + } 1.1462 + 1.1463 + 1.1464 + 1.1465 + public static function QuicktimeDCOMLookup($compression_id) { 1.1466 + 1.1467 + static $lookup = array ( 1.1468 + 'zlib' => 'ZLib Deflate', 1.1469 + 'adec' => 'Apple Compression' 1.1470 + ); 1.1471 + 1.1472 + return (isset($lookup[$compression_id]) ? $lookup[$compression_id] : ''); 1.1473 + } 1.1474 + 1.1475 + 1.1476 + 1.1477 + public static function QuicktimeColorNameLookup($color_depth_id) { 1.1478 + 1.1479 + static $lookup = array ( 1.1480 + 1 => '2-color (monochrome)', 1.1481 + 2 => '4-color', 1.1482 + 4 => '16-color', 1.1483 + 8 => '256-color', 1.1484 + 16 => 'thousands (16-bit color)', 1.1485 + 24 => 'millions (24-bit color)', 1.1486 + 32 => 'millions+ (32-bit color)', 1.1487 + 33 => 'black & white', 1.1488 + 34 => '4-gray', 1.1489 + 36 => '16-gray', 1.1490 + 40 => '256-gray', 1.1491 + ); 1.1492 + 1.1493 + return (isset($lookup[$color_depth_id]) ? $lookup[$color_depth_id] : 'invalid'); 1.1494 + } 1.1495 + 1.1496 + 1.1497 + 1.1498 + public static function NoNullString($null_terminated_string) { 1.1499 + 1.1500 + // remove the single null terminator on null terminated strings 1.1501 + if (substr($null_terminated_string, strlen($null_terminated_string) - 1, 1) === "\x00") { 1.1502 + return substr($null_terminated_string, 0, strlen($null_terminated_string) - 1); 1.1503 + } 1.1504 + 1.1505 + return $null_terminated_string; 1.1506 + } 1.1507 + 1.1508 + 1.1509 + 1.1510 + public static function FixedPoint8_8($raw_data) { 1.1511 + 1.1512 + return getid3_lib::BigEndian2Int($raw_data{0}) + (float)(getid3_lib::BigEndian2Int($raw_data{1}) / 256); 1.1513 + } 1.1514 + 1.1515 + 1.1516 + 1.1517 + public static function FixedPoint16_16($raw_data) { 1.1518 + 1.1519 + return getid3_lib::BigEndian2Int(substr($raw_data, 0, 2)) + (float)(getid3_lib::BigEndian2Int(substr($raw_data, 2, 2)) / 65536); 1.1520 + } 1.1521 + 1.1522 + 1.1523 + 1.1524 + public static function FixedPoint2_30($raw_data) { 1.1525 + 1.1526 + $binary_string = getid3_lib::BigEndian2Bin($raw_data); 1.1527 + return bindec(substr($binary_string, 0, 2)) + (float)(bindec(substr($binary_string, 2, 30)) / 1073741824); 1.1528 + } 1.1529 + 1.1530 +} 1.1531 + 1.1532 +?> 1.1533 \ No newline at end of file