[SPIP] v3.2.1-->v3.2.3
[lhc/web/www.git] / www / plugins-dist / medias / lib / getid3 / module.audio-video.riff.php
index f61f28a..8992ad7 100644 (file)
@@ -1,11 +1,11 @@
 <?php
+
 /////////////////////////////////////////////////////////////////
 /// getID3() by James Heinrich <info@getid3.org>               //
-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
-/////////////////////////////////////////////////////////////////
-// See readme.txt for more details                             //
+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
 /////////////////////////////////////////////////////////////////
 //                                                             //
 // module.audio-video.riff.php                                 //
@@ -27,10 +27,15 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE_
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
 
-class getid3_riff extends getid3_handler {
-
+class getid3_riff extends getid3_handler
+{
        protected $container = 'riff'; // default
 
+       /**
+        * @return bool
+        *
+        * @throws getid3_exception
+        */
        public function Analyze() {
                $info = &$this->getid3->info;
 
@@ -46,6 +51,7 @@ class getid3_riff extends getid3_handler {
                $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
                $thisfile_riff_audio       = &$thisfile_riff['audio'];
                $thisfile_riff_video       = &$thisfile_riff['video'];
+        $thisfile_riff_WAVE        = array();
 
                $Original['avdataoffset'] = $info['avdataoffset'];
                $Original['avdataend']    = $info['avdataend'];
@@ -357,6 +363,7 @@ class getid3_riff extends getid3_handler {
                                        }
                                        $thisfile_riff_WAVE_cart_0['url']              =                 trim(substr($thisfile_riff_WAVE_cart_0['data'],  748, 1024));
                                        $thisfile_riff_WAVE_cart_0['tag_text']         = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
+                                       $thisfile_riff['comments']['tag_text'][]       =                      substr($thisfile_riff_WAVE_cart_0['data'], 1772);
 
                                        $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
                                        $thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_cart_0['title'];
@@ -405,7 +412,6 @@ class getid3_riff extends getid3_handler {
                                                'tracktitle'=>'title',
                                                'category'  =>'genre',
                                                'cdtitle'   =>'album',
-                                               'tracktitle'=>'title',
                                        );
                                        foreach ($tagmapping as $fromkey => $tokey) {
                                                if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
@@ -613,6 +619,8 @@ class getid3_riff extends getid3_handler {
                                $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
                                $thisfile_video['dataformat']   = 'avi';
 
+                               $thisfile_riff_video_current = array();
+
                                if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
                                        if (isset($thisfile_riff['AVIX'])) {
@@ -701,6 +709,7 @@ class getid3_riff extends getid3_handler {
 
                                        // shortcut
                                        $thisfile_riff_video[$streamindex] = array();
+                    /** @var array $thisfile_riff_video_current */
                                        $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
 
                                        if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
@@ -867,7 +876,7 @@ class getid3_riff extends getid3_handler {
                                                                }
                                                        }
 
-                                                       if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
+                                                       if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
 
                                                                $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                                                                if (self::fourccLookup($thisfile_video['fourcc'])) {
@@ -1077,6 +1086,7 @@ class getid3_riff extends getid3_handler {
                                $thisfile_audio_dataformat         = '8svx';
                                $thisfile_audio['bits_per_sample'] = 8;
                                $thisfile_audio['channels']        = 1; // overridden below, if need be
+                               $ActualBitsPerSample               = 0;
 
                                if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
@@ -1114,7 +1124,7 @@ class getid3_riff extends getid3_handler {
                                                        break;
 
                                                default:
-                                                       $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
+                                                       $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
                                                        break;
                                        }
                                }
@@ -1174,10 +1184,53 @@ class getid3_riff extends getid3_handler {
 
                        case 'WEBP':
                                // https://developers.google.com/speed/webp/docs/riff_container
+                               // https://tools.ietf.org/html/rfc6386
+                               // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
                                $info['fileformat'] = 'webp';
                                $info['mime_type']  = 'image/webp';
 
-$this->error('WebP image parsing not supported in this version of getID3()');
+                               if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
+                                       $old_offset = $this->ftell();
+                                       $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
+                                       $WEBP_VP8_header = $this->fread(10);
+                                       $this->fseek($old_offset);
+                                       if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
+                                               $thisfile_riff['WEBP']['VP8 '][0]['keyframe']   = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['version']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >>  0;
+
+                                               $thisfile_riff['WEBP']['VP8 '][0]['scale_x']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['width']      =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
+                                               $thisfile_riff['WEBP']['VP8 '][0]['scale_y']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
+                                               $thisfile_riff['WEBP']['VP8 '][0]['height']     =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
+
+                                               $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
+                                               $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
+                                       } else {
+                                               $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
+                                       }
+
+                               }
+                               if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
+                                       $old_offset = $this->ftell();
+                                       $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
+                                       $WEBP_VP8L_header = $this->fread(10);
+                                       $this->fseek($old_offset);
+                                       if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
+                                               $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
+                                               $thisfile_riff['WEBP']['VP8L'][0]['width']         =        bindec(substr($width_height_flags, 18, 14)) + 1;
+                                               $thisfile_riff['WEBP']['VP8L'][0]['height']        =        bindec(substr($width_height_flags,  4, 14)) + 1;
+                                               $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags,  3,  1));
+                                               $thisfile_riff['WEBP']['VP8L'][0]['version']       =        bindec(substr($width_height_flags,  0,  3));
+
+                                               $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
+                                               $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
+                                       } else {
+                                               $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
+                                       }
+
+                               }
                                break;
 
                        default:
@@ -1329,6 +1382,15 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return true;
        }
 
+       /**
+        * @param int $startoffset
+        * @param int $maxoffset
+        *
+        * @return array|false
+        *
+        * @throws Exception
+        * @throws getid3_exception
+        */
        public function ParseRIFFAMV($startoffset, $maxoffset) {
                // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
 
@@ -1437,7 +1499,13 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return $RIFFchunk;
        }
 
-
+       /**
+        * @param int $startoffset
+        * @param int $maxoffset
+        *
+        * @return array|false
+        * @throws getid3_exception
+        */
        public function ParseRIFF($startoffset, $maxoffset) {
                $info = &$this->getid3->info;
 
@@ -1689,7 +1757,7 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                                                        //      break;
 
                                                        default:
-                                                               if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
+                                                               if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
                                                                        $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                                                        $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size']   = $RIFFchunk[$chunkname][$thisindex]['size'];
                                                                        unset($RIFFchunk[$chunkname][$thisindex]['offset']);
@@ -1724,6 +1792,11 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return $RIFFchunk;
        }
 
+       /**
+        * @param string $RIFFdata
+        *
+        * @return bool
+        */
        public function ParseRIFFdata(&$RIFFdata) {
                $info = &$this->getid3->info;
                if ($RIFFdata) {
@@ -1761,6 +1834,12 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return false;
        }
 
+       /**
+        * @param array $RIFFinfoArray
+        * @param array $CommentsTargetArray
+        *
+        * @return bool
+        */
        public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
                $RIFFinfoKeyLookup = array(
                        'IARL'=>'archivallocation',
@@ -1820,8 +1899,14 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return true;
        }
 
+       /**
+        * @param string $WaveFormatExData
+        *
+        * @return array
+        */
        public static function parseWAVEFORMATex($WaveFormatExData) {
                // shortcut
+               $WaveFormatEx        = array();
                $WaveFormatEx['raw'] = array();
                $WaveFormatEx_raw    = &$WaveFormatEx['raw'];
 
@@ -1845,6 +1930,11 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return $WaveFormatEx;
        }
 
+       /**
+        * @param string $WavPackChunkData
+        *
+        * @return bool
+        */
        public function parseWavPackHeader($WavPackChunkData) {
                // typedef struct {
                //     char ckID [4];
@@ -1906,6 +1996,12 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return true;
        }
 
+       /**
+        * @param string $BITMAPINFOHEADER
+        * @param bool   $littleEndian
+        *
+        * @return array
+        */
        public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
 
                $parsed['biSize']          = substr($BITMAPINFOHEADER,  0, 4); // number of bytes required by the BITMAPINFOHEADER structure
@@ -1925,6 +2021,12 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return $parsed;
        }
 
+       /**
+        * @param string $DIVXTAG
+        * @param bool   $raw
+        *
+        * @return array
+        */
        public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
                // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
                // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
@@ -1971,6 +2073,7 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                         5 => 'NC-17',
                );
 
+               $parsed              = array();
                $parsed['title']     =        trim(substr($DIVXTAG,   0, 32));
                $parsed['artist']    =        trim(substr($DIVXTAG,  32, 28));
                $parsed['year']      = intval(trim(substr($DIVXTAG,  60,  4)));
@@ -1986,8 +2089,8 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                if (!$raw) {
                        unset($parsed['genre_id'], $parsed['rating_id']);
                        foreach ($parsed as $key => $value) {
-                               if (!$value === '') {
-                                       unset($parsed['key']);
+                               if (empty($value)) {
+                                       unset($parsed[$key]);
                                }
                        }
                }
@@ -1999,6 +2102,11 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return $parsed;
        }
 
+       /**
+        * @param string $tagshortname
+        *
+        * @return string
+        */
        public static function waveSNDMtagLookup($tagshortname) {
                $begin = __LINE__;
 
@@ -2022,6 +2130,11 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
        }
 
+       /**
+        * @param int $wFormatTag
+        *
+        * @return string
+        */
        public static function wFormatTagLookup($wFormatTag) {
 
                $begin = __LINE__;
@@ -2191,6 +2304,11 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
        }
 
+       /**
+        * @param string $fourcc
+        *
+        * @return string
+        */
        public static function fourccLookup($fourcc) {
 
                $begin = __LINE__;
@@ -2585,6 +2703,12 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
        }
 
+       /**
+        * @param string $byteword
+        * @param bool   $signed
+        *
+        * @return int|float|false
+        */
        private function EitherEndian2Int($byteword, $signed=false) {
                if ($this->container == 'riff') {
                        return getid3_lib::LittleEndian2Int($byteword, $signed);
@@ -2592,4 +2716,4 @@ $this->error('WebP image parsing not supported in this version of getID3()');
                return getid3_lib::BigEndian2Int($byteword, false, $signed);
        }
 
-}
\ No newline at end of file
+}