From ca858a85620fa7ea07df1c07e19b01e965d5a208 Mon Sep 17 00:00:00 2001 From: stan Date: Fri, 8 May 2009 09:47:37 +0000 Subject: [PATCH] Applied patch from 'mitch' to improve error detection when streaming. git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2864 e3e1d417-86f3-4887-817a-d78f3d33393f --- src/zm_event.cpp | 2 +- src/zm_image.cpp | 2 +- src/zm_monitor.cpp | 4332 ++++++++++++++++++++++---------------------- 3 files changed, 2171 insertions(+), 2165 deletions(-) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 942c756c2..424fb839a 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -1235,7 +1235,7 @@ bool EventStream::sendFrame( int delta_us ) break; } fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 ) + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { Error( "Unable to send stream frame: %s", strerror(errno) ); return( false ); diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 113f8d864..a62e40368 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -295,7 +295,7 @@ bool Image::WriteRaw( const char *filename ) const return( false ); } - if ( fwrite( buffer, size, 1, outfile ) < 1 ) + if ( fwrite( buffer, size, 1, outfile ) != 1 ) { Error( "Unable to write to '%s': %s", filename, strerror(errno) ); return( false ); diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 14ccaa035..8077b0224 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -49,36 +49,36 @@ Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) { - strncpy( name, p_name, sizeof(name) ); + strncpy( name, p_name, sizeof(name) ); #if ZM_MEM_MAPPED - map_fd = -1; + map_fd = -1; snprintf( mem_file, sizeof(mem_file), "%s/.zm.mmap.%d", config.path_map, id ); #else // ZM_MEM_MAPPED shm_id = 0; #endif // ZM_MEM_MAPPED - mem_size = 0; - mem_ptr = 0; + mem_size = 0; + mem_ptr = 0; - last_event = 0; - last_state = IDLE; + last_event = 0; + last_state = IDLE; - last_connect_time = 0; - connected = false; + last_connect_time = 0; + connected = false; } Monitor::MonitorLink::~MonitorLink() { - disconnect(); + disconnect(); } bool Monitor::MonitorLink::connect() { - if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) - { - last_connect_time = time( 0 ); + if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) + { + last_connect_time = time( 0 ); - mem_size = sizeof(SharedData) + sizeof(TriggerData); + mem_size = sizeof(SharedData) + sizeof(TriggerData); Debug( 1, "link.mem.size=%d", mem_size ); #if ZM_MEM_MAPPED @@ -119,46 +119,46 @@ bool Monitor::MonitorLink::connect() return( false ); } #else // ZM_MEM_MAPPED - shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); - if ( shm_id < 0 ) - { - Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); - connected = false; - return( false ); - } - mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); - if ( mem_ptr < 0 ) - { - Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); - connected = false; - return( false ); - } + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); + if ( shm_id < 0 ) + { + Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } #endif // ZM_MEM_MAPPED - shared_data = (SharedData *)mem_ptr; - trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); - if ( !shared_data->valid ) - { - Debug( 3, "Linked memory not initialised by capture daemon" ); - disconnect(); - return( false ); - } + if ( !shared_data->valid ) + { + Debug( 3, "Linked memory not initialised by capture daemon" ); + disconnect(); + return( false ); + } - last_state = shared_data->state; - last_event = shared_data->last_event; - connected = true; + last_state = shared_data->state; + last_event = shared_data->last_event; + connected = true; - return( true ); - } - return( false ); + return( true ); + } + return( false ); } bool Monitor::MonitorLink::disconnect() { - if ( connected ) - { - connected = false; + if ( connected ) + { + connected = false; #if ZM_MEM_MAPPED if ( mem_ptr > 0 ) @@ -171,12 +171,12 @@ bool Monitor::MonitorLink::disconnect() map_fd = -1; #else // ZM_MEM_MAPPED - struct shmid_ds shm_data; - if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) - { - Debug( 3, "Can't shmctl: %s", strerror(errno) ); - return( false ); - } + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } shm_id = 0; @@ -196,104 +196,104 @@ bool Monitor::MonitorLink::disconnect() } #endif // ZM_MEM_MAPPED - mem_size = 0; - mem_ptr = 0; - } - return( true ); + mem_size = 0; + mem_ptr = 0; + } + return( true ); } bool Monitor::MonitorLink::isAlarmed() { - if ( !connected ) - { - return( false ); - } - return( shared_data->state == ALARM ); + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM ); } bool Monitor::MonitorLink::inAlarm() { - if ( !connected ) - { - return( false ); - } - return( shared_data->state == ALARM || shared_data->state == ALERT ); + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM || shared_data->state == ALERT ); } bool Monitor::MonitorLink::hasAlarmed() { - if ( shared_data->state == ALARM || shared_data->state == ALERT ) - { - return( true ); - } - else if( shared_data->last_event != last_event ) - { - last_event = shared_data->last_event; - return( true ); - } - return( false ); + if ( shared_data->state == ALARM || shared_data->state == ALERT ) + { + return( true ); + } + else if( shared_data->last_event != last_event ) + { + last_event = shared_data->last_event; + return( true ); + } + return( false ); } Monitor::Monitor( - int p_id, - const char *p_name, - int p_function, - bool p_enabled, - const char *p_linked_monitors, - Camera *p_camera, - int p_orientation, - const char *p_event_prefix, - const char *p_label_format, - const Coord &p_label_coord, - int p_image_buffer_count, - int p_warmup_count, - int p_pre_event_count, - int p_post_event_count, - int p_stream_replay_buffer, - int p_alarm_frame_count, - int p_section_length, - int p_frame_skip, - int p_capture_delay, - int p_alarm_capture_delay, - int p_fps_report_interval, - int p_ref_blend_perc, - bool p_track_motion, - Rgb p_signal_check_colour, - Purpose p_purpose, - int p_n_zones, - Zone *p_zones[] + int p_id, + const char *p_name, + int p_function, + bool p_enabled, + const char *p_linked_monitors, + Camera *p_camera, + int p_orientation, + const char *p_event_prefix, + const char *p_label_format, + const Coord &p_label_coord, + int p_image_buffer_count, + int p_warmup_count, + int p_pre_event_count, + int p_post_event_count, + int p_stream_replay_buffer, + int p_alarm_frame_count, + int p_section_length, + int p_frame_skip, + int p_capture_delay, + int p_alarm_capture_delay, + int p_fps_report_interval, + int p_ref_blend_perc, + bool p_track_motion, + Rgb p_signal_check_colour, + Purpose p_purpose, + int p_n_zones, + Zone *p_zones[] ) : id( p_id ), - function( (Function)p_function ), - enabled( p_enabled ), - width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), - height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), - orientation( (Orientation)p_orientation ), - label_coord( p_label_coord ), - image_buffer_count( p_image_buffer_count ), - warmup_count( p_warmup_count ), - pre_event_count( p_pre_event_count ), - post_event_count( p_post_event_count ), - stream_replay_buffer( p_stream_replay_buffer ), - section_length( p_section_length ), - frame_skip( p_frame_skip ), - capture_delay( p_capture_delay ), - alarm_capture_delay( p_alarm_capture_delay ), - alarm_frame_count( p_alarm_frame_count ), - fps_report_interval( p_fps_report_interval ), - ref_blend_perc( p_ref_blend_perc ), - track_motion( p_track_motion ), - signal_check_colour( p_signal_check_colour ), - image( width, height, p_camera->Colours() ), - ref_image( width, height, p_camera->Colours() ), - purpose( p_purpose ), - camera( p_camera ), - n_zones( p_n_zones ), - zones( p_zones ) + function( (Function)p_function ), + enabled( p_enabled ), + width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), + height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), + orientation( (Orientation)p_orientation ), + label_coord( p_label_coord ), + image_buffer_count( p_image_buffer_count ), + warmup_count( p_warmup_count ), + pre_event_count( p_pre_event_count ), + post_event_count( p_post_event_count ), + stream_replay_buffer( p_stream_replay_buffer ), + section_length( p_section_length ), + frame_skip( p_frame_skip ), + capture_delay( p_capture_delay ), + alarm_capture_delay( p_alarm_capture_delay ), + alarm_frame_count( p_alarm_frame_count ), + fps_report_interval( p_fps_report_interval ), + ref_blend_perc( p_ref_blend_perc ), + track_motion( p_track_motion ), + signal_check_colour( p_signal_check_colour ), + image( width, height, p_camera->Colours() ), + ref_image( width, height, p_camera->Colours() ), + purpose( p_purpose ), + camera( p_camera ), + n_zones( p_n_zones ), + zones( p_zones ) { - strncpy( name, p_name, sizeof(name) ); + strncpy( name, p_name, sizeof(name) ); - strncpy( event_prefix, p_event_prefix, sizeof(event_prefix) ); - strncpy( label_format, p_label_format, sizeof(label_format) ); + strncpy( event_prefix, p_event_prefix, sizeof(event_prefix) ); + strncpy( label_format, p_label_format, sizeof(label_format) ); // Change \n to actual line feeds char *token_ptr = label_format; @@ -313,20 +313,20 @@ Monitor::Monitor( } } - fps = 0.0; - event_count = 0; - image_count = 0; - ready_count = warmup_count; - first_alarm_count = 0; - last_alarm_count = 0; - state = IDLE; + fps = 0.0; + event_count = 0; + image_count = 0; + ready_count = warmup_count; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; - if ( alarm_frame_count < 1 ) - alarm_frame_count = 1; - else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) - alarm_frame_count = MAX_PRE_ALARM_FRAMES; + if ( alarm_frame_count < 1 ) + alarm_frame_count = 1; + else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) + alarm_frame_count = MAX_PRE_ALARM_FRAMES; - auto_resume_time = 0; + auto_resume_time = 0; if ( strcmp( config.event_close_mode, "time" ) == 0 ) event_close_mode = CLOSE_TIME; @@ -335,27 +335,27 @@ Monitor::Monitor( else event_close_mode = CLOSE_IDLE; - Debug( 1, "monitor purpose=%d", purpose ); + Debug( 1, "monitor purpose=%d", purpose ); - mem_size = sizeof(SharedData) - + sizeof(TriggerData) - + (image_buffer_count*sizeof(struct timeval)) - + (image_buffer_count*camera->ImageSize()); + mem_size = sizeof(SharedData) + + sizeof(TriggerData) + + (image_buffer_count*sizeof(struct timeval)) + + (image_buffer_count*camera->ImageSize()); - Debug( 1, "mem.size=%d", mem_size ); + Debug( 1, "mem.size=%d", mem_size ); #if ZM_MEM_MAPPED snprintf( mem_file, sizeof(mem_file), "%s/.zm.mmap.%d", config.path_map, id ); map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); if ( map_fd < 0 ) - Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); struct stat map_stat; if ( fstat( map_fd, &map_stat ) < 0 ) - Fatal( "Can't stat memory map file %s: %s", mem_file, strerror(errno) ); + Fatal( "Can't stat memory map file %s: %s", mem_file, strerror(errno) ); if ( map_stat.st_size == 0 ) { // 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) ); + Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); } else if ( map_stat.st_size != mem_size ) { @@ -366,186 +366,186 @@ Monitor::Monitor( 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 ); + 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_fd, 0 ); } if ( mem_ptr == MAP_FAILED ) - Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + 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 ); - if ( shm_id < 0 ) - { - Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); - exit( -1 ); - } - mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); - if ( mem_ptr < 0 ) - { - Error( "Can't shmat: %s", strerror(errno)); - exit( -1 ); - } + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); + if ( shm_id < 0 ) + { + Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); + exit( -1 ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Error( "Can't shmat: %s", strerror(errno)); + exit( -1 ); + } #endif // ZM_MEM_MAPPED - shared_data = (SharedData *)mem_ptr; - trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); - 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))); + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + 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))); - if ( purpose == CAPTURE ) - { - memset( mem_ptr, 0, mem_size ); - shared_data->size = sizeof(SharedData); - shared_data->valid = true; - shared_data->active = enabled; - shared_data->signal = false; - shared_data->state = IDLE; - shared_data->last_write_index = image_buffer_count; - shared_data->last_read_index = image_buffer_count; - shared_data->last_write_time = 0; - shared_data->last_event = 0; - shared_data->action = (Action)0; - shared_data->brightness = -1; - shared_data->hue = -1; - shared_data->colour = -1; - shared_data->contrast = -1; - shared_data->alarm_x = -1; - shared_data->alarm_y = -1; - trigger_data->size = sizeof(TriggerData); - trigger_data->trigger_state = TRIGGER_CANCEL; - trigger_data->trigger_score = 0; - trigger_data->trigger_cause[0] = 0; - trigger_data->trigger_text[0] = 0; - trigger_data->trigger_showtext[0] = 0; - } - else if ( purpose == ANALYSIS ) - { - shared_data->state = IDLE; - shared_data->last_read_time = 0; - shared_data->alarm_x = -1; - shared_data->alarm_y = -1; - } + if ( purpose == CAPTURE ) + { + memset( mem_ptr, 0, mem_size ); + shared_data->size = sizeof(SharedData); + shared_data->valid = true; + shared_data->active = enabled; + shared_data->signal = false; + shared_data->state = IDLE; + shared_data->last_write_index = image_buffer_count; + shared_data->last_read_index = image_buffer_count; + shared_data->last_write_time = 0; + shared_data->last_event = 0; + shared_data->action = (Action)0; + shared_data->brightness = -1; + shared_data->hue = -1; + shared_data->colour = -1; + shared_data->contrast = -1; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + trigger_data->size = sizeof(TriggerData); + trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_score = 0; + trigger_data->trigger_cause[0] = 0; + trigger_data->trigger_text[0] = 0; + trigger_data->trigger_showtext[0] = 0; + } + else if ( purpose == ANALYSIS ) + { + shared_data->state = IDLE; + shared_data->last_read_time = 0; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + } - if ( !shared_data->valid ) - { + if ( !shared_data->valid ) + { if ( purpose != QUERY ) { - Error( "Shared data not initialised by capture daemon" ); - exit( -1 ); + Error( "Shared data not initialised by capture daemon" ); + exit( -1 ); } else { - Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" ); + Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" ); } - } + } - image_buffer = new Snapshot[image_buffer_count]; - for ( int i = 0; i < image_buffer_count; i++ ) - { - image_buffer[i].timestamp = &(shared_timestamps[i]); - image_buffer[i].image = new Image( width, height, camera->Colours(), &(shared_images[i*camera->ImageSize()]) ); - } - if ( !n_zones ) - { - 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 ) }; - zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); - } - start_time = last_fps_time = time( 0 ); + image_buffer = new Snapshot[image_buffer_count]; + for ( int i = 0; i < image_buffer_count; i++ ) + { + image_buffer[i].timestamp = &(shared_timestamps[i]); + image_buffer[i].image = new Image( width, height, camera->Colours(), &(shared_images[i*camera->ImageSize()]) ); + } + if ( !n_zones ) + { + 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 ) }; + zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); + } + start_time = last_fps_time = time( 0 ); - event = 0; + event = 0; - Debug( 1, "Monitor %s has function %d", name, function ); - Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() ); - Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, track_motion ); + Debug( 1, "Monitor %s has function %d", name, function ); + Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() ); + Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, track_motion ); - if ( purpose == ANALYSIS ) - { - static char path[PATH_MAX]; + if ( purpose == ANALYSIS ) + { + static char path[PATH_MAX]; - strncpy( path, config.dir_events, sizeof(path) ); + strncpy( path, config.dir_events, sizeof(path) ); - struct stat statbuf; - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error( "Can't make %s: %s", path, strerror(errno)); - } - } + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + } - snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); + snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error( "Can't make %s: %s", path, strerror(errno)); - } - char temp_path[PATH_MAX]; - snprintf( temp_path, sizeof(temp_path), "%d", id ); - if ( chdir( config.dir_events ) < 0 ) + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + char temp_path[PATH_MAX]; + snprintf( temp_path, sizeof(temp_path), "%d", id ); + if ( chdir( config.dir_events ) < 0 ) Fatal( "Can't change directory to '%s': %s", config.dir_events, strerror(errno) ); - if ( symlink( temp_path, name ) < 0 ) + if ( symlink( temp_path, name ) < 0 ) Fatal( "Can't symlink '%s' to '%s': %s", temp_path, name, strerror(errno) ); - if ( chdir( ".." ) < 0 ) + if ( chdir( ".." ) < 0 ) Fatal( "Can't change to parent directory: %s", strerror(errno) ); - } + } - while( shared_data->last_write_index == image_buffer_count ) - { - Warning( "Waiting for capture daemon" ); - sleep( 1 ); - } - ref_image.Assign( width, height, camera->Colours(), image_buffer[shared_data->last_write_index].image->Buffer() ); + while( shared_data->last_write_index == image_buffer_count ) + { + Warning( "Waiting for capture daemon" ); + sleep( 1 ); + } + ref_image.Assign( width, height, camera->Colours(), image_buffer[shared_data->last_write_index].image->Buffer() ); - n_linked_monitors = 0; - linked_monitors = 0; - ReloadLinkedMonitors( p_linked_monitors ); - } + n_linked_monitors = 0; + linked_monitors = 0; + ReloadLinkedMonitors( p_linked_monitors ); + } } Monitor::~Monitor() { if ( event ) Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); - closeEvent(); + closeEvent(); - for ( int i = 0; i < image_buffer_count; i++ ) - { - delete image_buffer[i].image; - } - delete[] image_buffer; + for ( int i = 0; i < image_buffer_count; i++ ) + { + delete image_buffer[i].image; + } + delete[] image_buffer; - for ( int i = 0; i < n_zones; i++ ) - { - delete zones[i]; - } - delete[] zones; + for ( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; - delete camera; + delete camera; - if ( purpose == ANALYSIS ) - { - shared_data->state = state = IDLE; - shared_data->last_read_index = image_buffer_count; - shared_data->last_read_time = 0; - } - else if ( purpose == CAPTURE ) - { - shared_data->valid = false; - memset( mem_ptr, 0, mem_size ); - } + if ( purpose == ANALYSIS ) + { + shared_data->state = state = IDLE; + shared_data->last_read_index = image_buffer_count; + shared_data->last_read_time = 0; + } + 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_INVALIDATE ) < 0 ) - Fatal( "Can't msync: %s", strerror(errno) ); + Fatal( "Can't msync: %s", strerror(errno) ); if ( munmap( mem_ptr, mem_size ) < 0 ) - Fatal( "Can't munmap: %s", strerror(errno) ); + Fatal( "Can't munmap: %s", strerror(errno) ); close( map_fd ); #else // ZM_MEM_MAPPED struct shmid_ds shm_data; @@ -567,909 +567,909 @@ Monitor::~Monitor() void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) { - for ( int i = 0; i < n_zones; i++ ) - delete zones[i]; - delete[] zones; - n_zones = p_n_zones; - zones = p_zones; + for ( int i = 0; i < n_zones; i++ ) + delete zones[i]; + delete[] zones; + n_zones = p_n_zones; + zones = p_zones; } Monitor::State Monitor::GetState() const { - return( shared_data->state ); + return( shared_data->state ); } int Monitor::GetImage( int index, int scale ) const { - if ( index < 0 || index > image_buffer_count ) - { - index = shared_data->last_write_index; - } + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } - if ( index != image_buffer_count ) - { - Snapshot *snap = &image_buffer[index]; - Image snap_image( *(snap->image) ); + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; + Image snap_image( *(snap->image) ); - if ( scale != ZM_SCALE_BASE ) - { - snap_image.Scale( scale ); - } + if ( scale != ZM_SCALE_BASE ) + { + snap_image.Scale( scale ); + } - static char filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "%s.jpg", name ); - if ( !config.timestamp_on_capture ) - { - TimestampImage( &snap_image, snap->timestamp ); - } - snap_image.WriteJpeg( filename ); - } - else - { - Error( "Unable to generate image, no images in buffer" ); - } - return( 0 ); + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "%s.jpg", name ); + if ( !config.timestamp_on_capture ) + { + TimestampImage( &snap_image, snap->timestamp ); + } + snap_image.WriteJpeg( filename ); + } + else + { + Error( "Unable to generate image, no images in buffer" ); + } + return( 0 ); } struct timeval Monitor::GetTimestamp( int index ) const { - if ( index < 0 || index > image_buffer_count ) - { - index = shared_data->last_write_index; - } + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } - if ( index != image_buffer_count ) - { - Snapshot *snap = &image_buffer[index]; + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; - return( *(snap->timestamp) ); - } - else - { - static struct timeval null_tv = { 0, 0 }; + return( *(snap->timestamp) ); + } + else + { + static struct timeval null_tv = { 0, 0 }; - return( null_tv ); - } + return( null_tv ); + } } unsigned int Monitor::GetLastReadIndex() const { - return( shared_data->last_read_index!=image_buffer_count?shared_data->last_read_index:-1 ); + return( shared_data->last_read_index!=image_buffer_count?shared_data->last_read_index:-1 ); } unsigned int Monitor::GetLastWriteIndex() const { - return( shared_data->last_write_index!=image_buffer_count?shared_data->last_write_index:-1 ); + return( shared_data->last_write_index!=image_buffer_count?shared_data->last_write_index:-1 ); } unsigned int Monitor::GetLastEvent() const { - return( shared_data->last_event ); + return( shared_data->last_event ); } double Monitor::GetFPS() const { - int index1 = shared_data->last_write_index; - if ( index1 == image_buffer_count ) - { - return( 0.0 ); - } - Snapshot *snap1 = &image_buffer[index1]; - if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) - { - return( 0.0 ); - } - struct timeval time1 = *snap1->timestamp; + int index1 = shared_data->last_write_index; + if ( index1 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap1 = &image_buffer[index1]; + if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) + { + return( 0.0 ); + } + struct timeval time1 = *snap1->timestamp; - int image_count = image_buffer_count; - int index2 = (index1+1)%image_buffer_count; - if ( index2 == image_buffer_count ) - { - return( 0.0 ); - } - Snapshot *snap2 = &image_buffer[index2]; - while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) - { - if ( index1 == index2 ) - { - return( 0.0 ); - } - index2 = (index2+1)%image_buffer_count; - snap2 = &image_buffer[index2]; - image_count--; - } - struct timeval time2 = *snap2->timestamp; + int image_count = image_buffer_count; + int index2 = (index1+1)%image_buffer_count; + if ( index2 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap2 = &image_buffer[index2]; + while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) + { + if ( index1 == index2 ) + { + return( 0.0 ); + } + index2 = (index2+1)%image_buffer_count; + snap2 = &image_buffer[index2]; + image_count--; + } + struct timeval time2 = *snap2->timestamp; double time_diff = tvDiffSec( time2, time1 ); - double curr_fps = image_count/time_diff; + double curr_fps = image_count/time_diff; if ( curr_fps < 0.0 ) { //Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); return( 0.0 ); } - return( curr_fps ); + return( curr_fps ); } void Monitor::ForceAlarmOn( int force_score, const char *force_cause, const char *force_text ) { - trigger_data->trigger_state = TRIGGER_ON; - trigger_data->trigger_score = force_score; - strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); - strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); + trigger_data->trigger_state = TRIGGER_ON; + trigger_data->trigger_score = force_score; + strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); + strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); } void Monitor::ForceAlarmOff() { - trigger_data->trigger_state = TRIGGER_OFF; + trigger_data->trigger_state = TRIGGER_OFF; } void Monitor::CancelForced() { - trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_state = TRIGGER_CANCEL; } void Monitor::actionReload() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; } void Monitor::actionEnable() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; - static char sql[BUFSIZ]; - snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } void Monitor::actionDisable() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; - static char sql[BUFSIZ]; - snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } void Monitor::actionSuspend() { - shared_data->action |= SUSPEND; + shared_data->action |= SUSPEND; } void Monitor::actionResume() { - shared_data->action |= RESUME; + shared_data->action |= RESUME; } int Monitor::actionBrightness( int p_brightness ) { - if ( purpose != CAPTURE ) - { - if ( p_brightness >= 0 ) - { - shared_data->brightness = p_brightness; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + if ( purpose != CAPTURE ) + { + if ( p_brightness >= 0 ) + { + shared_data->brightness = p_brightness; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to set brightness" ); - return( -1 ); + return( -1 ); } - } - } - else - { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to get brightness" ); - return( -1 ); + return( -1 ); } - } - } - return( shared_data->brightness ); - } - return( camera->Brightness( p_brightness ) ); + } + } + return( shared_data->brightness ); + } + return( camera->Brightness( p_brightness ) ); } int Monitor::actionContrast( int p_contrast ) { - if ( purpose != CAPTURE ) - { - if ( p_contrast >= 0 ) - { - shared_data->contrast = p_contrast; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + if ( purpose != CAPTURE ) + { + if ( p_contrast >= 0 ) + { + shared_data->contrast = p_contrast; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to set contrast" ); - return( -1 ); + return( -1 ); } - } - } - else - { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to get contrast" ); - return( -1 ); + return( -1 ); } - } - } - return( shared_data->contrast ); - } - return( camera->Contrast( p_contrast ) ); + } + } + return( shared_data->contrast ); + } + return( camera->Contrast( p_contrast ) ); } int Monitor::actionHue( int p_hue ) { - if ( purpose != CAPTURE ) - { - if ( p_hue >= 0 ) - { - shared_data->hue = p_hue; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + if ( purpose != CAPTURE ) + { + if ( p_hue >= 0 ) + { + shared_data->hue = p_hue; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to set hue" ); - return( -1 ); + return( -1 ); } - } - } - else - { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to get hue" ); - return( -1 ); + return( -1 ); } - } - } - return( shared_data->hue ); - } - return( camera->Hue( p_hue ) ); + } + } + return( shared_data->hue ); + } + return( camera->Hue( p_hue ) ); } int Monitor::actionColour( int p_colour ) { - if ( purpose != CAPTURE ) - { - if ( p_colour >= 0 ) - { - shared_data->colour = p_colour; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + if ( purpose != CAPTURE ) + { + if ( p_colour >= 0 ) + { + shared_data->colour = p_colour; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to set colour" ); - return( -1 ); + return( -1 ); } - } - } - else - { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else { Warning( "Timed out waiting to get colour" ); - return( -1 ); + return( -1 ); } - } - } - return( shared_data->colour ); - } - return( camera->Colour( p_colour ) ); + } + } + return( shared_data->colour ); + } + return( camera->Colour( p_colour ) ); } void Monitor::DumpZoneImage( const char *zone_string ) { - int exclude_id = 0; - int extra_colour = 0; - Polygon extra_zone; + int exclude_id = 0; + int extra_colour = 0; + Polygon extra_zone; - if ( zone_string ) - { - if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) - { - Error( "Failed to parse zone string, ignoring" ); - } - } + if ( zone_string ) + { + if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) + { + Error( "Failed to parse zone string, ignoring" ); + } + } - int index = shared_data->last_write_index; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + int index = shared_data->last_write_index; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - Image zone_image( *snap_image ); - zone_image.Colourise(); - for( int i = 0; i < n_zones; i++ ) - { - if ( exclude_id && zones[i]->Id() == exclude_id ) - continue; + Image zone_image( *snap_image ); + zone_image.Colourise(); + for( int i = 0; i < n_zones; i++ ) + { + if ( exclude_id && zones[i]->Id() == exclude_id ) + continue; - Rgb colour; - if ( zones[i]->IsActive() ) - { - colour = RGB_RED; - } - else if ( zones[i]->IsInclusive() ) - { - colour = RGB_ORANGE; - } - else if ( zones[i]->IsExclusive() ) - { - colour = RGB_PURPLE; - } - else if ( zones[i]->IsPreclusive() ) - { - colour = RGB_BLUE; - } - else - { - colour = RGB_WHITE; - } - zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); - zone_image.Outline( colour, zones[i]->GetPolygon() ); - } + Rgb colour; + if ( zones[i]->IsActive() ) + { + colour = RGB_RED; + } + else if ( zones[i]->IsInclusive() ) + { + colour = RGB_ORANGE; + } + else if ( zones[i]->IsExclusive() ) + { + colour = RGB_PURPLE; + } + else if ( zones[i]->IsPreclusive() ) + { + colour = RGB_BLUE; + } + else + { + colour = RGB_WHITE; + } + zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); + zone_image.Outline( colour, zones[i]->GetPolygon() ); + } - if ( extra_zone.getNumCoords() ) - { - zone_image.Fill( extra_colour, 2, extra_zone ); - zone_image.Outline( extra_colour, extra_zone ); - } + if ( extra_zone.getNumCoords() ) + { + zone_image.Fill( extra_colour, 2, extra_zone ); + zone_image.Outline( extra_colour, extra_zone ); + } - static char filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); - zone_image.WriteJpeg( filename ); + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); + zone_image.WriteJpeg( filename ); } void Monitor::DumpImage( Image *dump_image ) const { - if ( image_count && !(image_count%10) ) - { - static char filename[PATH_MAX]; - static char new_filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "%s.jpg", name ); - snprintf( new_filename, sizeof(new_filename), "%s-new.jpg", name ); - dump_image->WriteJpeg( new_filename ); - rename( new_filename, filename ); - } + if ( image_count && !(image_count%10) ) + { + static char filename[PATH_MAX]; + static char new_filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "%s.jpg", name ); + snprintf( new_filename, sizeof(new_filename), "%s-new.jpg", name ); + dump_image->WriteJpeg( new_filename ); + rename( new_filename, filename ); + } } bool Monitor::CheckSignal( const Image *image ) { - static bool static_undef = true; - static unsigned char red_val; - static unsigned char green_val; - static unsigned char blue_val; + static bool static_undef = true; + static unsigned char red_val; + static unsigned char green_val; + static unsigned char blue_val; - if ( camera->IsLocal() && config.signal_check_points > 0 ) - { - if ( static_undef ) - { - static_undef = false; - red_val = RGB_RED_VAL(signal_check_colour); - green_val = RGB_GREEN_VAL(signal_check_colour); - blue_val = RGB_BLUE_VAL(signal_check_colour); - } + if ( camera->IsLocal() && config.signal_check_points > 0 ) + { + if ( static_undef ) + { + static_undef = false; + red_val = RGB_RED_VAL(signal_check_colour); + green_val = RGB_GREEN_VAL(signal_check_colour); + blue_val = RGB_BLUE_VAL(signal_check_colour); + } - const unsigned char *buffer = image->Buffer(); - int pixels = image->Pixels(); - int colours = image->Colours(); + const unsigned char *buffer = image->Buffer(); + int pixels = image->Pixels(); + int colours = image->Colours(); - for ( int i = 0; i < config.signal_check_points; i++ ) - { - int index = (rand()*pixels)/RAND_MAX; - const unsigned char *ptr = buffer+(index*colours); - if ( (RED(ptr) != red_val) || (GREEN(ptr) != green_val) || (BLUE(ptr) != blue_val) ) - { - return( true ); - } - } - return( false ); - } - return( true ); + for ( int i = 0; i < config.signal_check_points; i++ ) + { + int index = (rand()*pixels)/RAND_MAX; + const unsigned char *ptr = buffer+(index*colours); + if ( (RED(ptr) != red_val) || (GREEN(ptr) != green_val) || (BLUE(ptr) != blue_val) ) + { + return( true ); + } + } + return( false ); + } + return( true ); } bool Monitor::Analyse() { - if ( shared_data->last_read_index == shared_data->last_write_index ) - { - return( false ); - } + if ( shared_data->last_read_index == shared_data->last_write_index ) + { + return( false ); + } - struct timeval now; - gettimeofday( &now, NULL ); + struct timeval now; + gettimeofday( &now, NULL ); - if ( image_count && !(image_count%fps_report_interval) ) - { - fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); - Info( "%s: %d - Processing at %.2f fps", name, image_count, fps ); - last_fps_time = now.tv_sec; - } + if ( image_count && !(image_count%fps_report_interval) ) + { + fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); + Info( "%s: %d - Processing at %.2f fps", name, image_count, fps ); + last_fps_time = now.tv_sec; + } - int index; - if ( config.opt_adaptive_skip ) - { - int read_margin = shared_data->last_read_index - shared_data->last_write_index; - if ( read_margin < 0 ) read_margin += image_buffer_count; + int index; + if ( config.opt_adaptive_skip ) + { + int read_margin = shared_data->last_read_index - shared_data->last_write_index; + if ( read_margin < 0 ) read_margin += image_buffer_count; - int step = 1; - if ( read_margin > 0 ) - { - step = (9*image_buffer_count)/(5*read_margin); - } + int step = 1; + if ( read_margin > 0 ) + { + step = (9*image_buffer_count)/(5*read_margin); + } - int pending_frames = shared_data->last_write_index - shared_data->last_read_index; - if ( pending_frames < 0 ) pending_frames += image_buffer_count; + int pending_frames = shared_data->last_write_index - shared_data->last_read_index; + if ( pending_frames < 0 ) pending_frames += image_buffer_count; - Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); - if ( step <= pending_frames ) - { - index = (shared_data->last_read_index+step)%image_buffer_count; - } - else - { - if ( pending_frames ) - { - Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); - } - index = shared_data->last_write_index%image_buffer_count; - } - } - else - { - index = shared_data->last_write_index%image_buffer_count; - } + Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); + if ( step <= pending_frames ) + { + index = (shared_data->last_read_index+step)%image_buffer_count; + } + else + { + if ( pending_frames ) + { + Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); + } + index = shared_data->last_write_index%image_buffer_count; + } + } + else + { + index = shared_data->last_write_index%image_buffer_count; + } - Snapshot *snap = &image_buffer[index]; - struct timeval *timestamp = snap->timestamp; - Image *snap_image = snap->image; + Snapshot *snap = &image_buffer[index]; + struct timeval *timestamp = snap->timestamp; + Image *snap_image = snap->image; - if ( shared_data->action ) - { - if ( shared_data->action & RELOAD ) - { - Info( "Received reload indication at count %d", image_count ); - shared_data->action &= ~RELOAD; - Reload(); - } - if ( shared_data->action & SUSPEND ) - { - if ( Active() ) - { - Info( "Received suspend indication at count %d", image_count ); - shared_data->active = false; - //closeEvent(); - } - if ( config.max_suspend_time ) - { - auto_resume_time = now.tv_sec + config.max_suspend_time; - } - shared_data->action &= ~SUSPEND; - } - if ( shared_data->action & RESUME ) - { - if ( Enabled() && !Active() ) - { - Info( "Received resume indication at count %d", image_count ); - shared_data->active = true; - ref_image = *snap_image; - ready_count = image_count+(warmup_count/2); - shared_data->alarm_x = shared_data->alarm_y = -1; - } - shared_data->action &= ~RESUME; - } - } - if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) - { - Info( "Auto resuming at count %d", image_count ); - shared_data->active = true; - ref_image = *snap_image; - ready_count = image_count+(warmup_count/2); - auto_resume_time = 0; - } + if ( shared_data->action ) + { + if ( shared_data->action & RELOAD ) + { + Info( "Received reload indication at count %d", image_count ); + shared_data->action &= ~RELOAD; + Reload(); + } + if ( shared_data->action & SUSPEND ) + { + if ( Active() ) + { + Info( "Received suspend indication at count %d", image_count ); + shared_data->active = false; + //closeEvent(); + } + if ( config.max_suspend_time ) + { + auto_resume_time = now.tv_sec + config.max_suspend_time; + } + shared_data->action &= ~SUSPEND; + } + if ( shared_data->action & RESUME ) + { + if ( Enabled() && !Active() ) + { + Info( "Received resume indication at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + shared_data->alarm_x = shared_data->alarm_y = -1; + } + shared_data->action &= ~RESUME; + } + } + if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) + { + Info( "Auto resuming at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + auto_resume_time = 0; + } - static bool static_undef = true; - static struct timeval **timestamps; - static Image **images; - static int last_section_mod = 0; - static bool last_signal; + static bool static_undef = true; + static struct timeval **timestamps; + static Image **images; + static int last_section_mod = 0; + static bool last_signal; - if ( static_undef ) - { - static_undef = false; - timestamps = new struct timeval *[pre_event_count]; - images = new Image *[pre_event_count]; - last_signal = shared_data->signal; - } + if ( static_undef ) + { + static_undef = false; + timestamps = new struct timeval *[pre_event_count]; + images = new Image *[pre_event_count]; + last_signal = shared_data->signal; + } - if ( Enabled() ) - { - bool signal = shared_data->signal; - bool signal_change = (signal != last_signal); - if ( trigger_data->trigger_state != TRIGGER_OFF ) - { - unsigned int score = 0; - if ( Ready() ) - { + if ( Enabled() ) + { + bool signal = shared_data->signal; + bool signal_change = (signal != last_signal); + if ( trigger_data->trigger_state != TRIGGER_OFF ) + { + unsigned int score = 0; + if ( Ready() ) + { std::string cause; Event::StringSetMap noteSetMap; - if ( trigger_data->trigger_state == TRIGGER_ON ) - { - score += trigger_data->trigger_score; - if ( !event ) - { + if ( trigger_data->trigger_state == TRIGGER_ON ) + { + score += trigger_data->trigger_score; + if ( !event ) + { if ( cause.length() ) cause += ", "; cause += trigger_data->trigger_cause; - } + } Event::StringSet noteSet; noteSet.insert( trigger_data->trigger_text ); noteSetMap[trigger_data->trigger_cause] = noteSet; - } - if ( signal_change ) - { - score += 100; - const char *signalText; - if ( !signal ) - signalText = "Lost"; - else - signalText = "Reacquired"; - Warning( "%s: %s", SIGNAL_CAUSE, signalText ); - if ( event ) - { + } + if ( signal_change ) + { + score += 100; + const char *signalText; + if ( !signal ) + signalText = "Lost"; + else + signalText = "Reacquired"; + Warning( "%s: %s", SIGNAL_CAUSE, signalText ); + if ( event ) + { Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() ); - closeEvent(); - shared_data->state = state = IDLE; - last_section_mod = 0; - } - if ( !event ) - { + closeEvent(); + shared_data->state = state = IDLE; + last_section_mod = 0; + } + if ( !event ) + { if ( cause.length() ) cause += ", "; cause += SIGNAL_CAUSE; - } + } Event::StringSet noteSet; noteSet.insert( signalText ); noteSetMap[SIGNAL_CAUSE] = noteSet; - shared_data->active = signal; - ref_image = *snap_image; - } - else if ( Active() && function != RECORD && function != NODECT ) - { + shared_data->active = signal; + ref_image = *snap_image; + } + else if ( Active() && function != RECORD && function != NODECT ) + { Event::StringSet zoneSet; - int motion_score = DetectMotion( *snap_image, zoneSet ); - if ( motion_score ) - { - if ( !event ) - { - score += motion_score; + int motion_score = DetectMotion( *snap_image, zoneSet ); + if ( motion_score ) + { + if ( !event ) + { + score += motion_score; if ( cause.length() ) cause += ", "; cause += MOTION_CAUSE; - } - else - { - score += motion_score; - } + } + else + { + score += motion_score; + } noteSetMap[MOTION_CAUSE] = zoneSet; } - shared_data->active = signal; - } - if ( n_linked_monitors > 0 ) - { - bool first_link = true; + shared_data->active = signal; + } + if ( n_linked_monitors > 0 ) + { + bool first_link = true; Event::StringSet noteSet; - for ( int i = 0; i < n_linked_monitors; i++ ) - { - if ( linked_monitors[i]->isConnected() ) - { - if ( linked_monitors[i]->hasAlarmed() ) - { - if ( !event ) - { - if ( first_link ) - { + for ( int i = 0; i < n_linked_monitors; i++ ) + { + if ( linked_monitors[i]->isConnected() ) + { + if ( linked_monitors[i]->hasAlarmed() ) + { + if ( !event ) + { + if ( first_link ) + { if ( cause.length() ) cause += ", "; cause += LINKED_CAUSE; - first_link = false; - } - } + first_link = false; + } + } noteSet.insert( linked_monitors[i]->Name() ); - score += 50; - } - } - else - { - linked_monitors[i]->connect(); - } - } + score += 50; + } + } + else + { + linked_monitors[i]->connect(); + } + } if ( noteSet.size() > 0 ) noteSetMap[LINKED_CAUSE] = noteSet; - } - if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) - { - if ( event ) - { - int section_mod = timestamp->tv_sec%section_length; - if ( section_mod < last_section_mod ) - { - if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) - { - if ( state == IDLE || state == TAPE ) + } + if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) + { + if ( event ) + { + int section_mod = timestamp->tv_sec%section_length; + if ( section_mod < last_section_mod ) + { + if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) + { + if ( state == IDLE || state == TAPE ) Info( "%s: %03d - Closing event %d, section end", name, image_count, event->Id() ) - else + else Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() ); - closeEvent(); - last_section_mod = 0; - } - } - else - { - last_section_mod = section_mod; - } - } - if ( !event ) - { - shared_data->state = state = TAPE; + closeEvent(); + last_section_mod = 0; + } + } + else + { + last_section_mod = section_mod; + } + } + if ( !event ) + { + shared_data->state = state = TAPE; - // Create event - event = new Event( this, *timestamp, "Continuous", noteSetMap ); - shared_data->last_event = event->Id(); + // Create event + event = new Event( this, *timestamp, "Continuous", noteSetMap ); + shared_data->last_event = event->Id(); - Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); + Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); - //if ( config.overlap_timed_events ) - if ( false ) - { - int pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; - for ( int i = 0; i < pre_event_count; i++ ) - { - timestamps[i] = image_buffer[pre_index].timestamp; - images[i] = image_buffer[pre_index].image; + //if ( config.overlap_timed_events ) + if ( false ) + { + int pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + for ( int i = 0; i < pre_event_count; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; - pre_index = (pre_index+1)%image_buffer_count; - } - event->AddFrames( pre_event_count, images, timestamps ); - } - } - } - if ( score ) - { - if ( (state == IDLE || state == TAPE || state == PREALARM ) ) - { - if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) - { - Info( "%s: %03d - Gone into alarm state", name, image_count ); - shared_data->state = state = ALARM; - if ( signal_change || (function != MOCORD && state != ALERT) ) - { - int pre_index; - if ( alarm_frame_count > 1 ) - pre_index = ((index+image_buffer_count)-((alarm_frame_count-1)+pre_event_count))%image_buffer_count; - else - pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_count, images, timestamps ); + } + } + } + if ( score ) + { + if ( (state == IDLE || state == TAPE || state == PREALARM ) ) + { + if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) + { + Info( "%s: %03d - Gone into alarm state", name, image_count ); + shared_data->state = state = ALARM; + if ( signal_change || (function != MOCORD && state != ALERT) ) + { + int pre_index; + if ( alarm_frame_count > 1 ) + pre_index = ((index+image_buffer_count)-((alarm_frame_count-1)+pre_event_count))%image_buffer_count; + else + pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; - event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); - shared_data->last_event = event->Id(); + event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); + shared_data->last_event = event->Id(); - Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); + Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); - for ( int i = 0; i < pre_event_count; i++ ) - { - timestamps[i] = image_buffer[pre_index].timestamp; - images[i] = image_buffer[pre_index].image; + for ( int i = 0; i < pre_event_count; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; - pre_index = (pre_index+1)%image_buffer_count; - } - event->AddFrames( pre_event_count, images, timestamps ); - if ( alarm_frame_count ) - { - event->SavePreAlarmFrames(); - } - } - } - else if ( state != PREALARM ) - { - Info( "%s: %03d - Gone into prealarm state", name, image_count ); - shared_data->state = state = PREALARM; - } - } - else if ( state == ALERT ) - { - Info( "%s: %03d - Gone back into alarm state", name, image_count ); - shared_data->state = state = ALARM; - } - last_alarm_count = image_count; - } - else - { - if ( state == ALARM ) - { - Info( "%s: %03d - Gone into alert state", name, image_count ); - shared_data->state = state = ALERT; - } - else if ( state == ALERT ) - { - if ( image_count-last_alarm_count > post_event_count ) - { - Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); - if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == "Signal" ) - { - shared_data->state = state = IDLE; + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_count, images, timestamps ); + if ( alarm_frame_count ) + { + event->SavePreAlarmFrames(); + } + } + } + else if ( state != PREALARM ) + { + Info( "%s: %03d - Gone into prealarm state", name, image_count ); + shared_data->state = state = PREALARM; + } + } + else if ( state == ALERT ) + { + Info( "%s: %03d - Gone back into alarm state", name, image_count ); + shared_data->state = state = ALARM; + } + last_alarm_count = image_count; + } + else + { + if ( state == ALARM ) + { + Info( "%s: %03d - Gone into alert state", name, image_count ); + shared_data->state = state = ALERT; + } + else if ( state == ALERT ) + { + if ( image_count-last_alarm_count > post_event_count ) + { + Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); + if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == "Signal" ) + { + shared_data->state = state = IDLE; Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); closeEvent(); - } - else - { - shared_data->state = state = TAPE; - } - } - } - if ( state == PREALARM ) - { - if ( function != MOCORD ) - { - shared_data->state = state = IDLE; - } - else - { - shared_data->state = state = TAPE; - } - } - if ( Event::PreAlarmCount() ) - Event::EmptyPreAlarmFrames(); - } - if ( state != IDLE ) - { - if ( state == PREALARM || state == ALARM ) - { - if ( config.create_analysis_images ) - { - bool got_anal_image = false; - Image alarm_image( *snap_image ); - for( int i = 0; i < n_zones; i++ ) - { - if ( zones[i]->Alarmed() ) - { - if ( zones[i]->AlarmImage() ) - { - alarm_image.Overlay( *(zones[i]->AlarmImage()) ); - got_anal_image = true; - } - if ( config.record_event_stats && state == ALARM ) - { - zones[i]->RecordStats( event ); - } - } - } - if ( got_anal_image ) - { - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); - else - event->AddFrame( snap_image, *timestamp, score, &alarm_image ); - } - else - { - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score ); - else - event->AddFrame( snap_image, *timestamp, score ); - } - } - else - { - for( int i = 0; i < n_zones; i++ ) - { - if ( zones[i]->Alarmed() ) - { - if ( config.record_event_stats && state == ALARM ) - { - zones[i]->RecordStats( event ); - } - } - } - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score ); - else - event->AddFrame( snap_image, *timestamp, score ); - } + } + else + { + shared_data->state = state = TAPE; + } + } + } + if ( state == PREALARM ) + { + if ( function != MOCORD ) + { + shared_data->state = state = IDLE; + } + else + { + shared_data->state = state = TAPE; + } + } + if ( Event::PreAlarmCount() ) + Event::EmptyPreAlarmFrames(); + } + if ( state != IDLE ) + { + if ( state == PREALARM || state == ALARM ) + { + if ( config.create_analysis_images ) + { + bool got_anal_image = false; + Image alarm_image( *snap_image ); + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( zones[i]->AlarmImage() ) + { + alarm_image.Overlay( *(zones[i]->AlarmImage()) ); + got_anal_image = true; + } + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( got_anal_image ) + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); + else + event->AddFrame( snap_image, *timestamp, score, &alarm_image ); + } + else + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + } + else + { + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } if ( event && noteSetMap.size() > 0 ) event->updateNotes( noteSetMap ); - } - else if ( state == ALERT ) - { - event->AddFrame( snap_image, *timestamp ); + } + else if ( state == ALERT ) + { + event->AddFrame( snap_image, *timestamp ); if ( noteSetMap.size() > 0 ) event->updateNotes( noteSetMap ); - } - else if ( state == TAPE ) - { - if ( !(image_count%(frame_skip+1)) ) - { - if ( config.bulk_frame_interval > 1 ) - { - event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); - } - } - } - } - if ( function == RECORD || function == MOCORD ) - { - if ( state == IDLE || state == TAPE ) - { - int section_mod = timestamp->tv_sec%section_length; - if ( section_mod < last_section_mod ) - { + } + else if ( state == TAPE ) + { + if ( !(image_count%(frame_skip+1)) ) + { + if ( config.bulk_frame_interval > 1 ) + { + event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); + } + } + } + } + if ( function == RECORD || function == MOCORD ) + { + if ( state == IDLE || state == TAPE ) + { + int section_mod = timestamp->tv_sec%section_length; + if ( section_mod < last_section_mod ) + { Info( "%s: %03d - Closing event %d, section end2", name, image_count, event->Id() ); - closeEvent(); - last_section_mod = 0; - } - else - { - last_section_mod = section_mod; - } - } - } - } - } + closeEvent(); + last_section_mod = 0; + } + else + { + last_section_mod = section_mod; + } + } + } + } + } else { if ( event ) @@ -1480,427 +1480,427 @@ bool Monitor::Analyse() shared_data->state = state = IDLE; last_section_mod = 0; } - if ( !signal_change && (function == MODECT || function == MOCORD) && (config.blend_alarmed_images || state != ALARM) ) - { - ref_image.Blend( *snap_image, ref_blend_perc ); - } - last_signal = signal; - } + if ( !signal_change && (function == MODECT || function == MOCORD) && (config.blend_alarmed_images || state != ALARM) ) + { + ref_image.Blend( *snap_image, ref_blend_perc ); + } + last_signal = signal; + } - shared_data->last_read_index = index%image_buffer_count; - //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; - shared_data->last_read_time = now.tv_sec; - image_count++; + shared_data->last_read_index = index%image_buffer_count; + //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; + shared_data->last_read_time = now.tv_sec; + image_count++; - return( true ); + return( true ); } void Monitor::Reload() { - Debug( 1, "Reloading monitor %s", name ); + Debug( 1, "Reloading monitor %s", name ); if ( event ) Info( "%s: %03d - Closing event %d, reloading", name, image_count, event->Id() ); - closeEvent(); + closeEvent(); - static char sql[BUFSIZ]; - snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - if ( n_monitors != 1 ) - { - Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); - return; - } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors != 1 ) + { + Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); + return; + } - if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { - int index = 0; - function = (Function)atoi(dbrow[index++]); - enabled = atoi(dbrow[index++]); - const char *p_linked_monitors = dbrow[index++]; - strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); - strncpy( label_format, dbrow[index++], sizeof(label_format) ); - label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; - warmup_count = atoi(dbrow[index++]); - pre_event_count = atoi(dbrow[index++]); - post_event_count = atoi(dbrow[index++]); - alarm_frame_count = atoi(dbrow[index++]); - section_length = atoi(dbrow[index++]); - frame_skip = atoi(dbrow[index++]); - capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; - alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; - fps_report_interval = atoi(dbrow[index++]); - ref_blend_perc = atoi(dbrow[index++]); - track_motion = atoi(dbrow[index++]); + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + int index = 0; + function = (Function)atoi(dbrow[index++]); + enabled = atoi(dbrow[index++]); + const char *p_linked_monitors = dbrow[index++]; + strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); + strncpy( label_format, dbrow[index++], sizeof(label_format) ); + label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; + warmup_count = atoi(dbrow[index++]); + pre_event_count = atoi(dbrow[index++]); + post_event_count = atoi(dbrow[index++]); + alarm_frame_count = atoi(dbrow[index++]); + section_length = atoi(dbrow[index++]); + frame_skip = atoi(dbrow[index++]); + capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + fps_report_interval = atoi(dbrow[index++]); + ref_blend_perc = atoi(dbrow[index++]); + track_motion = atoi(dbrow[index++]); if ( dbrow[index][0] == '#' ) - signal_check_colour = strtol(dbrow[index]+1,0,16); + signal_check_colour = strtol(dbrow[index]+1,0,16); else - signal_check_colour = strtol(dbrow[index],0,16); + signal_check_colour = strtol(dbrow[index],0,16); index++; - shared_data->state = state = IDLE; - shared_data->alarm_x = shared_data->alarm_y = -1; - if ( enabled ) - shared_data->active = true; - ready_count = image_count+warmup_count; + shared_data->state = state = IDLE; + shared_data->alarm_x = shared_data->alarm_y = -1; + if ( enabled ) + shared_data->active = true; + ready_count = image_count+warmup_count; - ReloadLinkedMonitors( p_linked_monitors ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - mysql_free_result( result ); + ReloadLinkedMonitors( p_linked_monitors ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + mysql_free_result( result ); - ReloadZones(); + ReloadZones(); } void Monitor::ReloadZones() { - Debug( 1, "Reloading zones for monitor %s", name ); - for( int i = 0; i < n_zones; i++ ) - { - delete zones[i]; - } - delete[] zones; - zones = 0; - n_zones = Zone::Load( this, zones ); - //DumpZoneImage(); + Debug( 1, "Reloading zones for monitor %s", name ); + for( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + zones = 0; + n_zones = Zone::Load( this, zones ); + //DumpZoneImage(); } void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) { - Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); - if ( n_linked_monitors ) - { - for( int i = 0; i < n_linked_monitors; i++ ) - { - delete linked_monitors[i]; - } - delete[] linked_monitors; - linked_monitors = 0; - } + Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); + if ( n_linked_monitors ) + { + for( int i = 0; i < n_linked_monitors; i++ ) + { + delete linked_monitors[i]; + } + delete[] linked_monitors; + linked_monitors = 0; + } - n_linked_monitors = 0; - if ( p_linked_monitors ) - { - int n_link_ids = 0; - int link_ids[256]; + n_linked_monitors = 0; + if ( p_linked_monitors ) + { + int n_link_ids = 0; + int link_ids[256]; - char link_id_str[8]; - char *dest_ptr = link_id_str; - const char *src_ptr = p_linked_monitors; - while( 1 ) - { - dest_ptr = link_id_str; - while( *src_ptr >= '0' && *src_ptr <= '9' ) - { - if ( (dest_ptr-link_id_str) < (sizeof(link_id_str)-1) ) - { - *dest_ptr++ = *src_ptr++; - } - else - { - break; - } - } - // Add the link monitor - if ( dest_ptr != link_id_str ) - { - *dest_ptr = '\0'; - int link_id = atoi(link_id_str); - if ( link_id > 0 ) - { - Debug( 3, "Found linked monitor id %d", link_id ); - int j; - for ( j = 0; j < n_link_ids; j++ ) - { - if ( link_ids[j] == link_id ) - break; - } - if ( j == n_link_ids ) // Not already found - { - link_ids[n_link_ids++] = link_id; - } - } - } - if ( !*src_ptr ) - break; - while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) - src_ptr++; - if ( !*src_ptr ) - break; - } - if ( n_link_ids > 0 ) - { - Debug( 1, "Linking to %d monitors", n_link_ids ); - n_linked_monitors = n_link_ids; - linked_monitors = new MonitorLink *[n_linked_monitors]; - for ( int i = 0; i < n_linked_monitors; i++ ) - { - static char sql[BUFSIZ]; - Debug( 1, "Checking linked monitor %d", link_ids[i] ); + char link_id_str[8]; + char *dest_ptr = link_id_str; + const char *src_ptr = p_linked_monitors; + while( 1 ) + { + dest_ptr = link_id_str; + while( *src_ptr >= '0' && *src_ptr <= '9' ) + { + if ( (dest_ptr-link_id_str) < (sizeof(link_id_str)-1) ) + { + *dest_ptr++ = *src_ptr++; + } + else + { + break; + } + } + // Add the link monitor + if ( dest_ptr != link_id_str ) + { + *dest_ptr = '\0'; + int link_id = atoi(link_id_str); + if ( link_id > 0 ) + { + Debug( 3, "Found linked monitor id %d", link_id ); + int j; + for ( j = 0; j < n_link_ids; j++ ) + { + if ( link_ids[j] == link_id ) + break; + } + if ( j == n_link_ids ) // Not already found + { + link_ids[n_link_ids++] = link_id; + } + } + } + if ( !*src_ptr ) + break; + while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) + src_ptr++; + if ( !*src_ptr ) + break; + } + if ( n_link_ids > 0 ) + { + Debug( 1, "Linking to %d monitors", n_link_ids ); + n_linked_monitors = n_link_ids; + linked_monitors = new MonitorLink *[n_linked_monitors]; + for ( int i = 0; i < n_linked_monitors; i++ ) + { + static char sql[BUFSIZ]; + Debug( 1, "Checking linked monitor %d", link_ids[i] ); - snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - if ( n_monitors == 1 ) - { - MYSQL_ROW dbrow = mysql_fetch_row( result ); - Debug( 1, "Linking to monitor %d", link_ids[i] ); - linked_monitors[i] = new MonitorLink( link_ids[i], dbrow[1] ); - } - else - { - Debug( 1, "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); - } - mysql_free_result( result ); - } - } - } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors == 1 ) + { + MYSQL_ROW dbrow = mysql_fetch_row( result ); + Debug( 1, "Linking to monitor %d", link_ids[i] ); + linked_monitors[i] = new MonitorLink( link_ids[i], dbrow[1] ); + } + else + { + Debug( 1, "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); + } + mysql_free_result( result ); + } + } + } } int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { - static char sql[BUFSIZ]; - if ( !device[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + if ( !device[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device ); + } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; - const char *device = dbrow[col]; col++; - int channel = atoi(dbrow[col]); col++; - int format = atoi(dbrow[col]); col++; - const char *method = dbrow[col]; col++; + const char *device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + const char *method = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; int signal_check_colour; if ( dbrow[col][0] == '#' ) - signal_check_colour = strtol(dbrow[col]+1,0,16); + signal_check_colour = strtol(dbrow[col]+1,0,16); else - signal_check_colour = strtol(dbrow[col],0,16); + signal_check_colour = strtol(dbrow[col],0,16); col++; - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - Camera *camera = new LocalCamera( + Camera *camera = new LocalCamera( id, - device, - channel, - format, - method, - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + device, + channel, + format, + method, + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); - monitors[i] = new Monitor( - id, - name, - function, - enabled, - linked_monitors, - camera, - orientation, - event_prefix, - label_format, - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - track_motion, - signal_check_colour, - purpose - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); - return( n_monitors ); + return( n_monitors ); } int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) { - static char sql[BUFSIZ]; - if ( !protocol ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + if ( !protocol ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Remote' and Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); + } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; - std::string protocol = dbrow[col]; col++; - std::string method = dbrow[col]; col++; - std::string host = dbrow[col]; col++; - std::string port = dbrow[col]; col++; - std::string path = dbrow[col]; col++; - std::string subpath = dbrow[col]; col++; + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + std::string subpath = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - std::string event_prefix = dbrow[col]; col++; - std::string label_format = dbrow[col]; col++; + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - Camera *camera = 0; + Camera *camera = 0; if ( protocol == "http" ) { camera = new RemoteCameraHttp( @@ -1945,404 +1945,404 @@ int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const c Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); } - monitors[i] = new Monitor( - id, - name.c_str(), - function, - enabled, - linked_monitors, - camera, - orientation, - event_prefix.c_str(), - label_format.c_str(), - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - track_motion, + monitors[i] = new Monitor( + id, + name.c_str(), + function, + enabled, + linked_monitors, + camera, + orientation, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, RGB_WHITE, - purpose - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); - return( n_monitors ); + return( n_monitors ); } int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - static char sql[BUFSIZ]; - if ( !file[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); + } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; - const char *path = dbrow[col]; col++; + const char *path = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - Camera *camera = new FileCamera( + Camera *camera = new FileCamera( id, - path, // File - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + path, // File + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); - monitors[i] = new Monitor( - id, - name, - function, - enabled, - linked_monitors, - camera, - orientation, - event_prefix, - label_format, - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - track_motion, + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, RGB_WHITE, - purpose - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); - return( n_monitors ); + return( n_monitors ); } #if HAVE_LIBAVFORMAT int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - static char sql[BUFSIZ]; - if ( !file[0] ) - { - strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); - } - else - { - snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); - } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); + } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; - const char *path = dbrow[col]; col++; + const char *path = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - Camera *camera = new FfmpegCamera( + Camera *camera = new FfmpegCamera( id, - path, // File - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + path, // File + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); - monitors[i] = new Monitor( - id, - name, - function, - enabled, - linked_monitors, - camera, - orientation, - event_prefix, - label_format, - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - track_motion, + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, RGB_WHITE, - purpose - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); - return( n_monitors ); + return( n_monitors ); } #endif // HAVE_LIBAVFORMAT Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) { - static char sql[BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, SubPath, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = %d", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - Monitor *monitor = 0; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + Monitor *monitor = 0; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; - std::string type = dbrow[col]; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - std::string linked_monitors = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + std::string type = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + std::string linked_monitors = dbrow[col]; col++; - std::string device = dbrow[col]; col++; - int channel = atoi(dbrow[col]); col++; - int format = atoi(dbrow[col]); col++; + std::string device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; - std::string protocol = dbrow[col]; col++; - std::string method = dbrow[col]; col++; - std::string host = dbrow[col]; col++; - std::string port = dbrow[col]; col++; - std::string path = dbrow[col]; col++; - std::string subpath = dbrow[col]; col++; + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + std::string subpath = dbrow[col]; col++; - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; - std::string event_prefix = dbrow[col]; col++; - std::string label_format = dbrow[col]; col++; + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; int signal_check_colour; if ( dbrow[col][0] == '#' ) - signal_check_colour = strtol(dbrow[col]+1,0,16); + signal_check_colour = strtol(dbrow[col]+1,0,16); else - signal_check_colour = strtol(dbrow[col],0,16); + signal_check_colour = strtol(dbrow[col],0,16); - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - Camera *camera = 0; - if ( type == "Local" ) - { - camera = new LocalCamera( + Camera *camera = 0; + if ( type == "Local" ) + { + camera = new LocalCamera( id, - device.c_str(), - channel, - format, - method, - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } - else if ( type == "Remote" ) - { + device.c_str(), + channel, + format, + method, + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } + else if ( type == "Remote" ) + { if ( protocol == "http" ) { camera = new RemoteCameraHttp( @@ -2381,201 +2381,201 @@ Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) purpose==CAPTURE ); #else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); + Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); #endif // HAVE_LIBAVFORMAT } else - { - Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); - } - } - else if ( type == "File" ) - { - camera = new FileCamera( + { + Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); + } + } + else if ( type == "File" ) + { + camera = new FileCamera( id, - path.c_str(), - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } + path.c_str(), + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } #if HAVE_LIBAVFORMAT - else if ( type == "Ffmpeg" ) - { - camera = new FfmpegCamera( + else if ( type == "Ffmpeg" ) + { + camera = new FfmpegCamera( id, - path.c_str(), - cam_width, - cam_height, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } + path.c_str(), + cam_width, + cam_height, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } #endif // HAVE_LIBAVFORMAT - else - { - Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); - } - monitor = new Monitor( - id, - name.c_str(), - function, - enabled, - linked_monitors.c_str(), - camera, - orientation, - event_prefix.c_str(), - label_format.c_str(), - Coord( label_x, label_y ), - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - track_motion, - signal_check_colour, - purpose - ); + else + { + Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); + } + monitor = new Monitor( + id, + name.c_str(), + function, + enabled, + linked_monitors.c_str(), + camera, + orientation, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose + ); - int n_zones = 0; - if ( load_zones ) - { - Zone **zones = 0; - n_zones = Zone::Load( monitor, zones ); - monitor->AddZones( n_zones, zones ); - } - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); + int n_zones = 0; + if ( load_zones ) + { + Zone **zones = 0; + n_zones = Zone::Load( monitor, zones ); + monitor->AddZones( n_zones, zones ); + } + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); - return( monitor ); + return( monitor ); } int Monitor::Capture() { - if ( camera->Capture( image ) == 0 ) - { - if ( orientation != ROTATE_0 ) - { - switch ( orientation ) - { - case ROTATE_0 : + if ( camera->Capture( image ) == 0 ) + { + if ( orientation != ROTATE_0 ) + { + switch ( orientation ) + { + case ROTATE_0 : { // No action required break; } - case ROTATE_90 : - case ROTATE_180 : - case ROTATE_270 : - { - image.Rotate( (orientation-1)*90 ); - break; - } - case FLIP_HORI : - case FLIP_VERT : - { - image.Flip( orientation==FLIP_HORI ); - break; - } - } - } + case ROTATE_90 : + case ROTATE_180 : + case ROTATE_270 : + { + image.Rotate( (orientation-1)*90 ); + break; + } + case FLIP_HORI : + case FLIP_VERT : + { + image.Flip( orientation==FLIP_HORI ); + break; + } + } + } - if ( image.Size() != camera->ImageSize() ) - { - Error( "Captured image does not match expected size, check width, height and colour depth" ); - return( -1 ); - } + if ( image.Size() != camera->ImageSize() ) + { + Error( "Captured image does not match expected size, check width, height and colour depth" ); + return( -1 ); + } - int index = image_count%image_buffer_count; - if ( (index == shared_data->last_read_index) && (function > MONITOR) ) - { - Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); - time_t now = time(0); - double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); + int index = image_count%image_buffer_count; + if ( (index == shared_data->last_read_index) && (function > MONITOR) ) + { + Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); + time_t now = time(0); + double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); time_t last_read_delta = now - shared_data->last_read_time; if ( last_read_delta > (image_buffer_count/approxFps) ) { Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta ) shared_data->last_read_index = image_buffer_count; } - } + } - gettimeofday( image_buffer[index].timestamp, NULL ); - if ( config.timestamp_on_capture ) - { - TimestampImage( &image, image_buffer[index].timestamp ); - } - image_buffer[index].image->CopyBuffer( image ); + gettimeofday( image_buffer[index].timestamp, NULL ); + if ( config.timestamp_on_capture ) + { + TimestampImage( &image, image_buffer[index].timestamp ); + } + image_buffer[index].image->CopyBuffer( image ); - shared_data->signal = CheckSignal( &image ); - shared_data->last_write_index = index; - shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; + shared_data->signal = CheckSignal( &image ); + shared_data->last_write_index = index; + shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; - image_count++; + image_count++; - if ( image_count && !(image_count%fps_report_interval) ) - { - time_t now = image_buffer[index].timestamp->tv_sec; - fps = double(fps_report_interval)/(now-last_fps_time); - //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); - //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); - Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); - last_fps_time = now; - } + if ( image_count && !(image_count%fps_report_interval) ) + { + time_t now = image_buffer[index].timestamp->tv_sec; + fps = double(fps_report_interval)/(now-last_fps_time); + //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); + //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); + Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); + last_fps_time = now; + } - if ( shared_data->action & GET_SETTINGS ) - { - shared_data->brightness = camera->Brightness(); - shared_data->hue = camera->Hue(); - shared_data->colour = camera->Colour(); - shared_data->contrast = camera->Contrast(); - shared_data->action &= ~GET_SETTINGS; - } - if ( shared_data->action & SET_SETTINGS ) - { - camera->Brightness( shared_data->brightness ); - camera->Hue( shared_data->hue ); - camera->Colour( shared_data->colour ); - camera->Contrast( shared_data->contrast ); - shared_data->action &= ~SET_SETTINGS; - } - return( 0 ); - } - shared_data->signal = false; - return( -1 ); + if ( shared_data->action & GET_SETTINGS ) + { + shared_data->brightness = camera->Brightness(); + shared_data->hue = camera->Hue(); + shared_data->colour = camera->Colour(); + shared_data->contrast = camera->Contrast(); + shared_data->action &= ~GET_SETTINGS; + } + if ( shared_data->action & SET_SETTINGS ) + { + camera->Brightness( shared_data->brightness ); + camera->Hue( shared_data->hue ); + camera->Colour( shared_data->colour ); + camera->Contrast( shared_data->contrast ); + shared_data->action &= ~SET_SETTINGS; + } + return( 0 ); + } + shared_data->signal = false; + return( -1 ); } void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const { - if ( label_format[0] ) - { + if ( label_format[0] ) + { // Expand the strftime macros first - char label_time_text[256]; - strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); + char label_time_text[256]; + strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); - char label_text[1024]; + char label_text[1024]; const char *s_ptr = label_time_text; char *d_ptr = label_text; while ( *s_ptr && ((d_ptr-label_text) < sizeof(label_text)) ) @@ -2607,256 +2607,256 @@ void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) c *d_ptr++ = *s_ptr++; } *d_ptr = '\0'; - ts_image->Annotate( label_text, label_coord ); - } + ts_image->Annotate( label_text, label_coord ); + } } bool Monitor::closeEvent() { - if ( event ) - { - if ( function == RECORD || function == MOCORD ) - { - gettimeofday( &(event->EndTime()), NULL ); - } - delete event; - event = 0; - return( true ); - } - return( false ); + if ( event ) + { + if ( function == RECORD || function == MOCORD ) + { + gettimeofday( &(event->EndTime()), NULL ); + } + delete event; + event = 0; + return( true ); + } + return( false ); } unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) { - bool alarm = false; - unsigned int score = 0; + bool alarm = false; + unsigned int score = 0; - if ( n_zones <= 0 ) return( alarm ); + if ( n_zones <= 0 ) return( alarm ); - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); - } - ref_image.WriteJpeg( diag_path ); - } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); + } + ref_image.WriteJpeg( diag_path ); + } - Image *delta_image = ref_image.Delta( comp_image ); + Image *delta_image = ref_image.Delta( comp_image ); - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); - } - delta_image->WriteJpeg( diag_path ); - } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); + } + delta_image->WriteJpeg( diag_path ); + } - // Blank out all exclusion zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - zone->ClearAlarm(); - if ( !zone->IsInactive() ) - { - continue; - } - Debug( 3, "Blanking inactive zone %s", zone->Label() ); - delta_image->Fill( RGB_BLACK, zone->GetPolygon() ); - } + // Blank out all exclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + zone->ClearAlarm(); + if ( !zone->IsInactive() ) + { + continue; + } + Debug( 3, "Blanking inactive zone %s", zone->Label() ); + delta_image->Fill( RGB_BLACK, zone->GetPolygon() ); + } - // Check preclusive zones first - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsPreclusive() ) - { - continue; - } - Debug( 3, "Checking preclusive zone %s", zone->Label() ); - if ( zone->CheckAlarms( delta_image ) ) - { - alarm = true; - score += zone->Score(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + // Check preclusive zones first + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsPreclusive() ) + { + continue; + } + Debug( 3, "Checking preclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( delta_image ) ) + { + alarm = true; + score += zone->Score(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); zoneSet.insert( zone->Label() ); - //zone->ResetStats(); - } - } + //zone->ResetStats(); + } + } - Coord alarm_centre; - int top_score = -1; + Coord alarm_centre; + int top_score = -1; - if ( alarm ) - { - alarm = false; - score = 0; - } - else - { - // Find all alarm pixels in active zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsActive() ) - { - continue; - } - Debug( 3, "Checking active zone %s", zone->Label() ); - if ( zone->CheckAlarms( delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + if ( alarm ) + { + alarm = false; + score = 0; + } + else + { + // Find all alarm pixels in active zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() ) + { + continue; + } + Debug( 3, "Checking active zone %s", zone->Label() ); + if ( zone->CheckAlarms( delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); zoneSet.insert( zone->Label() ); - if ( config.opt_control && track_motion ) - { - if ( (int)zone->Score() > top_score ) - { - top_score = zone->Score(); - alarm_centre = zone->GetAlarmCentre(); - } - } - } - } + if ( config.opt_control && track_motion ) + { + if ( (int)zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } - if ( alarm ) - { - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsInclusive() ) - { - continue; - } - Debug( 3, "Checking inclusive zone %s", zone->Label() ); - if ( zone->CheckAlarms( delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + if ( alarm ) + { + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsInclusive() ) + { + continue; + } + Debug( 3, "Checking inclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); zoneSet.insert( zone->Label() ); - if ( config.opt_control && track_motion ) - { - if ( zone->Score() > top_score ) - { - top_score = zone->Score(); - alarm_centre = zone->GetAlarmCentre(); - } - } - } - } - } - else - { - // Find all alarm pixels in exclusive zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsExclusive() ) - { - continue; - } - Debug( 3, "Checking exclusive zone %s", zone->Label() ); - if ( zone->CheckAlarms( delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + if ( config.opt_control && track_motion ) + { + if ( zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } + } + else + { + // Find all alarm pixels in exclusive zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsExclusive() ) + { + continue; + } + Debug( 3, "Checking exclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); zoneSet.insert( zone->Label() ); - } - } - } - } + } + } + } + } - if ( top_score > 0 ) - { - shared_data->alarm_x = alarm_centre.X(); - shared_data->alarm_y = alarm_centre.Y(); + if ( top_score > 0 ) + { + shared_data->alarm_x = alarm_centre.X(); + shared_data->alarm_y = alarm_centre.Y(); - Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); - } - else - { - shared_data->alarm_x = shared_data->alarm_y = -1; - } + Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); + } + else + { + shared_data->alarm_x = shared_data->alarm_y = -1; + } - delete delta_image; - // This is a small and innocent hack to prevent scores of 0 being returned in alarm state - return( score?score:alarm ); + delete delta_image; + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + return( score?score:alarm ); } bool Monitor::DumpSettings( char *output, bool verbose ) { - output[0] = 0; + output[0] = 0; - sprintf( output+strlen(output), "Id : %d\n", id ); - sprintf( output+strlen(output), "Name : %s\n", name ); - sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); - if ( camera->IsLocal() ) - { - sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); - sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); - sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); - } - else if ( camera->IsRemote() ) - { - sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); - sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); - sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); - sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); - } - else if ( camera->IsFile() ) - { - sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); - } -#if HAVE_LIBAVFORMAT - else if ( camera->IsFfmpeg() ) - { - sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); - } -#endif // HAVE_LIBAVFORMAT - sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); - sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); - if ( camera->IsLocal() ) - { - sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); + sprintf( output+strlen(output), "Id : %d\n", id ); + sprintf( output+strlen(output), "Name : %s\n", name ); + sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); + sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); + sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); } - sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); - sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); - sprintf( output+strlen(output), "Label Format : %s\n", label_format ); - sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); - sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); - sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); - sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); - sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); - sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); - sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); - sprintf( output+strlen(output), "Section Length : %d\n", section_length ); - sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); - sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); - sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); - sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); - sprintf( output+strlen(output), "Function: %d - %s\n", function, - function==NONE?"None":( - function==MONITOR?"Monitor Only":( - function==MODECT?"Motion Detection":( - function==RECORD?"Continuous Record":( - function==MOCORD?"Continuous Record with Motion Detection":( - function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" - )))))); - sprintf( output+strlen(output), "Zones : %d\n", n_zones ); - for ( int i = 0; i < n_zones; i++ ) - { - zones[i]->DumpSettings( output+strlen(output), verbose ); - } - return( true ); + else if ( camera->IsRemote() ) + { + sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); + sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); + sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); + sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); + } + else if ( camera->IsFile() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); + } +#if HAVE_LIBAVFORMAT + else if ( camera->IsFfmpeg() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); + } +#endif // HAVE_LIBAVFORMAT + sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); + sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); + } + sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); + sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); + sprintf( output+strlen(output), "Label Format : %s\n", label_format ); + sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); + sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); + sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); + sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); + sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); + sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); + sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); + sprintf( output+strlen(output), "Section Length : %d\n", section_length ); + sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); + sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); + sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); + sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); + sprintf( output+strlen(output), "Function: %d - %s\n", function, + function==NONE?"None":( + function==MONITOR?"Monitor Only":( + function==MODECT?"Motion Detection":( + function==RECORD?"Continuous Record":( + function==MOCORD?"Continuous Record with Motion Detection":( + function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" + )))))); + sprintf( output+strlen(output), "Zones : %d\n", n_zones ); + for ( int i = 0; i < n_zones; i++ ) + { + zones[i]->DumpSettings( output+strlen(output), verbose ); + } + return( true ); } bool MonitorStream::checkSwapPath( const char *path, bool create_path ) @@ -3231,7 +3231,7 @@ bool MonitorStream::sendFrame( const char *filepath, struct timeval *timestamp ) fprintf( stdout, "--ZoneMinderFrame\r\n" ); fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 ) + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { Error( "Unable to send stream frame: %s", strerror(errno) ); return( false ); @@ -3284,9 +3284,9 @@ bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) else #endif // HAVE_LIBAVCODEC { - static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; - int img_buffer_size = 0; + int img_buffer_size = 0; unsigned char *img_buffer = temp_img_buffer; // Calculate how long it takes to actually send the frame @@ -3316,7 +3316,7 @@ bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) break; } fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 ) + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { Error( "Unable to send stream frame: %s", strerror(errno) ); return( false ); @@ -3354,14 +3354,14 @@ void MonitorStream::runStream() updateFrameRate( monitor->GetFPS() ); if ( type == STREAM_JPEG ) - fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); - int last_read_index = monitor->image_buffer_count; + int last_read_index = monitor->image_buffer_count; - time_t stream_start_time; - time( &stream_start_time ); + time_t stream_start_time; + time( &stream_start_time ); - frame_count = 0; + frame_count = 0; temp_image_buffer = 0; temp_image_buffer_count = playback_buffer; @@ -3402,13 +3402,14 @@ void MonitorStream::runStream() } } - while ( !zm_terminate ) - { + float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) + while ( !zm_terminate ) + { bool got_command = false; - if ( feof( stdout ) || ferror( stdout ) ) - { - break; - } + if ( feof( stdout ) || ferror( stdout ) ) + { + break; + } gettimeofday( &now, NULL ); @@ -3420,7 +3421,7 @@ void MonitorStream::runStream() bool frame_sent = false; if ( buffered_playback && delayed ) { - if ( temp_read_index == temp_write_index ) + if ( temp_read_index == temp_write_index ) { // Go back to live viewing Debug( 1, "Exceeded temporary streaming buffer" ); @@ -3430,7 +3431,7 @@ void MonitorStream::runStream() delayed = false; replay_rate = ZM_RATE_BASE; } - else + else { if ( !paused ) { @@ -3508,16 +3509,16 @@ void MonitorStream::runStream() replay_rate = ZM_RATE_BASE; } } - if ( last_read_index != monitor->shared_data->last_write_index ) - { - int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; - last_read_index = monitor->shared_data->last_write_index; - //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); - if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) - { + if ( last_read_index != monitor->shared_data->last_write_index ) + { + int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; + last_read_index = monitor->shared_data->last_write_index; + //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); + if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) + { if ( !paused && !delayed ) { - // Send the next frame + // Send the next frame Monitor::Snapshot *snap = &monitor->image_buffer[index]; if ( !sendFrame( snap->image, snap->timestamp ) ) @@ -3525,12 +3526,12 @@ void MonitorStream::runStream() memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); frame_sent = true; - temp_read_index = temp_write_index; + temp_read_index = temp_write_index; } - } + } if ( buffered_playback ) { - if ( monitor->shared_data->valid ) + if ( monitor->shared_data->valid ) { if ( monitor->image_buffer[index].timestamp->tv_sec ) { @@ -3565,9 +3566,9 @@ void MonitorStream::runStream() Warning( "Unable to store frame as shared memory invalid" ); } } - frame_count++; - } - usleep( (1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)) ); + frame_count++; + } + usleep( (1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2)) ); if ( ttl ) { if ( (now.tv_sec - stream_start_time) > ttl ) @@ -3575,7 +3576,12 @@ void MonitorStream::runStream() break; } } - } + if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) + { + Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); + break; + } + } if ( buffered_playback ) { char swap_path[PATH_MAX] = ""; @@ -3634,75 +3640,75 @@ void MonitorStream::runStream() void Monitor::SingleImage( int scale) { - int img_buffer_size = 0; - static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + int img_buffer_size = 0; + static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); - - fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); - fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); - fwrite( img_buffer, img_buffer_size, 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); } void Monitor::SingleImageRaw( int scale) { - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - - fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); - fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); - fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + + fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); + fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); + fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); } void Monitor::SingleImageZip( int scale) { - unsigned long img_buffer_size = 0; - static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + unsigned long img_buffer_size = 0; + static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - snap_image->Zip( img_buffer, &img_buffer_size ); - - fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); - fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); - fwrite( img_buffer, img_buffer_size, 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->Zip( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); }