Merge branch 'multi-server' into newpointone

Conflicts:
	distros/ubuntu1204/apache.conf
This commit is contained in:
Isaac Connor 2015-12-22 09:54:13 -05:00
commit eccfced6d4
9 changed files with 204 additions and 187 deletions

View File

@ -1,4 +1,3 @@
var/cache/zoneminder/events usr/share/zoneminder/events
var/cache/zoneminder/images usr/share/zoneminder/images
var/cache/zoneminder/temp usr/share/zoneminder/temp
usr/lib/zoneminder/cgi-bin usr/share/zoneminder/cgi-bin

View File

@ -12,10 +12,10 @@ Alias /zm /usr/share/zoneminder/www
</IfModule>
<IfModule mod_php5.c>
<Directory /usr/share/zoneminder/www>
php_flag register_globals off
Options Indexes FollowSymLinks
<IfModule mod_dir.c>
DirectoryIndex index.php
</IfModule>
php_flag register_globals off
Options Indexes FollowSymLinks
<IfModule mod_dir.c>
DirectoryIndex index.php
</IfModule>
</Directory>
</IfModule>

View File

@ -23,7 +23,7 @@ if [ "$1" = "configure" ]; then
zmupdate.pl --nointeractive
else
echo "Not doing database upgrade due to remote db server ($ZM_DB_HOST)"
fi;
fi;
fi

View File

@ -21,6 +21,9 @@ Monitor Tab
Name
The name for your monitor. This should be made up of alphanumeric characters (a-z,A-Z,0-9) and hyphen (-) and underscore(_) only. Whitespace is not allowed.
Server
Multi-Server implementation allows the ability to define multiple ZoneMinder servers sharing a single database. When servers are configured this setting allows you nominate the server for each monitor.
Source Type
This determines whether the camera is a local one attached to a physical video or USB port on your machine, a remote network camera or an image source that is represented by a file (for instance periodically downloaded from a alternate location). Choosing one or the other affects which set of options are shown in the Source tab.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,12 @@
Options - Servers
---------------
.. image:: images/Options_Servers.png
Servers tab is used for setting up multiple ZoneMinder servers sharing the same database and using a shared file share for all event data. To add a new server use the Add Server button. All that is required is a Name for the Server and Hostname.
To delete a server mark that server and click the Delete button.
Please note that all servers must have a functional web UI as the live view must come from the monitor's host server.
On each server, you will have to edit /etc/zm/zm.conf and set either ZM_SERVER_NAME=

View File

@ -398,11 +398,11 @@ Monitor::Monitor(
+ 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */
Debug( 1, "mem.size=%d", mem_size );
mem_ptr = NULL;
mem_ptr = NULL;
if ( purpose == CAPTURE ) {
this->connect();
if ( ! mem_ptr ) exit(-1);
this->connect();
if ( ! mem_ptr ) exit(-1);
memset( mem_ptr, 0, mem_size );
shared_data->size = sizeof(SharedData);
shared_data->active = enabled;
@ -429,8 +429,8 @@ Monitor::Monitor(
trigger_data->trigger_showtext[0] = 0;
shared_data->valid = true;
} else if ( purpose == ANALYSIS ) {
this->connect();
if ( ! mem_ptr ) exit(-1);
this->connect();
if ( ! mem_ptr ) exit(-1);
shared_data->state = IDLE;
shared_data->last_read_time = 0;
shared_data->alarm_x = -1;
@ -446,9 +446,9 @@ Monitor::Monitor(
}
}
// Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after..
// Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after..
if ( !n_zones ) {
Debug( 1, "Monitor %s has no zones, adding one.", name );
Debug( 1, "Monitor %s has no zones, adding one.", name );
n_zones = 1;
zones = new Zone *[1];
Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) };
@ -533,28 +533,28 @@ bool Monitor::connect() {
// Allocate the size
if ( ftruncate( map_fd, mem_size ) < 0 ) {
Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) );
}
}
} else if ( map_stat.st_size == 0 ) {
Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size );
return false;
return false;
} else if ( map_stat.st_size != mem_size ) {
Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size );
return false;
} else {
return false;
} else {
#ifdef MAP_LOCKED
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 );
if ( mem_ptr == MAP_FAILED ) {
if ( errno == EAGAIN ) {
Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size );
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 );
if ( mem_ptr == MAP_FAILED ) {
if ( errno == EAGAIN ) {
Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size );
#endif
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 );
Debug( 1, "Mapped file %s (%d bytes) to locked memory, unlocked", mem_file, mem_size );
mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 );
Debug( 1, "Mapped file %s (%d bytes) to locked memory, unlocked", mem_file, mem_size );
#ifdef MAP_LOCKED
}
}
}
}
#endif
if ( mem_ptr == MAP_FAILED )
Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno );
if ( mem_ptr == MAP_FAILED )
Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno );
}
#else // ZM_MEM_MAPPED
shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 );
@ -575,9 +575,9 @@ bool Monitor::connect() {
unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval)));
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)));
/* 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)));
}
image_buffer = new Snapshot[image_buffer_count];
for ( int i = 0; i < image_buffer_count; i++ )
@ -608,39 +608,39 @@ bool Monitor::connect() {
}
}
return true;
return true;
}
Monitor::~Monitor()
{
if ( timestamps ) {
delete[] timestamps;
timestamps = 0;
}
if ( images ) {
delete[] images;
images = 0;
}
if ( timestamps ) {
delete[] timestamps;
timestamps = 0;
}
if ( images ) {
delete[] images;
images = 0;
}
if ( privacy_bitmask ) {
delete[] privacy_bitmask;
privacy_bitmask = NULL;
}
if ( mem_ptr ) {
if ( event )
Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() );
closeEvent();
if ( mem_ptr ) {
if ( event )
Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() );
closeEvent();
if ( (deinterlacing & 0xff) == 4)
{
delete next_buffer.image;
delete next_buffer.timestamp;
}
for ( int i = 0; i < image_buffer_count; i++ )
{
delete image_buffer[i].image;
}
delete[] image_buffer;
} // end if mem_ptr
if ( (deinterlacing & 0xff) == 4)
{
delete next_buffer.image;
delete next_buffer.timestamp;
}
for ( int i = 0; i < image_buffer_count; i++ )
{
delete image_buffer[i].image;
}
delete[] image_buffer;
} // end if mem_ptr
for ( int i = 0; i < n_zones; i++ )
{
@ -651,49 +651,49 @@ Monitor::~Monitor()
delete camera;
delete storage;
if ( mem_ptr ) {
if ( purpose == ANALYSIS )
{
shared_data->state = state = IDLE;
shared_data->last_read_index = image_buffer_count;
shared_data->last_read_time = 0;
if ( mem_ptr ) {
if ( purpose == ANALYSIS )
{
shared_data->state = state = IDLE;
shared_data->last_read_index = image_buffer_count;
shared_data->last_read_time = 0;
if ( analysis_fps )
{
for ( int i = 0; i < pre_event_buffer_count; i++ )
{
delete pre_event_buffer[i].image;
delete pre_event_buffer[i].timestamp;
}
delete[] pre_event_buffer;
}
}
else if ( purpose == CAPTURE )
{
shared_data->valid = false;
memset( mem_ptr, 0, mem_size );
}
if ( analysis_fps )
{
for ( int i = 0; i < pre_event_buffer_count; i++ )
{
delete pre_event_buffer[i].image;
delete pre_event_buffer[i].timestamp;
}
delete[] pre_event_buffer;
}
}
else if ( purpose == CAPTURE )
{
shared_data->valid = false;
memset( mem_ptr, 0, mem_size );
}
#if ZM_MEM_MAPPED
if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 )
Error( "Can't msync: %s", strerror(errno) );
if ( munmap( mem_ptr, mem_size ) < 0 )
Fatal( "Can't munmap: %s", strerror(errno) );
close( map_fd );
if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 )
Error( "Can't msync: %s", strerror(errno) );
if ( munmap( mem_ptr, mem_size ) < 0 )
Fatal( "Can't munmap: %s", strerror(errno) );
close( map_fd );
#else // ZM_MEM_MAPPED
struct shmid_ds shm_data;
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) {
Error( "Can't shmctl: %s", strerror(errno) );
exit( -1 );
}
if ( shm_data.shm_nattch <= 1 ) {
if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) {
Error( "Can't shmctl: %s", strerror(errno) );
exit( -1 );
}
}
struct shmid_ds shm_data;
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) {
Error( "Can't shmctl: %s", strerror(errno) );
exit( -1 );
}
if ( shm_data.shm_nattch <= 1 ) {
if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) {
Error( "Can't shmctl: %s", strerror(errno) );
exit( -1 );
}
}
#endif // ZM_MEM_MAPPED
} // end if mem_ptr
} // end if mem_ptr
}
void Monitor::AddZones( int p_n_zones, Zone *p_zones[] )
@ -744,7 +744,7 @@ int Monitor::GetImage( int index, int scale )
if ( index != image_buffer_count )
{
Image *image;
// If we are going to be modifying the snapshot before writing, then we need to copy it
// If we are going to be modifying the snapshot before writing, then we need to copy it
if ( ( scale != ZM_SCALE_BASE ) || ( !config.timestamp_on_capture ) ) {
Snapshot *snap = &image_buffer[index];
Image *snap_image = snap->image;
@ -1244,32 +1244,32 @@ bool Monitor::CheckSignal( const Image *image )
break;
}
if(colours == ZM_COLOUR_GRAY8) {
if ( *(buffer+index) != grayscale_val )
return true;
} else if(colours == ZM_COLOUR_RGB24) {
const uint8_t *ptr = buffer+(index*colours);
if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) {
if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) )
return true;
} else {
/* Assume RGB */
if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) )
return true;
}
} else if(colours == ZM_COLOUR_RGB32) {
if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) {
if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) )
return true;
} else {
/* Assume RGBA or BGRA */
if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) )
return true;
}
}
if(colours == ZM_COLOUR_GRAY8) {
if ( *(buffer+index) != grayscale_val )
return true;
} else if(colours == ZM_COLOUR_RGB24) {
const uint8_t *ptr = buffer+(index*colours);
if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) {
if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) )
return true;
} else {
/* Assume RGB */
if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) )
return true;
}
} else if(colours == ZM_COLOUR_RGB32) {
if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) {
if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) )
return true;
} else {
/* Assume RGBA or BGRA */
if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) )
return true;
}
}
}
return( false );
@ -1740,7 +1740,7 @@ bool Monitor::Analyse()
if ( config.create_analysis_images )
{
bool got_anal_image = false;
alarm_image.Assign( *snap_image );
alarm_image.Assign( *snap_image );
for( int i = 0; i < n_zones; i++ )
{
if ( zones[i]->Alarmed() )
@ -2090,24 +2090,24 @@ Debug( 1, "Server ID %d", staticConfig.SERVER_ID );
const char *device = dbrow[col]; col++;
int channel = atoi(dbrow[col]); col++;
int format = atoi(dbrow[col]); col++;
bool v4l_multi_buffer = config.v4l_multi_buffer;
if ( dbrow[col] ) {
if (*dbrow[col] == '0' ) {
v4l_multi_buffer = false;
} else if ( *dbrow[col] == '1' ) {
v4l_multi_buffer = true;
}
}
col++;
int v4l_captures_per_frame = 0;
if ( dbrow[col] ) {
v4l_captures_per_frame = atoi(dbrow[col]);
} else {
v4l_captures_per_frame = config.captures_per_frame;
}
bool v4l_multi_buffer = config.v4l_multi_buffer;
if ( dbrow[col] ) {
if (*dbrow[col] == '0' ) {
v4l_multi_buffer = false;
} else if ( *dbrow[col] == '1' ) {
v4l_multi_buffer = true;
}
}
col++;
int v4l_captures_per_frame = 0;
if ( dbrow[col] ) {
v4l_captures_per_frame = atoi(dbrow[col]);
} else {
v4l_captures_per_frame = config.captures_per_frame;
}
Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
col++;
col++;
const char *method = dbrow[col]; col++;
int width = atoi(dbrow[col]); col++;
@ -2164,8 +2164,8 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
device,
channel,
format,
v4l_multi_buffer,
v4l_captures_per_frame,
v4l_multi_buffer,
v4l_captures_per_frame,
method,
cam_width,
cam_height,
@ -3019,30 +3019,30 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame );
int Monitor::Capture()
{
static int FirstCapture = 1;
int captureResult;
int index = image_count%image_buffer_count;
Image* capture_image = image_buffer[index].image;
if ( (deinterlacing & 0xff) == 4) {
if ( FirstCapture != 1 ) {
/* Copy the next image into the shared memory */
capture_image->CopyBuffer(*(next_buffer.image));
}
/* Capture a new next image */
captureResult = camera->Capture(*(next_buffer.image));
if ( FirstCapture ) {
FirstCapture = 0;
return 0;
}
} else {
/* Capture directly into image buffer, avoiding the need to memcpy() */
captureResult = camera->Capture(*capture_image);
}
static int FirstCapture = 1;
int captureResult;
int index = image_count%image_buffer_count;
Image* capture_image = image_buffer[index].image;
if ( (deinterlacing & 0xff) == 4) {
if ( FirstCapture != 1 ) {
/* Copy the next image into the shared memory */
capture_image->CopyBuffer(*(next_buffer.image));
}
/* Capture a new next image */
captureResult = camera->Capture(*(next_buffer.image));
if ( FirstCapture ) {
FirstCapture = 0;
return 0;
}
} else {
/* Capture directly into image buffer, avoiding the need to memcpy() */
captureResult = camera->Capture(*capture_image);
}
if ( captureResult != 0 )
{
@ -3059,18 +3059,18 @@ int Monitor::Capture()
if ( captureResult == 1 )
{
/* Deinterlacing */
if ( (deinterlacing & 0xff) == 1 ) {
capture_image->Deinterlace_Discard();
} else if ( (deinterlacing & 0xff) == 2 ) {
capture_image->Deinterlace_Linear();
} else if ( (deinterlacing & 0xff) == 3 ) {
capture_image->Deinterlace_Blend();
} else if ( (deinterlacing & 0xff) == 4 ) {
capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff );
} else if ( (deinterlacing & 0xff) == 5 ) {
capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff );
}
/* Deinterlacing */
if ( (deinterlacing & 0xff) == 1 ) {
capture_image->Deinterlace_Discard();
} else if ( (deinterlacing & 0xff) == 2 ) {
capture_image->Deinterlace_Linear();
} else if ( (deinterlacing & 0xff) == 3 ) {
capture_image->Deinterlace_Blend();
} else if ( (deinterlacing & 0xff) == 4 ) {
capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff );
} else if ( (deinterlacing & 0xff) == 5 ) {
capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff );
}
if ( orientation != ROTATE_0 )

@ -1 +1 @@
Subproject commit e22c1563a51d86aac0d5054beee28b4afb60c802
Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5

View File

@ -5,16 +5,19 @@ require_once( 'Server.php' );
class Monitor {
public function __construct( $IdOrRow ) {
$row = NULL;
if ( is_int( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array( $IdOrRow ) );
} else if ( is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array( $IdOrRow ) );
} else if ( is_array($IdOrRow) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Monitor Constructor ($IdOrRow)");
return;
}
if ( $IdOrRow ) {
if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) {
$row = dbFetchOne( 'SELECT * FROM Monitors WHERE Id=?', NULL, array( $IdOrRow ) );
if ( ! $row ) {
Error("Unable to load Server record for Id=" . $IdOrRow );
}
} elseif ( is_array( $IdOrRow ) ) {
$row = $IdOrRow;
} else {
Error("Unknown argument passed to Monitor Constructor ($IdOrRow)");
return;
}
} # end if isset($IdOrRow)
if ( $row ) {
foreach ($row as $k => $v) {