r61850 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r61849‎ | r61850 | r61851 >
Date:10:18, 2 February 2010
Author:dale
Status:deferred
Tags:
Comment:
* oggTranscode. Provides basic derivatives transcode script and derivatives lookup.
Modified paths:
  • /trunk/extensions/OggHandler/OggHandler.php (modified) (history)
  • /trunk/extensions/OggHandler/OggHandler_body.php (modified) (history)
  • /trunk/extensions/OggHandler/OggTranscode.php (added) (history)
  • /trunk/extensions/OggHandler/OggTranscode.sql (added) (history)
  • /trunk/extensions/OggHandler/OggTranscodeCron.php (added) (history)
  • /trunk/extensions/OggHandler/patch-image-index.sql (added) (history)

Diff [purge]

Index: trunk/extensions/OggHandler/OggTranscode.sql
@@ -0,0 +1,29 @@
 2+--
 3+-- Table structure for table `transcode_job`
 4+--
 5+
 6+CREATE TABLE IF NOT EXISTS /*_*/transcode_job (
 7+
 8+ --File name key ( called image to match table name )
 9+ tjob_name varbinary(255) NOT NULL,
 10+
 11+ --Derivative key of the transcode
 12+ tjob_derivative_key varbinary(40) NOT NULL,
 13+
 14+ -- Timestamp
 15+ `tjob_start_timestamp` char(14) NOT NULL,
 16+
 17+ -- Transcoding state
 18+ tjob_state enum('OK','ASSIGNED','FAILED') default NULL
 19+
 20+) /*$wgDBTableOptions*/;
 21+
 22+--
 23+-- Index for transcode_job_name
 24+--
 25+CREATE INDEX /*i*/transcode_job_name ON /*_*/transcode_job ( tjob_name );
 26+
 27+--
 28+-- Index for tjob_state
 29+--
 30+CREATE INDEX /*i*/transcode_job_state ON /*_*/transcode_job ( tjob_state );
Index: trunk/extensions/OggHandler/OggHandler_body.php
@@ -195,6 +195,15 @@
196196 // Set up the default targetUrl:
197197 $targetFileUrl = $file->getURL();
198198
 199+ // Check for $wgEnabledDerivatives
 200+ if ( isset( $wgEnabledDerivatives ) &&
 201+ is_array( $wgEnabledDerivatives ) &&
 202+ count( $wgEnabledDerivatives ) != 0
 203+ ){
 204+ // Get the derivative via embed width
 205+ //( will return $file->getURL() if no derivative is found )
 206+ $targetFileUrl = OggTranscode::getWidthDerivativeURL( $file, $width);
 207+ }
199208
200209 // Add temporal request parameter if $wgEnableTemporalOggUrls is on:
201210 if( $wgEnableTemporalOggUrls && isset( $params['start'] ) ){
@@ -203,31 +212,7 @@
204213 $targetFileUrl.='/'. seconds2npt( $this->parseTimeString( $params['end'], $length) );
205214 }
206215
207 - // Check if $wgEnabledDerivatives is "set" and we have a target derivative set:
208 - // (presently set by the wikiAtHome extension)
209 - if (isset( $wgEnabledDerivatives ) && is_array( $wgEnabledDerivatives ) && count( $wgEnabledDerivatives ) != 0){
210 - //get the encode key:
211 - $encodeKey = WikiAtHome::getTargetDerivative( $width, $file );
212 - if( $encodeKey == 'notransform'){
213 - $targetFileUrl = $file->getURL() ;
214 - }else{
215 - //get our job pointer
216 - $wjm = WahJobManager::newFromFile( $file , $encodeKey );
217216
218 - $derivativeUrl = $file->getThumbUrl( $wjm->getEncodeKey() . '.ogg');
219 - $derivativePath = $file->getThumbPath( $wjm->getEncodeKey() );
220 -
221 - // Check that we have the requested theora derivative
222 - if( is_file ( "{$derivativePath}.ogg" )){
223 - $targetFileUrl = $derivativeUrl;
224 - }else{
225 - // Output in queue text (send the dstUrl if available )
226 - return new MediaQueueTransformOutput($file, $dstUrl, $width, $height, $wjm->getDonePerc() );
227 - }
228 - }
229 - }
230 -
231 -
232217 if ( !$noPlayer ) {
233218 // Hack for miscellaneous callers
234219 global $wgOut;
Index: trunk/extensions/OggHandler/patch-image-index.sql
@@ -0,0 +1,14 @@
 2+--
 3+-- Add an index on img_media_type
 4+--
 5+CREATE INDEX /*i*/image_media_type ON /*_*/image ( img_media_type );
 6+
 7+--
 8+-- Index for transcode_job_name
 9+--
 10+CREATE INDEX /*i*/transcode_job_name ON /*_*/transcode_job ( tjob_name );
 11+
 12+--
 13+-- Index for tjob_state
 14+--
 15+CREATE INDEX /*i*/transcode_job_state ON /*_*/transcode_job ( tjob_state );
\ No newline at end of file
Index: trunk/extensions/OggHandler/OggTranscodeCron.php
@@ -0,0 +1,318 @@
 2+<?php
 3+
 4+/*
 5+* OggTranscodeCron.php
 6+*
 7+* Maintenance script overview:
 8+*
 9+* Designed to be run every 10 seconds or so. Will spawn threads
 10+* until max thread count reached
 11+*
 12+* 1) Check if number of instances is < $wgMaxTranscodeThreads
 13+* the script exits immediately.
 14+*
 15+* 2) Query the db for jobSets ( find a job that is not processed or > wgTranscodeJobTimeOut )
 16+*
 17+* 3) Does a incomplete transcode to temporary location
 18+* once done moves file into place.
 19+*
 20+*/
 21+require_once( dirname(__FILE__) . '/../../js2-work/maintenance/Maintenance.php' );
 22+
 23+class OggTranscodeCron extends Maintenance {
 24+
 25+ // The max number of threads ( can also be set when called via the command line )
 26+ private $maxThreads = 2;
 27+
 28+ public function __construct() {
 29+ global $wgUseNormalUser;
 30+ parent::__construct();
 31+ $this->mDescription = "Transcode video files";
 32+ $this->addOption( 'maxThreads', 'Maximum number of threads to run', false, true );
 33+ $wgUseNormalUser = true;
 34+ }
 35+
 36+ /**
 37+ * Main Execute method from Maintenance class
 38+ */
 39+ public function execute() {
 40+ global $wgEnabledDerivatives;
 41+ // Set command line options:
 42+ if ( $this->hasOption( 'maxThreads' ) ) {
 43+ $this->maxThreads = intval( $this->hasOption( 'maxThreads' ) );
 44+ }
 45+
 46+ // Check if number of instances is < $wgMaxTranscodeThreads
 47+ if( $this->checkMaxThreads() ){
 48+ exit( 0 );
 49+ }
 50+
 51+ // Check if we have $wgEnabledDerivatives to transcode to.
 52+ if( !isset( $wgEnabledDerivatives ) || count( $wgEnabledDerivatives ) == 0 ){
 53+ print "\$wgEnabledDerivatives is not set or empty \n";
 54+ exit( 0 );
 55+ }
 56+
 57+ // Check if there are any jobs to be done
 58+ $job = $this->getTranscodeJob();
 59+ if( $job ){
 60+ if( ! $this->processTranscodeJob( $job ) ){
 61+ // Mark the job as failed if it did not complete
 62+ $this->markJobState( $job, 'FAILED' );
 63+ exit( 1 );
 64+ }
 65+ // Else job was oky mark state and exit:
 66+ $this->markJobState( $job, 'OK' );
 67+ exit( 0 );
 68+ }
 69+ // No jobs found.
 70+
 71+ // Update Transcode Jobs table with images that are missing transcode jobs
 72+ // ( the updated transcode job set will be accessed the next time the script is run)
 73+ $this->updateTranscodeJobs();
 74+ exit( 0 );
 75+ }
 76+
 77+ /**
 78+ * Get a Transcode Job from the transcode_job table
 79+ */
 80+ function getTranscodeJob() {
 81+ $dbr = & wfGetDB( DB_SLAVE );
 82+
 83+ // Don't hit the slaves under high load:
 84+ wfWaitForSlaves( 5 );
 85+
 86+ // Grab transcode job
 87+ $res = $dbr->select(
 88+ 'transcode_job',
 89+ '*',
 90+ 'tjob_state IS NULL',
 91+ __METHOD__,
 92+ array(
 93+ 'USE INDEX' => array(
 94+ 'transcode_job' => 'transcode_job_state'
 95+ ),
 96+ 'LIMIT' => 20
 97+ )
 98+ );
 99+ return $dbr->fetchObject( $res );
 100+ }
 101+
 102+ /**
 103+ * Grab a batch of up-to 100 jobs and insert them into the jobs table.
 104+ *
 105+ * NOTE: this presently does not test for missing derivative keys /
 106+ * keep derivative keys "in-sync" with transcode_job table.
 107+ */
 108+ function updateTranscodeJobs( ){
 109+ global $wgEnabledDerivatives;
 110+ // Find new jobs and insert them into the db
 111+ $dbr = & wfGetDB( DB_SLAVE );
 112+
 113+ // Don't hit the slaves under high load:
 114+ wfWaitForSlaves( 5 );
 115+
 116+ // Get image files that don't have a transcode job
 117+ $res = $dbr->select(
 118+ array( 'image', 'transcode_job'),
 119+ array( 'img_name' ),
 120+ array( 'tjob_name IS NULL',
 121+ 'img_media_type' => 'VIDEO'),
 122+ __METHOD__,
 123+ array( 'LIMIT' => 100 ),
 124+ array(
 125+ 'transcode_job' => array(
 126+ 'LEFT JOIN',
 127+ array( 'img_name = tjob_name' )
 128+ )
 129+ )
 130+ );
 131+ $imageNames = array();
 132+ while( $row = $dbr->fetchObject( $res ) ) {
 133+ $imageNames[] = $row->img_name;
 134+ }
 135+ if( count( $imageNames ) == 0){
 136+ return false;
 137+ }
 138+
 139+ // Add the derivative set[s] to the transcode table
 140+ $dbw = & wfGetDB( DB_MASTER );
 141+ $dbw->begin();
 142+ foreach( $imageNames as $name){
 143+ foreach( $wgEnabledDerivatives as $derivativeKey ){
 144+
 145+ // Do not to add a derivative job that is > than the source asset
 146+ $fileTitle = Title::newFromText( $name, NS_FILE);
 147+
 148+ $file = wfFindFile( $fileTitle );
 149+ if( !$file ){
 150+ $this->output( "File not found: {$name} (not adding to jobQueue\n" );
 151+ continue;
 152+ }
 153+ $targetSize = OggTranscode::$derivativeSettings[ $derivativeKey ]['maxSize'];
 154+ $sourceSize = $file->getWidth();
 155+ if( $targetSize > $sourceSize ){
 156+ $this->output( "File:{$name} is too small for {$derivativeKey} ::\n" .
 157+ "target: {$targetSize} > source: {$sourceSize} \n\n" );
 158+ continue;
 159+ }
 160+ // Else $derivative size is < source size, do insert:
 161+ $dbw->insert(
 162+ 'transcode_job',
 163+ array(
 164+ 'tjob_name' => $name,
 165+ 'tjob_derivative_key' => $derivativeKey,
 166+ 'tjob_start_timestamp' => time()
 167+ ),
 168+ __METHOD__
 169+ );
 170+ }
 171+ }
 172+ $dbw->commit();
 173+ }
 174+
 175+ /**
 176+ * Process a transcode job
 177+ * @param {Object} $job Transcode job db row
 178+ * @return {Bollean}
 179+ * true if job was processed
 180+ * false if there was an error in the job
 181+ */
 182+ function processTranscodeJob( $job ){
 183+ $dbw = & wfGetDB( DB_MASTER );
 184+
 185+ // Update job state to "ASSIGNED"
 186+ $this->markJobState( $job, 'ASSIGNED');
 187+
 188+ // Get the source title from tjob_name
 189+ $fileTitle = Title::newFromText( $job->tjob_name, NS_FILE);
 190+ if( ! $fileTitle->exists() ){
 191+ $this->output( "Title not found: {$job->tjob_name}\n" );
 192+ return false;
 193+ }
 194+
 195+ // Get the file source:
 196+ $file = wfFindFile( $fileTitle );
 197+ if( !$file ){
 198+ $this->output( "File not found: {$job->tjob_name}\n" );
 199+ return false;
 200+ }
 201+
 202+ // Setup a temporary target location for encode output
 203+ $tempTarget = wfTempDir() .'/'. $fileTitle->getDbKey() . $job->tjob_derivative_key . '.ogv';
 204+
 205+ // Get encoding settings from encode key
 206+ if( !isset( OggTranscode::$derivativeSettings[ $job->tjob_derivative_key ] )){
 207+ $this->output( "Derivative key not found: {$job->tjob_name}\n" );
 208+ return false;
 209+ }
 210+ $encodeSettings = OggTranscode::$derivativeSettings[ $job->tjob_derivative_key ];
 211+
 212+ // Shell out the transcode command.
 213+ $this->output( "Starting transcode:\n" );
 214+ $result = $this->doEncode( $file->getPath(), $tempTarget, $encodeSettings );
 215+
 216+ // Check the result
 217+ if( !$result ){
 218+ $this->output( "Transcode failed: {$job->tjob_name}\n" );
 219+ return false;
 220+ }
 221+
 222+ // If result is "ok"
 223+ $this->output( "Transcode OK, moving thumb to public location\n" );
 224+ $derivativeTarget = $file->getThumbPath( $job->tjob_derivative_key ) . '.ogv';
 225+
 226+ if( !rename( $tempTarget, $derivativeTarget) ){
 227+ $this->output( "Renamed failed: {$tempTarget} to {$derivativeTarget}\n" );
 228+ return false;
 229+ }
 230+ // Return true to update the job state:
 231+ return true;
 232+ }
 233+ /**
 234+ * Mark a job as state
 235+ * @param {Object} $job Job db row object.
 236+ * @param {String} $state String to update state to can be:
 237+ * 'OK','ASSIGNED','FAILED'
 238+ */
 239+ function markJobState( $job , $state){
 240+ $dbw = & wfGetDB( DB_MASTER );
 241+ $dbw->update(
 242+ 'transcode_job',
 243+ array(
 244+ 'tjob_state' => $state
 245+ ),
 246+ array(
 247+ 'tjob_name' => $job->tjob_name,
 248+ 'tjob_derivative_key' => $job->tjob_derivative_key
 249+ )
 250+ );
 251+ }
 252+
 253+ /**
 254+ * Check the number if the instances of this script that are running
 255+ * are over the max allowed threads $this->maxThreads
 256+ *
 257+ * @return {Boolean}
 258+ * true if max Threads count has been reached
 259+ * false if less than max Threads
 260+ */
 261+ public function checkMaxThreads(){
 262+
 263+ // Get the list of processes:
 264+ $pslist = wfShellExec( "ps aux", $out);
 265+
 266+ // Return the count of php OggTranscodeCron.php found
 267+ $threadCount = preg_match_all( '/php\sOggTranscodeCron\.php/', $pslist, $matches);
 268+ if( $threadCount === false ){
 269+ print "Error in preg_match";
 270+ exit( 1 );
 271+ }
 272+ return ( $threadCount > $this->maxThreads );
 273+ }
 274+
 275+ /**
 276+ * Issues an encode command to ffmpeg2theora
 277+ *
 278+ * @param {String} $source Source file asset
 279+ * @param {String} $target Target output encode
 280+ * @param {Array} $encodeSettings Settings to encode the file with
 281+ */
 282+ function doEncode( $source, $target, $encodeSettings ){
 283+ global $wgffmpeg2theoraPath;
 284+
 285+ // Set up the base command
 286+ $cmd = wfEscapeShellArg( $wgffmpeg2theoraPath ) . ' ' . wfEscapeShellArg( $source );
 287+
 288+ // Add in the encode settings
 289+ foreach( $encodeSettings as $key => $val){
 290+ if( isset( OggTranscode::$foggMap[$key] ) ){
 291+ if( is_array( OggTranscode::$foggMap[$key] ) ){
 292+ $cmd.= ' '. implode(' ', OggTranscode::$foggMap[$key] );
 293+ }else if($val == 'true' || $val === true){
 294+ $cmd.= ' '. OggTranscode::$foggMap[$key];
 295+ }else if( $val === false){
 296+ //ignore "false" flags
 297+ }else{
 298+ //normal get/set value
 299+ $cmd.= ' '. OggTranscode::$foggMap[$key] . ' ' . wfEscapeShellArg( $val );
 300+ }
 301+ }
 302+ }
 303+ // Add the output target:
 304+ $cmd.= ' -o ' . wfEscapeShellArg ( $target );
 305+ $this->output( "Running cmd: \n\n" .$cmd . "\n\n" );
 306+ wfProfileIn( 'ffmpeg2theora_encode' );
 307+ wfShellExec( $cmd, $retval );
 308+ wfProfileOut( 'ffmpeg2theora_encode' );
 309+
 310+ if( $retval ){
 311+ return false;
 312+ }
 313+ return true;
 314+ }
 315+}
 316+
 317+$maintClass = "OggTranscodeCron";
 318+require_once( DO_MAINTENANCE );
 319+?>
\ No newline at end of file
Index: trunk/extensions/OggHandler/OggHandler.php
@@ -7,6 +7,7 @@
88
99 $oggDir = dirname(__FILE__);
1010 $wgAutoloadClasses['OggHandler'] = "$oggDir/OggHandler_body.php";
 11+$wgAutoloadClasses['OggTranscode'] = "$oggDir/OggTranscode.php";
1112
1213 $wgMediaHandlers['application/ogg'] = 'OggHandler';
1314 if ( !in_array( 'ogg', $wgFileExtensions ) ) {
@@ -32,9 +33,12 @@
3334 $wgHooks['LanguageGetMagic'][] = 'OggHandler::registerMagicWords';
3435
3536
36 -//Setup a hook for iframe=true (will strip the interface and only output the player)
 37+// Setup a hook for iframe=true (will strip the interface and only output the player)
3738 $wgHooks['ArticleFromTitle'][] = 'OggHandler::iframeOutputHook';
3839
 40+// Add the oggTranscode schema
 41+$wgHooks['LoadExtensionSchemaUpdates'][] = 'OggTranscode::schema';
 42+
3943 $wgExtensionCredits['media'][] = array(
4044 'path' => __FILE__,
4145 'name' => 'OggHandler',
@@ -46,32 +50,32 @@
4751
4852 /******************* CONFIGURATION STARTS HERE **********************/
4953
50 -//set the supported ogg codecs:
 54+// Set the supported ogg codecs:
5155 $wgOggVideoTypes = array( 'Theora' );
5256 $wgOggAudioTypes = array( 'Vorbis', 'Speex', 'FLAC' );
5357
54 -//if wgPlayerStats collection is enabled or not
55 -$wgPlayerStatsCollection=false;
 58+// if wgPlayerStats collection is enabled or not
 59+$wgPlayerStatsCollection = false;
5660
57 -// Output Video tag support
 61+// Output Video tag for player ( video tag is then rewritten to compatible player via mwEmbed )
5862 $wgVideoTagOut = false;
5963
6064 // Defautl skin for mwEmbed player
6165 // Skins presently available:
62 -// "kskin" kaltura skin
 66+// "kskin" kaltura skin
6367 // "mvpcf" a jquery ui like skin
6468 $wgVideoPlayerSkin = 'kskin';
6569
6670 // Support striped player iframe output for remote embedding
6771 $wgEnableIframeEmbed = false;
6872
69 -// If timedText is enabled
 73+// Inline timedText reference url output
7074 $wgEnableTimedText = false;
7175
72 -//Location of oggThumb binary (used over the ffmpeg version)
 76+//Location of oggThumb binary ( used instead of ffmpeg )
7377 $wgOggThumbLocation = '/usr/bin/oggThumb';
7478
75 -//the location of ffmpeg2theora
 79+//the location of ffmpeg2theora ( for grabbing
7680 $wgffmpeg2theoraPath = '/usr/bin/ffmpeg2theora';
7781
7882 // Location of the FFmpeg binary
@@ -79,11 +83,29 @@
8084
8185 /**
8286 * enable oggz_chop support
83 - * if enabled the mv_embed player will use temporal urls
 87+ * if enabled the mwEmbed player will use temporal urls
8488 * for helping with seeking with some plugin types
8589 */
8690 $wgEnableTemporalOggUrls = false;
8791
 92+// Enabled derivatives array
 93+//
 94+// Only derivatives with less width than the
 95+// source asset size will be created
 96+//
 97+// Derivatives can be created by running OggTranscodeCron.php
 98+// at regular intervals. The cron job
 99+// cycles through every ogg file and encodes the following derivative set:
 100+//
 101+// Derivative keys encode settings are defined in OggTranscode.php
 102+//
 103+$wgEnabledDerivatives = array(
 104+ OggTranscode::ENC_WEB_2MBS,
 105+ OggTranscode::ENC_WEB_4MBS,
 106+ OggTranscode::ENC_WEB_6MBS,
 107+ OggTranscode::ENC_HQ_VBR
 108+);
 109+
88110 // Filename or URL path to the Cortado Java player applet.
89111 //
90112 // If no path is included, the path to this extension's
@@ -100,35 +122,37 @@
101123
102124 /******************* CONFIGURATION ENDS HERE **********************/
103125
 126+// NOTE: normally configuration based code would go into extension setup
 127+// so config could follow the oggHandler include but we need add the namespace early.
104128 if( $wgEnableTimedText ){
105 -/**
106 - * Handle Adding of "timedText" NameSpace
107 - */
108 -$wgTimedTextNS = null;
 129+ /**
 130+ * Handle Adding of "timedText" NameSpace
 131+ */
 132+ $wgTimedTextNS = null;
109133
110 -// Make sure $wgExtraNamespaces in an array (set to NULL by default) :
111 -if ( !is_array( $wgExtraNamespaces ) ) {
112 - $wgExtraNamespaces = array();
113 -}
114 -// Check for "TimedText" NS
115 -$maxNS = 101; // content pages need "even" namespaces
116 -foreach($wgExtraNamespaces as $ns => $nsTitle ){
117 - if( $nsTitle == 'TimedText' ){
118 - $wgTimedTextNS = $ns;
 134+ // Make sure $wgExtraNamespaces in an array (set to NULL by default) :
 135+ if ( !is_array( $wgExtraNamespaces ) ) {
 136+ $wgExtraNamespaces = array();
119137 }
120 - if( $ns > $maxNS ){
121 - $maxNs = $ns;
 138+ // Check for "TimedText" NS
 139+ $maxNS = 101; // content pages need "even" namespaces
 140+ foreach($wgExtraNamespaces as $ns => $nsTitle ){
 141+ if( $nsTitle == 'TimedText' ){
 142+ $wgTimedTextNS = $ns;
 143+ }
 144+ if( $ns > $maxNS ){
 145+ $maxNs = $ns;
 146+ }
122147 }
123 -}
124 -// If not found add Add a custom timedText NS
125 -if( !$wgTimedTextNS ){
126 - $wgTimedTextNS = ( $maxNS + 1 );
127 - $wgExtraNamespaces[ $wgTimedTextNS ] = 'TimedText';
128 - $wgExtraNamespaces[ $wgTimedTextNS +1 ] = 'TimedText_talk';
129 -}
130 -define( "NS_TIMEDTEXT", $wgTimedTextNS);
131 -// Assume $wgTimedTextNS +1 for talk
132 -define( "NS_TIMEDTEXT_TALK", $wgTimedTextNS +1);
 148+ // If not found add Add a custom timedText NS
 149+ if( !$wgTimedTextNS ){
 150+ $wgTimedTextNS = ( $maxNS + 1 );
 151+ $wgExtraNamespaces[ $wgTimedTextNS ] = 'TimedText';
 152+ $wgExtraNamespaces[ $wgTimedTextNS +1 ] = 'TimedText_talk';
 153+ }
 154+ define( "NS_TIMEDTEXT", $wgTimedTextNS);
 155+ // Assume $wgTimedTextNS +1 for talk
 156+ define( "NS_TIMEDTEXT_TALK", $wgTimedTextNS +1);
133157
134158
135159 } // end of handling timedText
\ No newline at end of file
Index: trunk/extensions/OggHandler/OggTranscode.php
@@ -0,0 +1,199 @@
 2+<?php
 3+
 4+/*
 5+ * OggTranscode provides keys and encode settings
 6+ */
 7+
 8+
 9+/*
 10+ * Main OggTranscode Class hold some constants and config values
 11+ */
 12+class OggTranscode {
 13+ /**
 14+ * Key constants for the derivatives,
 15+ * this key is appended to the derivative file name
 16+ *
 17+ * If you update the wgDerivativeSettings for one of these keys
 18+ * and want to re-generate the video you should also update the
 19+ * key constant.
 20+ */
 21+ const ENC_WEB_2MBS = '256_200kbs';
 22+ const ENC_WEB_4MBS = '380_400kbs';
 23+ const ENC_WEB_6MBS = '480_600kbs';
 24+ const ENC_HQ_VBR = '720_VBR';
 25+
 26+ /**
 27+ * Encoding parameters are set via firefogg encode api
 28+ *
 29+ * For clarity and compatibility with passing down
 30+ * client side encode settings at point of upload
 31+ *
 32+ * http://firefogg.org/dev/index.html
 33+ */
 34+
 35+ public static $derivativeSettings = array(
 36+ OggTranscode::ENC_WEB_2MBS =>
 37+ array(
 38+ 'maxSize' => '200',
 39+ 'videoBitrate' => '128',
 40+ 'audioBitrate' => '32',
 41+ 'samplerate' => '22050',
 42+ 'framerate' => '15',
 43+ 'channels' => '1',
 44+ 'noUpscaling' => 'true',
 45+ 'twopass' => 'true',
 46+ 'keyframeInterval' => '64',
 47+ 'bufDelay' => '128'
 48+ ),
 49+ OggTranscode::ENC_WEB_4MBS =>
 50+ array(
 51+ 'maxSize' => '320',
 52+ 'videoBitrate' => '368',
 53+ 'audioBitrate' => '48',
 54+ 'noUpscaling' => 'true',
 55+ 'twopass' => 'true',
 56+ 'keyframeInterval' => '128',
 57+ 'bufDelay' => '256'
 58+ ),
 59+ OggTranscode::ENC_WEB_6MBS =>
 60+ array(
 61+ 'maxSize' => '480',
 62+ 'videoBitrate' => '512',
 63+ 'audioBitrate' => '96',
 64+ 'noUpscaling' => 'true',
 65+ 'twopass' => 'true',
 66+ 'keyframeInterval' => '128',
 67+ 'bufDelay' => '256'
 68+ ),
 69+ OggTranscode::ENC_HQ_VBR =>
 70+ array(
 71+ 'maxSize' => '720',
 72+ 'videoQuality' => 6,
 73+ 'audioQuality' => 3,
 74+ 'noUpscaling' => 'true'
 75+ )
 76+ );
 77+ /**
 78+ * Mapping between firefogg api and ffmpeg2theora command line
 79+ *
 80+ * This lets us share a common api between firefogg and oggTranscode
 81+ * also see: http://firefogg.org/dev/index.html
 82+ */
 83+ public static $foggMap = array(
 84+ //video
 85+ 'width' => "--width",
 86+ 'height' => "--height",
 87+ 'maxSize' => "--max_size",
 88+ 'noUpscaling' => "--no-upscaling",
 89+ 'videoQuality'=> "-v",
 90+ 'videoBitrate' => "-V",
 91+ 'twopass' => "--two-pass",
 92+ 'framerate' => "-F",
 93+ 'aspect' => "--aspect",
 94+ 'starttime' => "--starttime",
 95+ 'endtime' => "--endtime",
 96+ 'cropTop' => "--croptop",
 97+ 'cropBottom' => "--cropbottom",
 98+ 'cropLeft' => "--cropleft",
 99+ 'cropRight' => "--cropright",
 100+ 'keyframeInterval'=> "--key",
 101+ 'denoise' => array("--pp", "de"),
 102+ 'novideo' => array("--novideo", "--no-skeleton"),
 103+ 'bufDelay' => "--buf-delay",
 104+ //audio
 105+ 'audioQuality' => "-a",
 106+ 'audioBitrate' => "-A",
 107+ 'samplerate' => "-H",
 108+ 'channels' => "-c",
 109+ 'noaudio' => "--noaudio",
 110+ //metadata
 111+ 'artist' => "--artist",
 112+ 'title' => "--title",
 113+ 'date' => "--date",
 114+ 'location' => "--location",
 115+ 'organization' => "--organization",
 116+ 'copyright' => "--copyright",
 117+ 'license' => "--license",
 118+ 'contact' => "--contact"
 119+ );
 120+ /*
 121+ * Setup the OggTranscode tables
 122+ */
 123+ public static function schema() {
 124+ global $wgExtNewTables, $wgExtNewIndexes;
 125+
 126+ $wgExtNewTables[] = array(
 127+ 'transcode_job',
 128+ dirname( __FILE__ ) . '/OggTranscode.sql'
 129+ );
 130+
 131+ $wgExtNewIndexes[] = array(
 132+ 'image', 'image_media_type',
 133+ dirname( __FILE__ ) . '/patch-image-index.sql'
 134+ );
 135+
 136+ return true;
 137+ }
 138+
 139+ /**
 140+ * Get derivative url for given embed width
 141+ *
 142+ * @param {Object} $srcFile Source file object
 143+ * @param {Number} $targetWidth Target output width
 144+ * @return {String}
 145+ * the url for a given embed width,
 146+ * or the srcFile url if no derivative found
 147+ */
 148+ static function getWidthDerivativeURL( $srcFile, $targetWidth){
 149+ global $wgEnabledDerivatives;
 150+ $srcWidth = $srcFile->getWidth();
 151+ $srcHeight = $srcFile->getHeight();
 152+
 153+ // Return source file url if targetdWidth greater than our source file. )
 154+ // should cover audio as well
 155+
 156+ // NOTE removed: && get_class( $srcFile->handler) != 'NonFreeVideoHandler')
 157+ if( $targetWidth >= $srcWidth ){
 158+ $srcFile->getURL();
 159+ }
 160+
 161+ // Get the available derivatives by difference of 'maxSize' to 'targetWidth'
 162+ $derivativeSet = array();
 163+
 164+ // include the source asset in the $derivativeSet distance comparison
 165+ $derivativeSet[ 'SOURCE' ] = abs( $targetWidth - $srcWidth );
 166+
 167+ foreach( $wgEnabledDerivatives as $derivativeKey ){
 168+ if( isset( self::$derivativeSettings[ $derivativeKey ] ) ){
 169+ $derivativePath = $srcFile->getThumbPath( $derivativeKey );
 170+ // Check for derivative file:
 171+ if( is_file ( "{$derivativePath}.ogv" )){
 172+ $maxSize = self::$derivativeSettings[ $derivativeKey ]['maxSize'];
 173+ $derivativeSet[ $derivativeKey ] = abs( $targetWidth - $maxSize );
 174+ }
 175+ }
 176+ }
 177+
 178+ // No derivative found return the src url
 179+ if( count( $derivativeSet ) == 0 ){
 180+ return $srcFile->getURL();
 181+ }
 182+ // Sort the $derivativeSet
 183+ asort( $derivativeSet );
 184+
 185+ // Reset the pointer to start:
 186+ reset( $derivativeSet );
 187+
 188+ // Handle special case where source is closes to target:
 189+ if( key( $derivativeSet ) == 'SOURCE' ){
 190+ return $srcFile->getURL();
 191+ }
 192+
 193+ // Get the url for the closest derivative
 194+ return $srcFile->getThumbUrl( key( $derivativeSet ) . '.ogv');
 195+ }
 196+}
 197+
 198+
 199+
 200+?>
\ No newline at end of file

Status & tagging log