Changeset 92618 in spip-zone


Ignore:
Timestamp:
Nov 2, 2015, 1:49:55 PM (4 years ago)
Author:
brunobergot@…
Message:

version 1.3.8 : maj de la lib getID3 en version 1.9.10 + maj copyright

Location:
_plugins_/getID3/trunk
Files:
1 added
73 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/getID3/trunk/getid3/extension.cache.dbm.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78//                                                             //
     
    136137                }
    137138
    138                 parent::getID3();
     139                parent::__construct();
    139140        }
    140141
  • _plugins_/getID3/trunk/getid3/extension.cache.mysql.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78//                                                             //
     
    106107                // Check version number and clear cache if changed
    107108                $version = '';
    108                 if ($this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string(getID3::VERSION)."') AND (`filesize` = '-1') AND (`filetime` = '-1') AND (`analyzetime` = '-1')", $this->connection)) {
     109                $SQLquery  = 'SELECT `value`';
     110                $SQLquery .= ' FROM `'.mysql_real_escape_string($this->table).'`';
     111                $SQLquery .= ' WHERE (`filename` = \''.mysql_real_escape_string(getID3::VERSION).'\')';
     112                $SQLquery .= ' AND (`filesize` = -1)';
     113                $SQLquery .= ' AND (`filetime` = -1)';
     114                $SQLquery .= ' AND (`analyzetime` = -1)';
     115                if ($this->cursor = mysql_query($SQLquery, $this->connection)) {
    109116                        list($version) = mysql_fetch_array($this->cursor);
    110117                }
     
    113120                }
    114121
    115                 parent::getID3();
     122                parent::__construct();
    116123        }
    117124
     
    121128        public function clear_cache() {
    122129
    123                 $this->cursor = mysql_query("DELETE FROM `".mysql_real_escape_string($this->table)."`", $this->connection);
    124                 $this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` VALUES ('".getID3::VERSION."', -1, -1, -1, '".getID3::VERSION."')", $this->connection);
     130                $this->cursor = mysql_query('DELETE FROM `'.mysql_real_escape_string($this->table).'`', $this->connection);
     131                $this->cursor = mysql_query('INSERT INTO `'.mysql_real_escape_string($this->table).'` VALUES (\''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')', $this->connection);
    125132        }
    126133
     
    128135
    129136        // public: analyze file
    130         public function analyze($filename) {
     137        public function analyze($filename, $filesize=null, $original_filename='') {
    131138
    132139                if (file_exists($filename)) {
     
    134141                        // Short-hands
    135142                        $filetime = filemtime($filename);
    136                         $filesize = filesize($filename);
     143                        $filesize =  filesize($filename);
    137144
    138145                        // Lookup file
    139                         $this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string($filename)."') AND (`filesize` = '".mysql_real_escape_string($filesize)."') AND (`filetime` = '".mysql_real_escape_string($filetime)."')", $this->connection);
     146                        $SQLquery  = 'SELECT `value`';
     147                        $SQLquery .= ' FROM `'.mysql_real_escape_string($this->table).'`';
     148                        $SQLquery .= ' WHERE (`filename` = \''.mysql_real_escape_string($filename).'\')';
     149                        $SQLquery .= '   AND (`filesize` = \''.mysql_real_escape_string($filesize).'\')';
     150                        $SQLquery .= '   AND (`filetime` = \''.mysql_real_escape_string($filetime).'\')';
     151                        $this->cursor = mysql_query($SQLquery, $this->connection);
    140152                        if (mysql_num_rows($this->cursor) > 0) {
    141153                                // Hit
     
    146158
    147159                // Miss
    148                 $analysis = parent::analyze($filename);
     160                $analysis = parent::analyze($filename, $filesize, $original_filename);
    149161
    150162                // Save result
    151163                if (file_exists($filename)) {
    152                         $this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES ('".mysql_real_escape_string($filename)."', '".mysql_real_escape_string($filesize)."', '".mysql_real_escape_string($filetime)."', '".mysql_real_escape_string(time())."', '".mysql_real_escape_string(base64_encode(serialize($analysis)))."')", $this->connection);
     164                        $SQLquery  = 'INSERT INTO `'.mysql_real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (';
     165                        $SQLquery .=   '\''.mysql_real_escape_string($filename).'\'';
     166                        $SQLquery .= ', \''.mysql_real_escape_string($filesize).'\'';
     167                        $SQLquery .= ', \''.mysql_real_escape_string($filetime).'\'';
     168                        $SQLquery .= ', \''.mysql_real_escape_string(time()   ).'\'';
     169                        $SQLquery .= ', \''.mysql_real_escape_string(base64_encode(serialize($analysis))).'\')';
     170                        $this->cursor = mysql_query($SQLquery, $this->connection);
    153171                }
    154172                return $analysis;
     
    160178        private function create_table($drop=false) {
    161179
    162                 $this->cursor = mysql_query("CREATE TABLE IF NOT EXISTS `".mysql_real_escape_string($this->table)."` (
    163                         `filename` VARCHAR(255) NOT NULL DEFAULT '',
    164                         `filesize` INT(11) NOT NULL DEFAULT '0',
    165                         `filetime` INT(11) NOT NULL DEFAULT '0',
    166                         `analyzetime` INT(11) NOT NULL DEFAULT '0',
    167                         `value` TEXT NOT NULL,
    168                         PRIMARY KEY (`filename`,`filesize`,`filetime`)) ENGINE=MyISAM", $this->connection);
     180                $SQLquery  = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
     181                $SQLquery .=   '`filename` VARCHAR(500) NOT NULL DEFAULT \'\'';
     182                $SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
     183                $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
     184                $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
     185                $SQLquery .= ', `value` LONGTEXT NOT NULL';
     186                $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM';
     187                $this->cursor = mysql_query($SQLquery, $this->connection);
    169188                echo mysql_error($this->connection);
    170189        }
  • _plugins_/getID3/trunk/getid3/extension.cache.sqlite3.php

    r71835 r92618  
    33/// getID3() by James Heinrich <info@getid3.org>                               //
    44//  available at http://getid3.sourceforge.net                                 //
    5 //            or http://www.getid3.org                                        ///
     5//            or http://www.getid3.org                                         //
     6//          also https://github.com/JamesHeinrich/getID3                       //
    67/////////////////////////////////////////////////////////////////////////////////
    78///                                                                            //
     
    4950*   sqlite3             table='getid3_cache', hide=false        (PHP5)
    5051*
    51 
    52 ***  database file will be stored in the same directory as this script,
    53 ***  webserver must have write access to that directory!
    54 ***  set $hide to TRUE to prefix db file with .ht to pervent access from web client
    55 ***  this is a default setting in the Apache configuration:
    56 
    57 # The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
    58 
    59 <Files ~ "^\.ht">
    60     Order allow,deny
    61     Deny from all
    62     Satisfy all
    63 </Files>
    64 
     52*
     53* ***  database file will be stored in the same directory as this script,
     54* ***  webserver must have write access to that directory!
     55* ***  set $hide to TRUE to prefix db file with .ht to pervent access from web client
     56* ***  this is a default setting in the Apache configuration:
     57*
     58* The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
     59*
     60* <Files ~ "^\.ht">
     61*     Order allow,deny
     62*     Deny from all
     63*     Satisfy all
     64* </Files>
     65*
    6566********************************************************************************
    6667*
     
    159160        * @return boolean
    160161        */
    161         public function analyze($filename) {
     162        public function analyze($filename, $filesize=null, $original_filename='') {
    162163                if (!file_exists($filename)) {
    163164                        return false;
     
    182183                }
    183184                // if it hasn't been analyzed before, then do it now
    184                 $analysis = parent::analyze($filename);
     185                $analysis = parent::analyze($filename, $filesize=null, $original_filename='');
    185186                // Save result
    186187                $sql = $this->cache_file;
     
    253254                                break;
    254255                        case 'make_table':
    255                                 return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
     256                                //return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
     257                                return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
    256258                                break;
    257259                        case 'get_cached_dir':
  • _plugins_/getID3/trunk/getid3/getid3.lib.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78//                                                             //
     
    283284                        } else {
    284285                                throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()');
    285                                 break;
    286286                        }
    287287                }
     
    413413                }
    414414                return $newarray;
     415        }
     416
     417        public static function flipped_array_merge_noclobber($array1, $array2) {
     418                if (!is_array($array1) || !is_array($array2)) {
     419                        return false;
     420                }
     421                # naturally, this only works non-recursively
     422                $newarray = array_flip($array1);
     423                foreach (array_flip($array2) as $key => $val) {
     424                        if (!isset($newarray[$key])) {
     425                                $newarray[$key] = count($newarray);
     426                        }
     427                }
     428                return array_flip($newarray);
    415429        }
    416430
     
    520534
    521535        public static function XML2array($XMLstring) {
    522                 if (function_exists('simplexml_load_string')) {
    523                         if (function_exists('get_object_vars')) {
    524                                 $XMLobject = simplexml_load_string($XMLstring);
    525                                 return self::SimpleXMLelement2array($XMLobject);
    526                         }
     536                if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
     537                        // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
     538                        // https://core.trac.wordpress.org/changeset/29378
     539                        $loader = libxml_disable_entity_loader(true);
     540                        $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
     541                        $return = self::SimpleXMLelement2array($XMLobject);
     542                        libxml_disable_entity_loader($loader);
     543                        return $return;
    527544                }
    528545                return false;
     
    635652                if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
    636653                        if (($fp_dest = fopen($filename_dest, 'wb'))) {
    637                                 if (fseek($fp_src, $offset, SEEK_SET) == 0) {
     654                                if (fseek($fp_src, $offset) == 0) {
    638655                                        $byteslefttowrite = $length;
    639656                                        while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
     
    9861003        }
    9871004
     1005        public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
     1006                if (is_string($data)) {
     1007                        return self::MultiByteCharString2HTML($data, $charset);
     1008                } elseif (is_array($data)) {
     1009                        $return_data = array();
     1010                        foreach ($data as $key => $value) {
     1011                                $return_data[$key] = self::recursiveMultiByteCharString2HTML($value, $charset);
     1012                        }
     1013                        return $return_data;
     1014                }
     1015                // integer, float, objects, resources, etc
     1016                return $data;
     1017        }
    9881018
    9891019        public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
     
    11501180                                fclose($tmp);
    11511181                                $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
     1182                                if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
     1183                                        return false;
     1184                                }
     1185                                $GetDataImageSize['height'] = $GetDataImageSize[0];
     1186                                $GetDataImageSize['width']  = $GetDataImageSize[1];
    11521187                        }
    11531188                        unlink($tempfilename);
     
    12101245                                                                foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
    12111246                                                                        $oldvaluelength = strlen(trim($existingvalue));
    1212                                                                         if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
     1247                                                                        if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
    12131248                                                                                $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
    1214                                                                                 break 2;
     1249                                                                                //break 2;
     1250                                                                                break;
    12151251                                                                        }
    12161252                                                                }
     
    12191255                                                        if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
    12201256                                                                $value = (is_string($value) ? trim($value) : $value);
    1221                                                                 $ThisFileInfo['comments'][$tagname][] = $value;
     1257                                                                if (!is_numeric($key)) {
     1258                                                                        $ThisFileInfo['comments'][$tagname][$key] = $value;
     1259                                                                } else {
     1260                                                                        $ThisFileInfo['comments'][$tagname][]     = $value;
     1261                                                                }
    12221262                                                        }
    12231263                                                }
     
    12271267
    12281268                        // Copy to ['comments_html']
    1229                         foreach ($ThisFileInfo['comments'] as $field => $values) {
    1230                                 if ($field == 'picture') {
    1231                                         // pictures can take up a lot of space, and we don't need multiple copies of them
    1232                                         // let there be a single copy in [comments][picture], and not elsewhere
    1233                                         continue;
    1234                                 }
    1235                                 foreach ($values as $index => $value) {
    1236                                         if (is_array($value)) {
    1237                                                 $ThisFileInfo['comments_html'][$field][$index] = $value;
    1238                                         } else {
    1239                                                 $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
     1269                        if (!empty($ThisFileInfo['comments'])) {
     1270                                foreach ($ThisFileInfo['comments'] as $field => $values) {
     1271                                        if ($field == 'picture') {
     1272                                                // pictures can take up a lot of space, and we don't need multiple copies of them
     1273                                                // let there be a single copy in [comments][picture], and not elsewhere
     1274                                                continue;
    12401275                                        }
    1241                                 }
    1242                         }
     1276                                        foreach ($values as $index => $value) {
     1277                                                if (is_array($value)) {
     1278                                                        $ThisFileInfo['comments_html'][$field][$index] = $value;
     1279                                                } else {
     1280                                                        $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
     1281                                                }
     1282                                        }
     1283                                }
     1284                        }
     1285
    12431286                }
    12441287                return true;
     
    13401383        }
    13411384
     1385
     1386        /**
     1387        * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
     1388        * @param string $path A path.
     1389        * @param string $suffix If the name component ends in suffix this will also be cut off.
     1390        * @return string
     1391        */
     1392        public static function mb_basename($path, $suffix = null) {
     1393                $splited = preg_split('#/#', rtrim($path, '/ '));
     1394                return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
     1395        }
     1396
    13421397}
  • _plugins_/getID3/trunk/getid3/getid3.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78//                                                             //
     
    1819        define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
    1920}
     21// Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923)
     22if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
     23        define('IMG_JPG', IMAGETYPE_JPEG);
     24}
    2025
    2126// attempt to define temp dir as something flexible but reliable
     
    2429        $temp_dir = '';
    2530}
    26 if (!$temp_dir && function_exists('sys_get_temp_dir')) {
    27         // PHP v5.2.1+
     31if (!$temp_dir && function_exists('sys_get_temp_dir')) { // sys_get_temp_dir added in PHP v5.2.1
    2832        // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts
    2933        $temp_dir = sys_get_temp_dir();
    3034}
    31 $temp_dir = realpath($temp_dir);
     35$temp_dir = @realpath($temp_dir); // see https://github.com/JamesHeinrich/getID3/pull/10
    3236$open_basedir = ini_get('open_basedir');
    3337if ($open_basedir) {
     
    5862}
    5963// $temp_dir = '/something/else/';  // feel free to override temp dir here if it works better for your system
    60 define('GETID3_TEMP_DIR', $temp_dir);
     64if (!defined('GETID3_TEMP_DIR')) {
     65        define('GETID3_TEMP_DIR', $temp_dir);
     66}
    6167unset($open_basedir, $temp_dir);
    6268
     
    98104        public $info;                             // Result array.
    99105        public $tempdir = GETID3_TEMP_DIR;
     106        public $memory_limit = 0;
    100107
    101108        // Protected variables
    102109        protected $startup_error   = '';
    103110        protected $startup_warning = '';
    104         protected $memory_limit    = 0;
    105 
    106         const VERSION           = '1.9.5-20130220';
     111
     112        const VERSION           = '1.9.10-20150914';
    107113        const FREAD_BUFFER_SIZE = 32768;
    108114
     
    114120
    115121                // Check for PHP version
    116                 $required_php_version = '5.0.5';
     122                $required_php_version = '5.3.0';
    117123                if (version_compare(PHP_VERSION, $required_php_version, '<')) {
    118124                        $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION;
     
    238244
    239245
    240         public function openfile($filename) {
     246        public function openfile($filename, $filesize=null) {
    241247                try {
    242248                        if (!empty($this->startup_error)) {
     
    251257                        $this->info = array();
    252258                        $this->info['GETID3_VERSION']   = $this->version();
    253                         $this->info['php_memory_limit'] = $this->memory_limit;
     259                        $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
    254260
    255261                        // remote files not supported
     
    262268
    263269                        // open local file
    264                         if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
     270                        //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
     271                        if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
    265272                                // great
    266273                        } else {
    267                                 throw new getid3_exception('Could not open "'.$filename.'" (does not exist, or is not a file)');
    268                         }
    269 
    270                         $this->info['filesize'] = filesize($filename);
     274                                $errormessagelist = array();
     275                                if (!is_readable($filename)) {
     276                                        $errormessagelist[] = '!is_readable';
     277                                }
     278                                if (!is_file($filename)) {
     279                                        $errormessagelist[] = '!is_file';
     280                                }
     281                                if (!file_exists($filename)) {
     282                                        $errormessagelist[] = '!file_exists';
     283                                }
     284                                if (empty($errormessagelist)) {
     285                                        $errormessagelist[] = 'fopen failed';
     286                                }
     287                                throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
     288                        }
     289
     290                        $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
    271291                        // set redundant parameters - might be needed in some include file
    272                         $this->info['filename']     = basename($filename);
     292                        // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
     293                        $filename = str_replace('\\', '/', $filename);
    273294                        $this->info['filepath']     = str_replace('\\', '/', realpath(dirname($filename)));
     295                        $this->info['filename']     = getid3_lib::mb_basename($filename);
    274296                        $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
    275297
     
    296318                                                }
    297319                                                $this->info['filesize'] = $real_filesize;
    298                                                 $this->error('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
     320                                                $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
    299321                                }
    300322                        }
     
    321343
    322344        // public: analyze file
    323         public function analyze($filename) {
     345        public function analyze($filename, $filesize=null, $original_filename='') {
    324346                try {
    325                         if (!$this->openfile($filename)) {
     347                        if (!$this->openfile($filename, $filesize)) {
    326348                                return $this->info;
    327349                        }
     
    353375                        // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
    354376                        if (!$this->option_tag_id3v2) {
    355                                 fseek($this->fp, 0, SEEK_SET);
     377                                fseek($this->fp, 0);
    356378                                $header = fread($this->fp, 10);
    357379                                if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
     
    364386
    365387                        // read 32 kb file data
    366                         fseek($this->fp, $this->info['avdataoffset'], SEEK_SET);
     388                        fseek($this->fp, $this->info['avdataoffset']);
    367389                        $formattest = fread($this->fp, 32774);
    368390
    369391                        // determine format
    370                         $determined_format = $this->GetFileFormat($formattest, $filename);
     392                        $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
    371393
    372394                        // unable to determine file format
     
    587609                                                        'module'    => 'au',
    588610                                                        'mime_type' => 'audio/basic',
     611                                                ),
     612
     613                                // AMR  - audio       - Adaptive Multi Rate
     614                                'amr'  => array(
     615                                                        'pattern'   => '^\x23\x21AMR\x0A', // #!AMR[0A]
     616                                                        'group'     => 'audio',
     617                                                        'module'    => 'amr',
     618                                                        'mime_type' => 'audio/amr',
    589619                                                ),
    590620
     
    11621192                                'flac'      => array('vorbiscomment' , 'UTF-8'),
    11631193                                'divxtag'   => array('divx'          , 'ISO-8859-1'),
     1194                                'iptc'      => array('iptc'          , 'ISO-8859-1'),
    11641195                        );
    11651196                }
     
    11821213                                                }
    11831214                                                if ($value) {
    1184                                                         $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
     1215                                                        if (!is_numeric($key)) {
     1216                                                                $this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value;
     1217                                                        } else {
     1218                                                                $this->info['tags'][trim($tag_name)][trim($tag_key)][]     = $value;
     1219                                                        }
    11851220                                                }
    11861221                                        }
     
    11971232                                if ($this->option_tags_html) {
    11981233                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
    1199                                                 foreach ($valuearray as $key => $value) {
    1200                                                         if (is_string($value)) {
    1201                                                                 //$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding);
    1202                                                                 $this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('&#0;', '', trim(getid3_lib::MultiByteCharString2HTML($value, $encoding)));
    1203                                                         } else {
    1204                                                                 $this->info['tags_html'][$tag_name][$tag_key][$key] = $value;
     1234                                                $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
     1235                                        }
     1236                                }
     1237
     1238                                // ID3v1 encoding detection hack start
     1239                                // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
     1240                                // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
     1241                                if ($comment_name == 'id3v1') {
     1242                                        if ($encoding == 'ISO-8859-1') {
     1243                                                if (function_exists('iconv')) {
     1244                                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
     1245                                                                foreach ($valuearray as $key => $value) {
     1246                                                                        if (preg_match('#^[\\x80-\\xFF]+$#', $value)) {
     1247                                                                                foreach (array('windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
     1248                                                                                        if (@iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
     1249                                                                                                $encoding = $id3v1_bad_encoding;
     1250                                                                                                break 3;
     1251                                                                                        }
     1252                                                                                }
     1253                                                                        }
     1254                                                                }
    12051255                                                        }
    12061256                                                }
    12071257                                        }
    12081258                                }
     1259                                // ID3v1 encoding detection hack end
    12091260
    12101261                                $this->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
     
    12601311        }
    12611312
    1262 
    12631313        public function getHashdata($algorithm) {
    12641314                switch ($algorithm) {
     
    15661616
    15671617
    1568 abstract class getid3_handler
    1569 {
     1618abstract class getid3_handler {
     1619
     1620        /**
     1621        * @var getID3
     1622        */
    15701623        protected $getid3;                       // pointer
    15711624
     
    15941647        public function AnalyzeString($string) {
    15951648                // Enter string mode
    1596             $this->setStringMode($string);
     1649                $this->setStringMode($string);
    15971650
    15981651                // Save info
     
    16351688                        return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
    16361689                }
    1637             $pos = $this->ftell() + $bytes;
    1638             if (!getid3_lib::intValueSupported($pos)) {
     1690                $pos = $this->ftell() + $bytes;
     1691                if (!getid3_lib::intValueSupported($pos)) {
    16391692                        throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
    1640             }
     1693                }
    16411694                return fread($this->getid3->fp, $bytes);
    16421695        }
     
    16581711                        }
    16591712                        return 0;
    1660             } else {
    1661                 $pos = $bytes;
    1662                 if ($whence == SEEK_CUR) {
     1713                } else {
     1714                        $pos = $bytes;
     1715                        if ($whence == SEEK_CUR) {
    16631716                                $pos = $this->ftell() + $bytes;
    1664                 } elseif ($whence == SEEK_END) {
    1665                                 $pos = $this->info['filesize'] + $bytes;
    1666                 }
    1667                 if (!getid3_lib::intValueSupported($pos)) {
     1717                        } elseif ($whence == SEEK_END) {
     1718                                $pos = $this->getid3->info['filesize'] + $bytes;
     1719                        }
     1720                        if (!getid3_lib::intValueSupported($pos)) {
    16681721                                throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
    16691722                        }
     
    16831736        }
    16841737
    1685         protected function error($text)
    1686         {
     1738        protected function error($text) {
    16871739                $this->getid3->info['error'][] = $text;
    16881740
     
    16901742        }
    16911743
    1692         protected function warning($text)
    1693         {
     1744        protected function warning($text) {
    16941745                return $this->getid3->warning($text);
    16951746        }
    16961747
    1697         protected function notice($text)
    1698         {
     1748        protected function notice($text) {
    16991749                // does nothing for now
    17001750        }
  • _plugins_/getID3/trunk/getid3/module.archive.gzip.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    3637                //+---+---+---+---+---+---+---+---+---+---+
    3738
    38                 if ($info['filesize'] > $info['php_memory_limit']) {
     39                if ($info['php_memory_limit'] && ($info['filesize'] > $info['php_memory_limit'])) {
    3940                        $info['error'][] = 'File is too large ('.number_format($info['filesize']).' bytes) to read into memory (limit: '.number_format($info['php_memory_limit'] / 1048576).'MB)';
    4041                        return false;
    4142                }
    42                 fseek($this->getid3->fp, 0);
    43                 $buffer = fread($this->getid3->fp, $info['filesize']);
     43                $this->fseek(0);
     44                $buffer = $this->fread($info['filesize']);
    4445
    4546                $arr_members = explode("\x1F\x8B\x08", $buffer);
     
    5657                                if (!$this->get_os_type(ord($attr['os']))) {
    5758                                        // Merge member with previous if wrong OS type
    58                                         $arr_members[$i - 1] .= $buf;
     59                                        $arr_members[($i - 1)] .= $buf;
    5960                                        $arr_members[$i] = '';
    6061                                        $is_wrong_members = true;
  • _plugins_/getID3/trunk/getid3/module.archive.rar.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
  • _plugins_/getID3/trunk/getid3/module.archive.szip.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
  • _plugins_/getID3/trunk/getid3/module.archive.tar.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    3233                $null_512k = str_repeat("\x00", 512); // end-of-file marker
    3334
    34                 fseek($this->getid3->fp, 0);
     35                $this->fseek(0);
    3536                while (!feof($this->getid3->fp)) {
    36                         $buffer = fread($this->getid3->fp, 512);
     37                        $buffer = $this->fread(512);
    3738                        if (strlen($buffer) < 512) {
    3839                                break;
     
    8384
    8485                        // Read to the next chunk
    85                         fseek($this->getid3->fp, $size, SEEK_CUR);
     86                        $this->fseek($size, SEEK_CUR);
    8687
    8788                        $diff = $size % 512;
    8889                        if ($diff != 0) {
    8990                                // Padding, throw away
    90                                 fseek($this->getid3->fp, (512 - $diff), SEEK_CUR);
     91                                $this->fseek((512 - $diff), SEEK_CUR);
    9192                        }
    9293                        // Protect against tar-files with garbage at the end
  • _plugins_/getID3/trunk/getid3/module.archive.zip.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    3738                        while ($EOCDsearchCounter++ < 512) {
    3839
    39                                 fseek($this->getid3->fp, -128 * $EOCDsearchCounter, SEEK_END);
    40                                 $EOCDsearchData = fread($this->getid3->fp, 128).$EOCDsearchData;
     40                                $this->fseek(-128 * $EOCDsearchCounter, SEEK_END);
     41                                $EOCDsearchData = $this->fread(128).$EOCDsearchData;
    4142
    4243                                if (strstr($EOCDsearchData, 'PK'."\x05\x06")) {
    4344
    4445                                        $EOCDposition = strpos($EOCDsearchData, 'PK'."\x05\x06");
    45                                         fseek($this->getid3->fp, (-128 * $EOCDsearchCounter) + $EOCDposition, SEEK_END);
     46                                        $this->fseek((-128 * $EOCDsearchCounter) + $EOCDposition, SEEK_END);
    4647                                        $info['zip']['end_central_directory'] = $this->ZIPparseEndOfCentralDirectory();
    4748
    48                                         fseek($this->getid3->fp, $info['zip']['end_central_directory']['directory_offset'], SEEK_SET);
     49                                        $this->fseek($info['zip']['end_central_directory']['directory_offset']);
    4950                                        $info['zip']['entries_count'] = 0;
    5051                                        while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) {
     
    8283                                        // Local File Header entry will
    8384                                        foreach ($info['zip']['central_directory'] as $central_directory_entry) {
    84                                                 fseek($this->getid3->fp, $central_directory_entry['entry_offset'], SEEK_SET);
     85                                                $this->fseek($central_directory_entry['entry_offset']);
    8586                                                if ($fileentry = $this->ZIPparseLocalFileHeader()) {
    8687                                                        $info['zip']['entries'][] = $fileentry;
     
    200201
    201202        public function ZIPparseLocalFileHeader() {
    202                 $LocalFileHeader['offset'] = ftell($this->getid3->fp);
    203 
    204                 $ZIPlocalFileHeader = fread($this->getid3->fp, 30);
     203                $LocalFileHeader['offset'] = $this->ftell();
     204
     205                $ZIPlocalFileHeader = $this->fread(30);
    205206
    206207                $LocalFileHeader['raw']['signature']          = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader,  0, 4));
    207208                if ($LocalFileHeader['raw']['signature'] != 0x04034B50) { // "PK\x03\x04"
    208209                        // invalid Local File Header Signature
    209                         fseek($this->getid3->fp, $LocalFileHeader['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
     210                        $this->fseek($LocalFileHeader['offset']); // seek back to where filepointer originally was so it can be handled properly
    210211                        return false;
    211212                }
     
    231232                $FilenameExtrafieldLength = $LocalFileHeader['raw']['filename_length'] + $LocalFileHeader['raw']['extra_field_length'];
    232233                if ($FilenameExtrafieldLength > 0) {
    233                         $ZIPlocalFileHeader .= fread($this->getid3->fp, $FilenameExtrafieldLength);
     234                        $ZIPlocalFileHeader .= $this->fread($FilenameExtrafieldLength);
    234235
    235236                        if ($LocalFileHeader['raw']['filename_length'] > 0) {
     
    258259
    259260                }
    260                 $LocalFileHeader['data_offset'] = ftell($this->getid3->fp);
    261                 fseek($this->getid3->fp, $LocalFileHeader['compressed_size'], SEEK_CUR); // this should (but may not) match value in $LocalFileHeader['raw']['compressed_size'] -- $LocalFileHeader['compressed_size'] could have been overwritten above with value from Central Directory
     261                $LocalFileHeader['data_offset'] = $this->ftell();
     262                $this->fseek($LocalFileHeader['compressed_size'], SEEK_CUR); // this should (but may not) match value in $LocalFileHeader['raw']['compressed_size'] -- $LocalFileHeader['compressed_size'] could have been overwritten above with value from Central Directory
    262263
    263264                if ($LocalFileHeader['flags']['data_descriptor_used']) {
    264                         $DataDescriptor = fread($this->getid3->fp, 16);
     265                        $DataDescriptor = $this->fread(16);
    265266                        $LocalFileHeader['data_descriptor']['signature']         = getid3_lib::LittleEndian2Int(substr($DataDescriptor,  0, 4));
    266267                        if ($LocalFileHeader['data_descriptor']['signature'] != 0x08074B50) { // "PK\x07\x08"
    267                                 $this->getid3->warning[] = 'invalid Local File Header Data Descriptor Signature at offset '.(ftell($this->getid3->fp) - 16).' - expecting 08 07 4B 50, found '.getid3_lib::PrintHexBytes($LocalFileHeader['data_descriptor']['signature']);
    268                                 fseek($this->getid3->fp, $LocalFileHeader['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
     268                                $this->getid3->warning[] = 'invalid Local File Header Data Descriptor Signature at offset '.($this->ftell() - 16).' - expecting 08 07 4B 50, found '.getid3_lib::PrintHexBytes($LocalFileHeader['data_descriptor']['signature']);
     269                                $this->fseek($LocalFileHeader['offset']); // seek back to where filepointer originally was so it can be handled properly
    269270                                return false;
    270271                        }
     
    296297
    297298        public function ZIPparseCentralDirectory() {
    298                 $CentralDirectory['offset'] = ftell($this->getid3->fp);
    299 
    300                 $ZIPcentralDirectory = fread($this->getid3->fp, 46);
     299                $CentralDirectory['offset'] = $this->ftell();
     300
     301                $ZIPcentralDirectory = $this->fread(46);
    301302
    302303                $CentralDirectory['raw']['signature']            = getid3_lib::LittleEndian2Int(substr($ZIPcentralDirectory,  0, 4));
    303304                if ($CentralDirectory['raw']['signature'] != 0x02014B50) {
    304305                        // invalid Central Directory Signature
    305                         fseek($this->getid3->fp, $CentralDirectory['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
     306                        $this->fseek($CentralDirectory['offset']); // seek back to where filepointer originally was so it can be handled properly
    306307                        return false;
    307308                }
     
    335336                $FilenameExtrafieldCommentLength = $CentralDirectory['raw']['filename_length'] + $CentralDirectory['raw']['extra_field_length'] + $CentralDirectory['raw']['file_comment_length'];
    336337                if ($FilenameExtrafieldCommentLength > 0) {
    337                         $FilenameExtrafieldComment = fread($this->getid3->fp, $FilenameExtrafieldCommentLength);
     338                        $FilenameExtrafieldComment = $this->fread($FilenameExtrafieldCommentLength);
    338339
    339340                        if ($CentralDirectory['raw']['filename_length'] > 0) {
     
    352353
    353354        public function ZIPparseEndOfCentralDirectory() {
    354                 $EndOfCentralDirectory['offset'] = ftell($this->getid3->fp);
    355 
    356                 $ZIPendOfCentralDirectory = fread($this->getid3->fp, 22);
     355                $EndOfCentralDirectory['offset'] = $this->ftell();
     356
     357                $ZIPendOfCentralDirectory = $this->fread(22);
    357358
    358359                $EndOfCentralDirectory['signature']                   = getid3_lib::LittleEndian2Int(substr($ZIPendOfCentralDirectory,  0, 4));
    359360                if ($EndOfCentralDirectory['signature'] != 0x06054B50) {
    360361                        // invalid End Of Central Directory Signature
    361                         fseek($this->getid3->fp, $EndOfCentralDirectory['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
     362                        $this->fseek($EndOfCentralDirectory['offset']); // seek back to where filepointer originally was so it can be handled properly
    362363                        return false;
    363364                }
     
    371372
    372373                if ($EndOfCentralDirectory['comment_length'] > 0) {
    373                         $EndOfCentralDirectory['comment']                 = fread($this->getid3->fp, $EndOfCentralDirectory['comment_length']);
     374                        $EndOfCentralDirectory['comment']                 = $this->fread($EndOfCentralDirectory['comment_length']);
    374375                }
    375376
  • _plugins_/getID3/trunk/getid3/module.audio-video.asf.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    1617getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
    1718
    18 class getid3_asf extends getid3_handler
    19 {
     19class getid3_asf extends getid3_handler {
    2020
    2121        public function __construct(getID3 $getid3) {
     
    6767                $info['fileformat'] = 'asf';
    6868
    69                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
    70                 $HeaderObjectData = fread($this->getid3->fp, 30);
     69                $this->fseek($info['avdataoffset']);
     70                $HeaderObjectData = $this->fread(30);
    7171
    7272                $thisfile_asf_headerobject['objectid']      = substr($HeaderObjectData, 0, 16);
    7373                $thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']);
    7474                if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) {
    75                         $info['warning'][] = 'ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}';
    76                         unset($info['fileformat']);
    77                         unset($info['asf']);
    78                         return false;
    79                         break;
     75                        unset($info['fileformat'], $info['asf']);
     76                        return $this->error('ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}');
    8077                }
    8178                $thisfile_asf_headerobject['objectsize']    = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8));
     
    8481                $thisfile_asf_headerobject['reserved2']     = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1));
    8582
    86                 $NextObjectOffset = ftell($this->getid3->fp);
    87                 $ASFHeaderData = fread($this->getid3->fp, $thisfile_asf_headerobject['objectsize'] - 30);
     83                $NextObjectOffset = $this->ftell();
     84                $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
    8885                $offset = 0;
    8986
     
    285282                                        $thisfile_asf_headerextensionobject['extension_data']      =                              substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']);
    286283                                        $unhandled_sections = 0;
    287                                         $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->ASF_HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections);
     284                                        $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections);
    288285                                        if ($unhandled_sections === 0) {
    289286                                                unset($thisfile_asf_headerextensionobject['extension_data']);
     
    333330                                                $thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
    334331                                                $offset += 2;
    335                                                 $thisfile_asf_codeclistobject_codecentries_current['type'] = $this->ASFCodecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']);
     332                                                $thisfile_asf_codeclistobject_codecentries_current['type'] = self::codecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']);
    336333
    337334                                                $CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character
     
    827824
    828825                                                        case 'id3':
    829                                                                 // id3v2 module might not be loaded
    830                                                                 if (class_exists('getid3_id3v2')) {
    831                                                                         $tempfile         = tempnam(GETID3_TEMP_DIR, 'getID3');
    832                                                                         $tempfilehandle   = fopen($tempfile, 'wb');
    833                                                                         $tempThisfileInfo = array('encoding'=>$info['encoding']);
    834                                                                         fwrite($tempfilehandle, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
    835                                                                         fclose($tempfilehandle);
    836 
    837                                                                         $getid3_temp = new getID3();
    838                                                                         $getid3_temp->openfile($tempfile);
    839                                                                         $getid3_id3v2 = new getid3_id3v2($getid3_temp);
    840                                                                         $getid3_id3v2->Analyze();
    841                                                                         $info['id3v2'] = $getid3_temp->info['id3v2'];
    842                                                                         unset($getid3_temp, $getid3_id3v2);
    843 
    844                                                                         unlink($tempfile);
     826                                                                $this->getid3->include_module('tag.id3v2');
     827
     828                                                                $getid3_id3v2 = new getid3_id3v2($this->getid3);
     829                                                                $getid3_id3v2->AnalyzeString($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']);
     830                                                                unset($getid3_id3v2);
     831
     832                                                                if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] > 1024) {
     833                                                                        $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = '<value too large to display>';
    845834                                                                }
    846835                                                                break;
     
    861850                                                                $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 1));
    862851                                                                $wm_picture_offset += 1;
    863                                                                 $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type']    = $this->WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']);
     852                                                                $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type']    = self::WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']);
    864853                                                                $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_size']    = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 4));
    865854                                                                $wm_picture_offset += 4;
     
    11571146                }
    11581147
    1159                 while (ftell($this->getid3->fp) < $info['avdataend']) {
    1160                         $NextObjectDataHeader = fread($this->getid3->fp, 24);
     1148                while ($this->ftell() < $info['avdataend']) {
     1149                        $NextObjectDataHeader = $this->fread(24);
    11611150                        $offset = 0;
    11621151                        $NextObjectGUID = substr($NextObjectDataHeader, 0, 16);
     
    11801169                                        $thisfile_asf_dataobject     = &$thisfile_asf['data_object'];
    11811170
    1182                                         $DataObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 50 - 24);
     1171                                        $DataObjectData = $NextObjectDataHeader.$this->fread(50 - 24);
    11831172                                        $offset = 24;
    11841173
     
    12081197                                        // * Error Correction Data
    12091198
    1210                                         $info['avdataoffset'] = ftell($this->getid3->fp);
    1211                                         fseek($this->getid3->fp, ($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data
    1212                                         $info['avdataend'] = ftell($this->getid3->fp);
     1199                                        $info['avdataoffset'] = $this->ftell();
     1200                                        $this->fseek(($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data
     1201                                        $info['avdataend'] = $this->ftell();
    12131202                                        break;
    12141203
     
    12301219                                        $thisfile_asf_simpleindexobject      = &$thisfile_asf['simple_index_object'];
    12311220
    1232                                         $SimpleIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 56 - 24);
     1221                                        $SimpleIndexObjectData = $NextObjectDataHeader.$this->fread(56 - 24);
    12331222                                        $offset = 24;
    12341223
     
    12471236                                        $offset += 4;
    12481237
    1249                                         $IndexEntriesData = $SimpleIndexObjectData.fread($this->getid3->fp, 6 * $thisfile_asf_simpleindexobject['index_entries_count']);
     1238                                        $IndexEntriesData = $SimpleIndexObjectData.$this->fread(6 * $thisfile_asf_simpleindexobject['index_entries_count']);
    12501239                                        for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) {
    12511240                                                $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4));
     
    12841273                                        $thisfile_asf_asfindexobject      = &$thisfile_asf['asf_index_object'];
    12851274
    1286                                         $ASFIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 34 - 24);
     1275                                        $ASFIndexObjectData = $NextObjectDataHeader.$this->fread(34 - 24);
    12871276                                        $offset = 24;
    12881277
     
    12981287                                        $offset += 4;
    12991288
    1300                                         $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count']);
     1289                                        $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count']);
    13011290                                        for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
    13021291                                                $IndexSpecifierStreamNumber = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2));
     
    13081297                                        }
    13091298
    1310                                         $ASFIndexObjectData .= fread($this->getid3->fp, 4);
     1299                                        $ASFIndexObjectData .= $this->fread(4);
    13111300                                        $thisfile_asf_asfindexobject['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4));
    13121301                                        $offset += 4;
    13131302
    1314                                         $ASFIndexObjectData .= fread($this->getid3->fp, 8 * $thisfile_asf_asfindexobject['index_specifiers_count']);
     1303                                        $ASFIndexObjectData .= $this->fread(8 * $thisfile_asf_asfindexobject['index_specifiers_count']);
    13151304                                        for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
    13161305                                                $thisfile_asf_asfindexobject['block_positions'][$IndexSpecifiersCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8));
     
    13181307                                        }
    13191308
    1320                                         $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']);
     1309                                        $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']);
    13211310                                        for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) {
    13221311                                                for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) {
     
    13331322                                                $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8);
    13341323                                        } else {
    1335                                                 $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.(ftell($this->getid3->fp) - 16 - 8);
    1336                                         }
    1337                                         fseek($this->getid3->fp, ($NextObjectSize - 16 - 8), SEEK_CUR);
     1324                                                $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8);
     1325                                        }
     1326                                        $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
    13381327                                        break;
    13391328                        }
     
    14341423                }
    14351424                if (!empty($thisfile_video['streams'])) {
    1436                         $thisfile_video['streams']['resolution_x'] = 0;
    1437                         $thisfile_video['streams']['resolution_y'] = 0;
     1425                        $thisfile_video['resolution_x'] = 0;
     1426                        $thisfile_video['resolution_y'] = 0;
    14381427                        foreach ($thisfile_video['streams'] as $key => $valuearray) {
    1439                                 if (($valuearray['resolution_x'] > $thisfile_video['streams']['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['streams']['resolution_y'])) {
     1428                                if (($valuearray['resolution_x'] > $thisfile_video['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['resolution_y'])) {
    14401429                                        $thisfile_video['resolution_x'] = $valuearray['resolution_x'];
    14411430                                        $thisfile_video['resolution_y'] = $valuearray['resolution_y'];
     
    14521441        }
    14531442
    1454         public static function ASFCodecListObjectTypeLookup($CodecListType) {
    1455                 static $ASFCodecListObjectTypeLookup = array();
    1456                 if (empty($ASFCodecListObjectTypeLookup)) {
    1457                         $ASFCodecListObjectTypeLookup[0x0001] = 'Video Codec';
    1458                         $ASFCodecListObjectTypeLookup[0x0002] = 'Audio Codec';
    1459                         $ASFCodecListObjectTypeLookup[0xFFFF] = 'Unknown Codec';
    1460                 }
    1461 
    1462                 return (isset($ASFCodecListObjectTypeLookup[$CodecListType]) ? $ASFCodecListObjectTypeLookup[$CodecListType] : 'Invalid Codec Type');
     1443        public static function codecListObjectTypeLookup($CodecListType) {
     1444                static $lookup = array(
     1445                        0x0001 => 'Video Codec',
     1446                        0x0002 => 'Audio Codec',
     1447                        0xFFFF => 'Unknown Codec'
     1448                );
     1449
     1450                return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
    14631451        }
    14641452
     
    16671655
    16681656        public static function WMpictureTypeLookup($WMpictureType) {
    1669                 static $WMpictureTypeLookup = array();
    1670                 if (empty($WMpictureTypeLookup)) {
    1671                         $WMpictureTypeLookup[0x03] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Front Cover');
    1672                         $WMpictureTypeLookup[0x04] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Back Cover');
    1673                         $WMpictureTypeLookup[0x00] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'User Defined');
    1674                         $WMpictureTypeLookup[0x05] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Leaflet Page');
    1675                         $WMpictureTypeLookup[0x06] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Media Label');
    1676                         $WMpictureTypeLookup[0x07] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lead Artist');
    1677                         $WMpictureTypeLookup[0x08] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Artist');
    1678                         $WMpictureTypeLookup[0x09] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Conductor');
    1679                         $WMpictureTypeLookup[0x0A] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band');
    1680                         $WMpictureTypeLookup[0x0B] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Composer');
    1681                         $WMpictureTypeLookup[0x0C] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lyricist');
    1682                         $WMpictureTypeLookup[0x0D] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Recording Location');
    1683                         $WMpictureTypeLookup[0x0E] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Recording');
    1684                         $WMpictureTypeLookup[0x0F] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Performance');
    1685                         $WMpictureTypeLookup[0x10] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Video Screen Capture');
    1686                         $WMpictureTypeLookup[0x12] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Illustration');
    1687                         $WMpictureTypeLookup[0x13] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band Logotype');
    1688                         $WMpictureTypeLookup[0x14] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Publisher Logotype');
     1657                static $lookup = null;
     1658                if ($lookup === null) {
     1659                        $lookup = array(
     1660                                0x03 => 'Front Cover',
     1661                                0x04 => 'Back Cover',
     1662                                0x00 => 'User Defined',
     1663                                0x05 => 'Leaflet Page',
     1664                                0x06 => 'Media Label',
     1665                                0x07 => 'Lead Artist',
     1666                                0x08 => 'Artist',
     1667                                0x09 => 'Conductor',
     1668                                0x0A => 'Band',
     1669                                0x0B => 'Composer',
     1670                                0x0C => 'Lyricist',
     1671                                0x0D => 'Recording Location',
     1672                                0x0E => 'During Recording',
     1673                                0x0F => 'During Performance',
     1674                                0x10 => 'Video Screen Capture',
     1675                                0x12 => 'Illustration',
     1676                                0x13 => 'Band Logotype',
     1677                                0x14 => 'Publisher Logotype'
     1678                        );
     1679                        $lookup = array_map(function($str) {
     1680                                return getid3_lib::iconv_fallback('UTF-8', 'UTF-16LE', $str);
     1681                        }, $lookup);
    16891682                }
    1690                 return (isset($WMpictureTypeLookup[$WMpictureType]) ? $WMpictureTypeLookup[$WMpictureType] : '');
     1683
     1684                return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
    16911685        }
    16921686
    1693         public function ASF_HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
     1687        public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
    16941688                // http://msdn.microsoft.com/en-us/library/bb643323.aspx
    16951689
     
    18261820                                                $descriptionRecord['data_type']          = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
    18271821                                                $offset += 2;
    1828                                                 $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
     1822                                                $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
    18291823
    18301824                                                $descriptionRecord['data_length']        = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
     
    18981892                                                $descriptionRecord['data_type']           = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  2));
    18991893                                                $offset += 2;
    1900                                                 $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
     1894                                                $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']);
    19011895
    19021896                                                $descriptionRecord['data_length']         = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset,  4));
     
    19381932
    19391933
    1940         public static function ASFmetadataLibraryObjectDataTypeLookup($id) {
    1941                 static $ASFmetadataLibraryObjectDataTypeLookup = array(
     1934        public static function metadataLibraryObjectDataTypeLookup($id) {
     1935                static $lookup = array(
    19421936                        0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
    19431937                        0x0001 => 'BYTE array',     // The type of the data is implementation-specific
     
    19481942                        0x0006 => 'GUID',           // The data is 16 bytes long and should be interpreted as a 128-bit GUID
    19491943                );
    1950                 return (isset($ASFmetadataLibraryObjectDataTypeLookup[$id]) ? $ASFmetadataLibraryObjectDataTypeLookup[$id] : 'invalid');
     1944                return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
    19511945        }
    19521946
     
    19651959                $WMpicture['image_type_id'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 1));
    19661960                $offset += 1;
    1967                 $WMpicture['image_type']    = $this->WMpictureTypeLookup($WMpicture['image_type_id']);
     1961                $WMpicture['image_type']    = self::WMpictureTypeLookup($WMpicture['image_type_id']);
    19681962                $WMpicture['image_size']    = getid3_lib::LittleEndian2Int(substr($data, $offset, 4));
    19691963                $offset += 4;
  • _plugins_/getID3/trunk/getid3/module.audio-video.bink.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    2324$info['error'][] = 'Bink / Smacker files not properly processed by this version of getID3() ['.$this->getid3->version().']';
    2425
    25                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
    26                 $fileTypeID = fread($this->getid3->fp, 3);
     26                $this->fseek($info['avdataoffset']);
     27                $fileTypeID = $this->fread(3);
    2728                switch ($fileTypeID) {
    2829                        case 'BIK':
     
    4950                $info['video']['dataformat'] = 'bink';
    5051
    51                 $fileData = 'BIK'.fread($this->getid3->fp, 13);
     52                $fileData = 'BIK'.$this->fread(13);
    5253
    5354                $info['bink']['data_size']   = getid3_lib::LittleEndian2Int(substr($fileData, 4, 4));
  • _plugins_/getID3/trunk/getid3/module.audio-video.flv.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67//                                                             //
    78//  FLV module by Seth Kaufman <sethØwhirl-i-gig*com>          //
     
    3839//  * version 0.6.1 (30 May 2011)                              //
    3940//    prevent infinite loops in expGolombUe()                  //
     41//                                                             //
     42//  * version 0.7.0 (16 Jul 2013)                              //
     43//  handle GETID3_FLV_VIDEO_VP6FLV_ALPHA                       //
     44//  improved AVCSequenceParameterSetReader::readData()         //
     45//    by Xander Schouwerwou <schouwerwouØgmail*com>            //
    4046//                                                             //
    4147/////////////////////////////////////////////////////////////////
     
    6874define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
    6975
    70 class getid3_flv extends getid3_handler
    71 {
     76class getid3_flv extends getid3_handler {
     77
     78        const magic = 'FLV';
     79
    7280        public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration
    7381
     
    7583                $info = &$this->getid3->info;
    7684
    77                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
     85                $this->fseek($info['avdataoffset']);
    7886
    7987                $FLVdataLength = $info['avdataend'] - $info['avdataoffset'];
    80                 $FLVheader = fread($this->getid3->fp, 5);
     88                $FLVheader = $this->fread(5);
    8189
    8290                $info['fileformat'] = 'flv';
     
    8593                $TypeFlags                          = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
    8694
    87                 $magic = 'FLV';
    88                 if ($info['flv']['header']['signature'] != $magic) {
    89                         $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"';
    90                         unset($info['flv']);
    91                         unset($info['fileformat']);
     95                if ($info['flv']['header']['signature'] != self::magic) {
     96                        $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"';
     97                        unset($info['flv'], $info['fileformat']);
    9298                        return false;
    9399                }
     
    96102                $info['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 0x01);
    97103
    98                 $FrameSizeDataLength = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 4));
     104                $FrameSizeDataLength = getid3_lib::BigEndian2Int($this->fread(4));
    99105                $FLVheaderFrameLength = 9;
    100106                if ($FrameSizeDataLength > $FLVheaderFrameLength) {
    101                         fseek($this->getid3->fp, $FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR);
     107                        $this->fseek($FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR);
    102108                }
    103109                $Duration = 0;
     
    109115                $info['flv']['framecount'] = array('total'=>0, 'audio'=>0, 'video'=>0);
    110116                $flv_framecount = &$info['flv']['framecount'];
    111                 while (((ftell($this->getid3->fp) + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime))  {
    112                         $ThisTagHeader = fread($this->getid3->fp, 16);
     117                while ((($this->ftell() + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime))  {
     118                        $ThisTagHeader = $this->fread(16);
    113119
    114120                        $PreviousTagLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  0, 4));
     
    117123                        $Timestamp         = getid3_lib::BigEndian2Int(substr($ThisTagHeader,  8, 3));
    118124                        $LastHeaderByte    = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 15, 1));
    119                         $NextOffset = ftell($this->getid3->fp) - 1 + $DataLength;
     125                        $NextOffset = $this->ftell() - 1 + $DataLength;
    120126                        if ($Timestamp > $Duration) {
    121127                                $Duration = $Timestamp;
     
    141147                                                $info['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07;
    142148
    143                                                 $FLVvideoHeader = fread($this->getid3->fp, 11);
     149                                                $FLVvideoHeader = $this->fread(11);
    144150
    145151                                                if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) {
     
    161167                                                                        $spsSize = getid3_lib::LittleEndian2Int(substr($FLVvideoHeader, 9, 2));
    162168                                                                        //      read the first SequenceParameterSet
    163                                                                         $sps = fread($this->getid3->fp, $spsSize);
     169                                                                        $sps = $this->fread($spsSize);
    164170                                                                        if (strlen($sps) == $spsSize) { //      make sure that whole SequenceParameterSet was red
    165171                                                                                $spsReader = new AVCSequenceParameterSetReader($sps);
     
    186192                                                                        //$info['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8;
    187193
    188                                                                         $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2));
    189                                                                         $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2));
    190                                                                         $PictureSizeEnc['x'] >>= 7;
    191                                                                         $PictureSizeEnc['y'] >>= 7;
     194                                                                        $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2)) >> 7;
     195                                                                        $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)) >> 7;
    192196                                                                        $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFF;
    193197                                                                        $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFF;
     
    195199
    196200                                                                case 1:
    197                                                                         $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3));
    198                                                                         $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3));
    199                                                                         $PictureSizeEnc['x'] >>= 7;
    200                                                                         $PictureSizeEnc['y'] >>= 7;
     201                                                                        $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3)) >> 7;
     202                                                                        $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3)) >> 7;
    201203                                                                        $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFFFF;
    202204                                                                        $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFFFF;
     
    234236
    235237                                                        }
     238
     239                                                } elseif ($info['flv']['video']['videoCodec'] ==  GETID3_FLV_VIDEO_VP6FLV_ALPHA) {
     240
     241                                                        /* contributed by schouwerwouØgmail*com */
     242                                                        if (!isset($info['video']['resolution_x'])) { // only when meta data isn't set
     243                                                                $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 2));
     244                                                                $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 7, 2));
     245                                                                $info['video']['resolution_x'] = ($PictureSizeEnc['x'] & 0xFF) << 3;
     246                                                                $info['video']['resolution_y'] = ($PictureSizeEnc['y'] & 0xFF) << 3;
     247                                                        }
     248                                                        /* end schouwerwouØgmail*com */
     249
    236250                                                }
    237                                                 $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y'];
     251                                                if (!empty($info['video']['resolution_x']) && !empty($info['video']['resolution_y'])) {
     252                                                        $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y'];
     253                                                }
    238254                                        }
    239255                                        break;
     
    243259                                        if (!$found_meta) {
    244260                                                $found_meta = true;
    245                                                 fseek($this->getid3->fp, -1, SEEK_CUR);
    246                                                 $datachunk = fread($this->getid3->fp, $DataLength);
     261                                                $this->fseek(-1, SEEK_CUR);
     262                                                $datachunk = $this->fread($DataLength);
    247263                                                $AMFstream = new AMFStream($datachunk);
    248264                                                $reader = new AMFReader($AMFstream);
     
    280296                                        break;
    281297                        }
    282                         fseek($this->getid3->fp, $NextOffset, SEEK_SET);
     298                        $this->fseek($NextOffset);
    283299                }
    284300
     
    289305
    290306                if ($info['flv']['header']['hasAudio']) {
    291                         $info['audio']['codec']           =   $this->FLVaudioFormat($info['flv']['audio']['audioFormat']);
    292                         $info['audio']['sample_rate']     =     $this->FLVaudioRate($info['flv']['audio']['audioRate']);
    293                         $info['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($info['flv']['audio']['audioSampleSize']);
     307                        $info['audio']['codec']           =   self::audioFormatLookup($info['flv']['audio']['audioFormat']);
     308                        $info['audio']['sample_rate']     =     self::audioRateLookup($info['flv']['audio']['audioRate']);
     309                        $info['audio']['bits_per_sample'] = self::audioBitDepthLookup($info['flv']['audio']['audioSampleSize']);
    294310
    295311                        $info['audio']['channels']   =  $info['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo
     
    298314                }
    299315                if (!empty($info['flv']['header']['hasVideo'])) {
    300                         $info['video']['codec']      = $this->FLVvideoCodec($info['flv']['video']['videoCodec']);
     316                        $info['video']['codec']      = self::videoCodecLookup($info['flv']['video']['videoCodec']);
    301317                        $info['video']['dataformat'] = 'flv';
    302318                        $info['video']['lossless']   = false;
     
    309325                }
    310326                if (isset($info['flv']['meta']['onMetaData']['audiocodecid'])) {
    311                         $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['meta']['onMetaData']['audiocodecid']);
     327                        $info['audio']['codec'] = self::audioFormatLookup($info['flv']['meta']['onMetaData']['audiocodecid']);
    312328                }
    313329                if (isset($info['flv']['meta']['onMetaData']['videocodecid'])) {
    314                         $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['meta']['onMetaData']['videocodecid']);
     330                        $info['video']['codec'] = self::videoCodecLookup($info['flv']['meta']['onMetaData']['videocodecid']);
    315331                }
    316332                return true;
     
    318334
    319335
    320         public function FLVaudioFormat($id) {
    321                 $FLVaudioFormat = array(
     336        public static function audioFormatLookup($id) {
     337                static $lookup = array(
    322338                        0  => 'Linear PCM, platform endian',
    323339                        1  => 'ADPCM',
     
    331347                        9  => 'reserved',
    332348                        10 => 'AAC',
    333                         11 => false, // unknown?
     349                        11 => 'Speex',
    334350                        12 => false, // unknown?
    335351                        13 => false, // unknown?
     
    337353                        15 => 'Device-specific sound',
    338354                );
    339                 return (isset($FLVaudioFormat[$id]) ? $FLVaudioFormat[$id] : false);
    340         }
    341 
    342         public function FLVaudioRate($id) {
    343                 $FLVaudioRate = array(
     355                return (isset($lookup[$id]) ? $lookup[$id] : false);
     356        }
     357
     358        public static function audioRateLookup($id) {
     359                static $lookup = array(
    344360                        0 =>  5500,
    345361                        1 => 11025,
     
    347363                        3 => 44100,
    348364                );
    349                 return (isset($FLVaudioRate[$id]) ? $FLVaudioRate[$id] : false);
    350         }
    351 
    352         public function FLVaudioBitDepth($id) {
    353                 $FLVaudioBitDepth = array(
     365                return (isset($lookup[$id]) ? $lookup[$id] : false);
     366        }
     367
     368        public static function audioBitDepthLookup($id) {
     369                static $lookup = array(
    354370                        0 =>  8,
    355371                        1 => 16,
    356372                );
    357                 return (isset($FLVaudioBitDepth[$id]) ? $FLVaudioBitDepth[$id] : false);
    358         }
    359 
    360         public function FLVvideoCodec($id) {
    361                 $FLVvideoCodec = array(
     373                return (isset($lookup[$id]) ? $lookup[$id] : false);
     374        }
     375
     376        public static function videoCodecLookup($id) {
     377                static $lookup = array(
    362378                        GETID3_FLV_VIDEO_H263         => 'Sorenson H.263',
    363379                        GETID3_FLV_VIDEO_SCREEN       => 'Screen video',
     
    367383                        GETID3_FLV_VIDEO_H264         => 'Sorenson H.264',
    368384                );
    369                 return (isset($FLVvideoCodec[$id]) ? $FLVvideoCodec[$id] : false);
     385                return (isset($lookup[$id]) ? $lookup[$id] : false);
    370386        }
    371387}
     
    375391        public $pos;
    376392
    377         public function AMFStream(&$bytes) {
     393        public function __construct(&$bytes) {
    378394                $this->bytes =& $bytes;
    379395                $this->pos = 0;
     
    458474        public $stream;
    459475
    460         public function AMFReader(&$stream) {
     476        public function __construct(&$stream) {
    461477                $this->stream =& $stream;
    462478        }
     
    526542                        default:
    527543                                $value = '(unknown or unsupported data type)';
    528                         break;
     544                                break;
    529545                }
    530546
     
    620636        public $height;
    621637
    622         public function AVCSequenceParameterSetReader($sps) {
     638        public function __construct($sps) {
    623639                $this->sps = $sps;
    624640        }
     
    627643                $this->skipBits(8);
    628644                $this->skipBits(8);
    629                 $profile = $this->getBits(8);   //      read profile
    630                 $this->skipBits(16);
    631                 $this->expGolombUe();   //      read sps id
    632                 if (in_array($profile, array(H264_PROFILE_HIGH, H264_PROFILE_HIGH10, H264_PROFILE_HIGH422, H264_PROFILE_HIGH444, H264_PROFILE_HIGH444_PREDICTIVE))) {
    633                         if ($this->expGolombUe() == 3) {
    634                                 $this->skipBits(1);
    635                         }
    636                         $this->expGolombUe();
    637                         $this->expGolombUe();
    638                         $this->skipBits(1);
    639                         if ($this->getBit()) {
    640                                 for ($i = 0; $i < 8; $i++) {
    641                                         if ($this->getBit()) {
    642                                                 $size = $i < 6 ? 16 : 64;
    643                                                 $lastScale = 8;
    644                                                 $nextScale = 8;
    645                                                 for ($j = 0; $j < $size; $j++) {
    646                                                         if ($nextScale != 0) {
    647                                                                 $deltaScale = $this->expGolombUe();
    648                                                                 $nextScale = ($lastScale + $deltaScale + 256) % 256;
    649                                                         }
    650                                                         if ($nextScale != 0) {
    651                                                                 $lastScale = $nextScale;
    652                                                         }
    653                                                 }
    654                                         }
     645                $profile = $this->getBits(8);                               // read profile
     646                if ($profile > 0) {
     647                        $this->skipBits(8);
     648                        $level_idc = $this->getBits(8);                         // level_idc
     649                        $this->expGolombUe();                                   // seq_parameter_set_id // sps
     650                        $this->expGolombUe();                                   // log2_max_frame_num_minus4
     651                        $picOrderType = $this->expGolombUe();                   // pic_order_cnt_type
     652                        if ($picOrderType == 0) {
     653                                $this->expGolombUe();                               // log2_max_pic_order_cnt_lsb_minus4
     654                        } elseif ($picOrderType == 1) {
     655                                $this->skipBits(1);                                 // delta_pic_order_always_zero_flag
     656                                $this->expGolombSe();                               // offset_for_non_ref_pic
     657                                $this->expGolombSe();                               // offset_for_top_to_bottom_field
     658                                $num_ref_frames_in_pic_order_cnt_cycle = $this->expGolombUe(); // num_ref_frames_in_pic_order_cnt_cycle
     659                                for ($i = 0; $i < $num_ref_frames_in_pic_order_cnt_cycle; $i++) {
     660                                        $this->expGolombSe();                           // offset_for_ref_frame[ i ]
    655661                                }
    656662                        }
    657                 }
    658                 $this->expGolombUe();
    659                 $pocType = $this->expGolombUe();
    660                 if ($pocType == 0) {
    661                         $this->expGolombUe();
    662                 } elseif ($pocType == 1) {
    663                         $this->skipBits(1);
    664                         $this->expGolombSe();
    665                         $this->expGolombSe();
    666                         $pocCycleLength = $this->expGolombUe();
    667                         for ($i = 0; $i < $pocCycleLength; $i++) {
    668                                 $this->expGolombSe();
     663                        $this->expGolombUe();                                   // num_ref_frames
     664                        $this->skipBits(1);                                     // gaps_in_frame_num_value_allowed_flag
     665                        $pic_width_in_mbs_minus1 = $this->expGolombUe();        // pic_width_in_mbs_minus1
     666                        $pic_height_in_map_units_minus1 = $this->expGolombUe(); // pic_height_in_map_units_minus1
     667
     668                        $frame_mbs_only_flag = $this->getBits(1);               // frame_mbs_only_flag
     669                        if ($frame_mbs_only_flag == 0) {
     670                                $this->skipBits(1);                                 // mb_adaptive_frame_field_flag
    669671                        }
    670                 }
    671                 $this->expGolombUe();
    672                 $this->skipBits(1);
    673                 $this->width = ($this->expGolombUe() + 1) * 16;
    674                 $heightMap = $this->expGolombUe() + 1;
    675                 $this->height = (2 - $this->getBit()) * $heightMap * 16;
     672                        $this->skipBits(1);                                     // direct_8x8_inference_flag
     673                        $frame_cropping_flag = $this->getBits(1);               // frame_cropping_flag
     674
     675                        $frame_crop_left_offset   = 0;
     676                        $frame_crop_right_offset  = 0;
     677                        $frame_crop_top_offset    = 0;
     678                        $frame_crop_bottom_offset = 0;
     679
     680                        if ($frame_cropping_flag) {
     681                                $frame_crop_left_offset   = $this->expGolombUe();   // frame_crop_left_offset
     682                                $frame_crop_right_offset  = $this->expGolombUe();   // frame_crop_right_offset
     683                                $frame_crop_top_offset    = $this->expGolombUe();   // frame_crop_top_offset
     684                                $frame_crop_bottom_offset = $this->expGolombUe();   // frame_crop_bottom_offset
     685                        }
     686                        $this->skipBits(1);                                     // vui_parameters_present_flag
     687                        // etc
     688
     689                        $this->width  = (($pic_width_in_mbs_minus1 + 1) * 16) - ($frame_crop_left_offset * 2) - ($frame_crop_right_offset * 2);
     690                        $this->height = ((2 - $frame_mbs_only_flag) * ($pic_height_in_map_units_minus1 + 1) * 16) - ($frame_crop_top_offset * 2) - ($frame_crop_bottom_offset * 2);
     691                }
    676692        }
    677693
  • _plugins_/getID3/trunk/getid3/module.audio-video.matroska.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    217218        // public options
    218219        public static $hide_clusters    = true;  // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE]
    219     public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
    220 
    221     // private parser settings/placeholders
    222     private $EBMLbuffer        = '';
    223     private $EBMLbuffer_offset = 0;
    224     private $EBMLbuffer_length = 0;
    225     private $current_offset    = 0;
    226     private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
     220        public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
     221
     222        // private parser settings/placeholders
     223        private $EBMLbuffer        = '';
     224        private $EBMLbuffer_offset = 0;
     225        private $EBMLbuffer_length = 0;
     226        private $current_offset    = 0;
     227        private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
    227228
    228229        public function Analyze()
     
    282283                                                switch ($trackarray['CodecID']) {
    283284                                                        case 'V_MS/VFW/FOURCC':
    284                                                                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
    285                                                                         $this->warning('Unable to parse codec private data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"');
    286                                                                         break;
    287                                                                 }
     285                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
     286
    288287                                                                $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']);
    289288                                                                $track_info['codec'] = getid3_riff::fourccLookup($parsed['fourcc']);
     
    336335                                                        case 'A_MPEG/L2':
    337336                                                        case 'A_FLAC':
    338                                                                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, false)) {
    339                                                                         $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.'.$track_info['dataformat'].'.php"');
    340                                                                         break;
    341                                                                 }
     337                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true);
    342338
    343339                                                                if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
     
    386382                                                                if (!empty($getid3_temp->info['warning'])) {
    387383                                                                        foreach ($getid3_temp->info['warning'] as $newerror) {
    388                                                                                 if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \d+ bytes of audio data, only found \d+ \(short by \d+ bytes\)$/', $newerror)) {
    389                                                                                         // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning
    390                                                                                         continue;
    391                                                                                 }
    392384                                                                                $this->warning($class.'() says: ['.$newerror.']');
    393385                                                                        }
     
    401393                                                        case 'A_AAC/MPEG4/LC':
    402394                                                        case 'A_AAC/MPEG4/LC/SBR':
    403                                                             $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated');
     395                                                                $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated');
    404396                                                                break;
    405397
     
    416408                                                                $vorbis_offset -= 1;
    417409
    418                                                                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, false)) {
    419                                                                         $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.ogg.php"');
    420                                                                         break;
    421                                                                 }
     410                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true);
    422411
    423412                                                                // create temp instance
     
    456445
    457446                                                        case 'A_MS/ACM':
    458                                                                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
    459                                                                         $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"');
    460                                                                         break;
    461                                                                 }
     447                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
    462448
    463449                                                                $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
     
    472458                                                        default:
    473459                                                                $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
     460                                                                break;
    474461                                                }
    475462
     
    496483                }
    497484
    498         // determine mime type
     485                // determine mime type
    499486                if (!empty($info['video']['streams'])) {
    500487                        $info['mime_type'] = ($info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska');
     
    508495        }
    509496
    510     private function parseEBML(&$info) {
     497        private function parseEBML(&$info) {
    511498                // http://www.matroska.org/technical/specs/index.html#EBMLBasics
    512499                $this->current_offset = $info['avdataoffset'];
     
    516503
    517504                                case EBML_ID_EBML:
    518                                         $info['fileformat'] = 'matroska';
    519505                                        $info['matroska']['header']['offset'] = $top_element['offset'];
    520506                                        $info['matroska']['header']['length'] = $top_element['length'];
     
    535521                                                                $element_data['data'] = getid3_lib::trimNullByte($element_data['data']);
    536522                                                                $info['matroska']['doctype'] = $element_data['data'];
    537                                                                 break;
    538 
    539                                                         case EBML_ID_CRC32: // not useful, ignore
    540                                                                 $this->current_offset = $element_data['end'];
    541                                                                 unset($element_data);
     523                                                                $info['fileformat'] = $element_data['data'];
    542524                                                                break;
    543525
    544526                                                        default:
    545527                                                                $this->unhandledElement('header', __LINE__, $element_data);
     528                                                                break;
    546529                                                }
    547                                                 if (!empty($element_data)) {
    548                                                         unset($element_data['offset'], $element_data['end']);
    549                                                         $info['matroska']['header']['elements'][] = $element_data;
    550                                                 }
     530
     531                                                unset($element_data['offset'], $element_data['end']);
     532                                                $info['matroska']['header']['elements'][] = $element_data;
    551533                                        }
    552534                                        break;
     
    583565                                                                                                        default:
    584566                                                                                                                $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry);                                                                                            }
     567                                                                                                                break;
    585568                                                                                        }
    586569
     
    592575                                                                                default:
    593576                                                                                        $this->unhandledElement('seekhead', __LINE__, $seek_entry);
     577                                                                                        break;
    594578                                                                        }
    595579                                                                }
     
    674658                                                                                                                                default:
    675659                                                                                                                                        $this->unhandledElement('track.video', __LINE__, $sub_subelement);
     660                                                                                                                                        break;
    676661                                                                                                                        }
    677662                                                                                                                }
     
    699684                                                                                                                                default:
    700685                                                                                                                                        $this->unhandledElement('track.audio', __LINE__, $sub_subelement);
     686                                                                                                                                        break;
    701687                                                                                                                        }
    702688                                                                                                                }
     
    734720                                                                                                                                                                                default:
    735721                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     722                                                                                                                                                                                        break;
    736723                                                                                                                                                                        }
    737724                                                                                                                                                                }
     
    757744                                                                                                                                                                                default:
    758745                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     746                                                                                                                                                                                        break;
    759747                                                                                                                                                                        }
    760748                                                                                                                                                                }
     
    763751                                                                                                                                                        default:
    764752                                                                                                                                                                $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
     753                                                                                                                                                                break;
    765754                                                                                                                                                }
    766755                                                                                                                                        }
     
    769758                                                                                                                                default:
    770759                                                                                                                                        $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
     760                                                                                                                                        break;
    771761                                                                                                                        }
    772762                                                                                                                }
     
    775765                                                                                                        default:
    776766                                                                                                                $this->unhandledElement('track', __LINE__, $subelement);
     767                                                                                                                break;
    777768                                                                                                }
    778769                                                                                        }
     
    783774                                                                                default:
    784775                                                                                        $this->unhandledElement('tracks', __LINE__, $track_entry);
     776                                                                                        break;
    785777                                                                        }
    786778                                                                }
     
    846838                                                                                                        default:
    847839                                                                                                                $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
     840                                                                                                                break;
    848841                                                                                                }
    849842                                                                                        }
     
    853846                                                                                default:
    854847                                                                                        $this->unhandledElement('info', __LINE__, $subelement);
     848                                                                                        break;
    855849                                                                        }
    856850                                                                }
     
    875869
    876870                                                                                                        case EBML_ID_CUETRACKPOSITIONS:
    877                                                         $cuetrackpositions_entry = array();
     871                                                                                                                $cuetrackpositions_entry = array();
    878872
    879873                                                                                                                while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], true)) {
     
    889883                                                                                                                                default:
    890884                                                                                                                                        $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
     885                                                                                                                                        break;
    891886                                                                                                                        }
    892887                                                                                                                }
     
    900895                                                                                                        default:
    901896                                                                                                                $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
     897                                                                                                                break;
    902898                                                                                                }
    903899                                                                                        }
     
    907903                                                                                default:
    908904                                                                                        $this->unhandledElement('cues', __LINE__, $subelement);
     905                                                                                        break;
    909906                                                                        }
    910907                                                                }
     
    913910
    914911                                                        case EBML_ID_TAGS: // Element containing elements specific to Tracks/Chapters.
    915                                 $tags_entry = array();
     912                                                                $tags_entry = array();
    916913
    917914                                                                while ($this->getEBMLelement($subelement, $element_data['end'], false)) {
     
    948945                                                                                                                                default:
    949946                                                                                                                                        $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
     947                                                                                                                                        break;
    950948                                                                                                                        }
    951949                                                                                                                }
     
    959957                                                                                                        default:
    960958                                                                                                                $this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
     959                                                                                                                break;
    961960                                                                                                }
    962961                                                                                        }
     
    966965                                                                                default:
    967966                                                                                        $this->unhandledElement('tags', __LINE__, $subelement);
     967                                                                                        break;
    968968                                                                        }
    969969                                                                }
     
    10061006                                                                                                        default:
    10071007                                                                                                                $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
     1008                                                                                                                break;
    10081009                                                                                                }
    10091010                                                                                        }
     
    10131014                                                                                default:
    10141015                                                                                        $this->unhandledElement('attachments', __LINE__, $subelement);
     1016                                                                                        break;
    10151017                                                                        }
    10161018                                                                }
     
    10721074                                                                                                                                                        default:
    10731075                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
     1076                                                                                                                                                                break;
    10741077                                                                                                                                                }
    10751078                                                                                                                                        }
     
    10911094                                                                                                                                                        default:
    10921095                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
     1096                                                                                                                                                                break;
    10931097                                                                                                                                                }
    10941098                                                                                                                                        }
     
    10981102                                                                                                                                default:
    10991103                                                                                                                                        $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
     1104                                                                                                                                        break;
    11001105                                                                                                                        }
    11011106                                                                                                                }
     
    11051110                                                                                                        default:
    11061111                                                                                                                $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
     1112                                                                                                                break;
    11071113                                                                                                }
    11081114                                                                                        }
     
    11121118                                                                                default:
    11131119                                                                                        $this->unhandledElement('chapters', __LINE__, $subelement);
     1120                                                                                        break;
    11141121                                                                        }
    11151122                                                                }
     
    11401147                                                                                                        default:
    11411148                                                                                                                $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
     1149                                                                                                                break;
    11421150                                                                                                }
    11431151                                                                                        }
     
    11701178                                                                                                        default:
    11711179                                                                                                                $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
     1180                                                                                                                break;
    11721181                                                                                                }
    11731182                                                                                        }
     
    11811190                                                                                default:
    11821191                                                                                        $this->unhandledElement('cluster', __LINE__, $subelement);
     1192                                                                                        break;
    11831193                                                                        }
    11841194                                                                        $this->current_offset = $subelement['end'];
     
    12021212                                                        default:
    12031213                                                                $this->unhandledElement('segment', __LINE__, $element_data);
     1214                                                                break;
    12041215                                                }
    12051216                                        }
     
    12081219                                default:
    12091220                                        $this->unhandledElement('root', __LINE__, $top_element);
     1221                                        break;
    12101222                        }
    12111223                }
    1212     }
     1224        }
    12131225
    12141226        private function EnsureBufferHasEnoughData($min_data=1024) {
     
    13601372                                default:
    13611373                                        $this->unhandledElement('tag.simpletag', __LINE__, $element);
     1374                                        break;
    13621375                        }
    13631376                }
     
    13921405                $block_data['flags']['lacing_type'] = self::BlockLacingType($block_data['flags']['lacing']);
    13931406
    1394         // Lace (when lacing bit is set)
     1407                // Lace (when lacing bit is set)
    13951408                if ($block_data['flags']['lacing'] > 0) {
    13961409                        $block_data['lace_frames'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(1)) + 1; // Number of frames in the lace-1 (uint8)
     
    15331546                        $CodecIDlist['V_MPEG4/ISO/SP']   = 'mpeg4';
    15341547                        $CodecIDlist['V_VP8']            = 'vp8';
    1535                         $CodecIDlist['V_MS/VFW/FOURCC']  = 'riff';
    1536                         $CodecIDlist['A_MS/ACM']         = 'riff';
     1548                        $CodecIDlist['V_MS/VFW/FOURCC']  = 'vcm'; // Microsoft (TM) Video Codec Manager (VCM)
     1549                        $CodecIDlist['A_MS/ACM']         = 'acm'; // Microsoft (TM) Audio Codec Manager (ACM)
    15371550                }
    15381551                return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
  • _plugins_/getID3/trunk/getid3/module.audio-video.mpeg.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    1617getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
    1718
    18 define('GETID3_MPEG_VIDEO_PICTURE_START',   "\x00\x00\x01\x00");
    19 define('GETID3_MPEG_VIDEO_USER_DATA_START', "\x00\x00\x01\xB2");
    20 define('GETID3_MPEG_VIDEO_SEQUENCE_HEADER', "\x00\x00\x01\xB3");
    21 define('GETID3_MPEG_VIDEO_SEQUENCE_ERROR',  "\x00\x00\x01\xB4");
    22 define('GETID3_MPEG_VIDEO_EXTENSION_START', "\x00\x00\x01\xB5");
    23 define('GETID3_MPEG_VIDEO_SEQUENCE_END',    "\x00\x00\x01\xB7");
    24 define('GETID3_MPEG_VIDEO_GROUP_START',     "\x00\x00\x01\xB8");
    25 define('GETID3_MPEG_AUDIO_START',           "\x00\x00\x01\xC0");
    26 
    27 
    28 class getid3_mpeg extends getid3_handler
    29 {
     19class getid3_mpeg extends getid3_handler {
     20
     21        const START_CODE_BASE       = "\x00\x00\x01";
     22        const VIDEO_PICTURE_START   = "\x00\x00\x01\x00";
     23        const VIDEO_USER_DATA_START = "\x00\x00\x01\xB2";
     24        const VIDEO_SEQUENCE_HEADER = "\x00\x00\x01\xB3";
     25        const VIDEO_SEQUENCE_ERROR  = "\x00\x00\x01\xB4";
     26        const VIDEO_EXTENSION_START = "\x00\x00\x01\xB5";
     27        const VIDEO_SEQUENCE_END    = "\x00\x00\x01\xB7";
     28        const VIDEO_GROUP_START     = "\x00\x00\x01\xB8";
     29        const AUDIO_START           = "\x00\x00\x01\xC0";
     30
    3031
    3132        public function Analyze() {
    3233                $info = &$this->getid3->info;
    3334
    34                 if ($info['avdataend'] <= $info['avdataoffset']) {
    35                         $info['error'][] = '"avdataend" ('.$info['avdataend'].') is unexpectedly less-than-or-equal-to "avdataoffset" ('.$info['avdataoffset'].')';
    36                         return false;
    37                 }
    3835                $info['fileformat'] = 'mpeg';
    39                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
    40                 $MPEGstreamData       = fread($this->getid3->fp, min(100000, $info['avdataend'] - $info['avdataoffset']));
    41                 $MPEGstreamDataLength = strlen($MPEGstreamData);
    42 
    43                 $foundVideo = true;
    44                 $VideoChunkOffset = 0;
    45                 while (substr($MPEGstreamData, $VideoChunkOffset++, 4) !== GETID3_MPEG_VIDEO_SEQUENCE_HEADER) {
    46                         if ($VideoChunkOffset >= $MPEGstreamDataLength) {
    47                                 $foundVideo = false;
    48                                 break;
    49                         }
    50                 }
    51                 if ($foundVideo) {
    52 
    53                         // Start code                       32 bits
    54                         // horizontal frame size            12 bits
    55                         // vertical frame size              12 bits
    56                         // pixel aspect ratio                4 bits
    57                         // frame rate                        4 bits
    58                         // bitrate                          18 bits
    59                         // marker bit                        1 bit
    60                         // VBV buffer size                  10 bits
    61                         // constrained parameter flag        1 bit
    62                         // intra quant. matrix flag          1 bit
    63                         // intra quant. matrix values      512 bits (present if matrix flag == 1)
    64                         // non-intra quant. matrix flag      1 bit
    65                         // non-intra quant. matrix values  512 bits (present if matrix flag == 1)
    66 
    67                         $info['video']['dataformat'] = 'mpeg';
    68 
    69                         $VideoChunkOffset += (strlen(GETID3_MPEG_VIDEO_SEQUENCE_HEADER) - 1);
    70 
    71                         $FrameSizeDWORD = getid3_lib::BigEndian2Int(substr($MPEGstreamData, $VideoChunkOffset, 3));
    72                         $VideoChunkOffset += 3;
    73 
    74                         $AspectRatioFrameRateDWORD = getid3_lib::BigEndian2Int(substr($MPEGstreamData, $VideoChunkOffset, 1));
    75                         $VideoChunkOffset += 1;
    76 
    77                         $assortedinformation = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 4));
    78                         $VideoChunkOffset += 4;
    79 
    80                         $info['mpeg']['video']['raw']['framesize_horizontal'] = ($FrameSizeDWORD & 0xFFF000) >> 12; // 12 bits for horizontal frame size
    81                         $info['mpeg']['video']['raw']['framesize_vertical']   = ($FrameSizeDWORD & 0x000FFF);       // 12 bits for vertical frame size
    82                         $info['mpeg']['video']['raw']['pixel_aspect_ratio']   = ($AspectRatioFrameRateDWORD & 0xF0) >> 4;
    83                         $info['mpeg']['video']['raw']['frame_rate']           = ($AspectRatioFrameRateDWORD & 0x0F);
    84 
    85                         $info['mpeg']['video']['framesize_horizontal'] = $info['mpeg']['video']['raw']['framesize_horizontal'];
    86                         $info['mpeg']['video']['framesize_vertical']   = $info['mpeg']['video']['raw']['framesize_vertical'];
    87 
    88                         $info['mpeg']['video']['pixel_aspect_ratio']      = $this->MPEGvideoAspectRatioLookup($info['mpeg']['video']['raw']['pixel_aspect_ratio']);
    89                         $info['mpeg']['video']['pixel_aspect_ratio_text'] = $this->MPEGvideoAspectRatioTextLookup($info['mpeg']['video']['raw']['pixel_aspect_ratio']);
    90                         $info['mpeg']['video']['frame_rate']              = $this->MPEGvideoFramerateLookup($info['mpeg']['video']['raw']['frame_rate']);
    91 
    92                         $info['mpeg']['video']['raw']['bitrate']                =        getid3_lib::Bin2Dec(substr($assortedinformation,  0, 18));
    93                         $info['mpeg']['video']['raw']['marker_bit']             = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 18,  1));
    94                         $info['mpeg']['video']['raw']['vbv_buffer_size']        =        getid3_lib::Bin2Dec(substr($assortedinformation, 19, 10));
    95                         $info['mpeg']['video']['raw']['constrained_param_flag'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 29,  1));
    96                         $info['mpeg']['video']['raw']['intra_quant_flag']       = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 30,  1));
    97                         if ($info['mpeg']['video']['raw']['intra_quant_flag']) {
    98 
    99                                 // read 512 bits
    100                                 $info['mpeg']['video']['raw']['intra_quant']          = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 64));
    101                                 $VideoChunkOffset += 64;
    102 
    103                                 $info['mpeg']['video']['raw']['non_intra_quant_flag'] = (bool) getid3_lib::Bin2Dec(substr($info['mpeg']['video']['raw']['intra_quant'], 511,  1));
    104                                 $info['mpeg']['video']['raw']['intra_quant']          =        getid3_lib::Bin2Dec(substr($assortedinformation, 31,  1)).substr(getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $VideoChunkOffset, 64)), 0, 511);
    105 
    106                                 if ($info['mpeg']['video']['raw']['non_intra_quant_flag']) {
    107                                         $info['mpeg']['video']['raw']['non_intra_quant'] = substr($MPEGstreamData, $VideoChunkOffset, 64);
    108                                         $VideoChunkOffset += 64;
    109                                 }
    110 
    111                         } else {
    112 
    113                                 $info['mpeg']['video']['raw']['non_intra_quant_flag'] = (bool) getid3_lib::Bin2Dec(substr($assortedinformation, 31,  1));
    114                                 if ($info['mpeg']['video']['raw']['non_intra_quant_flag']) {
    115                                         $info['mpeg']['video']['raw']['non_intra_quant'] = substr($MPEGstreamData, $VideoChunkOffset, 64);
    116                                         $VideoChunkOffset += 64;
    117                                 }
    118 
    119                         }
    120 
    121                         if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits
    122 
    123                                 $info['warning'][] = 'This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files';
    124                                 $info['mpeg']['video']['bitrate_mode'] = 'vbr';
    125 
    126                         } else {
    127 
    128                                 $info['mpeg']['video']['bitrate']      = $info['mpeg']['video']['raw']['bitrate'] * 400;
    129                                 $info['mpeg']['video']['bitrate_mode'] = 'cbr';
    130                                 $info['video']['bitrate']              = $info['mpeg']['video']['bitrate'];
    131 
    132                         }
    133 
    134                         $info['video']['resolution_x']       = $info['mpeg']['video']['framesize_horizontal'];
    135                         $info['video']['resolution_y']       = $info['mpeg']['video']['framesize_vertical'];
    136                         $info['video']['frame_rate']         = $info['mpeg']['video']['frame_rate'];
    137                         $info['video']['bitrate_mode']       = $info['mpeg']['video']['bitrate_mode'];
    138                         $info['video']['pixel_aspect_ratio'] = $info['mpeg']['video']['pixel_aspect_ratio'];
    139                         $info['video']['lossless']           = false;
    140                         $info['video']['bits_per_sample']    = 24;
    141 
    142                 } else {
    143 
    144                         $info['error'][] = 'Could not find start of video block in the first 100,000 bytes (or before end of file) - this might not be an MPEG-video file?';
    145 
    146                 }
    147 
    148                 //0x000001B3 begins the sequence_header of every MPEG video stream.
    149                 //But in MPEG-2, this header must immediately be followed by an
    150                 //extension_start_code (0x000001B5) with a sequence_extension ID (1).
    151                 //(This extension contains all the additional MPEG-2 stuff.)
    152                 //MPEG-1 doesn't have this extension, so that's a sure way to tell the
    153                 //difference between MPEG-1 and MPEG-2 video streams.
    154 
    155                 if (substr($MPEGstreamData, $VideoChunkOffset, 4) == GETID3_MPEG_VIDEO_EXTENSION_START) {
    156                         $info['video']['codec'] = 'MPEG-2';
    157                 } else {
    158                         $info['video']['codec'] = 'MPEG-1';
    159                 }
    160 
    161 
    162                 $AudioChunkOffset = 0;
    163                 while (true) {
    164                         while (substr($MPEGstreamData, $AudioChunkOffset++, 4) !== GETID3_MPEG_AUDIO_START) {
    165                                 if ($AudioChunkOffset >= $MPEGstreamDataLength) {
    166                                         break 2;
     36                $this->fseek($info['avdataoffset']);
     37
     38                $MPEGstreamData = $this->fread($this->getid3->option_fread_buffer_size);
     39                $MPEGstreamBaseOffset = 0; // how far are we from the beginning of the file data ($info['avdataoffset'])
     40                $MPEGstreamDataOffset = 0; // how far are we from the beginning of the buffer data (~32kB)
     41
     42                $StartCodeValue     = false;
     43                $prevStartCodeValue = false;
     44
     45                $GOPcounter = -1;
     46                $FramesByGOP = array();
     47                $ParsedAVchannels = array();
     48
     49                do {
     50//echo $MPEGstreamDataOffset.' vs '.(strlen($MPEGstreamData) - 1024).'<Br>';
     51                        if ($MPEGstreamDataOffset > (strlen($MPEGstreamData) - 16384)) {
     52                                // buffer running low, get more data
     53//echo 'reading more data<br>';
     54                                $MPEGstreamData .= $this->fread($this->getid3->option_fread_buffer_size);
     55                                if (strlen($MPEGstreamData) > $this->getid3->option_fread_buffer_size) {
     56                                        $MPEGstreamData = substr($MPEGstreamData, $MPEGstreamDataOffset);
     57                                        $MPEGstreamBaseOffset += $MPEGstreamDataOffset;
     58                                        $MPEGstreamDataOffset  = 0;
    16759                                }
    16860                        }
    169 
    170                         $getid3_temp = new getID3();
    171                         $getid3_temp->openfile($this->getid3->filename);
    172                         $getid3_temp->info = $info;
    173                         $getid3_mp3 = new getid3_mp3($getid3_temp);
    174                         for ($i = 0; $i <= 7; $i++) {
    175                                 // some files have the MPEG-audio header 8 bytes after the end of the $00 $00 $01 $C0 signature, some have it up to 13 bytes (or more?) after
    176                                 // I have no idea why or what the difference is, so this is a stupid hack.
    177                                 // If anybody has any better idea of what's going on, please let me know - info@getid3.org
    178                                 fseek($getid3_temp->fp, ftell($this->getid3->fp), SEEK_SET);
    179                                 $getid3_temp->info = $info; // only overwrite real data if valid header found
    180                                 if ($getid3_mp3->decodeMPEGaudioHeader(($AudioChunkOffset + 3) + 8 + $i, $getid3_temp->info, false)) {
    181                                         $info = $getid3_temp->info;
    182                                         $info['audio']['bitrate_mode']    = 'cbr';
    183                                         $info['audio']['lossless']        = false;
     61                        if (($StartCodeOffset = strpos($MPEGstreamData, self::START_CODE_BASE, $MPEGstreamDataOffset)) === false) {
     62//echo 'no more start codes found.<br>';
     63                                break;
     64                        } else {
     65                                $MPEGstreamDataOffset = $StartCodeOffset;
     66                                $prevStartCodeValue = $StartCodeValue;
     67                                $StartCodeValue = ord(substr($MPEGstreamData, $StartCodeOffset + 3, 1));
     68//echo 'Found "'.strtoupper(dechex($StartCodeValue)).'" at offset '.($MPEGstreamBaseOffset + $StartCodeOffset).' ($MPEGstreamDataOffset = '.$MPEGstreamDataOffset.')<br>';
     69                        }
     70                        $MPEGstreamDataOffset += 4;
     71                        switch ($StartCodeValue) {
     72
     73                                case 0x00: // picture_start_code
     74                                        if (!empty($info['mpeg']['video']['bitrate_mode']) && ($info['mpeg']['video']['bitrate_mode'] == 'vbr')) {
     75                                                $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 4));
     76                                                $bitstreamoffset = 0;
     77
     78                                                $PictureHeader = array();
     79
     80                                                $PictureHeader['temporal_reference']  = self::readBitsFromStream($bitstream, $bitstreamoffset, 10); // 10-bit unsigned integer associated with each input picture. It is incremented by one, modulo 1024, for each input frame. When a frame is coded as two fields the temporal reference in the picture header of both fields is the same. Following a group start header the temporal reference of the earliest picture (in display order) shall be reset to zero.
     81                                                $PictureHeader['picture_coding_type'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  3); //  3 bits for picture_coding_type
     82                                                $PictureHeader['vbv_delay']           = self::readBitsFromStream($bitstream, $bitstreamoffset, 16); // 16 bits for vbv_delay
     83                                                //... etc
     84
     85                                                $FramesByGOP[$GOPcounter][] = $PictureHeader;
     86                                        }
     87                                        break;
     88
     89                                case 0xB3: // sequence_header_code
     90                                        /*
     91                                        Note: purposely doing the less-pretty (and probably a bit slower) method of using string of bits rather than bitwise operations.
     92                                              Mostly because PHP 32-bit doesn't handle unsigned integers well for bitwise operation.
     93                                              Also the MPEG stream is designed as a bitstream and often doesn't align nicely with byte boundaries.
     94                                        */
     95                                        $info['video']['codec'] = 'MPEG-1'; // will be updated if extension_start_code found
     96
     97                                        $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 8));
     98                                        $bitstreamoffset = 0;
     99
     100                                        $info['mpeg']['video']['raw']['horizontal_size_value']       = self::readBitsFromStream($bitstream, $bitstreamoffset, 12); // 12 bits for horizontal frame size. Note: horizontal_size_extension, if present, will add 2 most-significant bits to this value
     101                                        $info['mpeg']['video']['raw']['vertical_size_value']         = self::readBitsFromStream($bitstream, $bitstreamoffset, 12); // 12 bits for vertical frame size.   Note: vertical_size_extension,   if present, will add 2 most-significant bits to this value
     102                                        $info['mpeg']['video']['raw']['aspect_ratio_information']    = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); //  4 bits for aspect_ratio_information
     103                                        $info['mpeg']['video']['raw']['frame_rate_code']             = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); //  4 bits for Frame Rate id code
     104                                        $info['mpeg']['video']['raw']['bitrate']                     = self::readBitsFromStream($bitstream, $bitstreamoffset, 18); // 18 bits for bit_rate_value (18 set bits = VBR, otherwise bitrate = this value * 400)
     105                                        $marker_bit                                                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // The term "marker_bit" indicates a one bit field in which the value zero is forbidden. These marker bits are introduced at several points in the syntax to avoid start code emulation.
     106                                        $info['mpeg']['video']['raw']['vbv_buffer_size']             = self::readBitsFromStream($bitstream, $bitstreamoffset, 10); // 10 bits vbv_buffer_size_value
     107                                        $info['mpeg']['video']['raw']['constrained_param_flag']      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: constrained_param_flag
     108                                        $info['mpeg']['video']['raw']['load_intra_quantiser_matrix'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: load_intra_quantiser_matrix
     109
     110                                        if ($info['mpeg']['video']['raw']['load_intra_quantiser_matrix']) {
     111                                                $bitstream .= getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 12, 64));
     112                                                for ($i = 0; $i < 64; $i++) {
     113                                                        $info['mpeg']['video']['raw']['intra_quantiser_matrix'][$i] = self::readBitsFromStream($bitstream, $bitstreamoffset,  8);
     114                                                }
     115                                        }
     116                                        $info['mpeg']['video']['raw']['load_non_intra_quantiser_matrix'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  1);
     117
     118                                        if ($info['mpeg']['video']['raw']['load_non_intra_quantiser_matrix']) {
     119                                                $bitstream .= getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 12 + ($info['mpeg']['video']['raw']['load_intra_quantiser_matrix'] ? 64 : 0), 64));
     120                                                for ($i = 0; $i < 64; $i++) {
     121                                                        $info['mpeg']['video']['raw']['non_intra_quantiser_matrix'][$i] = self::readBitsFromStream($bitstream, $bitstreamoffset,  8);
     122                                                }
     123                                        }
     124
     125                                        $info['mpeg']['video']['pixel_aspect_ratio']      =     self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information']);
     126                                        $info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information']);
     127                                        $info['mpeg']['video']['frame_rate']              =       self::videoFramerateLookup($info['mpeg']['video']['raw']['frame_rate_code']);
     128                                        if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits = VBR
     129                                                //$this->warning('This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files');
     130                                                $info['mpeg']['video']['bitrate_mode'] = 'vbr';
     131                                        } else {
     132                                                $info['mpeg']['video']['bitrate']      = $info['mpeg']['video']['raw']['bitrate'] * 400;
     133                                                $info['mpeg']['video']['bitrate_mode'] = 'cbr';
     134                                                $info['video']['bitrate']              = $info['mpeg']['video']['bitrate'];
     135                                        }
     136                                        $info['video']['resolution_x']       = $info['mpeg']['video']['raw']['horizontal_size_value'];
     137                                        $info['video']['resolution_y']       = $info['mpeg']['video']['raw']['vertical_size_value'];
     138                                        $info['video']['frame_rate']         = $info['mpeg']['video']['frame_rate'];
     139                                        $info['video']['bitrate_mode']       = $info['mpeg']['video']['bitrate_mode'];
     140                                        $info['video']['pixel_aspect_ratio'] = $info['mpeg']['video']['pixel_aspect_ratio'];
     141                                        $info['video']['lossless']           = false;
     142                                        $info['video']['bits_per_sample']    = 24;
     143                                        break;
     144
     145                                case 0xB5: // extension_start_code
     146                                        $info['video']['codec'] = 'MPEG-2';
     147
     148                                        $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 8)); // 48 bits for Sequence Extension ID; 61 bits for Sequence Display Extension ID; 59 bits for Sequence Scalable Extension ID
     149                                        $bitstreamoffset = 0;
     150
     151                                        $info['mpeg']['video']['raw']['extension_start_code_identifier'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); //  4 bits for extension_start_code_identifier
     152//echo $info['mpeg']['video']['raw']['extension_start_code_identifier'].'<br>';
     153                                        switch ($info['mpeg']['video']['raw']['extension_start_code_identifier']) {
     154                                                case  1: // 0001 Sequence Extension ID
     155                                                        $info['mpeg']['video']['raw']['profile_and_level_indication']    = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  8 bits for profile_and_level_indication
     156                                                        $info['mpeg']['video']['raw']['progressive_sequence']            = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: progressive_sequence
     157                                                        $info['mpeg']['video']['raw']['chroma_format']                   = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for chroma_format
     158                                                        $info['mpeg']['video']['raw']['horizontal_size_extension']       = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for horizontal_size_extension
     159                                                        $info['mpeg']['video']['raw']['vertical_size_extension']         = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for vertical_size_extension
     160                                                        $info['mpeg']['video']['raw']['bit_rate_extension']              = self::readBitsFromStream($bitstream, $bitstreamoffset, 12); // 12 bits for bit_rate_extension
     161                                                        $marker_bit                                                      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // The term "marker_bit" indicates a one bit field in which the value zero is forbidden. These marker bits are introduced at several points in the syntax to avoid start code emulation.
     162                                                        $info['mpeg']['video']['raw']['vbv_buffer_size_extension']       = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  8 bits for vbv_buffer_size_extension
     163                                                        $info['mpeg']['video']['raw']['low_delay']                       = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: low_delay
     164                                                        $info['mpeg']['video']['raw']['frame_rate_extension_n']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for frame_rate_extension_n
     165                                                        $info['mpeg']['video']['raw']['frame_rate_extension_d']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for frame_rate_extension_d
     166
     167                                                        $info['video']['resolution_x']          = ($info['mpeg']['video']['raw']['horizontal_size_extension'] << 12) | $info['mpeg']['video']['raw']['horizontal_size_value'];
     168                                                        $info['video']['resolution_y']          = ($info['mpeg']['video']['raw']['vertical_size_extension']   << 12) | $info['mpeg']['video']['raw']['vertical_size_value'];
     169                                                        $info['video']['interlaced']            = !$info['mpeg']['video']['raw']['progressive_sequence'];
     170                                                        $info['mpeg']['video']['interlaced']    = !$info['mpeg']['video']['raw']['progressive_sequence'];
     171                                                        $info['mpeg']['video']['chroma_format'] = self::chromaFormatTextLookup($info['mpeg']['video']['raw']['chroma_format']);
     172                                                        break;
     173
     174                                                case  2: // 0010 Sequence Display Extension ID
     175                                                        $info['mpeg']['video']['raw']['video_format']                    = self::readBitsFromStream($bitstream, $bitstreamoffset,  3); //  3 bits for video_format
     176                                                        $info['mpeg']['video']['raw']['colour_description']              = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: colour_description
     177                                                        if ($info['mpeg']['video']['raw']['colour_description']) {
     178                                                                $info['mpeg']['video']['raw']['colour_primaries']            = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  8 bits for colour_primaries
     179                                                                $info['mpeg']['video']['raw']['transfer_characteristics']    = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  8 bits for transfer_characteristics
     180                                                                $info['mpeg']['video']['raw']['matrix_coefficients']         = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  8 bits for matrix_coefficients
     181                                                        }
     182                                                        $info['mpeg']['video']['raw']['display_horizontal_size']         = self::readBitsFromStream($bitstream, $bitstreamoffset, 14); // 14 bits for display_horizontal_size
     183                                                        $marker_bit                                                      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // The term "marker_bit" indicates a one bit field in which the value zero is forbidden. These marker bits are introduced at several points in the syntax to avoid start code emulation.
     184                                                        $info['mpeg']['video']['raw']['display_vertical_size']           = self::readBitsFromStream($bitstream, $bitstreamoffset, 14); // 14 bits for display_vertical_size
     185
     186                                                        $info['mpeg']['video']['video_format'] = self::videoFormatTextLookup($info['mpeg']['video']['raw']['video_format']);
     187                                                        break;
     188
     189                                                case  3: // 0011 Quant Matrix Extension ID
     190                                                        break;
     191
     192                                                case  5: // 0101 Sequence Scalable Extension ID
     193                                                        $info['mpeg']['video']['raw']['scalable_mode']                              = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for scalable_mode
     194                                                        $info['mpeg']['video']['raw']['layer_id']                                   = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); //  4 bits for layer_id
     195                                                        if ($info['mpeg']['video']['raw']['scalable_mode'] == 1) { // "spatial scalability"
     196                                                                $info['mpeg']['video']['raw']['lower_layer_prediction_horizontal_size'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 14); // 14 bits for lower_layer_prediction_horizontal_size
     197                                                                $marker_bit                                                             = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // The term "marker_bit" indicates a one bit field in which the value zero is forbidden. These marker bits are introduced at several points in the syntax to avoid start code emulation.
     198                                                                $info['mpeg']['video']['raw']['lower_layer_prediction_vertical_size']   = self::readBitsFromStream($bitstream, $bitstreamoffset, 14); // 14 bits for lower_layer_prediction_vertical_size
     199                                                                $info['mpeg']['video']['raw']['horizontal_subsampling_factor_m']        = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for horizontal_subsampling_factor_m
     200                                                                $info['mpeg']['video']['raw']['horizontal_subsampling_factor_n']        = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for horizontal_subsampling_factor_n
     201                                                                $info['mpeg']['video']['raw']['vertical_subsampling_factor_m']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for vertical_subsampling_factor_m
     202                                                                $info['mpeg']['video']['raw']['vertical_subsampling_factor_n']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for vertical_subsampling_factor_n
     203                                                        } elseif ($info['mpeg']['video']['raw']['scalable_mode'] == 3) { // "temporal scalability"
     204                                                                $info['mpeg']['video']['raw']['picture_mux_enable']                     = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: picture_mux_enable
     205                                                                if ($info['mpeg']['video']['raw']['picture_mux_enable']) {
     206                                                                        $info['mpeg']['video']['raw']['mux_to_progressive_sequence']        = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: mux_to_progressive_sequence
     207                                                                }
     208                                                                $info['mpeg']['video']['raw']['picture_mux_order']                      = self::readBitsFromStream($bitstream, $bitstreamoffset,  3); //  3 bits for picture_mux_order
     209                                                                $info['mpeg']['video']['raw']['picture_mux_factor']                     = self::readBitsFromStream($bitstream, $bitstreamoffset,  3); //  3 bits for picture_mux_factor
     210                                                        }
     211
     212                                                        $info['mpeg']['video']['scalable_mode'] = self::scalableModeTextLookup($info['mpeg']['video']['raw']['scalable_mode']);
     213                                                        break;
     214
     215                                                case  7: // 0111 Picture Display Extension ID
     216                                                        break;
     217
     218                                                case  8: // 1000 Picture Coding Extension ID
     219                                                        $info['mpeg']['video']['raw']['f_code_00']                       = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); // 4 bits for f_code[0][0] (forward horizontal)
     220                                                        $info['mpeg']['video']['raw']['f_code_01']                       = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); // 4 bits for f_code[0][1] (forward vertical)
     221                                                        $info['mpeg']['video']['raw']['f_code_10']                       = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); // 4 bits for f_code[1][0] (backward horizontal)
     222                                                        $info['mpeg']['video']['raw']['f_code_11']                       = self::readBitsFromStream($bitstream, $bitstreamoffset,  4); // 4 bits for f_code[1][1] (backward vertical)
     223                                                        $info['mpeg']['video']['raw']['intra_dc_precision']              = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); // 2 bits for intra_dc_precision
     224                                                        $info['mpeg']['video']['raw']['picture_structure']               = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); // 2 bits for picture_structure
     225                                                        $info['mpeg']['video']['raw']['top_field_first']                 = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: top_field_first
     226                                                        $info['mpeg']['video']['raw']['frame_pred_frame_dct']            = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: frame_pred_frame_dct
     227                                                        $info['mpeg']['video']['raw']['concealment_motion_vectors']      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: concealment_motion_vectors
     228                                                        $info['mpeg']['video']['raw']['q_scale_type']                    = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: q_scale_type
     229                                                        $info['mpeg']['video']['raw']['intra_vlc_format']                = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: intra_vlc_format
     230                                                        $info['mpeg']['video']['raw']['alternate_scan']                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: alternate_scan
     231                                                        $info['mpeg']['video']['raw']['repeat_first_field']              = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: repeat_first_field
     232                                                        $info['mpeg']['video']['raw']['chroma_420_type']                 = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: chroma_420_type
     233                                                        $info['mpeg']['video']['raw']['progressive_frame']               = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: progressive_frame
     234                                                        $info['mpeg']['video']['raw']['composite_display_flag']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: composite_display_flag
     235                                                        if ($info['mpeg']['video']['raw']['composite_display_flag']) {
     236                                                                $info['mpeg']['video']['raw']['v_axis']                      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: v_axis
     237                                                                $info['mpeg']['video']['raw']['field_sequence']              = self::readBitsFromStream($bitstream, $bitstreamoffset,  3); // 3 bits for field_sequence
     238                                                                $info['mpeg']['video']['raw']['sub_carrier']                 = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // 1 bit flag: sub_carrier
     239                                                                $info['mpeg']['video']['raw']['burst_amplitude']             = self::readBitsFromStream($bitstream, $bitstreamoffset,  7); // 7 bits for burst_amplitude
     240                                                                $info['mpeg']['video']['raw']['sub_carrier_phase']           = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); // 8 bits for sub_carrier_phase
     241                                                        }
     242
     243                                                        $info['mpeg']['video']['intra_dc_precision_bits'] = $info['mpeg']['video']['raw']['intra_dc_precision'] + 8;
     244                                                        $info['mpeg']['video']['picture_structure'] = self::pictureStructureTextLookup($info['mpeg']['video']['raw']['picture_structure']);
     245                                                        break;
     246
     247                                                case  9: // 1001 Picture Spatial Scalable Extension ID
     248                                                        break;
     249                                                case 10: // 1010 Picture Temporal Scalable Extension ID
     250                                                        break;
     251
     252                                                default:
     253                                                        $this->warning('Unexpected $info[mpeg][video][raw][extension_start_code_identifier] value of '.$info['mpeg']['video']['raw']['extension_start_code_identifier']);
     254                                                        break;
     255                                        }
     256                                        break;
     257
     258
     259                                case 0xB8: // group_of_pictures_header
     260                                        $GOPcounter++;
     261                                        if ($info['mpeg']['video']['bitrate_mode'] == 'vbr') {
     262                                                $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 4)); // 27 bits needed for group_of_pictures_header
     263                                                $bitstreamoffset = 0;
     264
     265                                                $GOPheader = array();
     266
     267                                                $GOPheader['byte_offset'] = $MPEGstreamBaseOffset + $StartCodeOffset;
     268                                                $GOPheader['drop_frame_flag']    = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: drop_frame_flag
     269                                                $GOPheader['time_code_hours']    = self::readBitsFromStream($bitstream, $bitstreamoffset,  5); //  5 bits for time_code_hours
     270                                                $GOPheader['time_code_minutes']  = self::readBitsFromStream($bitstream, $bitstreamoffset,  6); //  6 bits for time_code_minutes
     271                                                $marker_bit                      = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); // The term "marker_bit" indicates a one bit field in which the value zero is forbidden. These marker bits are introduced at several points in the syntax to avoid start code emulation.
     272                                                $GOPheader['time_code_seconds']  = self::readBitsFromStream($bitstream, $bitstreamoffset,  6); //  6 bits for time_code_seconds
     273                                                $GOPheader['time_code_pictures'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  6); //  6 bits for time_code_pictures
     274                                                $GOPheader['closed_gop']         = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: closed_gop
     275                                                $GOPheader['broken_link']        = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: broken_link
     276
     277                                                $time_code_separator = ($GOPheader['drop_frame_flag'] ? ';' : ':'); // While non-drop time code is displayed with colons separating the digit pairs—"HH:MM:SS:FF"—drop frame is usually represented with a semi-colon (;) or period (.) as the divider between all the digit pairs—"HH;MM;SS;FF", "HH.MM.SS.FF"
     278                                                $GOPheader['time_code'] = sprintf('%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d', $GOPheader['time_code_hours'], $GOPheader['time_code_minutes'], $GOPheader['time_code_seconds'], $GOPheader['time_code_pictures']);
     279
     280                                                $info['mpeg']['group_of_pictures'][] = $GOPheader;
     281                                        }
     282                                        break;
     283
     284                                case 0xC0: // audio stream
     285                                case 0xC1: // audio stream
     286                                case 0xC2: // audio stream
     287                                case 0xC3: // audio stream
     288                                case 0xC4: // audio stream
     289                                case 0xC5: // audio stream
     290                                case 0xC6: // audio stream
     291                                case 0xC7: // audio stream
     292                                case 0xC8: // audio stream
     293                                case 0xC9: // audio stream
     294                                case 0xCA: // audio stream
     295                                case 0xCB: // audio stream
     296                                case 0xCC: // audio stream
     297                                case 0xCD: // audio stream
     298                                case 0xCE: // audio stream
     299                                case 0xCF: // audio stream
     300                                case 0xD0: // audio stream
     301                                case 0xD1: // audio stream
     302                                case 0xD2: // audio stream
     303                                case 0xD3: // audio stream
     304                                case 0xD4: // audio stream
     305                                case 0xD5: // audio stream
     306                                case 0xD6: // audio stream
     307                                case 0xD7: // audio stream
     308                                case 0xD8: // audio stream
     309                                case 0xD9: // audio stream
     310                                case 0xDA: // audio stream
     311                                case 0xDB: // audio stream
     312                                case 0xDC: // audio stream
     313                                case 0xDD: // audio stream
     314                                case 0xDE: // audio stream
     315                                case 0xDF: // audio stream
     316                                //case 0xE0: // video stream
     317                                //case 0xE1: // video stream
     318                                //case 0xE2: // video stream
     319                                //case 0xE3: // video stream
     320                                //case 0xE4: // video stream
     321                                //case 0xE5: // video stream
     322                                //case 0xE6: // video stream
     323                                //case 0xE7: // video stream
     324                                //case 0xE8: // video stream
     325                                //case 0xE9: // video stream
     326                                //case 0xEA: // video stream
     327                                //case 0xEB: // video stream
     328                                //case 0xEC: // video stream
     329                                //case 0xED: // video stream
     330                                //case 0xEE: // video stream
     331                                //case 0xEF: // video stream
     332                                        if (isset($ParsedAVchannels[$StartCodeValue])) {
     333                                                break;
     334                                        }
     335                                        $ParsedAVchannels[$StartCodeValue] = $StartCodeValue;
     336                                        // http://en.wikipedia.org/wiki/Packetized_elementary_stream
     337                                        // http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
     338/*
     339                                        $PackedElementaryStream = array();
     340                                        if ($StartCodeValue >= 0xE0) {
     341                                                $PackedElementaryStream['stream_type'] = 'video';
     342                                                $PackedElementaryStream['stream_id']   = $StartCodeValue - 0xE0;
     343                                        } else {
     344                                                $PackedElementaryStream['stream_type'] = 'audio';
     345                                                $PackedElementaryStream['stream_id']   = $StartCodeValue - 0xC0;
     346                                        }
     347                                        $PackedElementaryStream['packet_length'] = getid3_lib::BigEndian2Int(substr($MPEGstreamData, $StartCodeOffset + 4, 2));
     348
     349                                        $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 6, 3)); // more may be needed below
     350                                        $bitstreamoffset = 0;
     351
     352                                        $PackedElementaryStream['marker_bits']               = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for marker_bits -- should be "10" = 2
     353echo 'marker_bits = '.$PackedElementaryStream['marker_bits'].'<br>';
     354                                        $PackedElementaryStream['scrambling_control']        = self::readBitsFromStream($bitstream, $bitstreamoffset,  2); //  2 bits for scrambling_control -- 00 implies not scrambled
     355                                        $PackedElementaryStream['priority']                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: priority
     356                                        $PackedElementaryStream['data_alignment_indicator']  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: data_alignment_indicator -- 1 indicates that the PES packet header is immediately followed by the video start code or audio syncword
     357                                        $PackedElementaryStream['copyright']                 = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: copyright -- 1 implies copyrighted
     358                                        $PackedElementaryStream['original_or_copy']          = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: original_or_copy -- 1 implies original
     359                                        $PackedElementaryStream['pts_flag']                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: pts_flag -- Presentation Time Stamp
     360                                        $PackedElementaryStream['dts_flag']                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: dts_flag -- Decode Time Stamp
     361                                        $PackedElementaryStream['escr_flag']                 = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: escr_flag -- Elementary Stream Clock Reference
     362                                        $PackedElementaryStream['es_rate_flag']              = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: es_rate_flag -- Elementary Stream [data] Rate
     363                                        $PackedElementaryStream['dsm_trick_mode_flag']       = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: dsm_trick_mode_flag -- DSM trick mode - not used by DVD
     364                                        $PackedElementaryStream['additional_copy_info_flag'] = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: additional_copy_info_flag
     365                                        $PackedElementaryStream['crc_flag']                  = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: crc_flag
     366                                        $PackedElementaryStream['extension_flag']            = self::readBitsFromStream($bitstream, $bitstreamoffset,  1); //  1 bit flag: extension_flag
     367                                        $PackedElementaryStream['pes_remain_header_length']  = self::readBitsFromStream($bitstream, $bitstreamoffset,  8); //  1 bit flag: priority
     368
     369                                        $additional_header_bytes = 0;
     370                                        $additional_header_bytes += ($PackedElementaryStream['pts_flag']                  ? 5 : 0);
     371                                        $additional_header_bytes += ($PackedElementaryStream['dts_flag']                  ? 5 : 0);
     372                                        $additional_header_bytes += ($PackedElementaryStream['escr_flag']                 ? 6 : 0);
     373                                        $additional_header_bytes += ($PackedElementaryStream['es_rate_flag']              ? 3 : 0);
     374                                        $additional_header_bytes += ($PackedElementaryStream['additional_copy_info_flag'] ? 1 : 0);
     375                                        $additional_header_bytes += ($PackedElementaryStream['crc_flag']                  ? 2 : 0);
     376                                        $additional_header_bytes += ($PackedElementaryStream['extension_flag']            ? 1 : 0);
     377$PackedElementaryStream['additional_header_bytes'] = $additional_header_bytes;
     378                                        $bitstream .= getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 9, $additional_header_bytes));
     379
     380                                        $info['mpeg']['packed_elementary_streams'][$PackedElementaryStream['stream_type']][$PackedElementaryStream['stream_id']][] = $PackedElementaryStream;
     381*/
     382                                        $getid3_temp = new getID3();
     383                                        $getid3_temp->openfile($this->getid3->filename);
     384                                        $getid3_temp->info = $info;
     385                                        $getid3_mp3 = new getid3_mp3($getid3_temp);
     386                                        for ($i = 0; $i <= 7; $i++) {
     387                                                // some files have the MPEG-audio header 8 bytes after the end of the $00 $00 $01 $C0 signature, some have it up to 13 bytes (or more?) after
     388                                                // I have no idea why or what the difference is, so this is a stupid hack.
     389                                                // If anybody has any better idea of what's going on, please let me know - info@getid3.org
     390                                                $getid3_temp->info = $info; // only overwrite real data if valid header found
     391//echo 'audio at? '.($MPEGstreamBaseOffset + $StartCodeOffset + 4 + 8 + $i).'<br>';
     392                                                if ($getid3_mp3->decodeMPEGaudioHeader($MPEGstreamBaseOffset + $StartCodeOffset + 4 + 8 + $i, $getid3_temp->info, false)) {
     393//echo 'yes!<br>';
     394                                                        $info = $getid3_temp->info;
     395                                                        $info['audio']['bitrate_mode'] = 'cbr';
     396                                                        $info['audio']['lossless']     = false;
     397                                                        break;
     398                                                }
     399                                        }
    184400                                        unset($getid3_temp, $getid3_mp3);
    185                                         break 2;
    186                                 }
     401                                        break;
     402
     403                                case 0xBC: // Program Stream Map
     404                                case 0xBD: // Private stream 1 (non MPEG audio, subpictures)
     405                                case 0xBE: // Padding stream
     406                                case 0xBF: // Private stream 2 (navigation data)
     407                                case 0xF0: // ECM stream
     408                                case 0xF1: // EMM stream
     409                                case 0xF2: // DSM-CC stream
     410                                case 0xF3: // ISO/IEC_13522_stream
     411                                case 0xF4: // ITU-I Rec. H.222.1 type A
     412                                case 0xF5: // ITU-I Rec. H.222.1 type B
     413                                case 0xF6: // ITU-I Rec. H.222.1 type C
     414                                case 0xF7: // ITU-I Rec. H.222.1 type D
     415                                case 0xF8: // ITU-I Rec. H.222.1 type E
     416                                case 0xF9: // ancilliary stream
     417                                case 0xFA: // ISO/IEC 14496-1 SL-packtized stream
     418                                case 0xFB: // ISO/IEC 14496-1 FlexMux stream
     419                                case 0xFC: // metadata stream
     420                                case 0xFD: // extended stream ID
     421                                case 0xFE: // reserved data stream
     422                                case 0xFF: // program stream directory
     423                                        // ignore
     424                                        break;
     425
     426                                default:
     427                                        // ignore
     428                                        break;
    187429                        }
    188                         unset($getid3_temp, $getid3_mp3);
     430                } while (true);
     431
     432
     433
     434//              // Temporary hack to account for interleaving overhead:
     435//              if (!empty($info['video']['bitrate']) && !empty($info['audio']['bitrate'])) {
     436//                      $info['playtime_seconds'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['video']['bitrate'] + $info['audio']['bitrate']);
     437//
     438//                      // Interleaved MPEG audio/video files have a certain amount of overhead that varies
     439//                      // by both video and audio bitrates, and not in any sensible, linear/logarithmic pattern
     440//                      // Use interpolated lookup tables to approximately guess how much is overhead, because
     441//                      // playtime is calculated as filesize / total-bitrate
     442//                      $info['playtime_seconds'] *= self::systemNonOverheadPercentage($info['video']['bitrate'], $info['audio']['bitrate']);
     443//
     444//                      //switch ($info['video']['bitrate']) {
     445//                      //      case('5000000'):
     446//                      //              $multiplier = 0.93292642112380355828048824319889;
     447//                      //              break;
     448//                      //      case('5500000'):
     449//                      //              $multiplier = 0.93582895375200989965359777343219;
     450//                      //              break;
     451//                      //      case('6000000'):
     452//                      //              $multiplier = 0.93796247714820932532911373859139;
     453//                      //              break;
     454//                      //      case('7000000'):
     455//                      //              $multiplier = 0.9413264083635103463010117778776;
     456//                      //              break;
     457//                      //      default:
     458//                      //              $multiplier = 1;
     459//                      //              break;
     460//                      //}
     461//                      //$info['playtime_seconds'] *= $multiplier;
     462//                      //$info['warning'][] = 'Interleaved MPEG audio/video playtime may be inaccurate. With current hack should be within a few seconds of accurate. Report to info@getid3.org if off by more than 10 seconds.';
     463//                      if ($info['video']['bitrate'] < 50000) {
     464//                              $this->warning('Interleaved MPEG audio/video playtime may be slightly inaccurate for video bitrates below 100kbps. Except in extreme low-bitrate situations, error should be less than 1%. Report to info@getid3.org if greater than this.');
     465//                      }
     466//              }
     467//
     468/*
     469$time_prev = 0;
     470$byte_prev = 0;
     471$vbr_bitrates = array();
     472foreach ($info['mpeg']['group_of_pictures'] as $gopkey => $gopdata) {
     473        $time_this = ($gopdata['time_code_hours'] * 3600) + ($gopdata['time_code_minutes'] * 60) + $gopdata['time_code_seconds'] + ($gopdata['time_code_seconds'] / 30);
     474        $byte_this = $gopdata['byte_offset'];
     475        if ($gopkey > 0) {
     476                if ($time_this > $time_prev) {
     477                        $bytedelta = $byte_this - $byte_prev;
     478                        $timedelta = $time_this - $time_prev;
     479                        $this_bitrate = ($bytedelta * 8) / $timedelta;
     480echo $gopkey.': ('.number_format($time_prev, 2).'-'.number_format($time_this, 2).') '.number_format($bytedelta).' bytes over '.number_format($timedelta, 3).' seconds = '.number_format($this_bitrate / 1000, 2).'kbps<br>';
     481                        $time_prev = $time_this;
     482                        $byte_prev = $byte_this;
     483                        $vbr_bitrates[] = $this_bitrate;
    189484                }
    190 
    191                 // Temporary hack to account for interleaving overhead:
    192                 if (!empty($info['video']['bitrate']) && !empty($info['audio']['bitrate'])) {
    193                         $info['playtime_seconds'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['video']['bitrate'] + $info['audio']['bitrate']);
    194 
    195                         // Interleaved MPEG audio/video files have a certain amount of overhead that varies
    196                         // by both video and audio bitrates, and not in any sensible, linear/logarithmic patter
    197                         // Use interpolated lookup tables to approximately guess how much is overhead, because
    198                         // playtime is calculated as filesize / total-bitrate
    199                         $info['playtime_seconds'] *= $this->MPEGsystemNonOverheadPercentage($info['video']['bitrate'], $info['audio']['bitrate']);
    200 
    201                         //switch ($info['video']['bitrate']) {
    202                         //      case('5000000'):
    203                         //              $multiplier = 0.93292642112380355828048824319889;
    204                         //              break;
    205                         //      case('5500000'):
    206                         //              $multiplier = 0.93582895375200989965359777343219;
    207                         //              break;
    208                         //      case('6000000'):
    209                         //              $multiplier = 0.93796247714820932532911373859139;
    210                         //              break;
    211                         //      case('7000000'):
    212                         //              $multiplier = 0.9413264083635103463010117778776;
    213                         //              break;
    214                         //      default:
    215                         //              $multiplier = 1;
    216                         //              break;
    217                         //}
    218                         //$info['playtime_seconds'] *= $multiplier;
    219                         //$info['warning'][] = 'Interleaved MPEG audio/video playtime may be inaccurate. With current hack should be within a few seconds of accurate. Report to info@getid3.org if off by more than 10 seconds.';
    220                         if ($info['video']['bitrate'] < 50000) {
    221                                 $info['warning'][] = 'Interleaved MPEG audio/video playtime may be slightly inaccurate for video bitrates below 100kbps. Except in extreme low-bitrate situations, error should be less than 1%. Report to info@getid3.org if greater than this.';
     485        }
     486}
     487echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($vbr_bitrates), 1).'<br>';
     488*/
     489//echo '<pre>'.print_r($FramesByGOP, true).'</pre>';
     490                if (!empty($info['mpeg']['video']['bitrate_mode']) && ($info['mpeg']['video']['bitrate_mode'] == 'vbr')) {
     491                        $last_GOP_id = max(array_keys($FramesByGOP));
     492                        $frames_in_last_GOP = count($FramesByGOP[$last_GOP_id]);
     493                        $gopdata = &$info['mpeg']['group_of_pictures'][$last_GOP_id];
     494                        $info['playtime_seconds'] = ($gopdata['time_code_hours'] * 3600) + ($gopdata['time_code_minutes'] * 60) + $gopdata['time_code_seconds'] + (($gopdata['time_code_pictures'] + $frames_in_last_GOP + 1) / $info['mpeg']['video']['frame_rate']);
     495                        if (!isset($info['video']['bitrate'])) {
     496                                $overall_bitrate = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['playtime_seconds'];
     497                                $info['video']['bitrate'] = $overall_bitrate - (isset($info['audio']['bitrate']) ? $info['audio']['bitrate'] : 0);
    222498                        }
     499                        unset($info['mpeg']['group_of_pictures']);
    223500                }
    224501
     
    226503        }
    227504
    228 
    229         public function MPEGsystemNonOverheadPercentage($VideoBitrate, $AudioBitrate) {
     505        private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) {
     506                $return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read));
     507                $bitstreamoffset += $bits_to_read;
     508                if (($bits_to_read == 1) && $return_singlebit_as_boolean) {
     509                        $return = (bool) $return;
     510                }
     511                return $return;
     512        }
     513
     514
     515        public static function systemNonOverheadPercentage($VideoBitrate, $AudioBitrate) {
    230516                $OverheadPercentage = 0;
    231517
     
    279565
    280566
    281         public function MPEGvideoFramerateLookup($rawframerate) {
    282                 $MPEGvideoFramerateLookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
    283                 return (isset($MPEGvideoFramerateLookup[$rawframerate]) ? (float) $MPEGvideoFramerateLookup[$rawframerate] : (float) 0);
    284         }
    285 
    286         public function MPEGvideoAspectRatioLookup($rawaspectratio) {
    287                 $MPEGvideoAspectRatioLookup = array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0);
    288                 return (isset($MPEGvideoAspectRatioLookup[$rawaspectratio]) ? (float) $MPEGvideoAspectRatioLookup[$rawaspectratio] : (float) 0);
    289         }
    290 
    291         public function MPEGvideoAspectRatioTextLookup($rawaspectratio) {
    292                 $MPEGvideoAspectRatioTextLookup = array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved');
    293                 return (isset($MPEGvideoAspectRatioTextLookup[$rawaspectratio]) ? $MPEGvideoAspectRatioTextLookup[$rawaspectratio] : '');
     567        public static function videoFramerateLookup($rawframerate) {
     568                $lookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
     569                return (isset($lookup[$rawframerate]) ? (float) $lookup[$rawframerate] : (float) 0);
     570        }
     571
     572        public static function videoAspectRatioLookup($rawaspectratio) {
     573                $lookup = array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0);
     574                return (isset($lookup[$rawaspectratio]) ? (float) $lookup[$rawaspectratio] : (float) 0);
     575        }
     576
     577        public static function videoAspectRatioTextLookup($rawaspectratio) {
     578                $lookup = array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved');
     579                return (isset($lookup[$rawaspectratio]) ? $lookup[$rawaspectratio] : '');
     580        }
     581
     582        public static function videoFormatTextLookup($video_format) {
     583                // ISO/IEC 13818-2, section 6.3.6, Table 6-6. Meaning of video_format
     584                $lookup = array('component', 'PAL', 'NTSC', 'SECAM', 'MAC', 'Unspecified video format', 'reserved(6)', 'reserved(7)');
     585                return (isset($lookup[$video_format]) ? $lookup[$video_format] : '');
     586        }
     587
     588        public static function scalableModeTextLookup($scalable_mode) {
     589                // ISO/IEC 13818-2, section 6.3.8, Table 6-10. Definition of scalable_mode
     590                $lookup = array('data partitioning', 'spatial scalability', 'SNR scalability', 'temporal scalability');
     591                return (isset($lookup[$scalable_mode]) ? $lookup[$scalable_mode] : '');
     592        }
     593
     594        public static function pictureStructureTextLookup($picture_structure) {
     595                // ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
     596                $lookup = array('reserved', 'Top Field', 'Bottom Field', 'Frame picture');
     597                return (isset($lookup[$picture_structure]) ? $lookup[$picture_structure] : '');
     598        }
     599
     600        public static function chromaFormatTextLookup($chroma_format) {
     601                // ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
     602                $lookup = array('reserved', '4:2:0', '4:2:2', '4:4:4');
     603                return (isset($lookup[$chroma_format]) ? $lookup[$chroma_format] : '');
    294604        }
    295605
  • _plugins_/getID3/trunk/getid3/module.audio-video.nsv.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    2122                $info = &$this->getid3->info;
    2223
    23                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
    24                 $NSVheader = fread($this->getid3->fp, 4);
     24                $this->fseek($info['avdataoffset']);
     25                $NSVheader = $this->fread(4);
    2526
    2627                switch ($NSVheader) {
     
    6162        public function getNSVsHeaderFilepointer($fileoffset) {
    6263                $info = &$this->getid3->info;
    63                 fseek($this->getid3->fp, $fileoffset, SEEK_SET);
    64                 $NSVsheader = fread($this->getid3->fp, 28);
     64                $this->fseek($fileoffset);
     65                $NSVsheader = $this->fread(28);
    6566                $offset = 0;
    6667
     
    134135        public function getNSVfHeaderFilepointer($fileoffset, $getTOCoffsets=false) {
    135136                $info = &$this->getid3->info;
    136                 fseek($this->getid3->fp, $fileoffset, SEEK_SET);
    137                 $NSVfheader = fread($this->getid3->fp, 28);
     137                $this->fseek($fileoffset);
     138                $NSVfheader = $this->fread(28);
    138139                $offset = 0;
    139140
     
    172173                }
    173174
    174                 $NSVfheader .= fread($this->getid3->fp, $info['nsv']['NSVf']['meta_size'] + (4 * $info['nsv']['NSVf']['TOC_entries_1']) + (4 * $info['nsv']['NSVf']['TOC_entries_2']));
     175                $NSVfheader .= $this->fread($info['nsv']['NSVf']['meta_size'] + (4 * $info['nsv']['NSVf']['TOC_entries_1']) + (4 * $info['nsv']['NSVf']['TOC_entries_2']));
    175176                $NSVfheaderlength = strlen($NSVfheader);
    176177                $info['nsv']['NSVf']['metadata']      =                  substr($NSVfheader, $offset, $info['nsv']['NSVf']['meta_size']);
  • _plugins_/getID3/trunk/getid3/module.audio-video.quicktime.php

    r71835 r92618  
    44//  available at http://getid3.sourceforge.net                 //
    55//            or http://www.getid3.org                         //
     6//          also https://github.com/JamesHeinrich/getID3       //
    67/////////////////////////////////////////////////////////////////
    78// See readme.txt for more details                             //
     
    1112// module for analyzing Quicktime and MP3-in-MP4 files         //
    1213// dependencies: module.audio.mp3.php                          //
     14// dependencies: module.tag.id3v2.php                          //
    1315//                                                            ///
    1416/////////////////////////////////////////////////////////////////
    1517
    1618getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
     19getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); // needed for ISO 639-2 language code lookup
    1720
    1821class getid3_quicktime extends getid3_handler
     
    2932                $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
    3033
    31                 fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
     34                $this->fseek($info['avdataoffset']);
    3235
    3336                $offset      = 0;
    3437                $atomcounter = 0;
    35 
     38                $atom_data_read_buffer_size = ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 2) : $this->getid3->option_fread_buffer_size * 1024); // allow [default: 32MB] if PHP configured with no memory_limit
    3639                while ($offset < $info['avdataend']) {
    3740                        if (!getid3_lib::intValueSupported($offset)) {
     
    3942                                break;
    4043                        }
    41                         fseek($this->getid3->fp, $offset, SEEK_SET);
    42                         $AtomHeader = fread($this->getid3->fp, 8);
     44                        $this->fseek($offset);
     45                        $AtomHeader = $this->fread(8);
    4346
    4447                        $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
     
    4750                        // 64-bit MOV patch by jlegateØktnc*com
    4851                        if ($atomsize == 1) {
    49                                 $atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8));
     52                                $atomsize = getid3_lib::BigEndian2Int($this->fread(8));
    5053                        }
    5154
     
    6568                                break;
    6669                        }
    67                         switch ($atomname) {
    68                                 case 'mdat': // Media DATa atom
    69                                         // 'mdat' contains the actual data for the audio/video
    70                                         if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
    71 
    72                                                 $info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8;
    73                                                 $OldAVDataEnd         = $info['avdataend'];
    74                                                 $info['avdataend']    = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
    75 
    76                                                 $getid3_temp = new getID3();
    77                                                 $getid3_temp->openfile($this->getid3->filename);
    78                                                 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
    79                                                 $getid3_temp->info['avdataend']    = $info['avdataend'];
    80                                                 $getid3_mp3 = new getid3_mp3($getid3_temp);
    81                                                 if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) {
    82                                                         $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
    83                                                         if (!empty($getid3_temp->info['warning'])) {
    84                                                                 foreach ($getid3_temp->info['warning'] as $value) {
    85                                                                         $info['warning'][] = $value;
    86                                                                 }
    87                                                         }
    88                                                         if (!empty($getid3_temp->info['mpeg'])) {
    89                                                                 $info['mpeg'] = $getid3_temp->info['mpeg'];
    90                                                                 if (isset($info['mpeg']['audio'])) {
    91                                                                         $info['audio']['dataformat']   = 'mp3';
    92                                                                         $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')));
    93                                                                         $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
    94                                                                         $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
    95                                                                         $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
    96                                                                         $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
    97                                                                         $info['bitrate']               = $info['audio']['bitrate'];
    98                                                                 }
    99                                                         }
    100                                                 }
    101                                                 unset($getid3_mp3, $getid3_temp);
    102                                                 $info['avdataend'] = $OldAVDataEnd;
    103                                                 unset($OldAVDataEnd);
    104 
    105                                         }
    106                                         break;
    107 
    108                                 case 'free': // FREE space atom
    109                                 case 'skip': // SKIP atom
    110                                 case 'wide': // 64-bit expansion placeholder atom
    111                                         // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
    112                                         break;
    113 
    114                                 default:
    115                                         $atomHierarchy = array();
    116                                         $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
    117                                         break;
    118                         }
     70                        $atomHierarchy = array();
     71                        $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
    11972
    12073                        $offset += $atomsize;
     
    168121        public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
    169122                // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
     123                // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
    170124
    171125                $info = &$this->getid3->info;
    172126
    173                 $atom_parent = array_pop($atomHierarchy);
     127                $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
    174128                array_push($atomHierarchy, $atomname);
    175129                $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
     
    177131                $atom_structure['size']      = $atomsize;
    178132                $atom_structure['offset']    = $baseoffset;
    179 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'<br>';
    180 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'<br><br>';
    181133                switch ($atomname) {
    182134                        case 'moov': // MOVie container atom
     
    198150
    199151                        case 'ilst': // Item LiST container atom
    200                                 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    201 
    202                                 // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
    203                                 $allnumericnames = true;
    204                                 foreach ($atom_structure['subatoms'] as $subatomarray) {
    205                                         if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
    206                                                 $allnumericnames = false;
    207                                                 break;
    208                                         }
    209                                 }
    210                                 if ($allnumericnames) {
    211                                         $newData = array();
     152                                if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
     153                                        // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
     154                                        $allnumericnames = true;
    212155                                        foreach ($atom_structure['subatoms'] as $subatomarray) {
    213                                                 foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
    214                                                         unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
    215                                                         $newData[$subatomarray['name']] = $newData_subatomarray;
     156                                                if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
     157                                                        $allnumericnames = false;
    216158                                                        break;
    217159                                                }
    218160                                        }
    219                                         $atom_structure['data'] = $newData;
    220                                         unset($atom_structure['subatoms']);
     161                                        if ($allnumericnames) {
     162                                                $newData = array();
     163                                                foreach ($atom_structure['subatoms'] as $subatomarray) {
     164                                                        foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
     165                                                                unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
     166                                                                $newData[$subatomarray['name']] = $newData_subatomarray;
     167                                                                break;
     168                                                        }
     169                                                }
     170                                                $atom_structure['data'] = $newData;
     171                                                unset($atom_structure['subatoms']);
     172                                        }
    221173                                }
    222174                                break;
     
    272224
    273225
     226                        case "\xA9".'alb': // ALBum
     227                        case "\xA9".'ART': //
     228                        case "\xA9".'art': // ARTist
     229                        case "\xA9".'aut': //
     230                        case "\xA9".'cmt': // CoMmenT
     231                        case "\xA9".'com': // COMposer
     232                        case "\xA9".'cpy': //
     233                        case "\xA9".'day': // content created year
     234                        case "\xA9".'dir': //
     235                        case "\xA9".'ed1': //
     236                        case "\xA9".'ed2': //
     237                        case "\xA9".'ed3': //
     238                        case "\xA9".'ed4': //
     239                        case "\xA9".'ed5': //
     240                        case "\xA9".'ed6': //
     241                        case "\xA9".'ed7': //
     242                        case "\xA9".'ed8': //
     243                        case "\xA9".'ed9': //
     244                        case "\xA9".'enc': //
     245                        case "\xA9".'fmt': //
     246                        case "\xA9".'gen': // GENre
     247                        case "\xA9".'grp': // GRouPing
     248                        case "\xA9".'hst': //
     249                        case "\xA9".'inf': //
     250                        case "\xA9".'lyr': // LYRics
     251                        case "\xA9".'mak': //
     252                        case "\xA9".'mod': //
     253                        case "\xA9".'nam': // full NAMe
     254                        case "\xA9".'ope': //
     255                        case "\xA9".'PRD': //
     256                        case "\xA9".'prf': //
     257                        case "\xA9".'req': //
     258                        case "\xA9".'src': //
     259                        case "\xA9".'swr': //
     260                        case "\xA9".'too': // encoder
     261                        case "\xA9".'trk': // TRacK
     262                        case "\xA9".'url': //
     263                        case "\xA9".'wrn': //
     264                        case "\xA9".'wrt': // WRiTer
     265                        case '----': // itunes specific
    274266                        case 'aART': // Album ARTist
     267                        case 'akID': // iTunes store account type
     268                        case 'apID': // Purchase Account
     269                        case 'atID': //
    275270                        case 'catg': // CaTeGory
     271                        case 'cmID': //
     272                        case 'cnID': //
    276273                        case 'covr': // COVeR artwork
    277274                        case 'cpil': // ComPILation
     
    280277                        case 'disk': // DISK number
    281278                        case 'egid': // Episode Global ID
     279                        case 'geID': //
    282280                        case 'gnre': // GeNRE
     281                        case 'hdvd': // HD ViDeo
    283282                        case 'keyw': // KEYWord
    284                         case 'ldes':
     283                        case 'ldes': // Long DEScription
    285284                        case 'pcst': // PodCaST
    286285                        case 'pgap': // GAPless Playback
     286                        case 'plID': //
    287287                        case 'purd': // PURchase Date
    288288                        case 'purl': // Podcast URL
    289                         case 'rati':
    290                         case 'rndu':
    291                         case 'rpdu':
     289                        case 'rati': //
     290                        case 'rndu': //
     291                        case 'rpdu': //
    292292                        case 'rtng': // RaTiNG
    293                         case 'stik':
     293                        case 'sfID': // iTunes store country
     294                        case 'soaa': // SOrt Album Artist
     295                        case 'soal': // SOrt ALbum
     296                        case 'soar': // SOrt ARtist
     297                        case 'soco': // SOrt COmposer
     298                        case 'sonm': // SOrt NaMe
     299                        case 'sosn': // SOrt Show Name
     300                        case 'stik': //
    294301                        case 'tmpo': // TeMPO (BPM)
    295302                        case 'trkn': // TRacK Number
     303                        case 'tven': // tvEpisodeID
    296304                        case 'tves': // TV EpiSode
    297305                        case 'tvnn': // TV Network Name
    298306                        case 'tvsh': // TV SHow Name
    299307                        case 'tvsn': // TV SeasoN
    300                         case 'akID': // iTunes store account type
    301                         case 'apID':
    302                         case 'atID':
    303                         case 'cmID':
    304                         case 'cnID':
    305                         case 'geID':
    306                         case 'plID':
    307                         case 'sfID': // iTunes store country
    308                         case '©alb': // ALBum
    309                         case '©art': // ARTist
    310                         case '©ART':
    311                         case '©aut':
    312                         case '©cmt': // CoMmenT
    313                         case '©com': // COMposer
    314                         case '©cpy':
    315                         case '©day': // content created year
    316                         case '©dir':
    317                         case '©ed1':
    318                         case '©ed2':
    319                         case '©ed3':
    320                         case '©ed4':
    321                         case '©ed5':
    322                         case '©ed6':
    323                         case '©ed7':
    324                         case '©ed8':
    325                         case '©ed9':
    326                         case '©enc':
    327                         case '©fmt':
    328                         case '©gen': // GENre
    329                         case '©grp': // GRouPing
    330                         case '©hst':
    331                         case '©inf':
    332                         case '©lyr': // LYRics
    333                         case '©mak':
    334                         case '©mod':
    335                         case '©nam': // full NAMe
    336                         case '©ope':
    337                         case '©PRD':
    338                         case '©prd':
    339                         case '©prf':
    340                         case '©req':
    341                         case '©src':
    342                         case '©swr':
    343                         case '©too': // encoder
    344                         case '©trk': // TRacK
    345                         case '©url':
    346                         case '©wrn':
    347                         case '©wrt': // WRiTer
    348                         case '----': // itunes specific
    349308                                if ($atom_parent == 'udta') {
    350309                                        // User data atom handler
     
    367326                                                        $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
    368327                                                        $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
     328                                                        if ($boxsmallsize <= 1) {
     329                                                                $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
     330                                                                $atom_structure['data'] = null;
     331                                                                $atomoffset = strlen($atom_data);
     332                                                                break;
     333                                                        }
    369334                                                        switch ($boxsmalltype) {
    370335                                                                case "\x10\xB5":
     
    372337                                                                        break;
    373338                                                                default:
    374                                                                         $info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset;
     339                                                                        $info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset;
    375340                                                                        $atom_structure['data'] = $atom_data;
    376341                                                                        break;
     
    384349                                                        $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
    385350                                                        if ($boxsize <= 1) {
    386                                                                 $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset);
     351                                                                $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
    387352                                                                $atom_structure['data'] = null;
    388353                                                                $atomoffset = strlen($atom_data);
     
    401366                                                                        $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
    402367                                                                        switch ($atom_structure['flags_raw']) {
    403                                                                                 case 0: // data flag
     368                                                                                case  0: // data flag
    404369                                                                                case 21: // tmpo/cpil flag
    405370                                                                                        switch ($atomname) {
    406371                                                                                                case 'cpil':
     372                                                                                                case 'hdvd':
    407373                                                                                                case 'pcst':
    408374                                                                                                case 'pgap':
     375                                                                                                        // 8-bit integer (boolean)
    409376                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    410377                                                                                                        break;
    411378
    412379                                                                                                case 'tmpo':
     380                                                                                                        // 16-bit integer
    413381                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
    414382                                                                                                        break;
     
    416384                                                                                                case 'disk':
    417385                                                                                                case 'trkn':
     386                                                                                                        // binary
    418387                                                                                                        $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
    419388                                                                                                        $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
     
    423392
    424393                                                                                                case 'gnre':
     394                                                                                                        // enum
    425395                                                                                                        $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    426396                                                                                                        $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
     
    428398
    429399                                                                                                case 'rtng':
     400                                                                                                        // 8-bit integer
    430401                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    431402                                                                                                        $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
     
    433404
    434405                                                                                                case 'stik':
     406                                                                                                        // 8-bit integer (enum)
    435407                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    436408                                                                                                        $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
     
    438410
    439411                                                                                                case 'sfID':
     412                                                                                                        // 32-bit integer
    440413                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    441414                                                                                                        $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
     
    447420                                                                                                        break;
    448421
     422                                                                                                case 'plID':
     423                                                                                                        // 64-bit integer
     424                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
     425
     426                                                                                                case 'atID':
     427                                                                                                case 'cnID':
     428                                                                                                case 'geID':
     429                                                                                                case 'tves':
     430                                                                                                case 'tvsn':
    449431                                                                                                default:
     432                                                                                                        // 32-bit integer
    450433                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    451434                                                                                        }
    452435                                                                                        break;
    453436
    454                                                                                 case 1: // text flag
     437                                                                                case  1: // text flag
    455438                                                                                case 13: // image flag
    456439                                                                                default:
    457440                                                                                        $atom_structure['data'] = substr($boxdata, 8);
     441                                                                                        if ($atomname == 'covr') {
     442                                                                                                // not a foolproof check, but better than nothing
     443                                                                                                if (preg_match('#^\xFF\xD8\xFF#', $atom_structure['data'])) {
     444                                                                                                        $atom_structure['image_mime'] = 'image/jpeg';
     445                                                                                                } elseif (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) {
     446                                                                                                        $atom_structure['image_mime'] = 'image/png';
     447                                                                                                } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
     448                                                                                                        $atom_structure['image_mime'] = 'image/gif';
     449                                                                                                }
     450                                                                                        }
    458451                                                                                        break;
    459452
     
    462455
    463456                                                                default:
    464                                                                         $info['warning'][] = 'Unknown QuickTime box type: "'.getid3_lib::PrintHexBytes($boxtype).'" at offset '.$baseoffset;
     457                                                                        $info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset;
    465458                                                                        $atom_structure['data'] = $atom_data;
    466459
     
    658651
    659652                                                case "\x00\x00\x00\x00":
    660                                                         // audio atom
     653                                                        // audio tracks
    661654                                                        $atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
    662655                                                        $atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
     
    665658                                                        $atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
    666659
     660                                                        // video tracks
     661                                                        // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
     662                                                        $atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
     663                                                        $atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
     664                                                        $atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
     665                                                        $atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
     666                                                        $atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
     667                                                        $atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
     668                                                        $atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
     669                                                        $atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
     670                                                        $atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
     671                                                        $atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
     672                                                        $atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
     673
    667674                                                        switch ($atom_structure['sample_description_table'][$i]['data_format']) {
     675                                                                case '2vuY':
    668676                                                                case 'avc1':
     677                                                                case 'cvid':
     678                                                                case 'dvc ':
     679                                                                case 'dvcp':
     680                                                                case 'gif ':
     681                                                                case 'h263':
     682                                                                case 'jpeg':
     683                                                                case 'kpcd':
     684                                                                case 'mjpa':
     685                                                                case 'mjpb':
    669686                                                                case 'mp4v':
     687                                                                case 'png ':
     688                                                                case 'raw ':
     689                                                                case 'rle ':
     690                                                                case 'rpza':
     691                                                                case 'smc ':
     692                                                                case 'SVQ1':
     693                                                                case 'SVQ3':
     694                                                                case 'tiff':
     695                                                                case 'v210':
     696                                                                case 'v216':
     697                                                                case 'v308':
     698                                                                case 'v408':
     699                                                                case 'v410':
     700                                                                case 'yuv2':
    670701                                                                        $info['fileformat'] = 'mp4';
    671702                                                                        $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
    672                                                                         //$info['warning'][] = 'This version of getID3() ['.$this->getid3->version().'] does not fully support MPEG-4 audio/video streams'; // 2011-02-18: why am I warning about this again? What's not supported?
     703// http://www.getid3.org/phpBB3/viewtopic.php?t=1550
     704//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
     705if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
     706        // assume that values stored here are more important than values stored in [tkhd] atom
     707        $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
     708        $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
     709        $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
     710        $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
     711}
    673712                                                                        break;
    674713
     
    786825                                //$FrameRateCalculatorArray = array();
    787826                                $frames_count = 0;
    788                                 for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
     827
     828                                $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
     829                                if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
     830                                        $info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).';
     831                                }
     832                                for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
    789833                                        $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
    790834                                        $sttsEntriesDataOffset += 4;
     
    10321076                        case 'scpt': // tranSCriPT atom
    10331077                        case 'ssrc': // non-primary SouRCe atom
    1034                                 for ($i = 0; $i < (strlen($atom_data) % 4); $i++) {
    1035                                         $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4));
     1078                                for ($i = 0; $i < strlen($atom_data); $i += 4) {
     1079                                        @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
    10361080                                }
    10371081                                break;
     
    11221166                                $atom_structure['volume']              =   getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
    11231167                                $atom_structure['reserved3']           =   getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
     1168// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
     1169// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
    11241170                                $atom_structure['matrix_a']            = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
    11251171                                $atom_structure['matrix_b']            = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
    1126                                 $atom_structure['matrix_u']            = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
     1172                                $atom_structure['matrix_u']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
    11271173                                $atom_structure['matrix_c']            = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
    11281174                                $atom_structure['matrix_d']            = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
    1129                                 $atom_structure['matrix_v']            = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
    1130                                 $atom_structure['matrix_x']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 64, 4));
    1131                                 $atom_structure['matrix_y']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
     1175                                $atom_structure['matrix_v']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
     1176                                $atom_structure['matrix_x']            = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
     1177                                $atom_structure['matrix_y']            = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
    11321178                                $atom_structure['matrix_w']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
    11331179                                $atom_structure['width']               = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
    11341180                                $atom_structure['height']              = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
    1135 
    11361181                                $atom_structure['flags']['enabled']    = (bool) ($atom_structure['flags_raw'] & 0x0001);
    11371182                                $atom_structure['flags']['in_movie']   = (bool) ($atom_structure['flags_raw'] & 0x0002);
     
    12051250
    12061251                        case 'mdat': // Media DATa atom
     1252                                // 'mdat' contains the actual data for the audio/video, possibly also subtitles
     1253
     1254/* 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 */
     1255
     1256                                // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
     1257                                $mdat_offset = 0;
     1258                                while (true) {
     1259                                        if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
     1260                                                $mdat_offset += 8;
     1261                                        } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
     1262                                                $mdat_offset += 8;
     1263                                        } else {
     1264                                                break;
     1265                                        }
     1266                                }
     1267
     1268                                // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
     1269                                while  (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
     1270                                        && ($chapter_string_length < 1000)
     1271                                        && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
     1272                                        && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
     1273                                                $mdat_offset += (2 + $chapter_string_length);
     1274                                                @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0];
     1275                                }
     1276
     1277
     1278
     1279                                if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
     1280
     1281                                        $info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
     1282                                        $OldAVDataEnd         = $info['avdataend'];
     1283                                        $info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
     1284
     1285                                        $getid3_temp = new getID3();
     1286                                        $getid3_temp->openfile($this->getid3->filename);
     1287                                        $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
     1288                                        $getid3_temp->info['avdataend']    = $info['avdataend'];
     1289                                        $getid3_mp3 = new getid3_mp3($getid3_temp);
     1290                                        if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
     1291                                                $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
     1292                                                if (!empty($getid3_temp->info['warning'])) {
     1293                                                        foreach ($getid3_temp->info['warning'] as $value) {
     1294                                                                $info['warning'][] = $value;
     1295                                                        }
     1296                                                }
     1297                                                if (!empty($getid3_temp->info['mpeg'])) {
     1298                                                        $info['mpeg'] = $getid3_temp->info['mpeg'];
     1299                                                        if (isset($info['mpeg']['audio'])) {
     1300                                                                $info['audio']['dataformat']   = 'mp3';
     1301                                                                $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')));
     1302                                                                $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
     1303                                                                $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
     1304                                                                $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
     1305                                                                $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
     1306                                                                $info['bitrate']               = $info['audio']['bitrate'];
     1307                                                        }
     1308                                                }
     1309                                        }
     1310