/**
     * Test time parsing to seconds
    */
    function testParseTimeString() {
    	// Some time conversions:
    	$this->assertEquals( TimedMediaHandler::parseTimeString( 100 ), 100 );
    	$this->assertEquals( TimedMediaHandler::parseTimeString( '1:0:0' ), 3600 );
    	$this->assertEquals( TimedMediaHandler::parseTimeString( -1 ), 0 );
    	// Test longer than duration check ( should return time -1 ) 
    	$this->assertEquals( TimedMediaHandler::parseTimeString( 10, 9 ), 8 );
    	
    	// Test failures:
    	$this->assertEquals( TimedMediaHandler::parseTimeString( '1:1:1:1' ), false );
    	$this->assertEquals( TimedMediaHandler::parseTimeString( 'abc' ), false );
    	
    }
	public function execute() {
		global $wgUser, $wgEnabledTranscodeSet, $wgEnableTranscode, $wgWaitTimeForTranscodeReset;		
		// Check if transcoding is enabled on this wiki at all: 
		if( !$wgEnableTranscode ){
			$this->dieUsage( 'Transcode is disabled on this wiki', 'disabledtranscode' );
		}
		
		// Confirm the user has the transcode-reset right
		if( !$wgUser->isAllowed( 'transcode-reset' ) ){
			$this->dieUsage( 'You don\'t have permission to reset transcodes', 'missingpermission' );
		}
		$params = $this->extractRequestParams();
		
		// Make sure we have a valid Title
		$titleObj = Title::newFromText( $params['title'] );
		if ( !$titleObj || $titleObj->isExternal() ) {
			$this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
		}
		// Make sure the title can be transcoded
		if( !TimedMediaHandlerHooks::isTranscodableTitle( $titleObj ) ){
			$this->dieUsage( array( 'invalidtranscodetitle', $params['title'] ) );
		}
		$transcodeKey = false;
		// Make sure its a enabled transcode key we are trying to remove:
		// ( if you update your transcode keys the api is not how you purge the database of expired keys ) 
		if( isset( $params['transcodekey'] ) ){
			global $wgEnabledTranscodeSet;
			if( !in_array( $params['transcodekey'], $wgEnabledTranscodeSet ) ){
				$this->dieUsage( 'Invalid or disabled transcode key: ' . htmlspecialchars( $params['transcodekey'] ) , 'badtranscodekey' );
			} else {	
				$transcodeKey = $params['transcodekey'];
			}
		} 
		
		// Don't reset if less than 1 hour has passed and we have no error )
		$timeSinceLastReset = self::checkTimeSinceLastRest( $titleObj->getDBKey(), $transcodeKey );
		if( $timeSinceLastReset < $wgWaitTimeForTranscodeReset){
			$this->dieUsage( 'Not enough time has passed since the last reset of this transcode. ' .
				TimedMediaHandler::getTimePassedMsg( $wgWaitTimeForTranscodeReset - $timeSinceLastReset  ) .
				' until this transcode can be reset', 'notenoughtimereset');
		}
		
		// All good do the transcode removal:		
		WebVideoTranscode::removeTranscodes( $titleObj, $transcodeKey );
		
		$this->getResult()->addValue(null, 'success', 'removed transcode');
	}
	static function getThumbTime( $options ){
		$length = $options['file']->getLength();
		$thumbtime = false;

		// If start time param isset use that for the thumb:
		if(  isset( $options['start'] ) ) {
			$thumbtime = TimedMediaHandler::parseTimeString( $options['start'], $length );
			if( $thumbtime )
		 		return $thumbtime;
		}
		// else use thumbtime
		if ( isset( $options['thumbtime'] ) ) {
		 	$thumbtime = TimedMediaHandler::parseTimeString( $options['thumbtime'], $length );
		 	if( $thumbtime )
		 		return $thumbtime;
		}
		// Seek to midpoint by default, it tends to be more interesting than the start
		return $length / 2;
	}
Exemplo n.º 4
0
 function runCheckJobThreadsLoop()
 {
     global $IP, $wgTranscodeBackgroundTimeLimit;
     // Check if we have $threads number of webTranscode jobs running else sleep
     $runingJobsCount = 0;
     foreach ($this->getProcessList() as $pid => $proc) {
         // Check that the process is a "runJobs.php" action with type webVideoTranscode argument
         if (strpos($proc['args'], 'runJobs.php') !== false && strpos($proc['args'], '--type webVideoTranscode') !== false) {
             if (TimedMediaHandler::parseTimeString($proc['time']) > $wgTranscodeBackgroundTimeLimit) {
                 // should probably "kill" the process
                 $killSuccess = posix_kill($pid);
                 $this->output("Trying to expire transcode job: " . $pid . " result:" . $killSuccess);
             } else {
                 // Job is oky add to count:
                 $runingJobsCount++;
             }
         }
     }
     if ($runingJobsCount < $this->threads) {
         // Add one process:
         $parameters = array();
         if ($this->wiki) {
             $parameters[] = '--wiki';
             $parameters[] = $this->wiki;
         }
         $parameters[] = '--type';
         $parameters[] = 'webVideoTranscode';
         $parameters[] = '--maxjobs';
         $parameters[] = '1';
         $parameters[] = '--maxtime';
         $parameters[] = $wgTranscodeBackgroundTimeLimit;
         $cmd = wfShellMaintenanceCmd("{$IP}/maintenance/runJobs.php", $parameters);
         $status = $this->runBackgroundProc($cmd);
         $this->output("{$runingJobsCount} existing job runners, Check for new transcode jobs:  ");
     } else {
         // Just output a "tick"
         $this->output("{$runingJobsCount} transcode jobs active:\n");
     }
 }
	public static function getStatusMsg( $file, $state ){
		// Check for success:
		if( !is_null( $state['time_success'] ) ) {
			return wfMsgHtml('timedmedia-completed-on', $state['time_success'] );
		}
		// Check for error: 
		if( !is_null( $state['time_error'] ) ){
			if( !is_null( $state['error'] ) ){
				$showErrorLink = self::$linker->link( $file->getTitle(), wfMsg('timedmedia-show-error'), array(
					'title' => wfMsgHtml('timedmedia-error-on', $state['time_error'] ),
					'class' => 'errorlink',
					'data-error' => $state['error']
				));
			}
			return wfMsgHtml('timedmedia-error-on', $state['time_error'] ) . $showErrorLink;
		}		
		$db = wfGetDB( DB_SLAVE );
		// Check for started encoding
		if( !is_null( $state['time_startwork'] ) ){
			$timePassed = wfTimestampNow() - $db->timestamp( $state['time_startwork'] );

			// Get the rough estimate of time done: ( this is not very costly considering everything else
			// that happens in an action=purge video page request ) 
			/*$filePath = WebVideoTranscode::getTargetEncodePath( $file, $state['key'] );
			if( is_file( $filePath ) ){
				$targetSize = WebVideoTranscode::getProjectedFileSize( $file, $state['key'] );
				if( $targetSize === false ){
					$doneMsg = wfMsgHtml('timedmedia-unknown-target-size', $wgLang->formatSize( filesize( $filePath ) ) );
				} else {
					$doneMsg = wfMsgHtml('timedmedia-percent-done', round( filesize( $filePath ) / $targetSize, 2 ) );
				}
			}	*/
			// Predicting percent done is not working well right now ( disabled for now )
			$doneMsg = '';
			return wfMsgHtml('timedmedia-started-transcode', TimedMediaHandler::getTimePassedMsg( $timePassed ), $doneMsg );
		}
		// Check for job added ( but not started encoding )
		if( !is_null( $state['time_addjob'] ) ){
			$timePassed =  wfTimestampNow() - $db->timestamp( $state['time_addjob'] ) ;
			return wfMsgHtml('timedmedia-in-job-queue', TimedMediaHandler::getTimePassedMsg( $timePassed ) );
		}
		// Return unknown status error:
		return wfMsgHtml('timedmedia-status-unknown');
	}
Exemplo n.º 6
0
	function getShortDesc( $file ) {
		global $wgLang, $wgMediaAudioTypes, $wgMediaVideoTypes;

		$streamTypes = $this->getStreamTypes( $file );
		if ( !$streamTypes ) {
			return parent::getShortDesc( $file );
		}
		return wfMsg( 'timedmedia-webm-short-video', implode( '/', $streamTypes ),
			$wgLang->formatTimePeriod( $this->getLength( $file ) ) );
	}
Exemplo n.º 7
0
	function getShortDesc( $file ) {
		global $wgLang, $wgMediaAudioTypes, $wgMediaVideoTypes;

		$streamTypes = $this->getStreamTypes( $file );
		if ( !$streamTypes ) {
			return parent::getShortDesc( $file );
		}
		if ( array_intersect( $streamTypes, $wgMediaVideoTypes ) ) {
			// Count multiplexed audio/video as video for short descriptions
			$msg = 'timedmedia-ogg-short-video';
		} elseif ( array_intersect( $streamTypes, $wgMediaAudioTypes ) ) {
			$msg = 'timedmedia-ogg-short-audio';
		} else {
			$msg = 'timedmedia-ogg-short-general';
		}
		return wfMsg( $msg, implode( '/', $streamTypes ),
			$wgLang->formatTimePeriod( $this->getLength( $file ) ) );
	}
	public function monitorTranscode( $pid, &$retval, $encodingLog, $retvalLog ){
		global $wgTranscodeBackgroundTimeLimit, $wgLang;
		$errorMsg = '';
		$loopCount = 0;
		$oldFileSize = 0;
		$startTime = time();
		$fileIsNotGrowing = false;

		$this->output( "Encoding with pid: $pid \npcntl_waitpid: " . pcntl_waitpid( $pid, $status, WNOHANG OR WUNTRACED) .
			"\nisProcessRunning: " . self::isProcessRunningKillZombie( $pid ) . "\n" );

		// Check that the child process is still running ( note this does not work well with  pcntl_waitpid
		// for some reason :(
		while( self::isProcessRunningKillZombie( $pid ) ) {
			//$this->output( "$pid is running" );

			// Check that the target file is growing ( every 5 seconds )
			if( $loopCount == 5 ){
				// only run check if we are outputing to target file
				// ( two pass encoding does not output to target on first pass )
				clearstatcache();
				$newFileSize = is_file( $this->getTargetEncodePath() ) ? filesize( $this->getTargetEncodePath() ) : 0;
				// Don't start checking for file growth until we have an initial positive file size:
				if( $newFileSize > 0 ){
					$this->output(  $wgLang->formatSize( $newFileSize ). ' Total size, encoding ' .
						$wgLang->formatSize( ( $newFileSize - $oldFileSize ) / 5 ) . ' per second' );
					if( $newFileSize == $oldFileSize ){
						if( $fileIsNotGrowing ){
							$errorMsg = "Target File is not increasing in size, kill process.";
							$this->output( $errorMsg );
							// file is not growing in size, kill proccess
							$retval = 1;

							//posix_kill( $pid, 9);
							self::killProcess( $pid );
							break;
						}
						// Wait an additional 5 seconds of the file not growing to confirm
						// the transcode is frozen.
						$fileIsNotGrowing = true;
					} else {
						$fileIsNotGrowing = false;
					}
					$oldFileSize = $newFileSize;
				}
				// reset the loop counter
				$loopCount = 0;
			}

			// Check if we have global job run-time has been exceeded:
			if ( $wgTranscodeBackgroundTimeLimit && time() - $startTime  > $wgTranscodeBackgroundTimeLimit ){
				$errorMsg = "Encoding exceeded max job run time ( " . TimedMediaHandler::seconds2npt( $maxTime ) . " ), kill process.";
				$this->output( $errorMsg );
				// File is not growing in size, kill proccess
				$retval = 1;
				//posix_kill( $pid, 9);
				self::killProcess( $pid );
				break;
			}

			// Sleep for one second before repeating loop
			$loopCount++;
			sleep( 1 );
		}

		$returnPcntl = pcntl_wexitstatus( $status );
		// check status
		wfSuppressWarnings();
		$returnCodeFile = file_get_contents( $retvalLog );
		wfRestoreWarnings();
		//$this->output( "TranscodeJob:: Child pcntl return:". $returnPcntl . ' Log file exit code:' . $returnCodeFile . "\n" );

		// File based exit code seems more reliable than pcntl_wexitstatus
		$retval = $returnCodeFile;

		// return the encoding log contents ( will be inserted into error table if an error )
		// ( will be ignored and removed if success )
		if( $errorMsg!= '' ){
			$errorMsg.="\n\n";
		}
		return $errorMsg . file_get_contents( $encodingLog );
	}
	function getTemporalUrlHash(){
		if( $this->hashTime ){
			return $this->hashTime;
		}
		$hash ='';
		if( $this->start ){
			$startSec = TimedMediaHandler::parseTimeString( $this->start );
			if( $startSec !== false ){
				$hash.= '#t=' . TimedMediaHandler::seconds2npt( $startSec );
			}
		}
		if( $this->end ){
			if( $hash == '' ){
				$hash .= '#t=0';
			}
			$endSec = TimedMediaHandler::parseTimeString( $this->end );
			if( $endSec !== false ){
				$hash.= ',' . TimedMediaHandler::seconds2npt( $endSec );
			}
		}
		$this->hashTime = $hash;
		return $this->hashTime;
	}