Created
December 6, 2010 06:42
-
-
Save shimondoodkin/729958 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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