summaryrefslogtreecommitdiffstats
path: root/play/index.php
diff options
context:
space:
mode:
authorPaul Arthur <flowerysong00@yahoo.com>2013-01-21 12:54:04 -0500
committerPaul Arthur <paul.arthur@flowerysong.com>2013-01-23 13:06:45 -0500
commite387a4caaf2b596c76cc6ff91bb2334c9bbd81d7 (patch)
treee5ae08736720b449f658e14203896359aae480e4 /play/index.php
parent984c738187b167d5ccd15263d45ac4ec0c3938dc (diff)
downloadampache-e387a4caaf2b596c76cc6ff91bb2334c9bbd81d7.tar.gz
ampache-e387a4caaf2b596c76cc6ff91bb2334c9bbd81d7.tar.bz2
ampache-e387a4caaf2b596c76cc6ff91bb2334c9bbd81d7.zip
Clean up Content-Range handling for playback
Transcoding can't cleanly support Content-Range, so ignore it if we receive it and send 'Accept-Ranges: none' so smart clients won't send it. The logic that determines when enough has been streamed that the stream should be recorded in the stats was complexified. Since we've given up on predetermining the file size for transcodes we have to account for that. Content-Ranges that start well into the file now won't update the stats, since we've probably already done it (this assumption is wrong if the client immediately seeks, but nothing's perfect.) Finally, a straight file size / 4 seemed too straighforward, so small files will be / 1.1 and large files will have the value capped.
Diffstat (limited to 'play/index.php')
-rw-r--r--play/index.php82
1 files changed, 56 insertions, 26 deletions
diff --git a/play/index.php b/play/index.php
index fb50a6ce..86932f81 100644
--- a/play/index.php
+++ b/play/index.php
@@ -57,9 +57,6 @@ if ($type == 'playlist') {
$demo_id = scrub_in($_REQUEST['demo_id']);
$random = scrub_in($_REQUEST['random']);
-// Parse byte range request
-$n = sscanf($_SERVER['HTTP_RANGE'], "bytes=%d-%d",$start,$end);
-
/* First things first, if we don't have a uid/oid stop here */
if (empty($oid) && empty($demo_id) && empty($random)) {
debug_event('play', 'No object UID specified, nothing to play', 2);
@@ -226,7 +223,7 @@ if ($catalog->catalog_type == 'remote') {
$sid = xmlRpcClient::ampache_create_stream_session($match['1'],$token);
$extra_info = "&xml_rpc=1&sid=$sid";
- header("Location: " . $media->file . $extra_info);
+ header('Location: ' . $media->file . $extra_info);
debug_event('xmlrpc-stream',"Start XML-RPC Stream - " . $media->file . $extra_info,'5');
/* If this is a voting tmp playlist remove the entry, we do this regardless of play amount */
@@ -304,8 +301,6 @@ if ($_GET['action'] == 'download' AND Config::get('download')) {
} // if they are trying to download and they can
-header("Accept-Ranges: bytes" );
-
// Prevent the script from timing out
set_time_limit(0);
@@ -330,12 +325,14 @@ if (((Config::get('transcode') == 'always' && !$video) ||
'Decided to transcode. Transcode:' . Config::get('transcode') .
' Native Stream: ' . ($media->native_stream() ? 'true' : 'false') .
' Remote: ' . ($downsample_remote ? 'true' : 'false'), 5);
+ header('Accept-Ranges: none');
$media->set_transcode();
$fp = Stream::start_transcode($media, $media_name, $start);
$media_name = $media->f_artist_full . " - " . $media->title . "." . $media->type;
$transcoded = true;
} // end if downsampling
else {
+ header('Accept-Ranges: bytes');
$fp = fopen($media->file, 'rb');
$transcoded = false;
}
@@ -350,59 +347,92 @@ if (get_class($media) == 'Song') {
Stream::insert_now_playing($media->id,$uid,$media->time,$sid,get_class($media));
}
+if ($transcoded) {
+ $stream_size = null;
+}
+else {
+ $stream_size = $media->size;
+}
+
+// Handle Content-Range
+
+sscanf($_SERVER['HTTP_RANGE'], "bytes=%d-%d", $start, $end);
+
if ($start > 0 || $end > 0 ) {
// Calculate stream size from byte range
- if(isset($end)) {
- $end = min($end,$media->size-1);
- $stream_size = ($end-$start)+1;
+ if (isset($end)) {
+ $end = min($end, $media->size - 1);
+ $stream_size = ($end - $start) + 1;
}
else {
$stream_size = $media->size - $start;
}
- debug_event('play', 'Content-Range header received, skipping ' . $start . ' bytes out of ' . $media->size, 5);
- $browser->downloadHeaders($media_name, $media->mime, false, $media->size);
- if (!$transcoded) {
+ if ($transcoded) {
+ debug_event('play', 'Bad client behaviour. Content-Range header received, which we cannot fulfill due to transcoding', 1);
+ $stream_size = null;
+ }
+ else {
+ debug_event('play', 'Content-Range header received, skipping ' . $start . ' bytes out of ' . $media->size, 5);
fseek($fp, $start);
+
+ $range = $start . '-' . $end . '/' . $media->size;
+ header('HTTP/1.1 206 Partial Content');
+ header('Content-Range: bytes ' . $range);
}
- $range = $start ."-". $end . "/" . $media->size;
- header('HTTP/1.1 206 Partial Content');
- header("Content-Range: bytes $range");
- header("Content-Length: $stream_size");
}
else {
debug_event('play','Starting stream of ' . $media->file . ' with size ' . $media->size, 5);
- header("Content-Length: $media->size");
- $browser->downloadHeaders($media_name, $media->mime, false, $media->size);
- $stream_size = $media->size;
}
+$browser->downloadHeaders($media_name, $media->mime, false, $stream_size);
+
$bytes_streamed = 0;
// Actually do the streaming
do {
- $buf = fread($fp, min(2048, $stream_size - $bytes_streamed));
+ $read_size = $transcoded
+ ? 2048
+ : min(2048, $stream_size - $bytes_streamed);
+ $buf = fread($fp, $read_size);
print($buf);
$bytes_streamed += strlen($buf);
-} while (!feof($fp) && (connection_status() == 0) && ($bytes_streamed < $stream_size));
+} while (!feof($fp) && (connection_status() == 0) && ($transcoded || $bytes_streamed < $stream_size));
+$real_bytes_streamed = $bytes_streamed;
// Need to make sure enough bytes were sent.
if($bytes_streamed < $stream_size && (connection_status() == 0)) {
print(str_repeat(' ', $stream_size - $bytes_streamed));
+ $bytes_streamed = $stream_size;
}
// Make sure that a good chunk of the song has been played
-if ($bytes_streamed > $media->size / 2) {
- // This check looks suspicious
+$target = 131072;
+if ($stream_size) {
+ if ($stream_size > 1048576) {
+ $target = 262144;
+ }
+ else if ($stream_size < 360448) {
+ $target = $stream_size / 1.1;
+ }
+ else {
+ $target = $stream_size / 4;
+ }
+}
+
+if ($start > $target) {
+ debug_event('play', 'Content-Range was more than ' . $target . ' into the file, not collecting stats', 5);
+}
+else if ($bytes_streamed > $target) {
+ // FIXME: This check looks suspicious
if (get_class($media) == 'Song') {
debug_event('play', 'Registering stats for ' . $media->title, 5);
$GLOBALS['user']->update_stats($media->id);
$media->set_played();
}
-
}
else {
- debug_event('play', $bytes_streamed .' of ' . $media->size . ' streamed; not collecting stats', 5);
+ debug_event('play', $bytes_streamed .' of ' . $stream_size . ' streamed; not collecting stats', 5);
}
// If this is a democratic playlist remove the entry.
@@ -416,6 +446,6 @@ else {
fclose($fp);
}
-debug_event('play', 'Stream ended at ' . $bytes_streamed . ' bytes out of ' . $media->size, 5);
+debug_event('play', 'Stream ended at ' . $bytes_streamed . ' (' . $real_bytes_streamed . ') bytes out of ' . $stream_size, 5);
?>