[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/video/transcoders/ -> video_ffmpeg.inc (source)

   1  <?php
   2  /*
   3   * @file
   4   * Transcoder class file to handle ffmpeg settings and conversions.
   5   */
   6  class video_ffmpeg implements transcoder_interface {
   7    private $name = 'Locally Installed Transcoder (FFmpeg/Handbreke/Mcoder)';
   8    private $value = 'video_ffmpeg';
   9  
  10    protected $nice;
  11    protected $thumbcmdoptions;
  12    protected $enablefaststart;
  13    protected $faststartcmd;
  14    protected $cmdpath;
  15    protected $logcommands;
  16  
  17    public function __construct() {
  18      $this->nice = variable_get('video_ffmpeg_nice_enable', FALSE) ? 'nice -n 19 ' : '';
  19      $this->thumbcmdoptions = variable_get('video_ffmpeg_thumbnailer_options', '-i !videofile -an -y -f mjpeg -ss !seek -vframes 1 !thumbfile');
  20      $this->enablefaststart = variable_get('video_ffmpeg_enable_faststart', FALSE);
  21      $this->faststartcmd = variable_get('video_ffmpeg_faststart_cmd', '/usr/bin/qt-faststart');
  22      $this->cmdpath = variable_get('video_transcoder_path', '/usr/bin/ffmpeg');
  23      $this->logcommands = (bool)variable_get('video_ffmpeg_log_commands', TRUE);
  24    }
  25  
  26    /**
  27     * Run the specified command
  28     * 
  29     * The nice prefix is automatically added.
  30     * The command is logged if the settings specify that all commands should be logged.
  31     * The command and error are logged if the command results in an error
  32     * 
  33     * @param string $command
  34     * @param string $output Output of the command
  35     * @param string $purpose Purpose of the command. This is logged.
  36     * @param bool $ignoreoutputfilenotfound Whether to the output file not found error. Useful for input file information.
  37     */
  38    private function run_command($command, &$output, $purpose = NULL, $ignoreoutputfilenotfound = FALSE) {
  39      $output = '';
  40      $command = $this->nice . $command .' 2>&1';
  41      $purposetext = !empty($purpose) ? (' '. t('for') .' '. $purpose) : '';
  42  
  43      if ($this->logcommands) {
  44        watchdog('video_ffmpeg', 'Executing ffmpeg command!purposetext: <pre>@command</pre>', array('@command' => $command, '!purposetext' => $purposetext), WATCHDOG_DEBUG);
  45      }
  46  
  47      $return_var = 0;
  48  
  49      ob_start();
  50      passthru($command, &$return_var);
  51      $output = ob_get_clean();
  52  
  53      // Returnvar 1 means input file not found. This is normal for information calls.
  54      if ($return_var != 0 && ($return_var != 1 || !$ignoreoutputfilenotfound)) {
  55        watchdog('video_ffmpeg',
  56            'Error executing ffmpeg command!purposetext:<br/><pre>@command</pre>Output:<br/><pre>@output</pre>',
  57          array('@command' => $command, '@output' => trim($output), '!purposetext' => $purposetext),
  58          WATCHDOG_ERROR);
  59        return FALSE;
  60      }
  61  
  62      return TRUE;
  63    }
  64  
  65    public function generate_thumbnails($video) {
  66      global $user;
  67      
  68      $final_thumb_path = video_thumb_path($video);
  69      $total_thumbs = variable_get('video_thumbs', 5);
  70  
  71      $files = NULL;
  72      for ($i = 1; $i <= $total_thumbs; $i++) {
  73        $filename = '/video-thumb-for-'. $video['fid'] .'-'. $i .'.jpg';
  74        $thumbfile = $final_thumb_path . $filename;
  75        
  76        //skip files already exists, this will save ffmpeg traffic
  77        if (!is_file($thumbfile)) {
  78          if (!isset($duration)) {
  79            $duration = $this->get_playtime($video['filepath']);
  80          }
  81          $seek = ($duration / $total_thumbs) * $i - 1;  //adding minus one to prevent seek times equaling the last second of the video
  82          //setup the command to be passed to the transcoder.
  83          $command = $this->cmdpath .' '. strtr($this->thumbcmdoptions, array('!videofile' => escapeshellarg($video['filepath']), '!seek' => $seek, '!thumbfile' => $thumbfile));
  84  
  85          // Generate the thumbnail from the video.
  86          $command_output = '';
  87          $this->run_command($command, $command_output, t('generating thumbnails'));
  88          
  89          // don't consider zero-byte files a success
  90          $exists = file_exists($thumbfile);
  91          if (!$exists || filesize($thumbfile) == 0) {
  92            $params = array('%file' => $thumbfile, '%video' => $video['filename']);
  93            
  94            if ($exists) {
  95              $error_msg = 'Error generating thumbnail for video %video: generated file %file is empty. This problem may be caused by a broken video file. The video reports that its length is @duration seconds. If this is wrong, please recreate the video and try again.';
  96              $params['@duration'] = $duration;
  97              unlink($thumbfile);
  98            }
  99            else {
 100              $error_msg = 'Error generating thumbnail for video %video: generated file %file does not exist.';
 101            }
 102            
 103            // Log the error message and break. Other thumbnails probably will not be generated as well.
 104            watchdog('video_ffmpeg', $error_msg, $params, WATCHDOG_ERROR);
 105            drupal_set_message(t($error_msg, $params), 'error');
 106            break;
 107          }
 108        }
 109        
 110        // Begin building the file object.
 111        // @TODO : use file_munge_filename()
 112        $file = new stdClass();
 113        $file->uid = $user->uid;
 114        $file->status = FILE_STATUS_TEMPORARY;
 115        $file->filename = $filename;
 116        $file->filepath = $thumbfile;
 117        $file->filemime = 'image/jpeg';
 118        $file->filesize = filesize($thumbfile);
 119        $file->timestamp = time();
 120        $files[] = $file;
 121      }
 122      return $files;
 123    }
 124  
 125    public function convert_video($video) {
 126      // This will update our current video status to active.
 127      $this->change_status($video->vid, VIDEO_RENDERING_ACTIVE);
 128  
 129      // Get the converted file object
 130      //we are going to move our video to an "original" folder
 131      //we are going to transcode the video to the "converted" folder
 132      // @TODO This about getting the correct path from the filefield if they active it
 133      $files = file_create_path();
 134      $originaldir = $files .'/videos/original';
 135      $converteddir = $files .'/videos/converted';
 136  
 137      if (!field_file_check_directory($originaldir, FILE_CREATE_DIRECTORY)) {
 138        watchdog('video_ffmpeg', 'Video conversion failed. Could not create directory %dir for storing original videos.', array('%dir' => $originaldir), WATCHDOG_ERROR);
 139        return false;
 140      }
 141      if (!field_file_check_directory($converteddir, FILE_CREATE_DIRECTORY)) {
 142        watchdog('video_ffmpeg', 'Video conversion failed. Could not create directory %dir for storing converted videos.', array('%dir' => $converteddir), WATCHDOG_ERROR);
 143        return false;
 144      }
 145  
 146      $original = $originaldir .'/'. $video->filename;
 147      //lets move our video and then convert it.
 148      if (!file_move($video, $original)) {
 149        watchdog('video_ffmpeg', 'Could not move video %orig to the original folder.', array('%orig' => $video->filepath), WATCHDOG_ERROR);
 150        $this->change_status($video->vid, VIDEO_RENDERING_FAILED);
 151        return FALSE;
 152      }
 153  
 154      // Update our filepath since we moved it
 155      drupal_write_record('files', $video, 'fid');
 156  
 157      // Increase the database timeout to prevent database errors after a long upload
 158      _video_db_increase_timeout();
 159  
 160      // Get video information before doing a chdir
 161      $dimensions = $this->dimensions($video);
 162      $dimension = explode('x', $dimensions, 2);
 163      $filepath = realpath($video->filepath);
 164  
 165      // Make the directories absolute
 166      $originaldir = realpath($originaldir);
 167      $converteddir = realpath($converteddir);
 168  
 169      // Create a temporary directory
 170      $drupaldir = getcwd();
 171      $drupaldirrp = realpath($drupaldir);
 172      $tmpdir = tempnam(file_directory_temp(), 'ffmpeg-'. $video->fid);
 173      unlink($tmpdir);
 174      mkdir($tmpdir, 0777);
 175      chdir($tmpdir);
 176  
 177      $result = TRUE;
 178      
 179      // process presets
 180      $presets = $video->presets;
 181      $converted_files = array();
 182      foreach ($presets as $presetname => $preset) {
 183        //update our filename after the move to maintain filename uniqueness.
 184        $converted = file_create_filename(str_replace(' ', '_', pathinfo($video->filepath, PATHINFO_FILENAME)) .'.'. $preset['extension'], $converteddir);
 185  
 186        //call our transcoder
 187        $ffmpeg_output = $converted;
 188        if ($this->enablefaststart && ($preset['extension'] == 'mp4' || $preset['extension'] == 'mov')) {
 189          $ffmpeg_output = file_directory_temp() .'/'. basename($converted);
 190        }
 191  
 192        $command_output = '';
 193  
 194        // Setup our default command to be run.
 195        foreach ($preset['command'] as $command) {
 196          $command = strtr($command, array(
 197            '!cmd_path' => $this->cmdpath,
 198            '!videofile' => escapeshellarg($filepath),
 199            '!audiobitrate' => $preset['audio_bitrate'],
 200            '!width' => intval($dimension[0]),
 201            '!height' => intval($dimension[1]),
 202            '!videobitrate' => $preset['video_bitrate'],
 203            '!convertfile' => escapeshellarg($ffmpeg_output),
 204          ));
 205  
 206          // Process our video
 207          if (!$this->run_command($command, $command_output, t('rendering preset %preset', array('%preset' => $presetname)))) {
 208            $result = FALSE;
 209            break 2;
 210          }
 211        }
 212  
 213        if ($ffmpeg_output != $converted && file_exists($ffmpeg_output)) {
 214          // Because the transcoder_interface doesn't allow the run_command() to include the ability to pass
 215          // the command to be execute so we need to fudge the command to run qt-faststart.
 216          $command_result = $this->run_command($this->faststartcmd .' '. $ffmpeg_output .' '. $converted, $command_output, t('running qt-faststart'));
 217  
 218          // Delete the temporary output file.
 219          file_delete($ffmpeg_output);
 220        }
 221  
 222        //lets check to make sure our file exists, if not error out
 223        if (!file_exists($converted) || ($filesize = filesize($converted)) === 0) {
 224          watchdog('video_ffmpeg', 'Video conversion failed for preset %preset: result file was not found.', array('%preset' => $presetname), WATCHDOG_ERROR);
 225          $result = FALSE;
 226          break;
 227        }
 228  
 229        $converted = realpath($converted);
 230  
 231        //Create result object
 232        $converted_files[] = $file = new stdClass();
 233        $file->vid = intval($video->vid);
 234        $file->filename = basename($converted);
 235        $file->filepath = substr($converted, strlen($drupaldirrp) + 1);
 236        $file->filemime = file_get_mimetype($converted);
 237        $file->filesize = $filesize;
 238        $file->preset = $presetname;
 239      }
 240  
 241      chdir($drupaldir);
 242      rmdirr($tmpdir);
 243  
 244      // Update our video_files table with the converted video information.
 245      if ($result) {
 246        $result = db_query('UPDATE {video_files} SET status = %d, completed = %d, data = "%s" WHERE vid = %d', VIDEO_RENDERING_COMPLETE, time(), serialize($converted_files), $video->vid);
 247  
 248        // Prepare the watchdog statement
 249        $destinationfiles = array();
 250        foreach ($converted_files as $file) {
 251          $destinationfiles[] = $file->filepath;
 252        }
 253        watchdog('video_ffmpeg', 'Successfully converted %orig to !destination-files', array('%orig' => $video->filepath, '!destination-files' => implode(', ', $destinationfiles)), WATCHDOG_INFO);
 254      }
 255      else {
 256        // Remove files that have been created
 257        foreach ($converted_files as $file) {
 258          file_delete($file->filepath);
 259        }
 260  
 261        // Try to move back the original file
 262        file_move($video, $files .'/videos');
 263        drupal_write_record('files', $video, 'fid');
 264  
 265        $this->change_status($video->vid, VIDEO_RENDERING_FAILED);
 266      }
 267  
 268      return $result;
 269    }
 270  
 271    /**
 272     * Get some information from the video file
 273     */
 274    private function get_video_info($video) {
 275      $command = $this->cmdpath .' -i '. escapeshellarg($video);
 276  
 277      // Execute the command
 278      $output = '';
 279      if ($this->run_command($command, $output, t('retrieving video info'), true)) {
 280        return $output;
 281      }
 282  
 283      return NULL;
 284    }
 285  
 286    /**
 287     * Return the playtime seconds of a video
 288     */
 289    public function get_playtime($video) {
 290      $ffmpeg_output = $this->get_video_info($video);
 291      // Get playtime
 292      $pattern = '/Duration: ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9])/';
 293      preg_match_all($pattern, $ffmpeg_output, $matches, PREG_PATTERN_ORDER);
 294      $playtime = $matches[1][0];
 295      // ffmpeg return length as 00:00:31.1 Let's get playtime from that
 296      $hmsmm = explode(':', $playtime);
 297      $tmp = explode('.', $hmsmm[2]);
 298      $seconds = $tmp[0];
 299      $hours = $hmsmm[0];
 300      $minutes = $hmsmm[1];
 301      return $seconds + ($hours * 3600) + ($minutes * 60);
 302    }
 303  
 304    /*
 305     * Return the dimensions of a video
 306     */
 307  
 308    public function get_dimensions($video) {
 309      $ffmpeg_output = $this->get_video_info($video);
 310      $res = array('width' => 0, 'height' => 0);
 311      // Get dimensions
 312      $regex = ereg('[0-9]?[0-9][0-9][0-9]x[0-9][0-9][0-9][0-9]?', $ffmpeg_output, $regs);
 313      if (isset($regs[0])) {
 314        $dimensions = explode("x", $regs[0]);
 315        $res['width'] = $dimensions[0] ? $dimensions[0] : NULL;
 316        $res['height'] = $dimensions[1] ? $dimensions[1] : NULL;
 317      }
 318      return $res;
 319    }
 320  
 321    /**
 322     * Interface Implementations
 323     * @see sites/all/modules/video/includes/transcoder_interface#get_name()
 324     */
 325    public function get_name() {
 326      return $this->name;
 327    }
 328  
 329    /**
 330     * Interface Implementations
 331     * @see sites/all/modules/video/includes/transcoder_interface#get_value()
 332     */
 333    public function get_value() {
 334      return $this->value;
 335    }
 336  
 337    /**
 338     * Interface Implementations
 339     * @see sites/all/modules/video/includes/transcoder_interface#get_help()
 340     */
 341    public function get_help() {
 342      return l(t('FFMPEG Online Manual'), 'http://www.ffmpeg.org/');
 343    }
 344  
 345    /**
 346     * Interface Implementations
 347     * @see sites/all/modules/video/includes/transcoder_interface#admin_settings()
 348     */
 349    public function admin_settings() {
 350      $form = array();
 351      $form['video_ffmpeg_start'] = array(
 352        '#type' => 'markup',
 353        '#value' => '<div id="video_ffmpeg">',
 354      );
 355  
 356      $form['video_transcoder_path'] = array(
 357        '#type' => 'textfield',
 358        '#title' => t('Path to Video Transcoder'),
 359        '#description' => t('Absolute path to ffmpeg.'),
 360        '#default_value' => $this->cmdpath,
 361      );
 362      $form['video_thumbs'] = array(
 363        '#type' => 'textfield',
 364        '#title' => t('Number of thumbnails'),
 365        '#description' => t('Number of thumbnails to display from video.'),
 366        '#default_value' => variable_get('video_thumbs', 5),
 367      );
 368      $form['video_ffmpeg_nice_enable'] = array(
 369        '#type' => 'checkbox',
 370        '#title' => t('Enable the use of nice when calling the ffmpeg command.'),
 371        '#default_value' => variable_get('video_ffmpeg_nice_enable', TRUE),
 372        '#description' => t('The nice command Invokes a command with an altered scheduling priority.  This option may not be available on windows machines, so disable it.')
 373      );
 374      $form['video_ffmpeg_log_commands'] = array(
 375        '#type' => 'checkbox',
 376        '#title' => t('Log all executed commands to the Drupal log.'),
 377        '#default_value' => $this->logcommands,
 378        '#description' => t('Enable this option when debugging ffmpeg encoding to log all commands to the <a href="@dblog-page">Drupal log</a>. This may help with debugging ffmpeg problems. When this option is disabled, only errors will be logged.', array('@dblog-page' => url('admin/reports/dblog')))
 379      );
 380      // Thumbnail Videos We need to put this stuff last.
 381      $form['autothumb'] = array(
 382        '#type' => 'fieldset',
 383        '#title' => t('Video Thumbnails'),
 384        '#collapsible' => TRUE,
 385        '#collapsed' => TRUE,
 386      );
 387      $form['autothumb']['video_thumb_path'] = array(
 388        '#type' => 'textfield',
 389        '#title' => t('Path to save thumbnails'),
 390        '#description' => t('Path to save video thumbnails extracted from the videos.'),
 391        '#default_value' => variable_get('video_thumb_path', 'video_thumbs'),
 392      );
 393      $form['autothumb']['advanced'] = array(
 394        '#type' => 'fieldset',
 395        '#title' => t('Advanced Settings'),
 396        '#collapsible' => TRUE,
 397        '#collapsed' => TRUE
 398      );
 399      $form['autothumb']['advanced']['video_ffmpeg_thumbnailer_options'] = array(
 400        '#type' => 'textarea',
 401        '#title' => t('Video thumbnailer options'),
 402        '#description' => t('Provide the options for the thumbnailer.  Available argument values are: ') . '<ol><li>' . t('!videofile (the video file to thumbnail)') . '<li>' . t('!thumbfile (a newly created temporary file to overwrite with the thumbnail)</ol>'),
 403        '#default_value' => $this->thumbcmdoptions,
 404      );
 405  
 406      // Video conversion settings.
 407      $form['autoconv'] = array(
 408        '#type' => 'fieldset',
 409        '#title' => t('Video Conversion'),
 410        '#collapsible' => TRUE,
 411        '#collapsed' => TRUE
 412      );
 413      $form['autoconv']['video_ffmpeg_enable_faststart'] = array(
 414        '#type' => 'checkbox',
 415        '#title' => t('Process mov/mp4 videos with qt-faststart'),
 416        '#default_value' => $this->enablefaststart,
 417      );
 418      $form['autoconv']['video_ffmpeg_faststart_cmd'] = array(
 419        '#type' => 'textfield',
 420        '#title' => t('Path to qt-faststart'),
 421        '#default_value' => $this->faststartcmd,
 422      );
 423  
 424      $form['autoconv']['video_ffmpeg_pad_method'] = array(
 425        '#type' => 'radios',
 426        '#title' => t('FFmpeg Padding method'),
 427        '#default_value' => variable_get('video_ffmpeg_pad_method', 0),
 428        '#options' => array(
 429          0 => t('Use -padtop, -padbottom, -padleft, -padright for padding'),
 430          1 => t('Use -vf "pad:w:h:x:y:c" for padding'),
 431        ),
 432      );
 433  
 434      $form['video_ffmpeg_end'] = array(
 435        '#type' => 'markup',
 436        '#value' => '</div>',
 437      );
 438      return $form;
 439    }
 440  
 441    /**
 442     * Interface Implementations
 443     * @see sites/all/modules/video/includes/transcoder_interface#admin_settings_validate()
 444     */
 445    public function admin_settings_validate($form, &$form_state) {
 446      return;
 447    }
 448  
 449    public function create_job($video) {
 450      if (empty($video['dimensions'])) {
 451        watchdog('video_ffmpeg', 'Tried to create ffmpeg job for video %video with empty dimensions value.', array('%video' => $video['fid']), WATCHDOG_ERROR);
 452        return FALSE;
 453      }
 454      
 455      return db_query("INSERT INTO {video_files} (fid, status, dimensions) VALUES (%d, %d, '%s')", $video['fid'], VIDEO_RENDERING_PENDING, $video['dimensions']);
 456    }
 457  
 458    public function update_job($video) {
 459      if (!$this->load_job($video['fid']))
 460        return;
 461      //lets update our table to include the nid
 462      db_query("UPDATE {video_files} SET nid=%d WHERE fid=%d", $video['nid'], $video['fid']);
 463    }
 464  
 465    public function delete_job($video) {
 466      if (!$this->load_job($video->fid))
 467        return;
 468      //lets get all our videos and unlink them
 469      $sql = db_query("SELECT data FROM {video_files} WHERE fid=%d", $video->fid);
 470      //we loop here as future development will include multiple video types (HTML 5)
 471      while ($row = db_fetch_object($sql)) {
 472        $data = unserialize($row->data);
 473        if (empty($data))
 474          continue;
 475        foreach ($data as $file) {
 476          if (file_exists($file->filepath))
 477            unlink($file->filepath);
 478        }
 479      }
 480      //now delete our rows.
 481      db_query('DELETE FROM {video_files} WHERE fid = %d', $video->fid);
 482    }
 483  
 484    public function load_job($fid) {
 485      $job = null;
 486      $result = db_query('SELECT f.*, vf.vid, vf.nid, vf.dimensions, vf.status as video_status FROM {video_files} vf LEFT JOIN {files} f ON vf.fid = f.fid WHERE f.fid=vf.fid AND f.fid = %d', $fid);
 487      $job = db_fetch_object($result);
 488      if (!empty($job))
 489        return $job;
 490      else
 491        return FALSE;
 492    }
 493  
 494    public function load_job_queue() {
 495      $total_videos = variable_get('video_ffmpeg_instances', 5);
 496      $videos = array();
 497      $result = db_query_range('SELECT f.*, vf.vid, vf.nid, vf.dimensions, vf.status as video_status FROM {video_files} vf LEFT JOIN {files} f ON vf.fid = f.fid WHERE vf.status = %d AND f.status = %d ORDER BY f.timestamp', VIDEO_RENDERING_PENDING, FILE_STATUS_PERMANENT, 0, $total_videos);
 498  
 499      while ($row = db_fetch_object($result)) {
 500        $videos[] = $row;
 501      }
 502      return $videos;
 503    }
 504  
 505    /**
 506     * @todo : replace with the load job method
 507     * @param <type> $video
 508     * @return <type>
 509     */
 510    public function load_completed_job(&$video) {
 511      $result = db_fetch_object(db_query('SELECT * FROM {video_files} WHERE fid = %d', $video->fid));
 512      $data = unserialize($result->data);
 513      if (empty($data))
 514        return $video;
 515      foreach ($data as $value) {
 516        $extension = pathinfo($value->filepath, PATHINFO_EXTENSION);
 517        $video->files->{$extension}->filename = pathinfo($value->filepath, PATHINFO_FILENAME) . '.' . $extension;
 518        $video->files->{$extension}->filepath = $value->filepath;
 519        $video->files->{$extension}->url = file_create_url($value->filepath);
 520        $video->files->{$extension}->extension = $extension;
 521        $video->files->{$extension}->filemime = file_get_mimetype($value->filepath);
 522        $video->player = strtolower($extension);
 523      }
 524      return $video;
 525    }
 526  
 527    /**
 528     * Change the status of the file.
 529     *
 530     * @param (int) $vid
 531     * @param (int) $status
 532     */
 533    public function change_status($vid, $status) {
 534      $result = db_query('UPDATE {video_files} SET status = %d WHERE vid = %d ', $status, $vid);
 535    }
 536  
 537    /*
 538     * Function determines the dimensions you want and compares with the actual wxh of the video.
 539     *
 540     * If they are not exact or the aspect ratio does not match, we then figure out how much padding
 541     * we should add.  We will either add a black bar on the top/bottom or on the left/right.
 542     *
 543     * @TODO I need to look more at this function.  I don't really like the guess work here.  Need to implement
 544     * a better way to check the end WxH.  Maybe compare the final resolution to our defaults?  I don't think
 545     * that just checking to make sure the final number is even is accurate enough.
 546     */
 547  
 548    public function dimensions($video) {
 549      //lets setup our dimensions.  Make sure our aspect ratio matches the dimensions to be used, if not lets add black bars.
 550      $aspect_ratio = _video_aspect_ratio($video->filepath);
 551      $ratio = $aspect_ratio['ratio'];
 552      $width = $aspect_ratio ['width'];
 553      $height = $aspect_ratio['height'];
 554  
 555      $wxh = explode('x', $video->dimensions);
 556      $output_width = $wxh[0];
 557      $output_height = $wxh[1];
 558      $output_ratio = number_format($output_width / $output_height, 4);
 559  
 560      if ($output_ratio != $ratio && $width && $height) {
 561        // TODO this probably doesn't work
 562        $options = array();
 563        // Figure out our black bar padding.
 564        if ($ratio < $output_width / $output_height) {
 565          $end_width = $output_height * $ratio;
 566          $end_height = $output_height;
 567        } else {
 568          $end_height = $output_width / $ratio;
 569          $end_width = $output_width;
 570        }
 571  
 572        // We need to get back to an even resolution and maybe compare with our defaults?
 573        // @TODO Make this more exact on actual video dimensions instead of making sure the wxh are even numbers
 574  
 575        if ($end_width == $output_width) {
 576          // We need to pad the top/bottom of the video
 577          $padding = round($output_height - $end_height);
 578          $pad1 = $pad2 = floor($padding / 2);
 579          if ($pad1 % 2 !== 0) {
 580            $pad1++;
 581            $pad2--;
 582          }
 583          if (variable_get('video_ffmpeg_pad_method', 0)) {
 584            $options[] = '-vf "pad=' . round($output_width) . ':' . round($output_height) . ':0:' . $pad1 . '"';
 585          } else {
 586            $options[] = '-padtop ' . $pad1;
 587            $options[] = '-padbottom ' . $pad2;
 588          }
 589        } else {
 590          // We are padding the left/right of the video.
 591          $padding = round($output_width - $end_width);
 592          $pad1 = $pad2 = floor($padding / 2);  //@todo does padding need to be an even number?
 593          if ($pad1 % 2 !== 0) {
 594            $pad1++;
 595            $pad2--;
 596          }
 597          if (variable_get('video_ffmpeg_pad_method', 0)) {
 598            $options[] = '-vf "pad=' . round($output_width) . ':' . round($output_height) . ':' . $pad1 . ':0"';
 599          } else {
 600            $options[] = '-padleft ' . $pad1;
 601            $options[] = '-padright ' . $pad2;
 602          }
 603        }
 604  
 605        $end_width = round($end_width) % 2 !== 0 ? round($end_width) + 1 : round($end_width);
 606        $end_height = round($end_height) % 2 !== 0 ? round($end_height) + 1 : round($end_height);
 607        //add our size to the beginning to make sure it hits our -s
 608        array_unshift($options, $end_width . 'x' . $end_height);
 609        return implode(' ', $options);
 610      }
 611      else {
 612        return $video->dimensions;
 613      }
 614    }
 615  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7