Ejemplo n.º 1
0
    /**
     * Returns information about the specified file without having to use ffmpeg-php
     * as it consults the ffmpeg binary directly. 
     * NOTE: calling this statically for caching to work you must set the temp directory.
     * 
     * @access public
     * @return mixed false on error encountered, true otherwise
     * */
    public function getFFmpegInfo($read_from_cache = true, $tmp_dir = false)
    {
        $cache_file = isset($this) === true || $tmp_dir !== false ? true : false;
        if ($read_from_cache === true && $cache_file !== false) {
            $cache_file = ($tmp_dir === false ? $this->_tmp_directory : $tmp_dir) . '_ffmpeg_info.php';
            if (is_file($cache_file) === true) {
                require_once $cache_file;
                if (isset($info) === true && $info['_cache_date'] > time() - 2678400) {
                    $info['reading_from_cache'] = true;
                    PHPVideoToolkit::$ffmpeg_info = $info;
                }
            }
        }
        //check to see if the info has already been cached
        if (PHPVideoToolkit::$ffmpeg_info !== false) {
            return PHPVideoToolkit::$ffmpeg_info;
        }
        //check to see if this is a static call
        if (isset($this) === false) {
            $toolkit = new PHPVideoToolkit();
            return $toolkit->getFFmpegInfo($read_from_cache, $tmp_dir);
        }
        $format = '';
        $data = array('reading_from_cache' => false);
        // 			execute the ffmpeg lookup
        $buffer = self::_captureExecBuffer($this->_ffmpeg_binary . ' -formats', $tmp_dir);
        $codecs = self::_captureExecBuffer($this->_ffmpeg_binary . ' -codecs', $tmp_dir);
        $filters = self::_captureExecBuffer($this->_ffmpeg_binary . ' -bsfs', $tmp_dir);
        $protocols = self::_captureExecBuffer($this->_ffmpeg_binary . ' -protocols', $tmp_dir);
        self::$ffmpeg_found = $data['ffmpeg-found'] = !(strpos($buffer[0], 'command not found') !== false || strpos($buffer[0], 'No such file or directory') !== false);
        $data['compiler'] = array();
        $data['binary'] = array();
        $data['ffmpeg-php-support'] = self::hasFFmpegPHPSupport();
        $data['raw'] = implode("\r\n", $buffer) . "\r\n" . implode("\r\n", $codecs) . "\r\n" . implode("\r\n", $filters) . implode("\r\n", $protocols);
        if (!self::$ffmpeg_found) {
            self::$ffmpeg_info = $data;
            return $data;
        }
        $buffer = $data['raw'];
        // 			start building the info array
        $look_ups = array('formats' => 'File formats:', 'configuration' => 'configuration: ', 'codecs' => 'Codecs:', 'filters' => 'Bitstream filters:', 'protocols' => 'Supported file protocols:', 'abbreviations' => 'Frame size, frame rate abbreviations:', 'Note:');
        $total_lookups = count($look_ups);
        $pregs = array();
        $indexs = array();
        // 			search for the content
        foreach ($look_ups as $key => $reg) {
            if (strpos($buffer, $reg) !== false) {
                $index = array_push($pregs, $reg);
                $indexs[$key] = $index;
            }
        }
        preg_match('/' . implode('(.*)', $pregs) . '(.*)/s', $buffer, $matches);
        $configuration = '';
        if (isset($indexs['configuration'])) {
            $configuration = trim($matches[$indexs['configuration']]);
        }
        // 			grab the ffmpeg configuration flags
        preg_match_all('/--[a-zA-Z0-9\\-]+/', $configuration, $config_flags);
        $data['binary']['configuration'] = $config_flags[0];
        $data['binary']['vhook-support'] = in_array('--enable-vhook', $config_flags[0]) || !in_array('--disable-vhook', $config_flags[0]);
        // 			grab the versions
        $data['binary']['versions'] = self::getVersion($buffer);
        // 			grab the ffmpeg compile info
        preg_match('/built on (.*), gcc: (.*)/', $configuration, $conf);
        if (count($conf) > 0) {
            $data['compiler']['gcc'] = $conf[2];
            $data['compiler']['build_date'] = $conf[1];
            $data['compiler']['build_date_timestamp'] = strtotime($conf[1]);
        }
        // 			grab the file formats available to ffmpeg
        preg_match_all('/ (DE|D|E) (.*) {1,} (.*)/', $matches[$indexs['formats']], $formats);
        $data['formats'] = array();
        // 			loop and clean
        // Formats:
        //  D. = Demuxing supported
        //  .E = Muxing supported
        for ($i = 0, $a = count($formats[0]); $i < $a; $i++) {
            $data['formats'][strtolower(trim($formats[2][$i]))] = array('mux' => $formats[1][$i] == 'DE' || $formats[1][$i] == 'E', 'demux' => $formats[1][$i] == 'DE' || $formats[1][$i] == 'D', 'fullname' => $formats[3][$i]);
        }
        // 			grab the codecs available
        preg_match_all('/ ([DEVAST ]{0,6}) ([A-Za-z0-9\\_]*) (.*)/', $matches[$indexs['codecs']], $codecs);
        $data['codecs'] = array('video' => array(), 'audio' => array(), 'subtitle' => array());
        // Codecs:
        //  D..... = Decoding supported
        //  .E.... = Encoding supported
        //  ..V... = Video codec
        //  ..A... = Audio codec
        //  ..S... = Subtitle codec
        //  ...S.. = Supports draw_horiz_band
        //  ....D. = Supports direct rendering method 1
        //  .....T = Supports weird frame truncation
        for ($i = 0, $a = count($codecs[0]); $i < $a; $i++) {
            $options = preg_split('//', $codecs[1][$i], -1, PREG_SPLIT_NO_EMPTY);
            if ($options) {
                $id = trim($codecs[2][$i]);
                $type = $options[2] === 'V' ? 'video' : ($options[2] === 'A' ? 'audio' : 'subtitle');
                switch ($options[2]) {
                    // 					video
                    case 'V':
                        $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === true && $options[1] === 'E', 'decode' => isset($options[0]) === true && $options[0] === 'D', 'draw_horizontal_band' => isset($options[3]) === true && $options[3] === 'S', 'direct_rendering_method_1' => isset($options[4]) === true && $options[4] === 'D', 'weird_frame_truncation' => isset($options[5]) === true && $options[5] === 'T', 'fullname' => trim($codecs[3][$i]));
                        break;
                        // 					audio
                    // 					audio
                    case 'A':
                        // 					subtitle
                    // 					subtitle
                    case 'S':
                        $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === true && $options[1] === 'E', 'decode' => isset($options[0]) === true && $options[0] === 'D', 'fullname' => trim($codecs[3][$i]));
                        break;
                }
            }
        }
        // 			grab the bitstream filters available to ffmpeg
        $data['filters'] = array();
        if (isset($indexs['filters']) === true && isset($matches[$indexs['filters']]) === true) {
            $filters = trim($matches[$indexs['filters']]);
            if (empty($filters) === false) {
                $data['filters'] = explode(' ', $filters);
            }
        }
        // 			grab the file prototcols available to ffmpeg
        $data['protocols'] = array();
        if (isset($indexs['protocols']) === true && isset($matches[$indexs['protocols']]) === true) {
            $protocols = trim($matches[$indexs['protocols']]);
            if (empty($protocols) === false) {
                $data['protocols'] = explode(' ', str_replace(':', '', $protocols));
            }
        }
        // 			grab the abbreviations available to ffmpeg
        $data['abbreviations'] = array();
        if (isset($indexs['abbreviations']) === true && isset($matches[$indexs['abbreviations']]) === true) {
            $abbreviations = array_shift(explode("\r", trim($matches[$indexs['abbreviations']])));
            if (empty($abbreviations) === false) {
                $data['abbreviations'] = explode(' ', $abbreviations);
            }
        }
        PHPVideoToolkit::$ffmpeg_info = $data;
        // 			cache the data
        if ($cache_file !== false && $read_from_cache === true) {
            $data['_cache_date'] = time();
            file_put_contents($cache_file, '<?php
	$info = ' . var_export($data, true) . ';');
        }
        return $data;
    }
Ejemplo n.º 2
0
    /**
     * Returns information about the specified file without having to use ffmpeg-php
     * as it consults the ffmpeg binary directly.
     * NOTE: calling this statically for caching to work you must set the temp directory.
     *
     * @access public
     * @return mixed FALSE on error encountered, TRUE otherwise
     * */
    public function getFFmpegInfo($read_from_cache = TRUE, $tmp_dir = FALSE)
    {
        $cache_file = isset($this) === TRUE || $tmp_dir !== FALSE ? TRUE : FALSE;
        if ($read_from_cache === TRUE && $cache_file !== FALSE) {
            $cache_file = ($tmp_dir === FALSE ? $this->_tmp_directory : $tmp_dir) . '_ffmpeg_info.php';
            if (is_file($cache_file) === TRUE) {
                require_once $cache_file;
                if (isset($info) === TRUE && $info['_cache_date'] > time() - 2678400) {
                    $info['reading_from_cache'] = TRUE;
                    PHPVideoToolkit::$ffmpeg_info = $info;
                }
            }
        }
        // check to see if the info has already been cached
        if (PHPVideoToolkit::$ffmpeg_info !== FALSE) {
            return PHPVideoToolkit::$ffmpeg_info;
        }
        // check to see if this is a static call
        if (isset($this) === FALSE) {
            $toolkit = new PHPVideoToolkit();
            return $toolkit->getFFmpegInfo($read_from_cache, $tmp_dir);
        }
        $format = '';
        $data = array('reading_from_cache' => FALSE);
        $formats = self::_captureExecBuffer($this->_ffmpeg_binary . ' -formats', $tmp_dir);
        $codecs = self::_captureExecBuffer($this->_ffmpeg_binary . ' -codecs', $tmp_dir);
        $filters = self::_captureExecBuffer($this->_ffmpeg_binary . ' -bsfs', $tmp_dir);
        $protocols = self::_captureExecBuffer($this->_ffmpeg_binary . ' -protocols', $tmp_dir);
        self::$ffmpeg_found = $data['ffmpeg-found'] = !empty($formats) && strpos($formats[0], 'not found') === FALSE && strpos($formats[0], 'No such file or directory') === FALSE;
        $data['compiler'] = array();
        $data['binary'] = array();
        $data['ffmpeg-php-support'] = self::hasFFmpegPHPSupport();
        if (!self::$ffmpeg_found) {
            self::$ffmpeg_info = $data;
            return $data;
        }
        // FFmpeg 0.5 and lower don't support -codecs, -bsfs or -protocols, but the info is in -formats
        if (strpos(end($codecs), 'missing argument for option')) {
            $formats = implode("\n", $formats);
            $codecs = $formats;
            $filters = $formats;
            $protocols = $formats;
            $data['raw'] = $formats;
        } else {
            $formats = implode("\n", $formats);
            $codecs = implode("\n", $codecs);
            $filters = implode("\n", $filters);
            $protocols = implode("\n", $protocols);
            $data['raw'] = $formats . "\n" . $codecs . "\n" . $filters . "\n" . $protocols;
        }
        // grab the versions
        $data['binary']['versions'] = self::getVersion($data['raw']);
        // grab the ffmpeg configuration flags
        $config_flags = array();
        if (preg_match_all('/--[a-zA-Z0-9\\-]+/', $formats, $config_flags)) {
            $data['binary']['configuration'] = $config_flags[0];
            $data['binary']['vhook-support'] = in_array('--enable-vhook', $config_flags[0]) || !in_array('--disable-vhook', $config_flags[0]);
            // grab the ffmpeg compile info
            preg_match('/built on (.*), gcc: (.*)/', $formats, $conf);
            if (count($conf) > 0) {
                $data['compiler']['gcc'] = $conf[2];
                $data['compiler']['build_date'] = $conf[1];
                $data['compiler']['build_date_timestamp'] = strtotime($conf[1]);
            }
        }
        // grab the file formats available to ffmpeg
        $formatmatches = array();
        $data['formats'] = array();
        if (preg_match_all('/ (DE|D|E) (.*) {1,} (.*)/', $formats, $formatmatches)) {
            // 			loop and clean
            // Formats:
            //  D. = Demuxing supported
            //  .E = Muxing supported
            for ($i = 0, $a = count($formatmatches[0]); $i < $a; $i++) {
                $data['formats'][strtolower(trim($formatmatches[2][$i]))] = array('mux' => $formatmatches[1][$i] == 'DE' || $formatmatches[1][$i] == 'E', 'demux' => $formatmatches[1][$i] == 'DE' || $formatmatches[1][$i] == 'D', 'fullname' => $formatmatches[3][$i]);
            }
        }
        // grab the codecs available
        $codecsmatches = array();
        $data['codecs'] = array('video' => array(), 'audio' => array(), 'subtitle' => array());
        if (preg_match_all('/ ([DEVAST ]{6}) ([A-Za-z0-9\\_]*) (.*)/', $codecs, $codecsmatches)) {
            // Codecs:
            //  D..... = Decoding supported
            //  .E.... = Encoding supported
            //  ..V... = Video codec
            //  ..A... = Audio codec
            //  ..S... = Subtitle codec
            //  ...S.. = Supports draw_horiz_band
            //  ....D. = Supports direct rendering method 1
            //  .....T = Supports weird frame truncation
            for ($i = 0, $a = count($codecsmatches[0]); $i < $a; $i++) {
                $options = preg_split('//', $codecsmatches[1][$i], -1, PREG_SPLIT_NO_EMPTY);
                if ($options) {
                    $id = trim($codecsmatches[2][$i]);
                    $type = $options[2] === 'V' ? 'video' : ($options[2] === 'A' ? 'audio' : 'subtitle');
                    switch ($options[2]) {
                        // 					video
                        case 'V':
                            $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === TRUE && $options[1] === 'E', 'decode' => isset($options[0]) === TRUE && $options[0] === 'D', 'draw_horizontal_band' => isset($options[3]) === TRUE && $options[3] === 'S', 'direct_rendering_method_1' => isset($options[4]) === TRUE && $options[4] === 'D', 'weird_frame_truncation' => isset($options[5]) === TRUE && $options[5] === 'T', 'fullname' => trim($codecsmatches[3][$i]));
                            break;
                            // 					audio
                        // 					audio
                        case 'A':
                            // 					subtitle
                        // 					subtitle
                        case 'S':
                            $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === TRUE && $options[1] === 'E', 'decode' => isset($options[0]) === TRUE && $options[0] === 'D', 'fullname' => trim($codecsmatches[3][$i]));
                            break;
                    }
                }
            }
        }
        // grab the bitstream filters available to ffmpeg
        $data['filters'] = array();
        $locate = 'Bitstream filters:';
        if (!empty($filters) && ($pos = strpos($filters, $locate)) !== FALSE) {
            $filters = trim(substr($filters, $pos + strlen($locate)));
            $data['filters'] = explode("\n", $filters);
        }
        // grab the file protocols available to ffmpeg
        $data['protocols'] = array();
        $locate = 'Supported file protocols:';
        if (!empty($protocols) && ($pos = strpos($protocols, $locate)) !== FALSE) {
            $protocols = trim(substr($filters, $pos + strlen($locate)));
            $data['protocols'] = explode("\n", $filters);
        }
        PHPVideoToolkit::$ffmpeg_info = $data;
        // cache the data
        if ($cache_file !== FALSE && $read_from_cache === TRUE) {
            $data['_cache_date'] = time();
            file_put_contents($cache_file, '<?php
	$info = ' . var_export($data, TRUE) . ';');
        }
        return $data;
    }
Ejemplo n.º 3
0
 /**
  * Returns information about the specified file without having to use ffmpeg-php
  * as it consults the ffmpeg binary directly.
  * NOTE: calling this statically for caching to work you must set the temp directory.
  *
  * @access public
  * @return mixed FALSE on error encountered, TRUE otherwise
  * */
 public function getFFmpegInfo($read_from_cache = TRUE, $tmp_dir = FALSE)
 {
     $cache_file = isset($this) === TRUE || $tmp_dir !== FALSE ? TRUE : FALSE;
     if ($read_from_cache === TRUE && $cache_file !== FALSE) {
         $cache_file = ($tmp_dir === FALSE ? $this->_tmp_directory : $tmp_dir) . '_ffmpeg_info.php';
         if (is_file($cache_file) === TRUE) {
             require_once $cache_file;
             if (isset($info) === TRUE && $info['_cache_date'] > time() - 2678400) {
                 $info['reading_from_cache'] = TRUE;
                 PHPVideoToolkit::$ffmpeg_info = $info;
             }
         }
     }
     // check to see if the info has already been cached
     if (PHPVideoToolkit::$ffmpeg_info !== FALSE) {
         return PHPVideoToolkit::$ffmpeg_info;
     }
     // check to see if this is a static call
     if (isset($this) === FALSE) {
         $toolkit = new PHPVideoToolkit();
         return $toolkit->getFFmpegInfo($read_from_cache, $tmp_dir);
     }
     $format = '';
     $data = array('reading_from_cache' => FALSE);
     $formats = $this->_captureExecBuffer($this->_ffmpeg_binary . ' -formats');
     $codecs = $this->_captureExecBuffer($this->_ffmpeg_binary . ' -codecs');
     $filters = $this->_captureExecBuffer($this->_ffmpeg_binary . ' -bsfs');
     $protocols = $this->_captureExecBuffer($this->_ffmpeg_binary . ' -protocols');
     $pixformats = $this->_captureExecBufferFallback($this->_ffmpeg_binary . ' -pix_fmts', $this->_ffmpeg_binary . ' -pix_fmt list');
     $help = $this->_captureExecBuffer($this->_ffmpeg_binary . ' -h');
     self::$ffmpeg_found = $data['ffmpeg-found'] = !empty($formats) && strpos($formats[0], 'not found') === FALSE && strpos($formats[0], 'No such file or directory') === FALSE;
     $data['compiler'] = array();
     $data['binary'] = array();
     $data['ffmpeg-php-support'] = self::hasFFmpegPHPSupport();
     if (!self::$ffmpeg_found) {
         self::$ffmpeg_info = $data;
         return $data;
     }
     // FFmpeg 0.5 and lower don't support -codecs, -bsfs or -protocols, but the info is in -formats
     if (strpos(end($codecs), 'missing argument for option')) {
         $formats = implode("\n", $formats);
         $codecs = $formats;
         $filters = $formats;
         $protocols = $formats;
         $pixformats = implode("\n", $pixformats);
         $help = implode("\n", $help);
         $data['raw'] = $formats . $pixformats;
     } else {
         $formats = implode("\n", $formats);
         $codecs = implode("\n", $codecs);
         $filters = implode("\n", $filters);
         $protocols = implode("\n", $protocols);
         $pixformats = implode("\n", $pixformats);
         $help = implode("\n", $help);
         $data['raw'] = $formats . "\n" . $codecs . "\n" . $filters . "\n" . $protocols . "\n" . $pixformats;
     }
     // grab the versions
     $data['binary']['versions'] = self::getVersion($data['raw']);
     // grab the ffmpeg configuration flags
     $config_flags = array();
     if (preg_match_all('/--[a-zA-Z0-9\\-]+/', $formats, $config_flags)) {
         $data['binary']['configuration'] = $config_flags[0];
         $data['binary']['vhook-support'] = in_array('--enable-vhook', $config_flags[0]) || !in_array('--disable-vhook', $config_flags[0]);
         // grab the ffmpeg compile info
         preg_match('/built on (.*), gcc: (.*)/', $formats, $conf);
         if (count($conf) > 0) {
             $data['compiler']['gcc'] = $conf[2];
             $data['compiler']['build_date'] = $conf[1];
             $data['compiler']['build_date_timestamp'] = strtotime($conf[1]);
         }
     }
     // grab the file formats available to ffmpeg
     $formatmatches = array();
     $data['formats'] = array();
     if (preg_match_all('/ (DE|D|E) (.*) {1,} (.*)/', $formats, $formatmatches)) {
         // 			loop and clean
         // Formats:
         //  D. = Demuxing supported
         //  .E = Muxing supported
         for ($i = 0, $a = count($formatmatches[0]); $i < $a; $i++) {
             $data['formats'][strtolower(trim($formatmatches[2][$i]))] = array('mux' => $formatmatches[1][$i] == 'DE' || $formatmatches[1][$i] == 'E', 'demux' => $formatmatches[1][$i] == 'DE' || $formatmatches[1][$i] == 'D', 'fullname' => $formatmatches[3][$i]);
         }
     }
     // grab the codecs available
     $codecsmatches = array();
     $data['codecs'] = array('video' => array(), 'audio' => array(), 'subtitle' => array());
     if (preg_match_all('/ ((?:[DEVAST ]{6})|(?:[DEVASTFB ]{8})|(?:[DEVASIL\\.]{6})) ([A-Za-z0-9\\_]+) (.+)/', $codecs, $codecsmatches)) {
         // FFmpeg 0.12+
         //  D..... = Decoding supported
         //  .E.... = Encoding supported
         //  ..V... = Video codec
         //  ..A... = Audio codec
         //  ..S... = Subtitle codec
         //  ...I.. = Intra frame-only codec
         //  ....L. = Lossy compression
         //  .....S = Lossless compression
         // FFmpeg other
         //  D..... = Decoding supported
         //  .E.... = Encoding supported
         //  ..V... = Video codec
         //  ..A... = Audio codec
         //  ..S... = Subtitle codec
         //  ...S.. = Supports draw_horiz_band
         //  ....D. = Supports direct rendering method 1
         //  .....T = Supports weird frame truncation
         for ($i = 0, $a = count($codecsmatches[0]); $i < $a; $i++) {
             $options = preg_split('//', $codecsmatches[1][$i], -1, PREG_SPLIT_NO_EMPTY);
             if ($options) {
                 $id = trim($codecsmatches[2][$i]);
                 $type = $options[2] === 'V' ? 'video' : ($options[2] === 'A' ? 'audio' : 'subtitle');
                 switch ($options[2]) {
                     // 					video
                     case 'V':
                         $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === TRUE && $options[1] === 'E', 'decode' => isset($options[0]) === TRUE && $options[0] === 'D', 'draw_horizontal_band' => isset($options[3]) === TRUE && $options[3] === 'S', 'direct_rendering_method_1' => isset($options[4]) === TRUE && $options[4] === 'D', 'weird_frame_truncation' => isset($options[5]) === TRUE && $options[5] === 'T', 'fullname' => trim($codecsmatches[3][$i]));
                         break;
                         // 					audio
                     // 					audio
                     case 'A':
                         // 					subtitle
                     // 					subtitle
                     case 'S':
                         $data['codecs'][$type][$id] = array('encode' => isset($options[1]) === TRUE && $options[1] === 'E', 'decode' => isset($options[0]) === TRUE && $options[0] === 'D', 'fullname' => trim($codecsmatches[3][$i]));
                         break;
                 }
             }
         }
     }
     // grab the bitstream filters available to ffmpeg
     $data['filters'] = array();
     $locate = 'Bitstream filters:';
     if (!empty($filters) && ($pos = strpos($filters, $locate)) !== FALSE) {
         $filters = trim(substr($filters, $pos + strlen($locate)));
         $data['filters'] = explode("\n", $filters);
     }
     // grab the file protocols available to ffmpeg
     $data['protocols'] = array();
     $locate = 'Supported file protocols:';
     if (!empty($protocols) && ($pos = strpos($protocols, $locate)) !== FALSE) {
         $protocols = trim(substr($filters, $pos + strlen($locate)));
         $data['protocols'] = explode("\n", $protocols);
     }
     // grab the pixel formats available to ffmpeg
     $data['pixelformats'] = array();
     // Separate code for FFmpeg 0.5
     if (strpos($pixformats, 'Pixel formats') === FALSE) {
         // Format:
         // name       nb_channels depth is_alpha
         // yuv420p         3         8      n
         // yuyv422         1         8      n
         $matches = array();
         preg_match_all('#(\\w+)\\s+(\\d+)\\s+(\\d+)\\s+(y|n)#', $pixformats, $matches, PREG_SET_ORDER);
         foreach ($matches as $match) {
             $data['pixelformats'][$match[1]] = array('encode' => TRUE, 'decode' => TRUE, 'components' => intval($match[2]), 'bpp' => intval($match[3]));
         }
     } else {
         // Format:
         // Pixel formats:
         // I.... = Supported Input  format for conversion
         // .O... = Supported Output format for conversion
         // ..H.. = Hardware accelerated format
         // ...P. = Paletted format
         // ....B = Bitstream format
         // FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL
         // -----
         // IO... yuv420p                3            12
         $matches = array();
         preg_match_all('#(I|\\.)(O|\\.)(H|\\.)(P|\\.)(B|\\.)\\s+(\\w+)\\s+(\\d+)\\s+(\\d+)#', $pixformats, $matches, PREG_SET_ORDER);
         foreach ($matches as $match) {
             $data['pixelformats'][$match[6]] = array('encode' => $match[1] == 'I', 'decode' => $match[2] == 'O', 'components' => intval($match[7]), 'bpp' => intval($match[8]));
         }
     }
     // grab the command line options available to ffmpeg
     $data['commandoptions'] = array();
     $matches = array();
     preg_match_all('#\\n-(\\w+)(?:\\s+<(int|string|binary|flags|int64|float|rational)>)?#', $help, $matches, PREG_SET_ORDER);
     foreach ($matches as $match) {
         $data['commandoptions'][$match[1]] = array('datatype' => isset($match[2]) ? $match[2] : NULL);
     }
     PHPVideoToolkit::$ffmpeg_info = $data;
     // cache the data
     if ($cache_file !== FALSE && $read_from_cache === TRUE) {
         $data['_cache_date'] = time();
         file_put_contents($cache_file, '<?php $info = ' . var_export($data, TRUE) . ';');
     }
     return $data;
 }