diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 078f9de64..ea43f3499 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -26,205 +26,28 @@ #include "zm_local_camera.h" #include "zm_remote_camera.h" -Monitor::Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_capture, int p_n_zones, Zone *p_zones[] ) : id( p_id ), function( (Function)p_function ), width( p_width ), height( p_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 ), capture_delay( p_capture_delay ), fps_report_interval( p_fps_report_interval ), ref_blend_perc( p_ref_blend_perc ), image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), ref_image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), n_zones( p_n_zones ), zones( p_zones ) +Monitor::Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, Mode p_mode, int p_n_zones, Zone *p_zones[] ) : id( p_id ), function( (Function)p_function ), width( p_width ), height( p_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 ), capture_delay( p_capture_delay ), fps_report_interval( p_fps_report_interval ), ref_blend_perc( p_ref_blend_perc ), image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), ref_image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), n_zones( p_n_zones ), zones( p_zones ) { name = new char[strlen(p_name)+1]; strcpy( name, p_name ); strcpy( label_format, p_label_format ); - camera = new LocalCamera( p_device, p_channel, p_format, (p_orientation%2)?width:height, (orientation%2)?height:width, p_palette, p_capture ); + camera = new LocalCamera( p_device, p_channel, p_format, (p_orientation%2)?width:height, (orientation%2)?height:width, p_palette, p_mode==CAPTURE ); - fps = 0.0; - event_count = 0; - image_count = 0; - first_alarm_count = 0; - last_alarm_count = 0; - state = IDLE; - - int shared_images_size = sizeof(SharedImages)+(image_buffer_count*sizeof(time_t))+(image_buffer_count*camera->ImageSize()); - Info(( "shm.size=%d", shared_images_size )); - shmid = shmget( ZM_SHM_KEY|id, shared_images_size, IPC_CREAT|0777 ); - if ( shmid < 0 ) - { - Error(( "Can't shmget: %s", strerror(errno))); - exit( -1 ); - } - unsigned char *shm_ptr = (unsigned char *)shmat( shmid, 0, 0 ); - shared_images = (SharedImages *)shm_ptr; - if ( shared_images < 0 ) - { - Error(( "Can't shmat: %s", strerror(errno))); - exit( -1 ); - } - - if ( p_capture ) - { - memset( shared_images, 0, shared_images_size ); - shared_images->state = IDLE; - shared_images->last_write_index = image_buffer_count; - shared_images->last_read_index = image_buffer_count; - shared_images->last_event = 0; - shared_images->force_state = FORCE_NEUTRAL; - } - shared_images->timestamps = (struct timeval *)(shm_ptr+sizeof(SharedImages)); - shared_images->images = (unsigned char *)(shm_ptr+sizeof(SharedImages)+(image_buffer_count*sizeof(struct timeval))); - - image_buffer = new Snapshot[image_buffer_count]; - for ( int i = 0; i < image_buffer_count; i++ ) - { - image_buffer[i].timestamp = &(shared_images->timestamps[i]); - image_buffer[i].image = new Image( width, height, camera->Colours(), &(shared_images->images[i*camera->ImageSize()]) ); - } - if ( !n_zones ) - { - n_zones = 1; - zones = new Zone *[1]; - zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED ); - } - start_time = last_fps_time = time( 0 ); - - event = 0; - - Info(( "Monitor %s has function %d", name, function )); - Info(( "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() )); - Info(( "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, FRI = %d, RBP = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, fps_report_interval, ref_blend_perc )); - - if ( !p_capture ) - { - ref_image.Assign( width, height, camera->Colours(), image_buffer[shared_images->last_write_index].image->Buffer() ); - } - else - { - static char path[PATH_MAX]; - - sprintf( path, ZM_DIR_EVENTS ); - - 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))); - } - } - - sprintf( path, ZM_DIR_EVENTS "/%s", name ); - - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error(( "Can't make %s: %s", path, strerror(errno))); - } - } - } - - record_event_stats = ZM_RECORD_EVENT_STATS; + Initialise( p_mode ); } -Monitor::Monitor( int p_id, char *p_name, int p_function, const char *p_host, const char *p_port, const char *p_path, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_capture, int p_n_zones, Zone *p_zones[] ) : id( p_id ), function( (Function)p_function ), width( p_width ), height( p_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 ), capture_delay( p_capture_delay ), fps_report_interval( p_fps_report_interval ), ref_blend_perc( p_ref_blend_perc ), image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), ref_image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), n_zones( p_n_zones ), zones( p_zones ) +Monitor::Monitor( int p_id, char *p_name, int p_function, const char *p_host, const char *p_port, const char *p_path, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, Mode p_mode, int p_n_zones, Zone *p_zones[] ) : id( p_id ), function( (Function)p_function ), width( p_width ), height( p_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 ), capture_delay( p_capture_delay ), fps_report_interval( p_fps_report_interval ), ref_blend_perc( p_ref_blend_perc ), image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), ref_image( width, height, (p_palette==VIDEO_PALETTE_GREY?1:3) ), n_zones( p_n_zones ), zones( p_zones ) { name = new char[strlen(p_name)+1]; strcpy( name, p_name ); strcpy( label_format, p_label_format ); - camera = new RemoteCamera( p_host, p_port, p_path, (p_orientation%2)?width:height, (orientation%2)?height:width, p_palette, p_capture ); + camera = new RemoteCamera( p_host, p_port, p_path, (p_orientation%2)?width:height, (orientation%2)?height:width, p_palette, p_mode==CAPTURE ); - fps = 0.0; - event_count = 0; - image_count = 0; - first_alarm_count = 0; - last_alarm_count = 0; - state = IDLE; - - int shared_images_size = sizeof(SharedImages)+(image_buffer_count*sizeof(time_t))+(image_buffer_count*camera->ImageSize()); - shmid = shmget( ZM_SHM_KEY|id, shared_images_size, IPC_CREAT|0777 ); - if ( shmid < 0 ) - { - Error(( "Can't shmget: %s", strerror(errno))); - exit( -1 ); - } - unsigned char *shm_ptr = (unsigned char *)shmat( shmid, 0, 0 ); - shared_images = (SharedImages *)shm_ptr; - if ( shared_images < 0 ) - { - Error(( "Can't shmat: %s", strerror(errno))); - exit( -1 ); - } - - if ( p_capture ) - { - memset( shared_images, 0, shared_images_size ); - shared_images->state = IDLE; - shared_images->last_write_index = image_buffer_count; - shared_images->last_read_index = image_buffer_count; - shared_images->last_event = 0; - shared_images->force_state = FORCE_NEUTRAL; - } - shared_images->timestamps = (struct timeval *)(shm_ptr+sizeof(SharedImages)); - shared_images->images = (unsigned char *)(shm_ptr+sizeof(SharedImages)+(image_buffer_count*sizeof(struct timeval))); - - image_buffer = new Snapshot[image_buffer_count]; - for ( int i = 0; i < image_buffer_count; i++ ) - { - image_buffer[i].timestamp = &(shared_images->timestamps[i]); - image_buffer[i].image = new Image( width, height, camera->Colours(), &(shared_images->images[i*camera->ImageSize()]) ); - } - if ( !n_zones ) - { - n_zones = 1; - zones = new Zone *[1]; - zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED ); - } - start_time = last_fps_time = time( 0 ); - - event = 0; - - Info(( "Monitor %s has function %d", name, function )); - Info(( "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() )); - Info(( "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, FRI = %d, RBP = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, fps_report_interval, ref_blend_perc )); - - if ( !p_capture ) - { - ref_image.Assign( width, height, camera->Colours(), image_buffer[shared_images->last_write_index].image->Buffer() ); - } - else - { - static char path[PATH_MAX]; - - sprintf( path, ZM_DIR_EVENTS ); - - 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))); - } - } - - sprintf( path, ZM_DIR_EVENTS "/%s", name ); - - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error(( "Can't make %s: %s", path, strerror(errno))); - } - } - } - - record_event_stats = ZM_RECORD_EVENT_STATS; + Initialise( p_mode); } Monitor::~Monitor() @@ -248,6 +71,111 @@ Monitor::~Monitor() } } +void Monitor::Initialise( Mode mode ) +{ + fps = 0.0; + event_count = 0; + image_count = 0; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; + + Info(( "monitor mode=%d", mode )); + + int shared_data_size = sizeof(SharedData)+(image_buffer_count*sizeof(time_t))+(image_buffer_count*camera->ImageSize()); + Info(( "shm.size=%d", shared_data_size )); + shmid = shmget( ZM_SHM_KEY|id, shared_data_size, IPC_CREAT|0777 ); + if ( shmid < 0 ) + { + Error(( "Can't shmget: %s", strerror(errno))); + exit( -1 ); + } + unsigned char *shm_ptr = (unsigned char *)shmat( shmid, 0, 0 ); + shared_data = (SharedData *)shm_ptr; + if ( shared_data < 0 ) + { + Error(( "Can't shmat: %s", strerror(errno))); + exit( -1 ); + } + + if ( mode == CAPTURE ) + { + memset( shared_data, 0, shared_data_size ); + shared_data->valid = true; + shared_data->state = IDLE; + shared_data->last_write_index = image_buffer_count; + shared_data->last_read_index = image_buffer_count; + shared_data->last_event = 0; + shared_data->force_state = FORCE_NEUTRAL; + } + if ( !shared_data->valid ) + { + Error(( "Shared memory not initialised by capture daemon" )); + exit( -1 ); + } + + struct timeval *shared_timestamps = (struct timeval *)(shm_ptr+sizeof(SharedData)); + unsigned char *shared_images = (unsigned char *)(shm_ptr+sizeof(SharedData)+(image_buffer_count*sizeof(struct timeval))); + 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]; + zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Box( width, height ), RGB_RED ); + } + start_time = last_fps_time = time( 0 ); + + event = 0; + + Info(( "Monitor %s has function %d", name, function )); + Info(( "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() )); + Info(( "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, FRI = %d, RBP = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, fps_report_interval, ref_blend_perc )); + + record_event_stats = ZM_RECORD_EVENT_STATS; + + if ( mode == ANALYSIS ) + { + static char path[PATH_MAX]; + + sprintf( path, ZM_DIR_EVENTS ); + + 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))); + } + } + + sprintf( path, ZM_DIR_EVENTS "/%s", name ); + + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error(( "Can't make %s: %s", path, 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() ); + } +} + void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) { n_zones = p_n_zones; @@ -256,14 +184,14 @@ void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) Monitor::State Monitor::GetState() const { - return( shared_images->state ); + return( shared_data->state ); } int Monitor::GetImage( int index ) const { if ( index < 0 || index > image_buffer_count ) { - index = shared_images->last_write_index; + index = shared_data->last_write_index; } Snapshot *snap = &image_buffer[index]; Image *image = snap->image; @@ -278,30 +206,34 @@ struct timeval Monitor::GetTimestamp( int index ) const { if ( index < 0 || index > image_buffer_count ) { - index = shared_images->last_write_index; + index = shared_data->last_write_index; } + + Info(( "Index %d = %x", index, image_buffer[index].timestamp )); + Info(( "Timestamp %d.%d", image_buffer[index].timestamp->tv_sec, image_buffer[index].timestamp->tv_usec )); + Snapshot *snap = &image_buffer[index]; return( *(snap->timestamp) ); } unsigned int Monitor::GetLastReadIndex() const { - return( shared_images->last_read_index ); + return( shared_data->last_read_index ); } unsigned int Monitor::GetLastWriteIndex() const { - return( shared_images->last_write_index ); + return( shared_data->last_write_index ); } unsigned int Monitor::GetLastEvent() const { - return( shared_images->last_event ); + return( shared_data->last_event ); } double Monitor::GetFPS() const { - int index1 = shared_images->last_write_index; + int index1 = shared_data->last_write_index; int index2 = (index1+1)%image_buffer_count; //Snapshot *snap1 = &image_buffer[index1]; @@ -318,22 +250,22 @@ double Monitor::GetFPS() const void Monitor::ForceAlarmOn() { - shared_images->force_state = FORCE_ON; + shared_data->force_state = FORCE_ON; } void Monitor::ForceAlarmOff() { - shared_images->force_state = FORCE_OFF; + shared_data->force_state = FORCE_OFF; } void Monitor::CancelForced() { - shared_images->force_state = FORCE_NEUTRAL; + shared_data->force_state = FORCE_NEUTRAL; } void Monitor::DumpZoneImage() { - int index = shared_images->last_write_index; + int index = shared_data->last_write_index; Snapshot *snap = &image_buffer[index]; Image *image = snap->image; @@ -380,7 +312,7 @@ void Monitor::DumpImage( Image *image ) const bool Monitor::Analyse() { - if ( shared_images->last_read_index == shared_images->last_write_index ) + if ( shared_data->last_read_index == shared_data->last_write_index ) { return( false ); } @@ -398,7 +330,7 @@ bool Monitor::Analyse() int index; if ( ZM_OPT_ADAPTIVE_SKIP ) { - int read_margin = shared_images->last_read_index - shared_images->last_write_index; + 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; @@ -407,13 +339,13 @@ bool Monitor::Analyse() step = (9*image_buffer_count)/(5*read_margin); } - int pending_frames = shared_images->last_write_index - shared_images->last_read_index; + int pending_frames = shared_data->last_write_index - shared_data->last_read_index; if ( pending_frames < 0 ) pending_frames += image_buffer_count; - Debug( 1, ( "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_images->last_read_index, shared_images->last_write_index, pending_frames, read_margin, step )); + Debug( 1, ( "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_images->last_read_index+step)%image_buffer_count; + index = (shared_data->last_read_index+step)%image_buffer_count; } else { @@ -421,12 +353,12 @@ bool Monitor::Analyse() { Warning(( "Approaching buffer overrun, consider increasing ring buffer size" )); } - index = shared_images->last_write_index%image_buffer_count; + index = shared_data->last_write_index%image_buffer_count; } } else { - index = shared_images->last_write_index%image_buffer_count; + index = shared_data->last_write_index%image_buffer_count; } Snapshot *snap = &image_buffer[index]; @@ -436,9 +368,9 @@ bool Monitor::Analyse() unsigned int score = 0; if ( Ready() ) { - if ( shared_images->force_state != FORCE_OFF ) + if ( shared_data->force_state != FORCE_OFF ) score = Compare( *image ); - if ( shared_images->force_state == FORCE_ON ) + if ( shared_data->force_state == FORCE_ON ) score = ZM_FORCED_ALARM_SCORE; if ( score ) @@ -461,23 +393,23 @@ bool Monitor::Analyse() event->AddFrames( pre_event_count, timestamps, images ); //event->AddFrame( now, &image ); } - shared_images->state = state = ALARM; + shared_data->state = state = ALARM; last_alarm_count = image_count; } else { if ( state == ALARM ) { - shared_images->state = state = ALERT; + 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() )); - shared_images->last_event = event->Id(); + shared_data->last_event = event->Id(); delete event; - shared_images->state = state = IDLE; + shared_data->state = state = IDLE; } } } @@ -512,7 +444,7 @@ bool Monitor::Analyse() //DumpImage( image ); } - shared_images->last_read_index = index%image_buffer_count; + shared_data->last_read_index = index%image_buffer_count; image_count++; return( true ); @@ -530,7 +462,7 @@ void Monitor::ReloadZones() DumpZoneImage(); } -int Monitor::Load( int device, Monitor **&monitors, bool capture ) +int Monitor::Load( int device, Monitor **&monitors, Mode mode ) { static char sql[256]; if ( device == -1 ) @@ -559,7 +491,7 @@ int Monitor::Load( int device, Monitor **&monitors, bool capture ) monitors = new Monitor *[n_monitors]; for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) { - monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), atoi(dbrow[9]), dbrow[10], Coord( atoi(dbrow[11]), atoi(dbrow[12]) ), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atof(dbrow[17])>0.0?int(DT_PREC_3/atof(dbrow[17])):0, atoi(dbrow[18]), atoi(dbrow[19]), capture ); + monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), atoi(dbrow[9]), dbrow[10], Coord( atoi(dbrow[11]), atoi(dbrow[12]) ), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atof(dbrow[17])>0.0?int(DT_PREC_3/atof(dbrow[17])):0, atoi(dbrow[18]), atoi(dbrow[19]), mode ); Zone **zones = 0; int n_zones = Zone::Load( monitors[i], zones ); monitors[i]->AddZones( n_zones, zones ); @@ -576,7 +508,7 @@ int Monitor::Load( int device, Monitor **&monitors, bool capture ) return( n_monitors ); } -int Monitor::Load( const char *host, const char*port, const char *path, Monitor **&monitors, bool capture ) +int Monitor::Load( const char *host, const char*port, const char *path, Monitor **&monitors, Mode mode ) { static char sql[256]; if ( !host ) @@ -605,7 +537,7 @@ int Monitor::Load( const char *host, const char*port, const char *path, Monitor monitors = new Monitor *[n_monitors]; for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) { - monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), dbrow[3], dbrow[4], dbrow[5], atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), atoi(dbrow[9]), dbrow[10], Coord( atoi(dbrow[11]), atoi(dbrow[12]) ), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atof(dbrow[17])>0.0?int(DT_PREC_3/atof(dbrow[17])):0, atoi(dbrow[18]), atoi(dbrow[19]), capture ); + monitors[i] = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[2]), dbrow[3], dbrow[4], dbrow[5], atoi(dbrow[6]), atoi(dbrow[7]), atoi(dbrow[8]), atoi(dbrow[9]), dbrow[10], Coord( atoi(dbrow[11]), atoi(dbrow[12]) ), atoi(dbrow[13]), atoi(dbrow[14]), atoi(dbrow[15]), atoi(dbrow[16]), atof(dbrow[17])>0.0?int(DT_PREC_3/atof(dbrow[17])):0, atoi(dbrow[18]), atoi(dbrow[19]), mode ); Zone **zones = 0; int n_zones = Zone::Load( monitors[i], zones ); monitors[i]->AddZones( n_zones, zones ); @@ -622,7 +554,7 @@ int Monitor::Load( const char *host, const char*port, const char *path, Monitor return( n_monitors ); } -Monitor *Monitor::Load( int id, bool load_zones ) +Monitor *Monitor::Load( int id, bool load_zones, Mode mode ) { static char sql[256]; sprintf( sql, "select Id, Name, Type, Function+0, Device, Channel, Format, Host, Port, Path, Width, Height, Palette, Orientation+0, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, MaxFPS, FPSReportInterval, RefBlendPerc from Monitors where Id = %d", id ); @@ -645,11 +577,11 @@ Monitor *Monitor::Load( int id, bool load_zones ) { if ( !strcmp( dbrow[2], "Local" ) ) { - monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[10]), atoi(dbrow[11]), atoi(dbrow[12]), atoi(dbrow[13]), dbrow[14], Coord( atoi(dbrow[15]), atoi(dbrow[16]) ), atoi(dbrow[17]), atoi(dbrow[18]), atoi(dbrow[19]), atoi(dbrow[20]), atof(dbrow[21])>0.0?int(DT_PREC_3/atof(dbrow[21])):0, atoi(dbrow[22]), atoi(dbrow[23]), false ); + monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[3]), atoi(dbrow[4]), atoi(dbrow[5]), atoi(dbrow[6]), atoi(dbrow[10]), atoi(dbrow[11]), atoi(dbrow[12]), atoi(dbrow[13]), dbrow[14], Coord( atoi(dbrow[15]), atoi(dbrow[16]) ), atoi(dbrow[17]), atoi(dbrow[18]), atoi(dbrow[19]), atoi(dbrow[20]), atof(dbrow[21])>0.0?int(DT_PREC_3/atof(dbrow[21])):0, atoi(dbrow[22]), atoi(dbrow[23]), mode ); } else { - monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[3]), dbrow[7], dbrow[8], dbrow[9], atoi(dbrow[10]), atoi(dbrow[11]), atoi(dbrow[12]), atoi(dbrow[13]), dbrow[14], Coord( atoi(dbrow[15]), atoi(dbrow[16]) ), atoi(dbrow[17]), atoi(dbrow[18]), atoi(dbrow[19]), atoi(dbrow[20]), atof(dbrow[21])>0.0?int(DT_PREC_3/atof(dbrow[21])):0, atoi(dbrow[22]), atoi(dbrow[23]), false ); + monitor = new Monitor( atoi(dbrow[0]), dbrow[1], atoi(dbrow[3]), dbrow[7], dbrow[8], dbrow[9], atoi(dbrow[10]), atoi(dbrow[11]), atoi(dbrow[12]), atoi(dbrow[13]), dbrow[14], Coord( atoi(dbrow[15]), atoi(dbrow[16]) ), atoi(dbrow[17]), atoi(dbrow[18]), atoi(dbrow[19]), atoi(dbrow[20]), atof(dbrow[21])>0.0?int(DT_PREC_3/atof(dbrow[21])):0, atoi(dbrow[22]), atoi(dbrow[23]), mode ); } int n_zones = 0; if ( load_zones ) @@ -693,11 +625,11 @@ void Monitor::StreamImages( unsigned long idle, unsigned long refresh, FILE *fd, { break; } - if ( last_read_index != shared_images->last_write_index ) + if ( last_read_index != shared_data->last_write_index ) { // Send the next frame - last_read_index = shared_images->last_write_index; - int index = shared_images->last_write_index%image_buffer_count; + last_read_index = shared_data->last_write_index; + int index = shared_data->last_write_index%image_buffer_count; //Info(( "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer )); Snapshot *snap = &image_buffer[index]; Image *image = snap->image; @@ -708,7 +640,7 @@ void Monitor::StreamImages( unsigned long idle, unsigned long refresh, FILE *fd, fprintf( fd, "\n--ZoneMinderFrame\n" ); } usleep( refresh*1000 ); - for ( int i = 0; shared_images->state == IDLE && i < loop_count; i++ ) + for ( int i = 0; shared_data->state == IDLE && i < loop_count; i++ ) { usleep( refresh*1000 ); } diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 5b9049258..48fb91203 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -36,6 +36,13 @@ static struct timezone dummy_tz; // To avoid declaring pointless one each time w class Monitor { public: + typedef enum + { + QUERY=0, + CAPTURE, + ANALYSIS + } Mode; + typedef enum { NONE=1, @@ -94,6 +101,7 @@ protected: typedef struct { + bool valid; State state; int last_write_index; int last_read_index; @@ -101,21 +109,28 @@ protected: ForceState force_state; struct timeval *timestamps; unsigned char *images; - } SharedImages; + } SharedData; - SharedImages *shared_images; + SharedData *shared_data; bool record_event_stats; Camera *camera; public: - Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_capture, int p_n_zones=0, Zone *p_zones[]=0 ); - Monitor( int p_id, char *p_name, int p_function, const char *p_host, const char *p_port, const char *p_path, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_capture, int p_n_zones=0, Zone *p_zones[]=0 ); + Monitor( int p_id, char *p_name, int p_function, int p_device, int p_channel, int p_format, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, Mode p_mode=QUERY, int p_n_zones=0, Zone *p_zones[]=0 ); + Monitor( int p_id, char *p_name, int p_function, const char *p_host, const char *p_port, const char *p_path, int p_width, int p_height, int p_palette, int p_orientation, 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_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, Mode p_mode=QUERY, int p_n_zones=0, Zone *p_zones[]=0 ); ~Monitor(); + void Initialise( Mode mode ); + void AddZones( int p_n_zones, Zone *p_zones[] ); + inline int ShmValid() const + { + return( shared_data->valid ); + } + inline int Id() const { return( id ); @@ -168,14 +183,14 @@ public: int index = image_count%image_buffer_count; - if ( index == shared_images->last_read_index && function == ACTIVE ) + if ( index == shared_data->last_read_index && function == ACTIVE ) { Warning(( "Buffer overrun at index %d\n", index )); } gettimeofday( image_buffer[index].timestamp, &dummy_tz ); image_buffer[index].image->CopyBuffer( image ); - shared_images->last_write_index = index; + shared_data->last_write_index = index; image_count++; @@ -185,6 +200,7 @@ public: Info(( "%s: %d - Capturing at %.2f fps", name, image_count, fps )); last_fps_time = now; } + sleep( 2 ); return( 0 ); } return( -1 ); @@ -205,9 +221,9 @@ public: unsigned int Compare( const Image &image ); void ReloadZones(); - static int Load( int device, Monitor **&monitors, bool capture=true ); - static int Load( const char *host, const char*port, const char*path, Monitor **&monitors, bool capture=true ); - static Monitor *Load( int id, bool load_zones=false ); + static int Load( int device, Monitor **&monitors, Mode mode=QUERY ); + static int Load( const char *host, const char*port, const char*path, Monitor **&monitors, Mode mode=QUERY ); + static Monitor *Load( int id, bool load_zones=false, Mode mode=QUERY ); void StreamImages( unsigned long idle=5000, unsigned long refresh=50, FILE *fd=stdout, time_t ttl=0 ); }; diff --git a/src/zma.cpp b/src/zma.cpp index f5f8dc505..cfb0cc44c 100644 --- a/src/zma.cpp +++ b/src/zma.cpp @@ -106,7 +106,7 @@ int main( int argc, char *argv[] ) zmDbConnect( ZM_DB_USERA, ZM_DB_PASSA ); - Monitor *monitor = Monitor::Load( id, true ); + Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS ); if ( monitor ) { diff --git a/src/zmc.cpp b/src/zmc.cpp index fcaec534b..db73ac90b 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -137,13 +137,13 @@ int main( int argc, char *argv[] ) int n_monitors = 0; if ( device >= 0 ) { - n_monitors = Monitor::Load( device, monitors ); + n_monitors = Monitor::Load( device, monitors, Monitor::CAPTURE ); } else { if ( !port ) port = "80"; - n_monitors = Monitor::Load( host, port, path, monitors ); + n_monitors = Monitor::Load( host, port, path, monitors, Monitor::CAPTURE ); } if ( !n_monitors )