Merge branch 'iconnor_video' into storageareas

This commit is contained in:
Isaac Connor 2016-04-01 11:35:38 -04:00
commit 6816a4c75b
9 changed files with 159 additions and 105 deletions

View File

@ -303,6 +303,9 @@ int main( int argc, const char *argv[] )
}
else if ( source == ZMS_EVENT )
{
if ( ! event_id ) {
Fatal( "Can't view an event without specifying an event_id." );
}
EventStream stream;
stream.setStreamScale( scale );
stream.setStreamReplayRate( rate );

View File

@ -3,112 +3,148 @@ require_once( 'database.php' );
require_once( 'Storage.php' );
class Event {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT *,unix_timestamp(StartTime) as Time FROM Events WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Event record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Event Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
} else {
Error("No row for Event " . $IdOrRow );
}
} // end function __construct
public function Storage() {
return new Storage( $this->{'StorageId'} );
}
public function __call( $fn, array $args){
if(isset($this->{$fn})){
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
public function __construct( $IdOrRow ) {
$row = NULL;
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT *,unix_timestamp(StartTime) as Time FROM Events WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Event record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Event Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {
$this->{$k} = $v;
}
} else {
Error("No row for Event " . $IdOrRow );
}
} // end function __construct
public function Storage() {
return new Storage( $this->{'StorageId'} );
}
public function __call( $fn, array $args){
if(isset($this->{$fn})){
return $this->{$fn};
#array_unshift($args, $this);
#call_user_func_array( $this->{$fn}, $args);
}
}
public function Time() {
if ( ! isset( $this->{'Time'} ) ) {
$this->{'Time'} = strtotime($this->{'StartTime'});
}
return $this->{'Time'};
}
public function Path() {
$Storage = $this->Storage();
return $Storage->Path().'/'.$this->Relative_Path();
}
public function Relative_Path() {
$event_path = "";
if ( ZM_USE_DEEP_STORAGE )
{
$event_path =
$this->{'MonitorId'}
.'/'.strftime( "%y/%m/%d/%H/%M/%S",
$this->{'Time'}
)
;
}
else
{
$event_path =
$this->{'MonitorId'}
.'/'.$this->{'Id'}
;
}
public function Path() {
$Storage = $this->Storage();
return $Storage->Path().'/'.$this->Relative_Path();
}
public function Relative_Path() {
$event_path = "";
return( $event_path );
if ( ZM_USE_DEEP_STORAGE )
{
$event_path =
$this->{'MonitorId'}
.'/'.strftime( "%y/%m/%d/%H/%M/%S",
$this->{'Time'}
)
;
}
else
{
$event_path =
$this->{'MonitorId'}
.'/'.$this->{'Id'}
;
}
}
return( $event_path );
public function LinkPath() {
if ( ZM_USE_DEEP_STORAGE ) {
return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->{'Time'}).$this->{'Id'};
}
Error("Calling Link_Path when not using deep storage");
return '';
}
}
public function delete() {
dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) );
if ( !ZM_OPT_FAST_DELETE ) {
dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) );
dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) );
if ( ZM_USE_DEEP_STORAGE ) {
public function LinkPath() {
if ( ZM_USE_DEEP_STORAGE ) {
return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->{'Time'}).$this->{'Id'};
}
Error("Calling Link_Path when not using deep storage");
return '';
}
# Assumption: All events haev a start time
$start_date = date_parse( $this->{'StartTime'} );
$start_date['year'] = $start_date['year'] % 100;
public function delete() {
dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) );
if ( !ZM_OPT_FAST_DELETE ) {
dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) );
dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) );
if ( ZM_USE_DEEP_STORAGE ) {
$Storage = $this->Storage();
# So this is because ZM creates a link under teh day pointing to the time that the event happened.
$eventlink_path = $Storage->Path().'/'.$this->Link_Path();
# Assumption: All events haev a start time
$start_date = date_parse( $this->{'StartTime'} );
$start_date['year'] = $start_date['year'] % 100;
if ( $id_files = glob( $eventlink_path ) ) {
# I know we are using arrays here, but really there can only ever be 1 in the array
$eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] );
deletePath( $eventPath );
deletePath( $id_files[0] );
$pathParts = explode( '/', $eventPath );
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
$deletePath = join( '/', array_slice( $pathParts, 0, $i ) );
if ( !glob( $deletePath."/*" ) ) {
deletePath( $deletePath );
}
}
} else {
Warning( "Found no event files under $eventlink_path" );
} # end if found files
} else {
$eventPath = $this->Path();
deletePath( $eventPath );
} # USE_DEEP_STORAGE OR NOT
} # ! ZM_OPT_FAST_DELETE
} # end Event->delete
$Storage = $this->Storage();
# So this is because ZM creates a link under teh day pointing to the time that the event happened.
$eventlink_path = $Storage->Path().'/'.$this->Link_Path();
public function getStreamSrc( $args, $querySep='&' ) {
$streamSrc = ZM_BASE_URL.ZM_PATH_ZMS;
if ( $id_files = glob( $eventlink_path ) ) {
# I know we are using arrays here, but really there can only ever be 1 in the array
$eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] );
deletePath( $eventPath );
deletePath( $id_files[0] );
$pathParts = explode( '/', $eventPath );
for ( $i = count($pathParts)-1; $i >= 2; $i-- ) {
$deletePath = join( '/', array_slice( $pathParts, 0, $i ) );
if ( !glob( $deletePath."/*" ) ) {
deletePath( $deletePath );
}
}
} else {
Warning( "Found no event files under $eventlink_path" );
} # end if found files
} else {
$eventPath = $this->Path();
deletePath( $eventPath );
} # USE_DEEP_STORAGE OR NOT
} # ! ZM_OPT_FAST_DELETE
} # end Event->delete
$args[] = "source=event&event=".$this->{'Id'};
if ( ZM_OPT_USE_AUTH ) {
if ( ZM_AUTH_RELAY == "hashed" ) {
$args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS );
} elseif ( ZM_AUTH_RELAY == "plain" ) {
$args[] = "user=".$_SESSION['username'];
$args[] = "pass=".$_SESSION['password'];
} elseif ( ZM_AUTH_RELAY == "none" ) {
$args[] = "user=".$_SESSION['username'];
}
}
if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) {
$args[] = "connkey=".$GLOBALS['connkey'];
}
if ( ZM_RAND_STREAM ) {
$args[] = "rand=".time();
}
if ( count($args) ) {
$streamSrc .= "?".join( $querySep, $args );
}
return( $streamSrc );
} // end function etStreamSrc
} # end class
?>

View File

@ -79,7 +79,7 @@ class Monitor {
}
return( $streamSrc );
} // end function etStreamSrc
} // end function getStreamSrc
public function Width() {
if ( $this->Orientation() == '90' or $this->Orientation() == '270' ) {
return $this->{'Height'};

View File

@ -26,7 +26,7 @@ class Storage {
public function Path() {
if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) {
return $this->{'Path'};
} else if ( ! $this->{'Id'} ) {
} else if ( ! isset($this->{'Id'}) ) {
return ZM_DIR_EVENTS;
}
return $this->{'Name'};

View File

@ -525,7 +525,9 @@ function getEventPath( $event )
}
function getEventDefaultVideoPath( $event ) {
return ZM_DIR_EVENTS . "/" . getEventPath($event) . "/" . $event['DefaultVideo'];
$Event = new Event( $event );
return $Event->getStreamSrc( array( "mode=mpeg" ) );
//$Event->Path().'/'.$event['DefaultVideo'];
}
function deletePath( $path )
@ -1144,10 +1146,19 @@ function getImageSrc( $event, $frame, $scale=SCALE_BASE, $captureOnly=false, $ov
//echo "S:$scale, CO:$captureOnly<br>";
$currEvent = dbFetchOne( 'SELECT M.SaveJPEGs FROM Events AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id WHERE E.Id = '.$event['Id'] );
if ( $currEvent['SaveJPEGs'] == "4" )
if ( $currEvent['SaveJPEGs'] == "4" ) {
# Snapshot only mode
$captImage = "snapshot.jpg";
else
} else {
$captImage = sprintf( "%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $frame['FrameId'] );
if ( $currEvent['SaveJPEGs'] == "0" ) {
# No JPEG saving, must pull from video
if ( ! file_exists( $Storage->Path() .'/'.$eventPath.'/'.$captImage ) ) {
# Generate the frame JPG
# See issue #1379
}
}
}
$captPath = $eventPath.'/'.$captImage;
$thumbCaptPath = ZM_DIR_IMAGES.'/'.$event['Id'].'-'.$captImage;
//echo "CI:$captImage, CP:$captPath, TCP:$thumbCaptPath<br>";
@ -1244,6 +1255,7 @@ function viewImagePath( $path, $querySep='&amp;' )
function createListThumbnail( $event, $overwrite=false )
{
# Load the frame with the highest score to use as a thumbnail
if ( !($frame = dbFetchOne( "SELECT * FROM Frames WHERE EventId=? AND Score=? ORDER BY FrameId LIMIT 1", NULL, array( $event['Id'], $event['MaxScore'] ) )) )
return( false );

View File

@ -585,6 +585,7 @@ $SLANG = array(
'Protocol' => 'Protocol',
'Rate' => 'Rate',
'RecaptchaWarning' => 'Your reCaptcha secret key is invalid. Please correct it, or reCaptcha will not work', // added Sep 24 2015 - PP
'RecordAudio' => 'Whether to store the audio stream when saving an event.',
'Real' => 'Real',
'Record' => 'Record',
'RefImageBlendPct' => 'Reference Image Blend %ge',

View File

@ -55,7 +55,7 @@ $replayModes = array(
if ( isset( $_REQUEST['streamMode'] ) )
$streamMode = validHtmlStr($_REQUEST['streamMode']);
else
$streamMode = video;
$streamMode = 'video';
if ( isset( $_REQUEST['replayMode'] ) )
$replayMode = validHtmlStr($_REQUEST['replayMode']);
@ -70,6 +70,7 @@ else {
$Zoom = 1;
$Rotation = 0;
if ( $event['VideoWriter'] == "2" ) {
# Passthrough
$Rotation = $event['Orientation'];
if ( in_array($event['Orientation'],array("90","270")))
$Zoom = $event['Height']/$event['Width'];

View File

@ -54,7 +54,7 @@ else
$scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE );
$Transpose = '';
if ( $event['VideoWriter'] == "2" ) {
if ( $event['VideoWriter'] == "2" ) { // PASSTHROUGH
$Rotation = $event['Orientation'];
// rotate right
if ( in_array($event['Orientation'],array("90")))

View File

@ -568,12 +568,12 @@ if ( $tab != 'source' )
<input type="hidden" name="newMonitor[Deinterlacing]" value="<?php echo validHtmlStr($monitor->Deinterlacing) ?>"/>
<?php
}
if ( $tab != 'storage' )
{
if ( $tab != 'storage' ) {
?>
<input type="hidden" name="newMonitor[SaveJPEGs]" value="<?php echo validHtmlStr($monitor->SaveJPEGs) ?>"/>
<input type="hidden" name="newMonitor[VideoWriter]" value="<?php echo validHtmlStr($monitor->VideoWriter) ?>"/>
<input type="hidden" name="newMonitor[EncoderParameters]" value="<?php echo validHtmlStr($monitor->EncoderParameters) ?>"/>
<input type="hidden" name="newMonitor[RecordAudio]" value="<?php echo validHtmlStr($monitor->RecordAudio) ?>"/>
<?php
}
if ( $tab != 'source' || ($monitor->Type != 'Remote' && $monitor->Protocol != 'RTSP'))
@ -877,6 +877,7 @@ switch ( $tab )
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->SaveJPEGs ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->VideoWriter ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters) ?></textarea></td></tr>
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ($monitor->RecordAudio) { ?> checked="checked"<?php } ?>/></td></tr>
<?php
break;
case 'timestamp' :