<?php
  class sfConversion {
    public static function ScaleAspect(&$width, &$height, $maxWidth, $maxHeight) {
      $sx = $maxWidth / $width;
      $sy = $maxHeight / $height;
      if ($sx>$sy) $sx = $sy;
      $width = round($width * $sx / 2) * 2;
      $height = round($height * $sx / 2) * 2;
    }

    /**
     * Enter description here...
     *
     * @param unknown_type $fileName
     * @param unknown_type $fileThumb
     * @param unknown_type $time
     * @param unknown_type $info
     * @return unknown
     */
    public static function FlvToThumbnail($fileName, $fileThumb, $time = null, $info = null) {
      try {
        if ($info==null) $info = self::GetVideoInfo($fileName);

        if (!isset($info['ID_VIDEO_FORMAT'])) return false;
        if (!isset($info['ID_LENGTH'])) return false;
        $width = doubleval($info['ID_VIDEO_WIDTH']);
        $height = doubleval($info['ID_VIDEO_HEIGHT']);

        self::ScaleAspect($width, $height, 150, 100);

        if ($time===null) $time = doubleval($info['ID_LENGTH']) / 2;

        $logFileName = 'convert_flv_thumb.log';

        // no .THM file so need to use ffmpeg to get tumbnail image
    		//ffmpeg -y -i MVI_6640.AVI -s qcif -f mjpeg -t 0.001 movie.jpg
    		$ffmpeg_cmd = sfConfig::get('app_ffmpeg_exe');
    		$command = "$ffmpeg_cmd -y -v 0 -itsoffset -$time -i ". escapeshellarg($fileName) ." -s {$width}x{$height} -f mjpeg -vframes 1 ". escapeshellarg($fileThumb);
    		//myUtility::log("\n\n\n********".$command, $logFileName);

    		$descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
           2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
        $process = proc_open($command, $descriptorspec, $pipes);
        if (is_resource($process)) {
          $ret = true;
          while (!feof($pipes[2])) {
            $line = fgets($pipes[2],1024);
            //myUtility::log($line, $logFileName);
            if (preg_match('@: no such file or directory@', $line)) $ret = false;
            if (preg_match('@^Error while opening codec for output stream@', $line)) $ret = false;
            if (preg_match('@Unknown format@', $line)) $ret = false;
          }
          fclose($pipes[2]);
          proc_close($process);
          return $ret;
        } else return false;
      } catch (Exception $e) {
        myUtility::log($e->getMessage(), $logFileName);
        return false;
      }
    }

    public static function ImageToJpg($imageName, $jpgName) {
      $convert_cmd = sfConfig::get('app_convert_exe');
      $command = "$convert_cmd ". escapeshellarg($imageName) ." ". escapeshellarg($jpgName);
      $descriptorspec = array(
         0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
         1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
      );
      $process = proc_open($command, $descriptorspec, $pipes);
      if (is_resource($process)) {
        while (!feof($pipes[1])) {
          $line = fgets($pipes[1], 1024);
        }
        fclose($pipes[1]);
        proc_close($process);
      }
    }

    public static function MovieToFlv($movieName, $flvName) {
      try {
        $logFileName = 'convert_flv.log';
        $ffmpeg_cmd = sfConfig::get('app_ffmpeg_exe');

    		// generate the Flash FLV version of the file
      	// cif = 352x288
      	$command = "$ffmpeg_cmd -y -v 0 -i ". escapeshellarg($movieName) ." -s cif -ar 44100 -r 15 ". escapeshellarg($flvName);
      	//myUtility::log("\n\n\n********".$command, $logFileName);

      	$descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
           2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
      	$process = proc_open($command, $descriptorspec, $pipes);
        if (is_resource($process)) {
          $ret = true;
          while (!feof($pipes[2])) {
            $line = fgets($pipes[2],1024);
            //myUtility::log($line, $logFileName);
            if (preg_match('@: no such file or directory@', $line)) $ret = false;
            if (preg_match('@^Error while opening codec for output stream@', $line)) $ret = false;
            if (preg_match('@Unknown format@', $line)) $ret = false;
          }
          fclose($pipes[2]);
          proc_close($process);
          return $ret;
        } else return false;
      } catch (Exception $e) {
        myUtility::log($e->getMessage(), $logFileName);
        return false;
      }
    }

    /**
     * Get Video info
     *
     * @param unknown_type $movieName
     * @return array of info
     *   'ID_VIDEO_WIDTH' => width of video
     *   'ID_VIDEO_HEIGHT' => height of video
     *   'ID_LENGTH' => lengh of video (in second)
     *   'ID_VIDEO_FORMAT' => video codec
     *   'ID_AUDIO_FORMAT' => audio codec
     */
    public static function GetVideoInfo($movieName) {
      try {
        $logFileName = 'video_info.log';
        $mplayer_cmd = sfConfig::get('app_mplayer_exe');

    		// generate the Flash FLV version of the file
      	// cif = 352x288
      	$command = "$mplayer_cmd -identify " . escapeshellarg($movieName) ." -ao null -vo null -frames 0";
      	//myUtility::log("\n\n\n********".$command, $logFileName);

      	$descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
           2 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
      	$process = proc_open($command, $descriptorspec, $pipes);
        if (is_resource($process)) {
          $ret = array();
          while (!feof($pipes[1])) {
            $line = fgets($pipes[1],1024);
            //myUtility::log($line, $logFileName);
            if (preg_match('@ID_VIDEO_FORMAT|ID_VIDEO_WIDTH|ID_VIDEO_HEIGHT|ID_AUDIO_FORMAT|ID_LENGTH@', $line)) {
              $col = explode('=', trim($line));
              $ret[$col[0]] = $col[1];
            }
          }
          fclose($pipes[1]);
          proc_close($process);
          return $ret;
        } else return false;
      } catch (Exception $e) {
        myUtility::log($e->getMessage(), $logFileName);
        return array();
      }
    }

    public static function SizeImage($maxWidth, $maxHW, $fileName, $thumbFileName, $allowBigger=true, $externalFileName=false) {
      try {
        $logFileName = 'convert_img.log';

        $width = intval($maxWidth); $height = intval($maxHW);
        if ($width==null || $height==null) return false;
        if (false==$allowBigger) {
          list($mwidth, $mheight) = self::getImageSize($fileName, $externalFileName);
          if ($mwidth==0 || $mheight==0) return  false;
          $mwidth = intval($mwidth); $mheight = intval($mheight);
          if ($mwidth<=$width && $mheight<=$height) {
            $width = $mwidth;
            $height = $mheight;
          }
        }

        $img_cmd = sfConfig::get('app_convert_exe');
        if ($externalFileName)
          $fileName = '"'.$fileName.'"';
        else
          $fileName = escapeshellarg($fileName);
      	$command = "$img_cmd -resize {$width}x{$height} -flatten -background white -verbose " . $fileName . ' ' . escapeshellarg($thumbFileName);
      	//myUtility::log("Execute ".$command, $logFileName, "\n");

      	$descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
      	$process = proc_open($command, $descriptorspec, $pipes);

      	if (is_resource($process)) {
      	  $ret = true;
      	  while (!feof($pipes[1])) {
            $line = fgets($pipes[1],1024);
            //if ($line != '') myUtility::log($line, $logFileName);
            if (preg_match('@missing an image filename@', $line)) $ret = false;
          }
          fclose($pipes[1]);
      	  proc_close($process);
      	  return $ret;
      	}
      	return false;
      } catch (Exception $e) {
        myUtility::log($e->getMessage(), $logFileName);
        return false;
      }
    }

    public static function FlvAddMeta($fileName) {
      try {
        $logFileName = 'meta_flv.log';
        $img_cmd = sfConfig::get('app_flvtool2_exe');

        $command = "$img_cmd -U " . escapeshellarg($fileName);
        $descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
        //myUtility::log($command, $logFileName);
        $process = proc_open($command, $descriptorspec, $pipes);

        if (is_resource($process)) {
          $ret = true;
          while (!feof($pipes[1])) {
            //myUtility::log($line, $logFileName);
            $line = fgets($pipes[1],1024);
          }
          fclose($pipes[1]);
          proc_close($process);
          return $ret;
        } else return false;
      } catch (Exception $e) {
        myUtility::log($e->getMessage(), $logFileName);
        return false;
      }
    }

    public static function getSWFImageSize($fileName) {
      try {
        $width = 640;
        $height = 480;

        $img_cmd =sfConfig::get('app_swfdump_exe');
        $command = "$img_cmd -X -Y " . escapeshellarg($fileName);
        $descriptorspec = array(
           0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
           1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        );
        $process = proc_open($command, $descriptorspec, $pipes);

        if (is_resource($process)) {
          while (!feof($pipes[1])) {
            $line = fgets($pipes[1],1024);
            if (preg_match('@-X ([0-9]+) -Y ([0-9]+)@', $line, $size)) {
              $width = intval($size[1]);
              $height = intval($size[2]);
            }
          }
          fclose($pipes[1]);
          proc_close($process);
        }
        return array($width, $height);
      } catch (Exception $e) {
        return array($width, $height);
      }
    }

    public static function getImageSize($fileName, $externalFile=false) {

      $length = strlen($fileName);
      $ext = $length>3?substr($fileName, $length-3, 3):'';
      $ext = strtolower($ext);
      if ($ext=='swf') return self::getSWFImageSize($fileName);
      $width = 0;
      $height = 0;

      if ($externalFile)
        $fileName = '"'.$fileName.'"';
      else
        $fileName = escapeshellarg($fileName);

      $img_cmd = sfConfig::get('app_identify_exe');
      $command = "$img_cmd -format %wx%h\\n " . $fileName;
      $descriptorspec = array(
         0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
         1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
      );
      $process = proc_open($command, $descriptorspec, $pipes);

      if (is_resource($process)) {
        $ret = true;
        while (!feof($pipes[1])) {
          $line = trim(fgets($pipes[1],1024));
          if (preg_match('@Improper image header@', $line)) $ret = false;
          if (preg_match('@Not a JPEG file@', $line)) $ret = false;
          if (preg_match('@no decode delegate for this image format@', $line)) $ret = false;
          if ($line!=null) {
            if ($width == null && preg_match('@([0-9]+)x([0-9]+)@', $line, $size)) {
              $width = intval($size[1]);
              $height = intval($size[2]);
            }
          }
        }
        fclose($pipes[1]);
        proc_close($process);
      } else $ret = false;
      return array($width, $height);
    }
  }
?>
