1) Made shared memory 16 byte aligned and identical size and layout for all platforms.
2) Fixed a bug in zmwatch.pl: Not freeing shared memory handles between iterations. 3) Modified default monitor options to simplify new monitor creation.pull/49/head
parent
ea3a1a9072
commit
b0bc227232
|
@ -134,30 +134,35 @@ our $mem_seq = 0;
|
|||
our $mem_data =
|
||||
{
|
||||
"shared_data" => { "type"=>"SharedData", "seq"=>$mem_seq++, "contents"=> {
|
||||
"size" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"valid" => { "type"=>"bool1", "seq"=>$mem_seq++ },
|
||||
"active" => { "type"=>"bool1", "seq"=>$mem_seq++ },
|
||||
"signal" => { "type"=>"bool1", "seq"=>$mem_seq++ },
|
||||
"state" => { "type"=>"enum", "seq"=>$mem_seq++},
|
||||
"last_write_index" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"last_read_index" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"last_write_time" => { "type"=>"time_t", "seq"=>$mem_seq++ },
|
||||
"last_read_time" => { "type"=>"time_t", "seq"=>$mem_seq++ },
|
||||
"last_event" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"action" => { "type"=>"enum", "seq"=>$mem_seq++ },
|
||||
"brightness" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"hue" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"colour" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"contrast" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"alarm_x" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"alarm_y" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"size" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"last_write_index" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"last_read_index" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"state" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"last_event" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"action" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"brightness" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"hue" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"colour" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"contrast" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ },
|
||||
"valid" => { "type"=>"uchar", "seq"=>$mem_seq++ },
|
||||
"active" => { "type"=>"uchar", "seq"=>$mem_seq++ },
|
||||
"signal" => { "type"=>"uchar", "seq"=>$mem_seq++ },
|
||||
"bpadding" => { "type"=>"uchar", "seq"=>$mem_seq++ },
|
||||
"epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"epadding3" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ },
|
||||
"last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ },
|
||||
"control_state" => { "type"=>"uchar[256]", "seq"=>$mem_seq++ },
|
||||
}
|
||||
},
|
||||
"trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> {
|
||||
"size" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"trigger_state" => { "type"=>"enum", "seq"=>$mem_seq++ },
|
||||
"trigger_score" => { "type"=>"int", "seq"=>$mem_seq++ },
|
||||
"size" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"padding" => { "type"=>"uint32", "seq"=>$mem_seq++ },
|
||||
"trigger_cause" => { "type"=>"char[32]", "seq"=>$mem_seq++ },
|
||||
"trigger_text" => { "type"=>"char[256]", "seq"=>$mem_seq++ },
|
||||
"trigger_showtext" => { "type"=>"char[256]", "seq"=>$mem_seq++ },
|
||||
|
@ -176,7 +181,7 @@ sub zmMemInit
|
|||
foreach my $section_data ( sort { $a->{seq} <=> $b->{seq} } values( %$mem_data ) )
|
||||
{
|
||||
$section_data->{offset} = $offset;
|
||||
$section_data->{align} = 4;
|
||||
$section_data->{align} = 0;
|
||||
|
||||
if ( $section_data->{align} > 1 )
|
||||
{
|
||||
|
@ -188,11 +193,15 @@ sub zmMemInit
|
|||
}
|
||||
foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) )
|
||||
{
|
||||
if ( $member_data->{type} eq "long" || $member_data->{type} eq "time_t" || $member_data->{type} eq "size_t" || $member_data->{type} eq "bool8" )
|
||||
if ( $member_data->{type} eq "long" || $member_data->{type} eq "ulong" || $member_data->{type} eq "size_t")
|
||||
{
|
||||
$member_data->{size} = $member_data->{align} = $native;
|
||||
}
|
||||
elsif ( $member_data->{type} eq "int" || $member_data->{type} eq "enum" || $member_data->{type} eq "bool4" )
|
||||
elsif( $member_data->{type} eq "int64" || $member_data->{type} eq "uint64" || $member_data->{type} eq "time_t64")
|
||||
{
|
||||
$member_data->{size} = $member_data->{align} = 8;
|
||||
}
|
||||
elsif ( $member_data->{type} eq "int32" || $member_data->{type} eq "uint32" || $member_data->{type} eq "bool4" )
|
||||
{
|
||||
$member_data->{size} = $member_data->{align} = 4;
|
||||
}
|
||||
|
@ -200,7 +209,7 @@ sub zmMemInit
|
|||
{
|
||||
$member_data->{size} = $member_data->{align} = 2;
|
||||
}
|
||||
elsif ( $member_data->{type} =~ "/^u?char$/" || $member_data->{type} eq "bool1" )
|
||||
elsif ( $member_data->{type} eq "char" || $member_data->{type} eq "uchar" || $member_data->{type} eq "bool1" )
|
||||
{
|
||||
$member_data->{size} = $member_data->{align} = 1;
|
||||
}
|
||||
|
@ -304,11 +313,16 @@ sub zmMemRead( $$;$ )
|
|||
return( undef );
|
||||
}
|
||||
my $value;
|
||||
if ( $type eq "long" || $type eq "time_t" || $type eq "size_t" || $type eq "bool8" )
|
||||
if ( $type eq "long" || $type eq "ulong" || $type eq "size_t")
|
||||
{
|
||||
( $value ) = unpack( "l!", $data );
|
||||
}
|
||||
elsif ( $type eq "int" || $type eq "enum" || $type eq "bool4" )
|
||||
elsif ( $type eq "int64" || $type eq "uint64" || $type eq "time_t64" )
|
||||
{
|
||||
# The "q" type is only available on 64bit platforms.
|
||||
( $value ) = unpack( "l!", $data );
|
||||
}
|
||||
elsif ( $type eq "int32" || $type eq "uint32" || $type eq "bool4" )
|
||||
{
|
||||
( $value ) = unpack( "l", $data );
|
||||
}
|
||||
|
@ -382,11 +396,16 @@ sub zmMemWrite( $$;$ )
|
|||
my $size = $mem_data->{$section}->{contents}->{$element}->{size};
|
||||
|
||||
my $data;
|
||||
if ( $type eq "long" || $type eq "time_t" || $type eq "size_t" || $type eq "bool8" )
|
||||
if ( $type eq "long" || $type eq "ulong" || $type eq "size_t")
|
||||
{
|
||||
$data = pack( "l!", $value );
|
||||
}
|
||||
elsif ( $type eq "int" || $type eq "enum" || $type eq "bool4" )
|
||||
elsif ( $type eq "int64" || $type eq "uint64" || $type eq "time_t64" )
|
||||
{
|
||||
# The "q" type is only available on 64bit platforms.
|
||||
$data = pack( "l!", $value );
|
||||
}
|
||||
elsif ( $type eq "int32" || $type eq "uint32" || $type eq "bool4" )
|
||||
{
|
||||
$data = pack( "l", $value );
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ while( 1 )
|
|||
{
|
||||
# Check we have got an image recently
|
||||
my $image_time = zmGetLastWriteTime( $monitor );
|
||||
zmMemInvalidate( $monitor );
|
||||
next if ( !defined($image_time) ); # Can't read from shared data
|
||||
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
||||
|
||||
|
@ -95,9 +96,9 @@ while( 1 )
|
|||
Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" );
|
||||
if ( $image_delay > $max_image_delay )
|
||||
{
|
||||
Info( "Restarting capture daemon for ".$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n" );
|
||||
$restart = 1;
|
||||
}
|
||||
Info( "Restarting capture daemon for ".$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n" );
|
||||
$restart = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -124,6 +125,7 @@ while( 1 )
|
|||
{
|
||||
# Check we have got an image recently
|
||||
my $image_time = zmGetLastReadTime( $monitor );
|
||||
zmMemInvalidate( $monitor );
|
||||
next if ( !defined($image_time) ); # Can't read from shared data
|
||||
next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died.
|
||||
|
||||
|
|
|
@ -394,8 +394,10 @@ Monitor::Monitor(
|
|||
struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData));
|
||||
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
|
||||
|
||||
/* This shouldn't be needed if the shared memory start address is multiple of 16, but just in case */
|
||||
if(((unsigned long)shared_images % 16) != 0) {
|
||||
/* Align images buffer to nearest 16 byte boundary */
|
||||
Debug(3,"Aligning shared memory images to the next 16 byte boundary");
|
||||
shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16)));
|
||||
}
|
||||
|
||||
|
@ -585,7 +587,7 @@ void Monitor::AddZones( int p_n_zones, Zone *p_zones[] )
|
|||
|
||||
Monitor::State Monitor::GetState() const
|
||||
{
|
||||
return( shared_data->state );
|
||||
return( (State)shared_data->state );
|
||||
}
|
||||
|
||||
int Monitor::GetImage( int index, int scale ) const
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "zm_camera.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SIGNAL_CAUSE "Signal"
|
||||
#define MOTION_CAUSE "Motion"
|
||||
|
@ -86,43 +87,64 @@ protected:
|
|||
|
||||
typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode;
|
||||
|
||||
/* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
bool valid;
|
||||
bool active;
|
||||
bool signal;
|
||||
State state;
|
||||
int last_write_index;
|
||||
int last_read_index;
|
||||
time_t last_write_time;
|
||||
time_t last_read_time;
|
||||
int last_event;
|
||||
unsigned int action;
|
||||
int brightness;
|
||||
int hue;
|
||||
int colour;
|
||||
int contrast;
|
||||
int alarm_x;
|
||||
int alarm_y;
|
||||
char control_state[256];
|
||||
uint32_t size; /* +0 */
|
||||
uint32_t last_write_index; /* +4 */
|
||||
uint32_t last_read_index; /* +8 */
|
||||
uint32_t state; /* +12 */
|
||||
uint32_t last_event; /* +16 */
|
||||
uint32_t action; /* +20 */
|
||||
int32_t brightness; /* +24 */
|
||||
int32_t hue; /* +28 */
|
||||
int32_t colour; /* +32 */
|
||||
int32_t contrast; /* +36 */
|
||||
int32_t alarm_x; /* +40 */
|
||||
int32_t alarm_y; /* +44 */
|
||||
uint8_t valid; /* +48 */
|
||||
uint8_t active; /* +49 */
|
||||
uint8_t signal; /* +50 */
|
||||
uint8_t bpadding; /* +51 */
|
||||
uint32_t epadding1; /* +52 */
|
||||
uint32_t epadding2; /* +56 */
|
||||
uint32_t epadding3; /* +60 */
|
||||
/*
|
||||
** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038.
|
||||
** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16.
|
||||
*/
|
||||
union { /* +64 */
|
||||
time_t last_write_time;
|
||||
uint64_t extrapad1;
|
||||
};
|
||||
union { /* +72 */
|
||||
time_t last_read_time;
|
||||
uint64_t extrapad2;
|
||||
};
|
||||
uint8_t control_state[256]; /* +80 */
|
||||
|
||||
} SharedData;
|
||||
|
||||
typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState;
|
||||
|
||||
/* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
TriggerState trigger_state;
|
||||
int trigger_score;
|
||||
uint32_t size;
|
||||
uint32_t trigger_state;
|
||||
uint32_t trigger_score;
|
||||
uint32_t padding;
|
||||
char trigger_cause[32];
|
||||
char trigger_text[256];
|
||||
char trigger_showtext[256];
|
||||
} TriggerData;
|
||||
|
||||
/* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */
|
||||
struct Snapshot
|
||||
{
|
||||
struct timeval *timestamp;
|
||||
Image *image;
|
||||
void* padding;
|
||||
};
|
||||
|
||||
class MonitorLink
|
||||
|
@ -317,7 +339,7 @@ public:
|
|||
void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" );
|
||||
void ForceAlarmOff();
|
||||
void CancelForced();
|
||||
TriggerState GetTriggerState() const { return( trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL ); }
|
||||
TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); }
|
||||
|
||||
void actionReload();
|
||||
void actionEnable();
|
||||
|
|
|
@ -56,26 +56,26 @@ else
|
|||
'Enabled' => true,
|
||||
'LinkedMonitors' => "",
|
||||
'Type' => "",
|
||||
'Device' => "/dev/video",
|
||||
'Device' => "/dev/video0",
|
||||
'Channel' => "0",
|
||||
'Format' => "",
|
||||
'Format' => 0x000000ff,
|
||||
'Protocol' => "",
|
||||
'Method' => "",
|
||||
'Host' => "",
|
||||
'Path' => "",
|
||||
'Port' => "80",
|
||||
'Colours' => "",
|
||||
'Palette' => "",
|
||||
'Width' => "",
|
||||
'Height' => "",
|
||||
'Colours' => 4,
|
||||
'Palette' => fourcc('B','G','R','4'),
|
||||
'Width' => "320",
|
||||
'Height' => "240",
|
||||
'Orientation' => "0",
|
||||
'LabelFormat' => '%N - %y/%m/%d %H:%M:%S',
|
||||
'LabelFormat' => '%N - %d/%m/%y %H:%M:%S',
|
||||
'LabelX' => 0,
|
||||
'LabelY' => 0,
|
||||
'ImageBufferCount' => 40,
|
||||
'ImageBufferCount' => 60,
|
||||
'WarmupCount' => 25,
|
||||
'PreEventCount' => 10,
|
||||
'PostEventCount' => 10,
|
||||
'PreEventCount' => 25,
|
||||
'PostEventCount' => 25,
|
||||
'StreamReplayBuffer' => 1000,
|
||||
'AlarmFrameCount' => 1,
|
||||
'Controllable' => 0,
|
||||
|
@ -91,14 +91,14 @@ else
|
|||
'SectionLength' => 600,
|
||||
'FrameSkip' => 0,
|
||||
'EventPrefix' => 'Event-',
|
||||
'MaxFPS' => "",
|
||||
'AlarmMaxFPS' => "",
|
||||
'MaxFPS' => "5",
|
||||
'AlarmMaxFPS' => "5",
|
||||
'FPSReportInterval' => 1000,
|
||||
'RefBlendPerc' => 7,
|
||||
'DefaultView' => 'Events',
|
||||
'DefaultRate' => '100',
|
||||
'DefaultScale' => '100',
|
||||
'SignalCheckColour' => '#0100BE',
|
||||
'SignalCheckColour' => '#0000C0',
|
||||
'WebColour' => 'red',
|
||||
'Triggers' => "",
|
||||
);
|
||||
|
@ -328,8 +328,8 @@ if ( ZM_HAS_V4L2 )
|
|||
//"SBGGR16" => fourcc('B','Y','R','2'), /* 16 BGBG.. GRGR.. */
|
||||
|
||||
/* compressed formats */
|
||||
//"MJPEG" => fourcc('M','J','P','G'), /* Motion-JPEG */
|
||||
"JPEG" => fourcc('J','P','E','G'), /* JFIF JPEG */
|
||||
"*JPEG" => fourcc('J','P','E','G'), /* JFIF JPEG */
|
||||
"*MJPEG" => fourcc('M','J','P','G'), /* Motion-JPEG */
|
||||
//"DV" => fourcc('d','v','s','d'), /* 1394 */
|
||||
//"MPEG" => fourcc('M','P','E','G'), /* MPEG-1/2/4 */
|
||||
|
||||
|
@ -608,14 +608,6 @@ switch ( $tab )
|
|||
}
|
||||
case 'source' :
|
||||
{
|
||||
// Set up initial palette value
|
||||
if ( $newMonitor['Palette'] == '' )
|
||||
{
|
||||
if ( ZM_HAS_V4L && $newMonitor['Type'] == 'Local' )
|
||||
$newMonitor['Palette'] = 4;
|
||||
else
|
||||
$newMonitor['Palette'] = 3;
|
||||
}
|
||||
if ( ZM_HAS_V4L && $newMonitor['Type'] == "Local" )
|
||||
{
|
||||
?>
|
||||
|
@ -630,7 +622,7 @@ switch ( $tab )
|
|||
<tr><td><?= $SLANG['CapturePalette'] ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $v4l1LocalPalettes as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Palette'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
|
||||
<?php
|
||||
}
|
||||
else if ( ZM_HAS_V4L2 && $newMonitor['Method'] == 'v4l2' )
|
||||
else
|
||||
{
|
||||
?>
|
||||
<tr><td><?= $SLANG['DeviceChannel'] ?></td><td><select name="newMonitor[Channel]"><?php foreach ( $v4l2DeviceChannels as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Channel'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
|
||||
|
|
Loading…
Reference in New Issue