Skip to content

Instantly share code, notes, and snippets.

@shimondoodkin
Created December 6, 2010 06:42
Show Gist options
  • Save shimondoodkin/729958 to your computer and use it in GitHub Desktop.
Save shimondoodkin/729958 to your computer and use it in GitHub Desktop.
<?php
while(ob_get_level())
ob_end_clean();
//header("Content-Encoding:");
header("Content-Type: text/plain");
function flv_parse_header($file)
{
$content = fread($file,9);
//echo urlencode($content);
$header=unpack('A3signature/Cversion/Cflags/Noffset', $content);
//print_r( $header);
//$header=array_values($header);
//$has_audio = $flags & 0x04 ? true : false;
//$has_video = $flags & 0x01 ? true : false;
# Seek ahead in file
if ($header['offset'] > 9) // The DataOffset field usually has a value of 9 for FLV version 1. This field is present to accommodate larger headers in future versions.
{
//should we read some more?
$content.=fread($file,$header['offset'] - 9);
}
$header['content']=$content;
$header['size']=strlen($content);
return $header;
//return array( 'content'=>$content, 'signature'=>$signature, 'version'=>$version, 'flags'=>$flags, 'offset'=>$offset, 'has_audio'=>$has_audio, 'has_video'=>$has_video, 'header'=>$header );
}
function flv_parse_tag($file)
{
$content = fread($file,15);
if(strlen($content)!=15)
{
$tagheader=unpack ( 'Cprevsize0/Cprevsize1/Cprevsize2/Cprevsize3' , $content );
return array(
'prevsize'=>((((($tagheader['prevsize0']*256)+$tagheader['prevsize1'])*256)+$tagheader['prevsize2'])*256)+$tagheader['prevsize3'],
'type'=>0,
'datasize'=>0,
'timestamp'=>0,
'streamid'=>0,
'content'=>$content,
'size'=>strlen($content)
);
}
$tagheader=unpack (
'Cprevsize0/Cprevsize1/Cprevsize2/Cprevsize3/'.
'Ctype/'.
'Cdatasize0/Cdatasize1/Cdatasize2/'.
'Ctimestamp0/Ctimestamp1/Ctimestamp2/Ctimestamp3/'.
'Cstreamid0/Cstreamid1/Cstreamid2', $content);
$tagheader=array(
'prevsize'=>((((($tagheader['prevsize0']*256)+$tagheader['prevsize1'])*256)+$tagheader['prevsize2'])*256)+$tagheader['prevsize3'],
'type'=>$tagheader['type'],
'datasize'=>$datasize=((($tagheader['datasize0']*256)+$tagheader['datasize1'])*256)+$tagheader['datasize2'], //signed long int SI32 but this usualy will be unsidend because size is always positive
'timestamp'=>((((($tagheader['timestamp3']*256)+$tagheader['timestamp0'])*256)+$tagheader['timestamp1'])*256)+$tagheader['timestamp2'],
'streamid'=>((($tagheader['streamid0']*256)+$tagheader['streamid1'])*256)+$tagheader['streamid2'],
'content'=>$content,
'size'=>$datasize+15
);
$tagheader['content'] .= fread($file,$tagheader['datasize']);
return $tagheader;
}
function flv_parse_last_tag($file)
{
global $fsize;
$curpos=ftell($file);
fseek( $file, $fsize-4 );
$content = fread($file,4);
$tagheader=unpack ( 'Cprevsize0/Cprevsize1/Cprevsize2/Cprevsize3' , $content );
$prevsize=((((($tagheader['prevsize0']*256)+$tagheader['prevsize1'])*256)+$tagheader['prevsize2'])*256)+$tagheader['prevsize3'];
$prevsize+=(11-3);
fseek( $file , $fsize-$prevsize );
//echo ftell($file);
$content = fread($file,1000);
//echo urlencode($content );
//exit;
$tagheader=unpack (
'Cprevsize0/Cprevsize1/Cprevsize2/Cprevsize3/'.
'Ctype/'.
'Cdatasize0/Cdatasize1/Cdatasize2/'.
'Ctimestamp0/Ctimestamp1/Ctimestamp2/Ctimestamp3/'.
'Cstreamid0/Cstreamid1/Cstreamid2', $content );
$tagheader=array(
'prevsize'=>((((($tagheader['prevsize0']*256)+$tagheader['prevsize1'])*256)+$tagheader['prevsize2'])*256)+$tagheader['prevsize3'],
'type'=>$tagheader['type'],
'datasize'=>$datasize=((($tagheader['datasize0']*256)+$tagheader['datasize1'])*256)+$tagheader['datasize2'], //signed long int SI32 but this usualy will be unsidend because size is always positive
'timestamp'=>((((($tagheader['timestamp3']*256)+$tagheader['timestamp0'])*256)+$tagheader['timestamp1'])*256)+$tagheader['timestamp2'],
'streamid'=>((($tagheader['streamid0']*256)+$tagheader['streamid1'])*256)+$tagheader['streamid2'],
'content'=>$content,
'size'=>$datasize+15
);
$tagheader['content'] .= fread($file,$tagheader['datasize']);
fseek( $file, $curpos); // go back to previus place
return $tagheader;
}
//------------------------------------------------------------------------------------------
// MEDIA PATH
//------------------------------------------------------------------------------------------
// you can configure these settings to point to video files outside the public html folder.
//
// points to server root
define('XMOOV_PATH_ROOT', dirname(dirname(__FILE__)).'/');
//
// points to the folder containing the video files.
define('XMOOV_PATH_FILES', 'clips/');
//------------------------------------------------------------------------------------------
// BEHAVIOR
//------------------------------------------------------------------------------------------
//
//set to TRUE to use bandwidth limiting.
define('XMOOV_CONF_LIMIT_BANDWIDTH', FALSE);
//
//set to FALSE to prohibit caching of video files.
define('XMOOV_CONF_ALLOW_FILE_CACHE', false);
//------------------------------------------------------------------------------------------
// BANDWIDTH SETTINGS
//------------------------------------------------------------------------------------------
// these settings are only needed when using bandwidth limiting.
//
// bandwidth is limited my sending a limited amount of video data(XMOOV_BW_PACKET_SIZE),
// in specified time intervals(XMOOV_BW_PACKET_INTERVAL).
// avoid time intervals over 1.5 seconds for best results.
//
// you can also control bandwidth limiting via http command using your video player.
// the function getBandwidthLimit($part) holds three preconfigured presets(low, mid, high),
// which can be changed to meet your needs
//
//set how many kilobytes will be sent per time interval
define('XMOOV_BW_PACKET_SIZE', 90);
//
//set the time interval in which data packets will be sent in seconds.
define('XMOOV_BW_PACKET_INTERVAL', 0.3);
//
//set to TRUE to control bandwidth externally via http.
define('XMOOV_CONF_ALLOW_DYNAMIC_BANDWIDTH', TRUE);
//------------------------------------------------------------------------------------------
// INCOMING GET VARIABLES CONFIGURATION
//------------------------------------------------------------------------------------------
//
// use these settings to configure how video files, seek position and bandwidth settings are
// accessed by your player
//
define('XMOOV_GET_FILE', 'file');
// define('XMOOV_GET_POSITION', 'pos'); // v3.x player
define('XMOOV_GET_POSITION', 'start'); // v4.x player
define('XMOOV_GET_AUTHENTICATION', 'key');
define('XMOOV_GET_BANDWIDTH', 'bw');
function alog($t)
{
$f=fopen(dirname(__FILE__).'/logtest2.txt','a');
fwrite($f,$t."\r\n");
fclose($f);
}
ob_start();
print_r($_SERVER);
alog(ob_get_contents());
ob_end_clean();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END SCRIPT CONFIGURATION - do not change anything beyond this point if you do not know what you are doing //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------------
// PROCESS FILE REQUEST
//------------------------------------------------------------------------------------------
if(isset($_GET[XMOOV_GET_FILE]))
{
// PROCESS VARIABLES
// get seek position
// Will - 07-31-08 JWMP doesn't send pos on the first request
$seekPos = isset($_GET[XMOOV_GET_POSITION]) ? intval($_GET[XMOOV_GET_POSITION]) : 0;
// get file name
$fileName = htmlspecialchars($_GET[XMOOV_GET_FILE]);
$fileName = basename($fileName);
// assemble file path
$file = XMOOV_PATH_ROOT . XMOOV_PATH_FILES . $fileName;
//print "File: " . $file;
// assemble packet interval
$packet_interval = (XMOOV_CONF_ALLOW_DYNAMIC_BANDWIDTH && isset($_GET[XMOOV_GET_BANDWIDTH])) ? getBandwidthLimit('interval') : XMOOV_BW_PACKET_INTERVAL;
// assemble packet size
$packet_size = ((XMOOV_CONF_ALLOW_DYNAMIC_BANDWIDTH && isset($_GET[XMOOV_GET_BANDWIDTH])) ? getBandwidthLimit('size') : XMOOV_BW_PACKET_SIZE) * 1042;
// security improved by by TRUI www.trui.net
if (!file_exists($file))
{
print('<b>ERROR:</b> xmoov-php could not find (' . $file . ') please check your settings.');
exit();
}
if(file_exists($file) && strrchr($fileName, '.') == '.flv' && strlen($fileName) > 2 && !eregi(basename($_SERVER['PHP_SELF']), $fileName) && ereg('^[^./][^/]*$', $fileName))
{
$fh = fopen($file, 'rb') or die ('<b>ERROR:</b> xmoov-php could not open (' . $fileName . ')');
$fileSize = filesize($file) - (($seekPos > 0) ? $seekPos + 1 : 0);
// SEND HEADERS
if(!XMOOV_CONF_ALLOW_FILE_CACHE)
{
// prohibit caching (different methods for different clients)
// session_cache_limiter("nocache");
// header("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
// header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
// header("Pragma: no-cache");
}
//header("Content-Type: video/x-flv");
//header("Content-Type: video/x-flv");
header("Content-Length: " . $fileSize);
//header("Content-Disposition: filename=\"" . $fileName . "\"");
$fsize=filesize($file);
$tag_data = flv_parse_header($fh);
echo $tag_data['content'];
$tag_data = flv_parse_tag($fh);
echo $tag_data['content'];
$from_the_end_time=false;
if ($from_the_end_time)
{
$last_tag = flv_parse_last_tag($fh);
$end_time=$last_tag['timestamp']-$from_the_end_time;
}
echo $header_data['content'];
//echo $header_data['header'];
$passed_size=0;
$passed_time=0;
$seekPos-=2000;
$start_time=0;
while (!feof($fh))
{
if(XMOOV_CONF_LIMIT_BANDWIDTH)
{
// get start time
list($usec, $sec) = explode(' ', microtime());
$time_start = ((float)$usec + (float)$sec);
}
$tag_data = flv_parse_tag($fh);
$passed_size+=$tag_data['size'];
$passed_time=$tag_data['timestamp'];
if(($passed_size>=$seekPos&&$passed_time>$start_time) && ($from_the_end_time === false || $passed_time< $end_time))
{
echo $tag_data['content'];
if(XMOOV_CONF_LIMIT_BANDWIDTH)
{
// get end time
list($usec, $sec) = explode(' ', microtime());
$time_stop = ((float)$usec + (float)$sec);
// wait if output is slower than $packet_interval
$time_difference = $time_stop - $time_start;
if($time_difference < (float)$packet_interval)
{
usleep((float)$packet_interval * 1000000 - (float)$time_difference * 1000000);
}
}
}
unset($tag_data);
}
exit;
////////////////////////////////END//////////////////////////////////
////////////////////////////////END//////////////////////////////////
////////////////////////////////END//////////////////////////////////
////////////////////////////////END//////////////////////////////////
// content headers
header("Content-Type: video/x-flv");
header("Content-Disposition: filename=\"" . $fileName . "\"");
header("Content-Length: " . $fileSize);
// FLV file format header
if($seekPos != 0)
{
print('FLV');
print(pack('C', 1));
print(pack('C', 1));
print(pack('N', 9));
print(pack('N', 9));
}
// seek to requested file position
fseek($fh, $seekPos);
// output file
while(!feof($fh))
{
// use bandwidth limiting - by Terry
if(XMOOV_CONF_LIMIT_BANDWIDTH)
{
// get start time
list($usec, $sec) = explode(' ', microtime());
$time_start = ((float)$usec + (float)$sec);
// output packet
print(fread($fh, $packet_size));
// get end time
list($usec, $sec) = explode(' ', microtime());
$time_stop = ((float)$usec + (float)$sec);
// wait if output is slower than $packet_interval
$time_difference = $time_stop - $time_start;
if($time_difference < (float)$packet_interval)
{
usleep((float)$packet_interval * 1000000 - (float)$time_difference * 1000000);
}
}
else
{
// output file without bandwidth limiting
while (!feof($fh))
{
print(fread($fh, 16384));
}
}
}
}
}
//------------------------------------------------------------------------------------------
// DYNAMIC BANDWIDTH CONTROL
//------------------------------------------------------------------------------------------
//
function getBandwidthLimit($part)
{
switch($part)
{
case 'interval' :
switch($_GET[XMOOV_GET_BANDWIDTH])
{
case 'low' :
return 1;
break;
case 'mid' :
return 0.5;
break;
case 'high' :
return 0.3;
break;
default :
return XMOOV_BW_PACKET_INTERVAL;
break;
}
break;
case 'size' :
switch($_GET[XMOOV_GET_BANDWIDTH])
{
case 'low' :
return 10;
break;
case 'mid' :
return 40;
break;
case 'high' :
return 90;
break;
default :
return XMOOV_BW_PACKET_SIZE;
break;
}
break;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment