2016-04-11 22:31:51 +08:00
|
|
|
<?php
|
|
|
|
//
|
2020-04-17 21:45:40 +08:00
|
|
|
// ZoneMinder web video view file
|
2016-04-11 22:31:51 +08:00
|
|
|
// Copyright (C) 2001-2008 Philip Coombes
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
2017-07-14 23:39:50 +08:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2016-04-11 22:31:51 +08:00
|
|
|
//
|
|
|
|
|
|
|
|
// Calling sequence: ... /zm/index.php?view=video&event_id=123
|
|
|
|
//
|
|
|
|
// event_id is the id of the event to view
|
|
|
|
//
|
|
|
|
// Does not support scaling at this time.
|
|
|
|
//
|
|
|
|
|
2018-08-31 23:58:33 +08:00
|
|
|
if ( !canView('Events') ) {
|
2017-04-01 02:33:00 +08:00
|
|
|
$view = 'error';
|
2016-08-31 22:09:01 +08:00
|
|
|
return;
|
2016-04-11 22:31:51 +08:00
|
|
|
}
|
|
|
|
|
2020-09-05 02:58:43 +08:00
|
|
|
# in index.php we do ob_end_start but there can be no output before view_video and we often don't have enough ram to buffer the content.
|
|
|
|
ob_end_clean();
|
2016-04-11 22:31:51 +08:00
|
|
|
require_once('includes/Event.php');
|
|
|
|
|
|
|
|
$errorText = false;
|
2016-08-31 22:09:01 +08:00
|
|
|
$path = '';
|
|
|
|
|
2017-04-20 01:11:15 +08:00
|
|
|
$Event = null;
|
|
|
|
|
2018-08-31 23:58:33 +08:00
|
|
|
if ( ! empty($_REQUEST['eid']) ) {
|
2019-02-22 22:19:07 +08:00
|
|
|
$Event = new ZM\Event($_REQUEST['eid']);
|
2016-08-31 22:09:01 +08:00
|
|
|
$path = $Event->Path().'/'.$Event->DefaultVideo();
|
2018-08-31 23:58:33 +08:00
|
|
|
} else if ( ! empty($_REQUEST['event_id']) ) {
|
2019-02-22 22:19:07 +08:00
|
|
|
$Event = new ZM\Event($_REQUEST['event_id']);
|
2017-11-14 03:51:54 +08:00
|
|
|
$path = $Event->Path().'/'.$Event->DefaultVideo();
|
2016-04-11 22:31:51 +08:00
|
|
|
} else {
|
2017-04-19 22:09:27 +08:00
|
|
|
$errorText = 'No video path';
|
2016-04-11 22:31:51 +08:00
|
|
|
}
|
|
|
|
|
2016-08-31 22:09:01 +08:00
|
|
|
if ( $errorText ) {
|
2019-02-22 22:19:07 +08:00
|
|
|
ZM\Error($errorText);
|
2017-04-19 22:09:27 +08:00
|
|
|
header('HTTP/1.0 404 Not Found');
|
2016-08-31 22:09:01 +08:00
|
|
|
die();
|
|
|
|
}
|
|
|
|
|
2020-04-17 21:45:40 +08:00
|
|
|
if ( ! ($fh = @fopen($path,'rb') ) ) {
|
2017-04-19 22:09:27 +08:00
|
|
|
header('HTTP/1.0 404 Not Found');
|
2016-08-31 22:09:01 +08:00
|
|
|
die();
|
|
|
|
}
|
|
|
|
|
2020-04-17 21:45:40 +08:00
|
|
|
$size = filesize($path);
|
2016-08-31 22:09:01 +08:00
|
|
|
$begin = 0;
|
2016-11-03 23:23:10 +08:00
|
|
|
$end = $size-1;
|
|
|
|
$length = $size;
|
2016-08-31 22:09:01 +08:00
|
|
|
|
2018-08-31 23:58:33 +08:00
|
|
|
if ( isset($_SERVER['HTTP_RANGE']) ) {
|
2020-04-17 21:45:40 +08:00
|
|
|
ZM\Logger::Debug('Using Range '.$_SERVER['HTTP_RANGE']);
|
2018-08-31 23:58:33 +08:00
|
|
|
if ( preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches) ) {
|
|
|
|
$begin = intval($matches[1]);
|
2020-04-17 21:45:40 +08:00
|
|
|
if ( !empty($matches[2]) ) {
|
2018-08-31 23:58:33 +08:00
|
|
|
$end = intval($matches[2]);
|
2016-04-11 22:31:51 +08:00
|
|
|
}
|
2016-11-03 23:23:10 +08:00
|
|
|
$length = $end - $begin + 1;
|
2019-02-22 22:19:07 +08:00
|
|
|
ZM\Logger::Debug("Using Range $begin $end size: $size, length: $length");
|
2016-08-31 22:09:01 +08:00
|
|
|
}
|
|
|
|
} # end if HTTP_RANGE
|
|
|
|
|
2016-11-03 23:23:10 +08:00
|
|
|
header('Content-type: video/mp4');
|
|
|
|
header('Accept-Ranges: bytes');
|
|
|
|
header('Content-Length: '.$length);
|
2017-04-20 01:11:15 +08:00
|
|
|
# This is so that Save Image As give a useful filename
|
|
|
|
if ( $Event ) {
|
|
|
|
header('Content-Disposition: inline; filename="' . $Event->DefaultVideo() . '"');
|
|
|
|
} else {
|
2017-05-19 00:49:59 +08:00
|
|
|
header('Content-Disposition: inline;');
|
2017-04-20 01:11:15 +08:00
|
|
|
}
|
2016-11-03 23:23:10 +08:00
|
|
|
if ( $begin > 0 || $end < $size-1 ) {
|
2016-08-31 22:09:01 +08:00
|
|
|
header('HTTP/1.0 206 Partial Content');
|
2016-11-03 23:23:10 +08:00
|
|
|
header("Content-Range: bytes $begin-$end/$size");
|
|
|
|
header("Content-Transfer-Encoding: binary\n");
|
|
|
|
header('Connection: close');
|
2016-08-31 22:09:01 +08:00
|
|
|
} else {
|
|
|
|
header('HTTP/1.0 200 OK');
|
2016-04-11 22:31:51 +08:00
|
|
|
}
|
2016-08-31 22:09:01 +08:00
|
|
|
|
2016-09-22 22:37:32 +08:00
|
|
|
// Apparently without these we get a few extra bytes of output at the end...
|
|
|
|
flush();
|
|
|
|
|
2016-08-31 22:09:01 +08:00
|
|
|
$cur = $begin;
|
2018-08-31 23:58:33 +08:00
|
|
|
fseek($fh, $begin, 0);
|
2016-08-31 22:09:01 +08:00
|
|
|
|
2020-04-17 21:45:40 +08:00
|
|
|
while ( $length && ( !feof($fh) ) && ( connection_status() == 0 ) ) {
|
2018-08-31 23:58:33 +08:00
|
|
|
$amount = min(1024*16, $length);
|
2016-11-03 23:42:42 +08:00
|
|
|
|
2020-04-17 21:45:40 +08:00
|
|
|
print fread($fh, $amount);
|
2016-11-03 23:42:42 +08:00
|
|
|
$length -= $amount;
|
2017-05-19 00:49:59 +08:00
|
|
|
# Why introduce a speed limit?
|
|
|
|
#usleep(100);
|
2017-04-01 02:33:00 +08:00
|
|
|
flush();
|
2016-08-31 22:09:01 +08:00
|
|
|
}
|
2016-11-03 23:23:10 +08:00
|
|
|
|
2018-08-31 23:58:33 +08:00
|
|
|
fclose($fh);
|
2016-11-03 23:23:10 +08:00
|
|
|
exit();
|