2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
//
|
|
|
|
// ZoneMinder web timeline view file, $Date$, $Revision$
|
|
|
|
//
|
|
|
|
// 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
|
2016-12-26 23:23:16 +08:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2013-05-02 22:20:06 +08:00
|
|
|
//
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !canView( 'Events' ) ) {
|
|
|
|
$view = 'error';
|
|
|
|
return;
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
foreach ( getSkinIncludes( 'includes/timeline_functions.php' ) as $includeFile )
|
2017-05-19 02:04:24 +08:00
|
|
|
require_once $includeFile;
|
2013-05-02 22:20:06 +08:00
|
|
|
|
|
|
|
//
|
|
|
|
// Date/time formats used in charts
|
|
|
|
//
|
|
|
|
// These are the time axis range text. The first of each pair is the start date/time
|
|
|
|
// and the second is the last so often contains additional information
|
|
|
|
//
|
|
|
|
|
|
|
|
// When the chart range is years
|
|
|
|
define( "STRF_TL_AXIS_RANGE_YEAR1", "%b %Y" );
|
|
|
|
define( "STRF_TL_AXIS_RANGE_YEAR2", STRF_TL_AXIS_RANGE_YEAR1 );
|
|
|
|
|
|
|
|
// When the chart range is months
|
|
|
|
define( "STRF_TL_AXIS_RANGE_MONTH1", "%b" );
|
|
|
|
define( "STRF_TL_AXIS_RANGE_MONTH2", STRF_TL_AXIS_RANGE_MONTH1." %Y" );
|
|
|
|
|
|
|
|
// When the chart range is days
|
|
|
|
define( "STRF_TL_AXIS_RANGE_DAY1", "%d" );
|
|
|
|
define( "STRF_TL_AXIS_RANGE_DAY2", STRF_TL_AXIS_RANGE_DAY1." %b %Y" );
|
|
|
|
|
|
|
|
// When the chart range is less than a day
|
|
|
|
define( "STRF_TL_AXIS_RANGE_TIME1", "%H:%M" );
|
|
|
|
define( "STRF_TL_AXIS_RANGE_TIME2", STRF_TL_AXIS_RANGE_TIME1.", %d %b %Y" );
|
|
|
|
|
|
|
|
//
|
|
|
|
// These are the time axis tick labels
|
|
|
|
//
|
|
|
|
define( "STRF_TL_AXIS_LABEL_YEAR", "%Y" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_MONTH", "%M" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_WEEK", "%d/%m" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_DAY", "%d" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_4HOUR", "%H:00" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_HOUR", "%H:00" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_10MINUTE", "%H:%M" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_MINUTE", "%H:%M" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_10SECOND", "%S" );
|
|
|
|
define( "STRF_TL_AXIS_LABEL_SECOND", "%S" );
|
|
|
|
|
|
|
|
$mouseover = true;
|
|
|
|
if ( !isset($mouseover) )
|
2017-05-19 02:04:24 +08:00
|
|
|
$mouseover = true;
|
2013-05-02 22:20:06 +08:00
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
$mode = 'overlay';
|
2013-05-02 22:20:06 +08:00
|
|
|
if ( !isset($mode) )
|
2017-05-19 02:04:24 +08:00
|
|
|
$mode = 'overlay';
|
2013-05-02 22:20:06 +08:00
|
|
|
|
|
|
|
$minEventWidth = 3;
|
|
|
|
$maxEventWidth = 6;
|
|
|
|
|
|
|
|
$chart = array(
|
|
|
|
"width"=>700,
|
|
|
|
"height"=>460,
|
|
|
|
"image" => array(
|
|
|
|
"width"=>264,
|
|
|
|
"height"=>220,
|
|
|
|
"topOffset"=>20,
|
|
|
|
),
|
|
|
|
"imageText" => array(
|
|
|
|
"width"=>400,
|
|
|
|
"height"=>30,
|
|
|
|
"topOffset"=>20,
|
|
|
|
),
|
|
|
|
"graph" => array(
|
|
|
|
"width"=>600,
|
|
|
|
"height"=>160,
|
|
|
|
"topOffset"=>30,
|
|
|
|
),
|
|
|
|
"title" => array(
|
|
|
|
"topOffset"=>50
|
|
|
|
),
|
|
|
|
"key" => array(
|
|
|
|
"topOffset"=>50
|
|
|
|
),
|
|
|
|
"axes" => array(
|
|
|
|
"x" => array(
|
|
|
|
"height" => 20,
|
|
|
|
),
|
|
|
|
"y" => array(
|
|
|
|
"width" => 30,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
"grid" => array(
|
|
|
|
"x" => array(
|
|
|
|
"major" => array(
|
|
|
|
"max" => 12,
|
|
|
|
"min" => 4,
|
|
|
|
),
|
|
|
|
"minor" => array(
|
|
|
|
"max" => 48,
|
|
|
|
"min" => 12,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
"y" => array(
|
|
|
|
"major" => array(
|
|
|
|
"max" => 8,
|
|
|
|
"min" => 1,
|
|
|
|
),
|
|
|
|
"minor" => array(
|
|
|
|
"max" => 0,
|
|
|
|
"min" => 0,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
$monitors = array();
|
2017-05-19 02:04:24 +08:00
|
|
|
$monitorsSql = 'SELECT * FROM Monitors ORDER BY Sequence ASC';
|
2013-05-02 22:20:06 +08:00
|
|
|
//srand( 97981 );
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( dbFetchAll( $monitorsSql ) as $row ) {
|
|
|
|
//if ( empty($row['WebColour']) )
|
|
|
|
//{
|
|
|
|
//$row['WebColour'] = sprintf( "#%02x%02x%02x", rand( 0, 255 ), rand( 0, 255), rand( 0, 255 ) );
|
|
|
|
//}
|
|
|
|
$monitors[$row['Id']] = $row;
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
$rangeSql = 'SELECT min(StartTime) as MinTime, max(EndTime) AS MaxTime FROM Events WHERE NOT isnull(StartTime) AND NOT isnull(EndTime)';
|
|
|
|
$eventsSql = "SELECT * FROM Events WHERE NOT isnull(StartTime)";
|
2013-05-02 22:20:06 +08:00
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !empty($user['MonitorIds']) ) {
|
|
|
|
$monFilterSql = ' AND MonitorId IN ('.$user['MonitorIds'].')';
|
2013-05-02 22:20:06 +08:00
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
$rangeSql .= $monFilterSql;
|
|
|
|
$eventsSql .= $monFilterSql;
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( isset($_REQUEST['filter']) )
|
2017-05-19 02:04:24 +08:00
|
|
|
$tree = parseFilterToTree( $_REQUEST['filter'] );
|
2013-05-02 22:20:06 +08:00
|
|
|
else
|
2017-05-19 02:04:24 +08:00
|
|
|
$tree = false;
|
2013-05-02 22:20:06 +08:00
|
|
|
|
|
|
|
if ( isset($_REQUEST['range']) )
|
|
|
|
$range = validHtmlStr($_REQUEST['range']);
|
|
|
|
if ( isset($_REQUEST['minTime']) )
|
|
|
|
$minTime = validHtmlStr($_REQUEST['minTime']);
|
|
|
|
if ( isset($_REQUEST['midTime']) )
|
|
|
|
$midTime = validHtmlStr($_REQUEST['midTime']);
|
|
|
|
if ( isset($_REQUEST['maxTime']) )
|
|
|
|
$maxTime = validHtmlStr($_REQUEST['maxTime']);
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($range) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$halfRange = (int)($range/2);
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($midTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$midTimeT = strtotime($midTime);
|
|
|
|
$minTimeT = $midTimeT-$halfRange;
|
|
|
|
$maxTimeT = $midTimeT+$halfRange;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !($range%1) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$maxTimeT--;
|
|
|
|
}
|
|
|
|
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
|
|
|
|
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( isset($minTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$minTimeT = strtotime($minTime);
|
|
|
|
$maxTimeT = $minTimeT + $range;
|
|
|
|
$midTimeT = $minTimeT + $halfRange;
|
|
|
|
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
|
|
|
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( isset($maxTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$maxTimeT = strtotime($maxTime);
|
|
|
|
$minTimeT = $maxTimeT - $range;
|
|
|
|
$midTimeT = $minTimeT + $halfRange;
|
|
|
|
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
|
|
|
|
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( isset($minTime) && isset($maxTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$minTimeT = strtotime($minTime);
|
|
|
|
$maxTimeT = strtotime($maxTime);
|
|
|
|
$range = ($maxTimeT - $minTimeT) + 1;
|
|
|
|
$halfRange = (int)($range/2);
|
|
|
|
$midTimeT = $minTimeT + $halfRange;
|
|
|
|
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($minTime) && isset($maxTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$tempMinTime = $tempMaxTime = $tempExpandable = false;
|
|
|
|
extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable );
|
|
|
|
$filterSql = parseTreeToSQL( $tree );
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $filterSql ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$filterSql = " and $filterSql";
|
|
|
|
$eventsSql .= $filterSql;
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$filterSql = parseTreeToSQL( $tree );
|
|
|
|
$tempMinTime = $tempMaxTime = $tempExpandable = false;
|
|
|
|
extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable );
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $filterSql ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$filterSql = " and $filterSql";
|
|
|
|
$rangeSql .= $filterSql;
|
|
|
|
$eventsSql .= $filterSql;
|
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !isset($minTime) || !isset($maxTime) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Dynamically determine range
|
|
|
|
$row = dbFetchOne( $rangeSql );
|
|
|
|
|
|
|
|
if ( !isset($minTime) )
|
|
|
|
$minTime = $row['MinTime'];
|
|
|
|
if ( !isset($maxTime) )
|
|
|
|
$maxTime = $row['MaxTime'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( empty($minTime) )
|
|
|
|
$minTime = $tempMinTime;
|
|
|
|
if ( empty($maxTime) )
|
|
|
|
$maxTime = $tempMaxTime;
|
|
|
|
if ( empty($maxTime) )
|
|
|
|
$maxTime = "now";
|
|
|
|
|
|
|
|
$minTimeT = strtotime($minTime);
|
|
|
|
$maxTimeT = strtotime($maxTime);
|
|
|
|
$range = ($maxTimeT - $minTimeT) + 1;
|
|
|
|
$halfRange = (int)($range/2);
|
|
|
|
$midTimeT = $minTimeT + $halfRange;
|
|
|
|
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
|
|
|
}
|
|
|
|
|
|
|
|
//echo "MnT: $tempMinTime, MxT: $tempMaxTime, ExP: $tempExpandable<br>";
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $tree ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
appendDatetimeRange( $tree, $minTime, $maxTime );
|
|
|
|
|
|
|
|
$filterQuery = parseTreeToQuery( $tree );
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$filterQuery = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$scales = array(
|
|
|
|
array( "name"=>"year", "factor"=>60*60*24*365, "align"=>1, "zoomout"=>2, "label"=>STRF_TL_AXIS_LABEL_YEAR ),
|
|
|
|
array( "name"=>"month", "factor"=>60*60*24*30, "align"=>1, "zoomout"=>12, "label"=>STRF_TL_AXIS_LABEL_MONTH ),
|
|
|
|
array( "name"=>"week", "factor"=>60*60*24*7, "align"=>1, "zoomout"=>4.25, "label"=>STRF_TL_AXIS_LABEL_WEEK, "labelCheck"=>"%W" ),
|
|
|
|
array( "name"=>"day", "factor"=>60*60*24, "align"=>1, "zoomout"=>7, "label"=>STRF_TL_AXIS_LABEL_DAY ),
|
|
|
|
array( "name"=>"hour4", "factor"=>60*60, "align"=>4, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_4HOUR, "labelCheck"=>"%H" ),
|
|
|
|
array( "name"=>"hour", "factor"=>60*60, "align"=>1, "zoomout"=>4, "label"=>STRF_TL_AXIS_LABEL_HOUR, "labelCheck"=>"%H" ),
|
|
|
|
array( "name"=>"minute10", "factor"=>60, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10MINUTE, "labelCheck"=>"%M" ),
|
|
|
|
array( "name"=>"minute", "factor"=>60, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_MINUTE, "labelCheck"=>"%M" ),
|
|
|
|
array( "name"=>"second10", "factor"=>1, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10SECOND ),
|
|
|
|
array( "name"=>"second", "factor"=>1, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_SECOND ),
|
|
|
|
);
|
|
|
|
|
|
|
|
$majXScale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] );
|
|
|
|
|
|
|
|
// Adjust the range etc for scale
|
|
|
|
$minTimeT -= $minTimeT%($majXScale['factor']*$majXScale['align']);
|
|
|
|
$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT );
|
|
|
|
$maxTimeT += (($majXScale['factor']*$majXScale['align'])-$maxTimeT%($majXScale['factor']*$majXScale['align']))-1;
|
|
|
|
if ( $maxTimeT > time() )
|
|
|
|
$maxTimeT = time();
|
|
|
|
$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT );
|
|
|
|
$range = ($maxTimeT - $minTimeT) + 1;
|
|
|
|
$halfRange = (int)($range/2);
|
|
|
|
$midTimeT = $minTimeT + $halfRange;
|
|
|
|
$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT );
|
|
|
|
|
|
|
|
//echo "R:$range<br>";
|
|
|
|
//echo "MnT:$minTime<br>";
|
|
|
|
//echo "MnTt:$minTimeT<br>";
|
|
|
|
//echo "MdT:$midTime<br>";
|
|
|
|
//echo "MdTt:$midTimeT<br>";
|
|
|
|
//echo "MxT:$maxTime<br>";
|
|
|
|
//echo "MxTt:$maxTimeT<br>";
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($minTime) && isset($maxTime) ) {
|
Feature h264 videostorage (#1882)
* Moved writing of configure options from Controller to Model. Fixes #191.
* Initial commit for saving events as videos :)
* Add zm_video.cpp to autotools
* Add zm_video.h to autotools
* Search for MP4V2 header file 3 times: mp4v2/mp4v2.h, mp4v2.h, mp4.h
* Fix serve memory leak
* Few minor code improvements
* Added the ability to override preset, tune, profile and few other improvements
* Correctly write SPS & PPS from x264 encoder headers
* Remove unnessecary SPS & PPS writing code
* Imported missing files from master to feature-h264-videostorage
* Audio support including fixes for dts/pts, split on keyframe and update to mkv extension to prevent ffmpeg problems writing rtsp audio to mp4 containter (header problem)
* Updates to make gcc happy
* Add html5 video control to timeline and event to support mkv playback
* Add zm_videostore.cpp to CMakeLists.txt
* Remove Modern Branch for now
* Fix minor bug
* Option handled added in master, removing duplicate declaration
* Add CaptureandRecord from zm_camera.h
* Putting placeholder in for CaptureAndRecord function
* Removed duplicate code and brackets
* add digest auth file for cmake
Conflicts:
src/CMakeLists.txt
* Add web dir back into Makefile.am
Revert "Removed web from SUBDIRS in Makefile.am"
This reverts commit d9bbcdf3a94cba4d8955fcd03bd965ed2772f34d.
* Add CaptureAndRecord to vlc, still need to make it record
* Resolve SegFault on videostore
* Swap to mp4 container
* mp4 changes
* spaces to tabs, hide video stuff if video writer is turned off
* Make timeline open event.mp4 instead of mkv
* Missed mkv in timeline.js
* Fix some issues from the merge conflict
* Resolve post merge build issues with braces
* Fix whitespace
* Update Jpeg and Video options for passthrough options
* Whitespace fix zm_camera.h
* Fix array mkssing comma
* Add support for Jpeg save options for h264 branch snapshot. Might remove altogether if snapshots not needed
* Update VideoStoreData memory size comment
* Change from config.use_mkv_storage to per monitor option VideoWriter from video branch
* Fix bracket issues post merge
* Clean up comments and add av_free_packet
* Convert from event_directory to event file as per Video branch
* Testing videojs for video playback
* Fixed a missing bracket post merge and also SQL_values now used for EventID and Monitors
* bring recent improvements in ffmpeg capture function into captureandrecord
* Remove pict from writeAudioFramePacket as not used
* Add translate options for h264 Storage options in Monitor and update en_gb file
* Cherry-Pick from iconnor - make it compile on ubuntu 15.04. Which is libav 56.1.0
Conflicts:
src/zm_ffmpeg.cpp
src/zm_remote_camera_rtsp.cpp
Conflicts:
distros/ubuntu1204/changelog
* Clean up videostore code and remove lots of unused code
* proof of concept for dynamic/automatic video rotation using video-js plugin zoomrotate
Conflicts:
web/skins/classic/views/event.php
* removed redundant field in sql query
Conflicts:
web/skins/classic/views/event.php
* local storage of video js plugin
* Beautify!
Make the code somewhat readable.
* added missing videojs.zoomrotate.js file
added missing videojs.zoomrotate.js file
* Typo
added missing "
* Added missing brackets
* fix to display thumbnails when only storing snapshot.jpg
* added control for video playback rate
Conflicts:
web/skins/classic/views/event.php
* dynamically create jpegs from video file for viewing in browser
* fix timeline view for SaveJPEGs monitors (without enabled VideoWriter)
* only expose monitor info which are being used in client
* fix segmentation fault in zma with ubuntu 14.04 and ffmpeg 2.5.8 (gcc 4.8)
when libx264 is not installed
* better way of detecting showing image or video in timeline and event view
instead of Monitor.VideoWriter, Event.DefaultVideo is used, so even if
VideoWriter/SaveJPEG option is changed, a valid image or video will always be
displayed for historical events in both timeline and event view
this also fixes loading videos in timeline view
* Fixes problem of crashing zmc when bad packet arrives causing av_interleaved_write_frame() to return non-zero (-22). Prefilters common packet issues. Add metadata title to generated video file
* Remove syslog.h
* fixed SaveJPEGs are not working
which is caused in errors introduced when merging with master
* Update README.md
* Fix build warnings specific to h264 branch, unused FrameImg, unused ret and int64_t snprintf issues
* Fix PRId64 issue in travis, builds locally fine, but I can see a gcc version issue here
* Fix PRId64 issue in travis, another try
* Try "STDC_FORMAT_MACROS" to see if that helps Travis on gcc 4.6.3
* Revert space removal around PRId64
* video branch ffmpeg 2.9 fixes
ffmpeg 2.9 patched removed SSE2 CPU
* Add FFMPEGInit back
* use webvvt to overlay timestamp (honoring Monitor.LabelFormat) to videos in timeline and event
also fixed bug which prevented seeking in timeline video preview
* ffmpeg 3.0 API build failure fixes
* Update README.md
* merge all the commits from the messed up iconnor_video branch
* fix whitespace
* revert
* whitespace fixes
* spelling fix
* put back some text
* add these back
* fix spelling mistake
* Steal some packet dumping routines from ffmpeg. Convert them to use our logging routines
* add a test and error message if the codec is not h264
* these have been removed in master
* add a view to check auth and just send the video
* add some comments, and dump filename and AVFormatContext on failure to write header
* add the toggle for RecordAudio so that the checkbox works to turn off Audio
* Must init videoStore in constuctor
* more debug and comments, return checking
* Fix dropped part of sql query.
* fix extra else and some whitespace
* Fix missing } from merge that was preventing building.
* fix tabs
* get rid of use of separator, just use \n
* Restore lost fixes for deprecation
* Why are these failing
* Respect record_audio flag when setting up video file so dont try and initiliase mp4 with unsupported audio
* Forgot that I was trying to solve case of stream is true and record_audio
is false.
* Pass swscale_ctx back in to getCachedContext or it will create new
context every frame and leak memory like a mofo.
* Add libx264-dev and libmp4v2-dev to build requires to save hassle of
ensuring they are installed before build.
* Merge my Rotation/Orientation work and fixes for bad h264 streams
* need arpa/inet for reverse lookups
* pull in the new byte range code for viewing videos
* Move our recording flag deeper into closeevent
* add braces and only call closeEvent if there is an event
* deprecate the z_frame_rate stuff which is deprecated in ffmpeg
* remark out some debugging
* fix for video on stream 1
* fix audio_stream to audio_st
* Ignore bad decodes
* fix problems with content-length causing viewing to not work in chrome/android
* change logic of sending file contents to handle an off by one and be more readable
* Some fixes pointed out by Maxim Romanov. Also simply the loading of events to not join the Monitors table
* fix to sql for timeline
* added RecordAudio to sql in README
* Use sub queries instead of joins to fix errors when using new mysql defaults.
* fix sql queries
* Dockerfile to build feature-h264-videostorage
* Must cast codec
* add php-acpu as a dependency
* require php5-acpu
* fix typo
* remove extra /
* Add a line for out-of-tree builds to do api/lib/Cake/bootstrap.php
* delete merge conflict files
* delete merge conflict files
2017-05-16 10:02:48 +08:00
|
|
|
$eventsSql .= " and EndTime >= '$minTime' and StartTime <= '$maxTime'";
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
$eventsSql .= " order by Id asc";
|
|
|
|
//echo "ESQL: $eventsSql<br>";
|
|
|
|
|
|
|
|
$chart['data'] = array(
|
|
|
|
"x" => array(
|
|
|
|
"lo" => strtotime( $minTime ),
|
|
|
|
"hi" => strtotime( $maxTime ),
|
|
|
|
),
|
|
|
|
"y" => array(
|
|
|
|
"lo" => 0,
|
|
|
|
"hi" => 0,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$chart['data']['x']['range'] = ($chart['data']['x']['hi'] - $chart['data']['x']['lo']) + 1;
|
|
|
|
$chart['data']['x']['density'] = $chart['data']['x']['range']/$chart['graph']['width'];
|
|
|
|
|
|
|
|
$monEventSlots = array();
|
|
|
|
$monFrameSlots = array();
|
|
|
|
$monitorIds = array();
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( dbFetchAll( $eventsSql ) as $event ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
if ( !isset($monitorIds[$event['MonitorId']]) )
|
|
|
|
$monitorIds[$event['MonitorId']] = true;
|
|
|
|
|
|
|
|
if ( !isset($monEventSlots[$event['MonitorId']]) )
|
|
|
|
$monEventSlots[$event['MonitorId']] = array();
|
|
|
|
if ( !isset($monFrameSlots[$event['MonitorId']]) )
|
|
|
|
$monFrameSlots[$event['MonitorId']] = array();
|
|
|
|
|
|
|
|
$currEventSlots = &$monEventSlots[$event['MonitorId']];
|
|
|
|
$currFrameSlots = &$monFrameSlots[$event['MonitorId']];
|
|
|
|
|
|
|
|
$startTimeT = strtotime($event['StartTime']);
|
|
|
|
$startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
|
|
|
if ( $startIndex < 0 )
|
|
|
|
$startIndex = 0;
|
|
|
|
|
|
|
|
if ( isset($event['EndTime']) )
|
|
|
|
$endTimeT = strtotime($event['EndTime']);
|
|
|
|
else
|
|
|
|
$endTimeT = time();
|
|
|
|
$endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
|
|
|
|
|
|
|
if ( $endIndex >= $chart['graph']['width'] )
|
|
|
|
$endIndex = $chart['graph']['width'] - 1;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = $startIndex; $i <= $endIndex; $i++ ) {
|
|
|
|
if ( !isset($currEventSlots[$i]) ) {
|
|
|
|
if ( $rawStartIndex == $rawEndIndex ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$offset = 1;
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$offset = 1 + ($event['Frames']?((int)(($event['Frames']-1)*(($i-$rawStartIndex)/($rawEndIndex-$rawStartIndex)))):0);
|
|
|
|
}
|
|
|
|
$currEventSlots[$i] = array( "count"=>0, "width"=>1, "offset"=>$offset, "event"=>$event );
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currEventSlots[$i]['count']++;
|
|
|
|
}
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $event['MaxScore'] > 0 ) {
|
|
|
|
if ( $startIndex == $endIndex ) {
|
2013-11-02 00:30:07 +08:00
|
|
|
$framesSql = "select FrameId,Score from Frames where EventId = ? and Score > 0 order by Score desc limit 1";
|
|
|
|
$frame = dbFetchOne( $framesSql, NULL, array($event['Id']) );
|
2013-05-02 22:20:06 +08:00
|
|
|
|
|
|
|
$i = $startIndex;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !isset($currFrameSlots[$i]) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$i] = array( "count"=>1, "value"=>$event['MaxScore'], "event"=>$event, "frame"=>$frame );
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$i]['count']++;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $event['MaxScore'] > $currFrameSlots[$i]['value'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$i]['value'] = $event['MaxScore'];
|
|
|
|
$currFrameSlots[$i]['event'] = $event;
|
|
|
|
$currFrameSlots[$i]['frame'] = $frame;
|
|
|
|
}
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $event['MaxScore'] > $chart['data']['y']['hi'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['data']['y']['hi'] = $event['MaxScore'];
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-11-02 00:30:07 +08:00
|
|
|
$framesSql = "select FrameId,Delta,unix_timestamp(TimeStamp) as TimeT,Score from Frames where EventId = ? and Score > 0";
|
|
|
|
$result = dbQuery( $framesSql, array( $event['Id'] ) );
|
2017-05-19 02:04:24 +08:00
|
|
|
while( $frame = dbFetchNext( $result ) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
if ( $frame['Score'] == 0 )
|
|
|
|
continue;
|
|
|
|
$frameTimeT = $frame['TimeT'];
|
|
|
|
$frameTimeT = $startTimeT + $frame['Delta'];
|
|
|
|
$frameIndex = (int)(($frameTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']);
|
|
|
|
if ( $frameIndex < 0 )
|
|
|
|
continue;
|
|
|
|
if ( $frameIndex >= $chart['graph']['width'] )
|
|
|
|
continue;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !isset($currFrameSlots[$frameIndex]) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$frameIndex] = array( "count"=>1, "value"=>$frame['Score'], "event"=>$event, "frame"=>$frame );
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$frameIndex]['count']++;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $frame['Score'] > $currFrameSlots[$frameIndex]['value'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$currFrameSlots[$frameIndex]['value'] = $frame['Score'];
|
|
|
|
$currFrameSlots[$frameIndex]['event'] = $event;
|
|
|
|
$currFrameSlots[$frameIndex]['frame'] = $frame;
|
|
|
|
}
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $frame['Score'] > $chart['data']['y']['hi'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['data']['y']['hi'] = $frame['Score'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ksort( $monitorIds, SORT_NUMERIC );
|
|
|
|
ksort( $monEventSlots, SORT_NUMERIC );
|
|
|
|
ksort( $monFrameSlots, SORT_NUMERIC );
|
|
|
|
|
|
|
|
// No longer needed?
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( false ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Add on missing frames
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( array_keys($monFrameSlots) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
unset( $currFrameSlots );
|
|
|
|
$currFrameSlots = &$monFrameSlots[$monitorId];
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
|
|
|
if ( isset($currFrameSlots[$i]) ) {
|
|
|
|
if ( !isset($currFrameSlots[$i]['frame']) ) {
|
2013-11-02 00:30:07 +08:00
|
|
|
$framesSql = "select FrameId,Score from Frames where EventId = ? and Score > 0 order by FrameId limit 1";
|
|
|
|
$currFrameSlots[$i]['frame'] = dbFetchOne( $framesSql, NULL, array( $currFrameSlots[$i]['event']['Id'] ) );
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$chart['data']['y']['range'] = ($chart['data']['y']['hi'] - $chart['data']['y']['lo']) + 1;
|
|
|
|
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['height'];
|
|
|
|
|
|
|
|
$majYScale = getYScale( $chart['data']['y']['range'], $chart['grid']['y']['major']['min'], $chart['grid']['y']['major']['max'] );
|
|
|
|
|
|
|
|
$maxWidth = 0;
|
|
|
|
$maxHeight = 0;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach ( array_keys($monitorIds) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
if ( $maxWidth < $monitors[$monitorId]['Width'] )
|
|
|
|
$maxWidth = $monitors[$monitorId]['Width'];
|
|
|
|
if ( $maxHeight < $monitors[$monitorId]['Height'] )
|
|
|
|
$maxHeight = $monitors[$monitorId]['Height'];
|
|
|
|
}
|
|
|
|
|
|
|
|
//print_r( $monEventSlots );
|
|
|
|
// Optimise boxes
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( array_keys($monEventSlots) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
unset( $currEventSlots );
|
|
|
|
$currEventSlots = &$monEventSlots[$monitorId];
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
|
|
|
if ( isset($currEventSlots[$i]) ) {
|
|
|
|
if ( isset($currSlot) ) {
|
|
|
|
if ( $currSlot['event']['Id'] == $currEventSlots[$i]['event']['Id'] ) {
|
|
|
|
if ( $currSlot['width'] < $maxEventWidth ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Merge slots for the same long event
|
|
|
|
$currSlot['width']++;
|
|
|
|
unset( $currEventSlots[$i] );
|
|
|
|
continue;
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $currSlot['offset'] < $currEventSlots[$i]['offset'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Split very long events
|
|
|
|
$currEventSlots[$i]['frame'] = array( 'FrameId'=>$currEventSlots[$i]['offset'] );
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $currSlot['width'] < $minEventWidth ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Merge multiple small events
|
|
|
|
$currSlot['width']++;
|
|
|
|
unset( $currEventSlots[$i] );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$currSlot = &$currEventSlots[$i];
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
unset( $currSlot );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( isset( $currSlot ) )
|
|
|
|
unset( $currSlot );
|
|
|
|
}
|
|
|
|
//print_r( $monEventSlots );
|
|
|
|
|
|
|
|
// Stack events
|
|
|
|
$frameSlots = array();
|
|
|
|
$frameMonitorIds = array_keys($monFrameSlots);
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
|
|
|
foreach ( $frameMonitorIds as $frameMonitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
unset( $currFrameSlots );
|
|
|
|
$currFrameSlots = &$monFrameSlots[$frameMonitorId];
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($currFrameSlots[$i]) ) {
|
|
|
|
if ( !isset($frameSlots[$i]) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$frameSlots[$i] = array();
|
|
|
|
$frameSlots[$i][] = &$currFrameSlots[$i];
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$slotCount = count($frameSlots[$i]);
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $j = 0; $j < $slotCount; $j++ ) {
|
|
|
|
if ( $currFrameSlots[$i]['value'] > $frameSlots[$i][$j]['value'] ) {
|
|
|
|
for ( $k = $slotCount; $k > $j; $k-- ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$frameSlots[$i][$k] = $frameSlots[$i][$k-1];
|
|
|
|
}
|
|
|
|
$frameSlots[$i][$j] = &$currFrameSlots[$i];
|
|
|
|
break 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$frameSlots[$i][] = &$currFrameSlots[$i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//print_r( $monEventSlots );
|
|
|
|
//print_r( $monFrameSlots );
|
|
|
|
//print_r( $chart );
|
|
|
|
|
|
|
|
$graphHeight = $chart['graph']['height'];
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $mode == "overlay" ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$minEventBarHeight = 10;
|
|
|
|
$maxEventBarHeight = 40;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( count($monitorIds) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight'] = $minEventBarHeight;
|
2017-05-19 02:04:24 +08:00
|
|
|
while ( ($chart['graph']['eventsHeight'] = (($chart['graph']['eventBarHeight'] * count($monitorIds)) + (count($monitorIds)-1))) < $maxEventBarHeight ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight']++;
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight'] = $maxEventBarHeight;
|
|
|
|
$chart['graph']['eventsHeight'] = $maxEventBarHeight;
|
|
|
|
}
|
|
|
|
$chart['graph']['activityHeight'] = ($graphHeight - $chart['graph']['eventsHeight']);
|
|
|
|
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityHeight'];
|
|
|
|
|
|
|
|
$chart['eventBars'] = array();
|
|
|
|
$top = $chart['graph']['activityHeight'];
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach ( array_keys($monitorIds) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['eventBars'][$monitorId] = array( 'top' => $top );
|
|
|
|
$top += $chart['graph']['eventBarHeight']+1;
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $mode == "split" ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$minActivityBarHeight = 30;
|
|
|
|
$minEventBarHeight = 10;
|
|
|
|
$maxEventBarHeight = 40;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( count($monitorIds) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight'] = $minEventBarHeight;
|
|
|
|
$chart['graph']['activityBarHeight'] = $minActivityBarHeight;
|
2017-05-19 02:04:24 +08:00
|
|
|
while ( ((($chart['graph']['eventBarHeight']+$chart['graph']['activityBarHeight']) * count($monitorIds)) + ((2*count($monitorIds))-1)) < $graphHeight ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['activityBarHeight']++;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $chart['graph']['eventBarHeight'] < $maxEventBarHeight ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight']++;
|
|
|
|
}
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['graph']['eventBarHeight'] = $maxEventBarHeight;
|
|
|
|
$chart['graph']['activityBarHeight'] = $graphHeight - $chart['graph']['eventBarHeight'];
|
|
|
|
}
|
|
|
|
$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityBarHeight'];
|
|
|
|
|
|
|
|
?>
|
|
|
|
<?php
|
|
|
|
$chart['activityBars'] = array();
|
|
|
|
$chart['eventBars'] = array();
|
|
|
|
$top = 0;
|
|
|
|
$barCount = 1;
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach ( array_keys($monitorIds) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$chart['eventBars'][$monitorId] = array( 'top' => $top );
|
|
|
|
$chart['eventBars'][$monitorId] = array( 'top' => $top+$chart['graph']['activityBarHeight']+1 );
|
|
|
|
$top += $chart['graph']['activityBarHeight']+1+$chart['graph']['eventBarHeight']+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $minTime, $startMatches );
|
|
|
|
preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $maxTime, $endMatches );
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $startMatches[1] != $endMatches[1] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Different years
|
|
|
|
$title = strftime( STRF_TL_AXIS_RANGE_YEAR1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_YEAR2, $chart['data']['x']['hi'] );
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $startMatches[2] != $endMatches[2] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Different months
|
|
|
|
$title = strftime( STRF_TL_AXIS_RANGE_MONTH1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_MONTH2, $chart['data']['x']['hi'] );
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $startMatches[3] != $endMatches[3] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Different dates
|
|
|
|
$title = strftime( STRF_TL_AXIS_RANGE_DAY1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_DAY2, $chart['data']['x']['hi'] );
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
// Different times
|
|
|
|
$title = strftime( STRF_TL_AXIS_RANGE_TIME1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_TIME2, $chart['data']['x']['hi'] );
|
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
function drawXGrid( $chart, $scale, $labelClass, $tickClass, $gridClass, $zoomClass=false ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
ob_start();
|
|
|
|
$labelCount = 0;
|
|
|
|
$lastTick = 0;
|
|
|
|
unset( $lastLabel );
|
|
|
|
$labelCheck = isset($scale['labelCheck'])?$scale['labelCheck']:$scale['label'];
|
|
|
|
?>
|
|
|
|
<div id="xScale">
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$x = $i - 1;
|
|
|
|
$timeOffset = (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density']));
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $scale['align'] > 1 ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$label = (int)(strftime( $labelCheck, $timeOffset )/$scale['align']);
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$label = strftime( $labelCheck, $timeOffset );
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( !isset($lastLabel) || ($lastLabel != $label) ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$labelCount++;
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $labelCount >= $scale['divisor'] ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$labelCount = 0;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( isset($lastLabel) ) {
|
|
|
|
if ( $labelClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $labelClass ?>" style="left: <?php echo $x-25 ?>px;"><?php echo strftime( $scale['label'], $timeOffset ); ?></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $tickClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $tickClass ?>" style="left: <?php echo $x ?>px;"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $gridClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $gridClass ?>" style="left: <?php echo $x ?>px;"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $scale['name'] != 'second' && $zoomClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$zoomMinTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($lastTick * $chart['data']['x']['density'])) );
|
|
|
|
$zoomMaxTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density'])) );
|
|
|
|
?>
|
2015-05-10 21:10:30 +08:00
|
|
|
<div class="<?php echo $zoomClass ?>" style="left: <?php echo $lastTick-1 ?>px; width: <?php echo $i-$lastTick ?>px;" title="<?php echo translate('ZoomIn') ?>" onclick="tlZoomBounds( '<?php echo $zoomMinTime ?>', '<?php echo $zoomMaxTime ?>' )"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
$lastTick = $i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$lastLabel = $label;
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $zoomClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$zoomMinTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($lastTick * $chart['data']['x']['density'])) );
|
|
|
|
$zoomMaxTime = strftime( STRF_FMT_DATETIME_DB, (int)($chart['data']['x']['lo'] + ($i * $chart['data']['x']['density'])) );
|
|
|
|
?>
|
2015-05-10 21:10:30 +08:00
|
|
|
<div class="<?php echo $zoomClass ?>" style="left: <?php echo $lastTick-1 ?>px; width: <?php echo $i-$lastTick ?>px;" title="<?php echo translate('ZoomIn') ?>" onclick="tlZoomBounds( '<?php echo $zoomMinTime ?>', '<?php echo $zoomMaxTime ?>' )"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
<?php
|
|
|
|
return( ob_get_clean() );
|
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
function drawYGrid( $chart, $scale, $labelClass, $tickClass, $gridClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
ob_start();
|
|
|
|
?>
|
|
|
|
<div id="yScale">
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
for ( $i = 0; $i < $scale['lines']; $i++ ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$label = (int)($i * $scale['divisor']);
|
|
|
|
$y = $chart['graph']['eventsHeight']+(int)(($i * $scale['divisor'])/$chart['data']['y']['density'])-1;
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $labelClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $labelClass ?>" style="top: <?php echo $chart['graph']['height']-($y+8) ?>px;"><?php echo $label ?></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $tickClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $tickClass ?>" style="top: <?php echo $chart['graph']['height']-($y+2) ?>px;"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $gridClass ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="<?php echo $gridClass ?>" style="top: <?php echo $chart['graph']['height']-($y+2) ?>px;<?php echo $i <= 0?' border-top: solid 1px black;':'' ?>"></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
<?php
|
|
|
|
|
|
|
|
return( ob_get_clean() );
|
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
function getSlotPreviewEventBehaviour( $slot ) {
|
|
|
|
return( "previewEvent( '".$slot['event']['Id']."', '".getSlotFrame( $slot )."' )" );
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
function getSlotShowEventBehaviour( $slot ) {
|
|
|
|
global $monitors;
|
2013-05-02 22:20:06 +08:00
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
$monitor = &$monitors[$slot['event']['MonitorId']];
|
2013-05-02 22:20:06 +08:00
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
return( "showEvent( '".$slot['event']['Id']."', '".getSlotFrame( $slot )."', '".reScale( $monitor['Width'], $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE )."', '".reScale( $monitor['Height'], $monitor['DefaultScale'], ZM_WEB_DEFAULT_SCALE )."' )" );
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
$focusWindow = true;
|
|
|
|
|
2015-05-10 21:10:30 +08:00
|
|
|
xhtmlHeaders(__FILE__, translate('Timeline') );
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
|
|
|
<body>
|
|
|
|
<div id="page">
|
|
|
|
<div id="header">
|
|
|
|
<div id="headerButtons">
|
2015-05-10 21:10:30 +08:00
|
|
|
<?php echo makePopupLink( '?view=events&page=1'.htmlspecialchars($filterQuery), 'zmEvents', 'events', translate('List'), canView( 'Events' ) ) ?>
|
|
|
|
<a href="#" onclick="closeWindow();"><?php echo translate('Close') ?></a>
|
2013-05-02 22:20:06 +08:00
|
|
|
</div>
|
2015-05-10 21:10:30 +08:00
|
|
|
<h2><?php echo translate('Timeline') ?></h2>
|
2013-05-02 22:20:06 +08:00
|
|
|
</div>
|
|
|
|
<div id="content" class="chartSize">
|
|
|
|
<div id="topPanel" class="graphWidth">
|
|
|
|
<div id="imagePanel">
|
Feature h264 videostorage (#1882)
* Moved writing of configure options from Controller to Model. Fixes #191.
* Initial commit for saving events as videos :)
* Add zm_video.cpp to autotools
* Add zm_video.h to autotools
* Search for MP4V2 header file 3 times: mp4v2/mp4v2.h, mp4v2.h, mp4.h
* Fix serve memory leak
* Few minor code improvements
* Added the ability to override preset, tune, profile and few other improvements
* Correctly write SPS & PPS from x264 encoder headers
* Remove unnessecary SPS & PPS writing code
* Imported missing files from master to feature-h264-videostorage
* Audio support including fixes for dts/pts, split on keyframe and update to mkv extension to prevent ffmpeg problems writing rtsp audio to mp4 containter (header problem)
* Updates to make gcc happy
* Add html5 video control to timeline and event to support mkv playback
* Add zm_videostore.cpp to CMakeLists.txt
* Remove Modern Branch for now
* Fix minor bug
* Option handled added in master, removing duplicate declaration
* Add CaptureandRecord from zm_camera.h
* Putting placeholder in for CaptureAndRecord function
* Removed duplicate code and brackets
* add digest auth file for cmake
Conflicts:
src/CMakeLists.txt
* Add web dir back into Makefile.am
Revert "Removed web from SUBDIRS in Makefile.am"
This reverts commit d9bbcdf3a94cba4d8955fcd03bd965ed2772f34d.
* Add CaptureAndRecord to vlc, still need to make it record
* Resolve SegFault on videostore
* Swap to mp4 container
* mp4 changes
* spaces to tabs, hide video stuff if video writer is turned off
* Make timeline open event.mp4 instead of mkv
* Missed mkv in timeline.js
* Fix some issues from the merge conflict
* Resolve post merge build issues with braces
* Fix whitespace
* Update Jpeg and Video options for passthrough options
* Whitespace fix zm_camera.h
* Fix array mkssing comma
* Add support for Jpeg save options for h264 branch snapshot. Might remove altogether if snapshots not needed
* Update VideoStoreData memory size comment
* Change from config.use_mkv_storage to per monitor option VideoWriter from video branch
* Fix bracket issues post merge
* Clean up comments and add av_free_packet
* Convert from event_directory to event file as per Video branch
* Testing videojs for video playback
* Fixed a missing bracket post merge and also SQL_values now used for EventID and Monitors
* bring recent improvements in ffmpeg capture function into captureandrecord
* Remove pict from writeAudioFramePacket as not used
* Add translate options for h264 Storage options in Monitor and update en_gb file
* Cherry-Pick from iconnor - make it compile on ubuntu 15.04. Which is libav 56.1.0
Conflicts:
src/zm_ffmpeg.cpp
src/zm_remote_camera_rtsp.cpp
Conflicts:
distros/ubuntu1204/changelog
* Clean up videostore code and remove lots of unused code
* proof of concept for dynamic/automatic video rotation using video-js plugin zoomrotate
Conflicts:
web/skins/classic/views/event.php
* removed redundant field in sql query
Conflicts:
web/skins/classic/views/event.php
* local storage of video js plugin
* Beautify!
Make the code somewhat readable.
* added missing videojs.zoomrotate.js file
added missing videojs.zoomrotate.js file
* Typo
added missing "
* Added missing brackets
* fix to display thumbnails when only storing snapshot.jpg
* added control for video playback rate
Conflicts:
web/skins/classic/views/event.php
* dynamically create jpegs from video file for viewing in browser
* fix timeline view for SaveJPEGs monitors (without enabled VideoWriter)
* only expose monitor info which are being used in client
* fix segmentation fault in zma with ubuntu 14.04 and ffmpeg 2.5.8 (gcc 4.8)
when libx264 is not installed
* better way of detecting showing image or video in timeline and event view
instead of Monitor.VideoWriter, Event.DefaultVideo is used, so even if
VideoWriter/SaveJPEG option is changed, a valid image or video will always be
displayed for historical events in both timeline and event view
this also fixes loading videos in timeline view
* Fixes problem of crashing zmc when bad packet arrives causing av_interleaved_write_frame() to return non-zero (-22). Prefilters common packet issues. Add metadata title to generated video file
* Remove syslog.h
* fixed SaveJPEGs are not working
which is caused in errors introduced when merging with master
* Update README.md
* Fix build warnings specific to h264 branch, unused FrameImg, unused ret and int64_t snprintf issues
* Fix PRId64 issue in travis, builds locally fine, but I can see a gcc version issue here
* Fix PRId64 issue in travis, another try
* Try "STDC_FORMAT_MACROS" to see if that helps Travis on gcc 4.6.3
* Revert space removal around PRId64
* video branch ffmpeg 2.9 fixes
ffmpeg 2.9 patched removed SSE2 CPU
* Add FFMPEGInit back
* use webvvt to overlay timestamp (honoring Monitor.LabelFormat) to videos in timeline and event
also fixed bug which prevented seeking in timeline video preview
* ffmpeg 3.0 API build failure fixes
* Update README.md
* merge all the commits from the messed up iconnor_video branch
* fix whitespace
* revert
* whitespace fixes
* spelling fix
* put back some text
* add these back
* fix spelling mistake
* Steal some packet dumping routines from ffmpeg. Convert them to use our logging routines
* add a test and error message if the codec is not h264
* these have been removed in master
* add a view to check auth and just send the video
* add some comments, and dump filename and AVFormatContext on failure to write header
* add the toggle for RecordAudio so that the checkbox works to turn off Audio
* Must init videoStore in constuctor
* more debug and comments, return checking
* Fix dropped part of sql query.
* fix extra else and some whitespace
* Fix missing } from merge that was preventing building.
* fix tabs
* get rid of use of separator, just use \n
* Restore lost fixes for deprecation
* Why are these failing
* Respect record_audio flag when setting up video file so dont try and initiliase mp4 with unsupported audio
* Forgot that I was trying to solve case of stream is true and record_audio
is false.
* Pass swscale_ctx back in to getCachedContext or it will create new
context every frame and leak memory like a mofo.
* Add libx264-dev and libmp4v2-dev to build requires to save hassle of
ensuring they are installed before build.
* Merge my Rotation/Orientation work and fixes for bad h264 streams
* need arpa/inet for reverse lookups
* pull in the new byte range code for viewing videos
* Move our recording flag deeper into closeevent
* add braces and only call closeEvent if there is an event
* deprecate the z_frame_rate stuff which is deprecated in ffmpeg
* remark out some debugging
* fix for video on stream 1
* fix audio_stream to audio_st
* Ignore bad decodes
* fix problems with content-length causing viewing to not work in chrome/android
* change logic of sending file contents to handle an off by one and be more readable
* Some fixes pointed out by Maxim Romanov. Also simply the loading of events to not join the Monitors table
* fix to sql for timeline
* added RecordAudio to sql in README
* Use sub queries instead of joins to fix errors when using new mysql defaults.
* fix sql queries
* Dockerfile to build feature-h264-videostorage
* Must cast codec
* add php-acpu as a dependency
* require php5-acpu
* fix typo
* remove extra /
* Add a line for out-of-tree builds to do api/lib/Cake/bootstrap.php
* delete merge conflict files
* delete merge conflict files
2017-05-16 10:02:48 +08:00
|
|
|
<div id="image" class="imageHeight">
|
|
|
|
<img id="imageSrc" class="imageWidth" src="graphics/transparent.gif" alt="<?php echo translate('ViewEvent') ?>" title="<?php echo translate('ViewEvent') ?>"/>
|
|
|
|
<?php
|
|
|
|
//due to chrome bug, has to enable https://code.google.com/p/chromium/issues/detail?id=472300
|
|
|
|
//crossorigin has to be added below to make caption work in chrome
|
|
|
|
?>
|
|
|
|
<video id="preview" width="100%" controls crossorigin="anonymous">
|
|
|
|
<source src="<?php echo getEventDefaultVideoPath($event); ?>" type="video/mp4">
|
|
|
|
Your browser does not support the video tag.
|
|
|
|
</video>
|
|
|
|
|
|
|
|
</div>
|
2013-05-02 22:20:06 +08:00
|
|
|
</div>
|
|
|
|
<div id="dataPanel">
|
|
|
|
<div id="textPanel">
|
|
|
|
<div id="instruction">
|
2015-05-10 21:10:30 +08:00
|
|
|
<p><?php echo translate('TimelineTip1') ?></p>
|
|
|
|
<p><?php echo translate('TimelineTip2') ?></p>
|
|
|
|
<p><?php echo translate('TimelineTip3') ?></p>
|
|
|
|
<p><?php echo translate('TimelineTip4') ?></p>
|
2013-08-16 00:58:08 +08:00
|
|
|
</div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<div id="eventData">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="navPanel">
|
2015-05-10 21:10:30 +08:00
|
|
|
<input type="button" title="<?php echo translate('PanLeft') ?>" value="<<" onclick="tlPan( '<?php echo $minTime ?>', '<?php echo $range ?>' )"/>
|
|
|
|
<input type="button" title="<?php echo translate('ZoomOut') ?>" value="–" onclick="tlZoomRange( '<?php echo $midTime ?>', '<?php echo (int)($range*$majXScale['zoomout']) ?>' )"/>
|
|
|
|
<input type="button" title="<?php echo translate('PanRight') ?>" value=">>" onclick="tlPan( '<?php echo $maxTime ?>', '<?php echo $range ?>' )"/>
|
2013-05-02 22:20:06 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="chartPanel">
|
|
|
|
<div id="chart" class="graphSize">
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $mode == "overlay" ) {
|
|
|
|
echo drawYGrid( $chart, $majYScale, "majLabelY", "majTickY", "majGridY graphWidth" );
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
|
|
|
echo drawXGrid( $chart, $majXScale, "majLabelX", "majTickX", "majGridX graphHeight", "zoom graphHeight" );
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $mode == "overlay" ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
|
|
|
<div id="activity" class="activitySize">
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach ( $frameSlots as $index=>$slots ) {
|
|
|
|
foreach ( $slots as $slot ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$slotHeight = (int)($slot['value']/$chart['data']['y']['density']);
|
|
|
|
|
|
|
|
if ( $slotHeight <= 0 )
|
|
|
|
continue;
|
|
|
|
|
2017-05-19 02:04:24 +08:00
|
|
|
if ( $mouseover ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotShowEventBehaviour( $slot ).'"',
|
|
|
|
'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
2017-05-19 02:04:24 +08:00
|
|
|
} else {
|
2013-05-02 22:20:06 +08:00
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="activity monitorColour<?php echo $slot['event']['MonitorId'] ?>" style="left: <?php echo $index ?>px; height: <?php echo $slotHeight ?>px;" <?php echo join( " ", $behaviours ) ?>></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
} elseif ( $mode == "split" ) {
|
|
|
|
foreach( array_keys($monFrameSlots) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2017-05-19 02:04:24 +08:00
|
|
|
<div id="activity<?php echo $monitorId ?>">
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
unset( $currFrameSlots );
|
|
|
|
$currFrameSlots = &$monFrameSlots[$monitorId];
|
|
|
|
foreach ( $currFrameSlots as $index=>$slot ) {
|
|
|
|
$slotHeight = (int)($slot['value']/$chart['data']['y']['density']);
|
|
|
|
|
|
|
|
if ( $slotHeight <= 0 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( $mouseover ) {
|
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotShowEventBehaviour( $slot ).'"',
|
|
|
|
'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
|
|
|
}
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2017-05-19 02:04:24 +08:00
|
|
|
<div class="activity activity<?php echo $slot['event']['MonitorId'] ?>" style="left: <?php echo $index ?>px; height: <?php echo $slotHeight ?>px;" <?php echo join( " ", $behaviours ) ?>></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
<?php
|
|
|
|
}
|
2013-05-02 22:20:06 +08:00
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( array_keys($monEventSlots) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div id="events<?php echo $monitorId ?>" class="events eventsSize eventsPos<?php echo $monitorId ?>">
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
unset( $currEventSlots );
|
|
|
|
$currEventSlots = &$monEventSlots[$monitorId];
|
|
|
|
$monitorMouseover = $mouseover;
|
|
|
|
if ($monitors[$monitorId]['SaveJPEGs'] == 2) {
|
|
|
|
$monitorMouseover = false;
|
|
|
|
}
|
|
|
|
for ( $i = 0; $i < $chart['graph']['width']; $i++ ) {
|
|
|
|
if ( isset($currEventSlots[$i]) ) {
|
|
|
|
unset( $slot );
|
|
|
|
$slot = &$currEventSlots[$i];
|
|
|
|
|
|
|
|
if ( $monitorMouseover ) {
|
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotShowEventBehaviour( $slot ).'"',
|
|
|
|
'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
$behaviours = array(
|
|
|
|
'onclick="'.getSlotPreviewEventBehaviour( $slot ).'"'
|
|
|
|
);
|
|
|
|
}
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div class="event eventsHeight monitorColour<?php echo $monitorId ?>" style="left: <?php echo $i ?>px; width: <?php echo $slot['width'] ?>px;" <?php echo join( " ", $behaviours ) ?>></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
2017-05-19 02:04:24 +08:00
|
|
|
}
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
<?php
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div id="chartLabels" class="graphWidth">
|
|
|
|
<div id="key">
|
|
|
|
<?php
|
2017-05-19 02:04:24 +08:00
|
|
|
foreach( array_keys($monEventSlots) as $monitorId ) {
|
2013-05-02 22:20:06 +08:00
|
|
|
?>
|
2014-12-05 07:44:23 +08:00
|
|
|
<span class="keyEntry"><?php echo $monitors[$monitorId]['Name'] ?><img id="keyBox<?php echo $monitorId ?>" class="keyBox monitorColour<?php echo $monitorId ?>" src="graphics/transparent.gif" alt="<?php echo $monitors[$monitorId]['Name'] ?>"/></span>
|
2013-05-02 22:20:06 +08:00
|
|
|
<?php
|
|
|
|
}
|
|
|
|
?>
|
|
|
|
</div>
|
2014-12-05 07:44:23 +08:00
|
|
|
<div id="range"><?php echo $title ?></div>
|
2013-05-02 22:20:06 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
Feature h264 videostorage (#1882)
* Moved writing of configure options from Controller to Model. Fixes #191.
* Initial commit for saving events as videos :)
* Add zm_video.cpp to autotools
* Add zm_video.h to autotools
* Search for MP4V2 header file 3 times: mp4v2/mp4v2.h, mp4v2.h, mp4.h
* Fix serve memory leak
* Few minor code improvements
* Added the ability to override preset, tune, profile and few other improvements
* Correctly write SPS & PPS from x264 encoder headers
* Remove unnessecary SPS & PPS writing code
* Imported missing files from master to feature-h264-videostorage
* Audio support including fixes for dts/pts, split on keyframe and update to mkv extension to prevent ffmpeg problems writing rtsp audio to mp4 containter (header problem)
* Updates to make gcc happy
* Add html5 video control to timeline and event to support mkv playback
* Add zm_videostore.cpp to CMakeLists.txt
* Remove Modern Branch for now
* Fix minor bug
* Option handled added in master, removing duplicate declaration
* Add CaptureandRecord from zm_camera.h
* Putting placeholder in for CaptureAndRecord function
* Removed duplicate code and brackets
* add digest auth file for cmake
Conflicts:
src/CMakeLists.txt
* Add web dir back into Makefile.am
Revert "Removed web from SUBDIRS in Makefile.am"
This reverts commit d9bbcdf3a94cba4d8955fcd03bd965ed2772f34d.
* Add CaptureAndRecord to vlc, still need to make it record
* Resolve SegFault on videostore
* Swap to mp4 container
* mp4 changes
* spaces to tabs, hide video stuff if video writer is turned off
* Make timeline open event.mp4 instead of mkv
* Missed mkv in timeline.js
* Fix some issues from the merge conflict
* Resolve post merge build issues with braces
* Fix whitespace
* Update Jpeg and Video options for passthrough options
* Whitespace fix zm_camera.h
* Fix array mkssing comma
* Add support for Jpeg save options for h264 branch snapshot. Might remove altogether if snapshots not needed
* Update VideoStoreData memory size comment
* Change from config.use_mkv_storage to per monitor option VideoWriter from video branch
* Fix bracket issues post merge
* Clean up comments and add av_free_packet
* Convert from event_directory to event file as per Video branch
* Testing videojs for video playback
* Fixed a missing bracket post merge and also SQL_values now used for EventID and Monitors
* bring recent improvements in ffmpeg capture function into captureandrecord
* Remove pict from writeAudioFramePacket as not used
* Add translate options for h264 Storage options in Monitor and update en_gb file
* Cherry-Pick from iconnor - make it compile on ubuntu 15.04. Which is libav 56.1.0
Conflicts:
src/zm_ffmpeg.cpp
src/zm_remote_camera_rtsp.cpp
Conflicts:
distros/ubuntu1204/changelog
* Clean up videostore code and remove lots of unused code
* proof of concept for dynamic/automatic video rotation using video-js plugin zoomrotate
Conflicts:
web/skins/classic/views/event.php
* removed redundant field in sql query
Conflicts:
web/skins/classic/views/event.php
* local storage of video js plugin
* Beautify!
Make the code somewhat readable.
* added missing videojs.zoomrotate.js file
added missing videojs.zoomrotate.js file
* Typo
added missing "
* Added missing brackets
* fix to display thumbnails when only storing snapshot.jpg
* added control for video playback rate
Conflicts:
web/skins/classic/views/event.php
* dynamically create jpegs from video file for viewing in browser
* fix timeline view for SaveJPEGs monitors (without enabled VideoWriter)
* only expose monitor info which are being used in client
* fix segmentation fault in zma with ubuntu 14.04 and ffmpeg 2.5.8 (gcc 4.8)
when libx264 is not installed
* better way of detecting showing image or video in timeline and event view
instead of Monitor.VideoWriter, Event.DefaultVideo is used, so even if
VideoWriter/SaveJPEG option is changed, a valid image or video will always be
displayed for historical events in both timeline and event view
this also fixes loading videos in timeline view
* Fixes problem of crashing zmc when bad packet arrives causing av_interleaved_write_frame() to return non-zero (-22). Prefilters common packet issues. Add metadata title to generated video file
* Remove syslog.h
* fixed SaveJPEGs are not working
which is caused in errors introduced when merging with master
* Update README.md
* Fix build warnings specific to h264 branch, unused FrameImg, unused ret and int64_t snprintf issues
* Fix PRId64 issue in travis, builds locally fine, but I can see a gcc version issue here
* Fix PRId64 issue in travis, another try
* Try "STDC_FORMAT_MACROS" to see if that helps Travis on gcc 4.6.3
* Revert space removal around PRId64
* video branch ffmpeg 2.9 fixes
ffmpeg 2.9 patched removed SSE2 CPU
* Add FFMPEGInit back
* use webvvt to overlay timestamp (honoring Monitor.LabelFormat) to videos in timeline and event
also fixed bug which prevented seeking in timeline video preview
* ffmpeg 3.0 API build failure fixes
* Update README.md
* merge all the commits from the messed up iconnor_video branch
* fix whitespace
* revert
* whitespace fixes
* spelling fix
* put back some text
* add these back
* fix spelling mistake
* Steal some packet dumping routines from ffmpeg. Convert them to use our logging routines
* add a test and error message if the codec is not h264
* these have been removed in master
* add a view to check auth and just send the video
* add some comments, and dump filename and AVFormatContext on failure to write header
* add the toggle for RecordAudio so that the checkbox works to turn off Audio
* Must init videoStore in constuctor
* more debug and comments, return checking
* Fix dropped part of sql query.
* fix extra else and some whitespace
* Fix missing } from merge that was preventing building.
* fix tabs
* get rid of use of separator, just use \n
* Restore lost fixes for deprecation
* Why are these failing
* Respect record_audio flag when setting up video file so dont try and initiliase mp4 with unsupported audio
* Forgot that I was trying to solve case of stream is true and record_audio
is false.
* Pass swscale_ctx back in to getCachedContext or it will create new
context every frame and leak memory like a mofo.
* Add libx264-dev and libmp4v2-dev to build requires to save hassle of
ensuring they are installed before build.
* Merge my Rotation/Orientation work and fixes for bad h264 streams
* need arpa/inet for reverse lookups
* pull in the new byte range code for viewing videos
* Move our recording flag deeper into closeevent
* add braces and only call closeEvent if there is an event
* deprecate the z_frame_rate stuff which is deprecated in ffmpeg
* remark out some debugging
* fix for video on stream 1
* fix audio_stream to audio_st
* Ignore bad decodes
* fix problems with content-length causing viewing to not work in chrome/android
* change logic of sending file contents to handle an off by one and be more readable
* Some fixes pointed out by Maxim Romanov. Also simply the loading of events to not join the Monitors table
* fix to sql for timeline
* added RecordAudio to sql in README
* Use sub queries instead of joins to fix errors when using new mysql defaults.
* fix sql queries
* Dockerfile to build feature-h264-videostorage
* Must cast codec
* add php-acpu as a dependency
* require php5-acpu
* fix typo
* remove extra /
* Add a line for out-of-tree builds to do api/lib/Cake/bootstrap.php
* delete merge conflict files
* delete merge conflict files
2017-05-16 10:02:48 +08:00
|
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
|
2013-05-02 22:20:06 +08:00
|
|
|
</body>
|
|
|
|
</html>
|