public function run() {
		// get a local pointer to the file
		$file = wfLocalFile( $this->title );

		// Validate the file exists :
		if( !$file || !is_file( $this->getSourceFilePath() ) ){
			$this->output( 'File not found: ' . $this->title );
			return false;
		}

		// Validate the transcode key param:
		$transcodeKey = $this->params['transcodeKey'];
		// Build the destination target
		if( ! isset(  WebVideoTranscode::$derivativeSettings[ $transcodeKey ] )){
			$this->output( "Transcode key $transcodeKey not found, skipping" );
			return false;
		}

		$options = WebVideoTranscode::$derivativeSettings[ $transcodeKey ];

		$this->output( "Encoding to codec: " . $options['videoCodec'] );

		$dbw = wfGetDB( DB_MASTER );
		$db = wfGetDB( DB_SLAVE );

		// Check if we have "already started" the transcode ( possible error )
		$dbStartTime = $db->selectField( 'transcode', 'transcode_time_startwork',
			array( 	'transcode_image_name = ' . $db->addQuotes( $this->title->getDBKey() ),
					'transcode_key =' . $db->addQuotes( $transcodeKey ) )
		);
		if( ! is_null( $dbStartTime ) ){
			$this->output( 'Error, running transcode job, for job that has already started' );
			// back out of this job. ( if there was a transcode error it should be restarted with api transcode-reset )
			// not some strange out-of-order error.
			return false;
		}

		// Update the transcode table letting it know we have "started work":
		$jobStartTimeCache = $db->timestamp();
		$dbw->update(
			'transcode',
			array( 'transcode_time_startwork' => $jobStartTimeCache ),
			array(
				'transcode_image_name' => $this->title->getDBkey(),
				'transcode_key' => $transcodeKey
			),
			__METHOD__,
			array( 'LIMIT' => 1 )
		);


		// Check the codec see which encode method to call;
		if( $options['videoCodec'] == 'theora' ){
			$status = $this->ffmpeg2TheoraEncode( $options );
		} elseif( $options['videoCodec'] == 'vp8' ){
			// Check for twopass:
			if( isset( $options['twopass'] ) ){
				// ffmpeg requires manual two pass
				$status = $this->ffmpegEncode( $options, 1 );
				if( $status ){
					$status = $this->ffmpegEncode( $options, 2 );
				}
			} else {
				$status = $this->ffmpegEncode( $options );
			}
		} else {
			wfDebug( 'Error unknown codec:' . $options['codec'] );
			$status =  'Error unknown target encode codec:' . $options['codec'];
		}

		// Remove any log files all useful info should be in status and or we are done with 2 passs encoding
		$this->removeFffmpgeLogFiles();

		// Do a quick check to confirm the job was not restarted or removed while we were transcoding
		// Confirm the in memory $jobStartTimeCache matches db start time
		$dbStartTime = $db->selectField( 'transcode', 'transcode_time_startwork',
			array( 	'transcode_image_name = ' . $db->addQuotes( $this->title->getDBKey() ),
					'transcode_key =' . $db->addQuotes( $transcodeKey )
			)
		);

		// Check for ( hopefully rare ) issue of or job restarted while transcode in progress
		if(  $db->timestamp( $jobStartTimeCache ) != $db->timestamp( $dbStartTime ) ){
			$this->output('Possible Error, transcode task restarted, removed, or completed while transcode was in progress');
			// if an error; just error out, we can't remove temp files or update states, because the new job may be doing stuff.
			if( $status !== true ){
				return false;
			}
			// else just continue with db updates, and when the new job comes around it won't start because it will see
			// that the job has already been started.
		}

		// If status is oky and file exists and is larger than 0 bytes
		if( $status === true && is_file( $this->getTargetEncodePath() ) && filesize( $this->getTargetEncodePath() ) > 0 ){
			$finalDerivativeFilePath = WebVideoTranscode::getDerivativeFilePath( $file, $transcodeKey);
			//wfSuppressWarnings();
			// @TODO: use a FileRepo store function
			$op = array( 'op' => 'store',
				'src' => $this->getTargetEncodePath(), 'dst' => $finalDerivativeFilePath, 'overwriteDest' => true );
			// Copy derivaitve from the FS into storage at $finalDerivativeFilePath
			$opts = array( 'ignoreErrors' => true, 'nonLocking' => true ); // performance
			$file = $this->getFile();
			$status = $file->getRepo()->getBackend()->doOperation( $op, $opts );
			if (!$status->isOK() ) {
				// Update the transcode table with failure time and error
				$dbw->update(
					'transcode',
					array(
						'transcode_time_error' => $db->timestamp(),
						'transcode_error' => $status
					),
					array(
							'transcode_image_name' => $this->title->getDBkey(),
							'transcode_key' => $transcodeKey
					),
					__METHOD__,
					array( 'LIMIT' => 1 )
				);
				// no need to invalidate all pages with video. Because all pages remain valid ( no $transcodeKey derivative )
				// just clear the file page ( so that the transcode table shows the error )
				$this->title->invalidateCache();
			} else {
				$bitrate = round( intval( filesize( $finalDerivativeFilePath ) /  $file->getLength() ) * 8 );
				//wfRestoreWarnings();
				// Update the transcode table with success time:
				$dbw->update(
					'transcode',
					array(
						'transcode_time_success' => $db->timestamp(),
						'transcode_final_bitrate' => $bitrate
					),
					array(
						'transcode_image_name' => $this->title->getDBkey(),
						'transcode_key' => $transcodeKey,
					),
					__METHOD__,
					array( 'LIMIT' => 1 )
				);
				WebVideoTranscode::invalidatePagesWithFile( $this->title );
			}
			//remove temoprary file in any case
			$this->getTargetEncodePath()->purge();
		} else {
			// Update the transcode table with failure time and error
			$dbw->update(
				'transcode',
				array(
					'transcode_time_error' => $db->timestamp(),
					'transcode_error' => $status
				),
				array(
						'transcode_image_name' => $this->title->getDBkey(),
						'transcode_key' => $transcodeKey
				),
				__METHOD__,
				array( 'LIMIT' => 1 )
			);
			// no need to invalidate all pages with video. Because all pages remain valid ( no $transcodeKey derivative )
			// just clear the file page ( so that the transcode table shows the error )
			$this->title->invalidateCache();
		}
		// Clear the webVideoTranscode cache ( so we don't keep out dated table cache around )
		webVideoTranscode::clearTranscodeCache( $this->title->getDBkey() );

		// pass along result status:
		return $status;
	}