From dcf7c4fdded8aa5fd49d23db60bfa32ae9cc5c58 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 9 Mar 2018 07:23:40 -0500 Subject: [PATCH] rework loading Monitor using consistent db query --- src/zm_monitor.cpp | 1513 ++++++++++++++------------------------------ src/zm_monitor.h | 56 +- 2 files changed, 489 insertions(+), 1080 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 164376100..53e75d9d3 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1,21 +1,21 @@ // // ZoneMinder Monitor Class Implementation, $Date$, $Revision$ // Copyright (C) 2001-2008 Philip Coombes -// +// // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// +// #include #include @@ -63,6 +63,32 @@ #define MAP_LOCKED 0 #endif +// This is the official SQL (and ordering of the fields) to load a Monitor. +// It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended +std::string load_monitor_sql = +"SELECT Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, " +"AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS," +"Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings +"Protocol, Method, Options, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, " +"SaveJPEGs, VideoWriter, EncoderParameters, " +//" OutputCodec, Encoder, OutputContainer, " +"RecordAudio, " +"Brightness, Contrast, Hue, Colour, " +"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize," +"ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, " +"SectionLength, FrameSkip, MotionFrameSkip, " +"FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, SignalCheckColour FROM Monitors"; + +std::string CameraType_Strings[] = { + "Local", + "Remote", + "File", + "Ffmpeg", + "LibVLC", + "CURL", +}; + + std::vector split(const std::string &s, char delim) { std::vector elems; std::stringstream ss(s); @@ -292,7 +318,7 @@ Monitor::Monitor( height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), orientation( (Orientation)p_orientation ), deinterlacing( p_deinterlacing ), - savejpegspref( p_savejpegs ), + savejpegs( p_savejpegs ), videowriter( p_videowriter ), encoderparams( p_encoderparams ), record_audio( p_record_audio ), @@ -390,24 +416,25 @@ Monitor::Monitor( // Should maybe store this for later use char monitor_dir[PATH_MAX] = ""; snprintf( monitor_dir, sizeof(monitor_dir), "%s/%d", storage->Path(), id ); - struct stat statbuf; - - if ( stat( monitor_dir, &statbuf ) ) { - if ( errno == ENOENT || errno == ENOTDIR ) { - if ( mkdir( monitor_dir, 0755 ) ) { - Error( "Can't mkdir %s: %s", monitor_dir, strerror(errno)); - } - } else { - Warning( "Error stat'ing %s, may be fatal. error is %s", monitor_dir, strerror(errno)); - } - } if ( purpose == CAPTURE ) { + struct stat statbuf; + + if ( stat(monitor_dir, &statbuf) ) { + if ( errno == ENOENT || errno == ENOTDIR ) { + if ( mkdir(monitor_dir, 0755) ) { + Error("Can't mkdir %s: %s", monitor_dir, strerror(errno)); + } + } else { + Warning("Error stat'ing %s, may be fatal. error is %s", monitor_dir, strerror(errno)); + } + } if ( ! this->connect() ) { Error("unable to connect, but doing capture"); exit(-1); } + memset( mem_ptr, 0, mem_size ); shared_data->size = sizeof(SharedData); shared_data->active = enabled; @@ -447,20 +474,11 @@ Monitor::Monitor( if ( ( ! mem_ptr ) || ! shared_data->valid ) { if ( purpose != QUERY ) { - Error( "Shared data not initialised by capture daemon for monitor %s", name ); - exit( -1 ); + Error("Shared data not initialised by capture daemon for monitor %s", name); + exit(-1); } } - // Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after.. - // In my storage areas branch, I took this out.. and didn't notice any problems. - if ( false && !n_zones ) { - Debug( 1, "Monitor %s has no zones, adding one.", name ); - n_zones = 1; - zones = new Zone *[1]; - Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) }; - 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; @@ -477,11 +495,11 @@ Monitor::Monitor( if ( purpose == ANALYSIS ) { Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_index, shared_data->last_write_time ); - while( + while( ( shared_data->last_write_index == (unsigned int)image_buffer_count ) && - ( shared_data->last_write_time == 0 ) - && + ( shared_data->last_write_time == 0 ) + && ( !zm_terminate ) ) { Debug(1, "Waiting for capture daemon"); @@ -494,8 +512,320 @@ Debug(2,"last_write_index(%d), last_write_time(%d)", shared_data->last_write_ind } } // Monitor::Monitor +/* + std::string load_monitor_sql = + "SELECT Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, " + "AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS," + "Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings + "Protocol, Method, Options, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, " + "SaveJPEGs, VideoWriter, EncoderParameters, +"OutputCodec, Encoder, OutputContainer," +" RecordAudio, " + "Brightness, Contrast, Hue, Colour, " + "EventPrefix, LabelFormat, LabelX, LabelY, LabelSize," + "ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, " + "SectionLength, FrameSkip, MotionFrameSkip, " + "FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif, SignalCheckColour FROM Monitors"; +*/ + +Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + int storage_id = atoi(dbrow[col]); col++; + std::string type = dbrow[col] ? dbrow[col] : ""; col++; + Function function = (Function)atoi(dbrow[col]); col++; + int enabled = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + const char *linked_monitors = dbrow[col];col++; + + double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; + unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); + double capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + unsigned int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + + const char *device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + bool v4l_multi_buffer = config.v4l_multi_buffer; + if ( dbrow[col] ) { + if (*dbrow[col] == '0' ) { + v4l_multi_buffer = false; + } else if ( *dbrow[col] == '1' ) { + v4l_multi_buffer = true; + } + } + col++; + + int v4l_captures_per_frame = 0; + if ( dbrow[col] ) { + v4l_captures_per_frame = atoi(dbrow[col]); + } else { + v4l_captures_per_frame = config.captures_per_frame; + } + Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); + col++; + + std::string protocol = dbrow[col] ? dbrow[col] : ""; col++; + std::string method = dbrow[col] ? dbrow[col] : ""; col++; + std::string options = dbrow[col] ? dbrow[col] : ""; col++; + std::string host = dbrow[col] ? dbrow[col] : ""; col++; + std::string port = dbrow[col] ? dbrow[col] : ""; col++; + std::string path = dbrow[col] ? dbrow[col] : ""; col++; + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + int deinterlacing = atoi(dbrow[col]); col++; + bool rtsp_describe = (dbrow[col] && *dbrow[col] != '0'); col++; + + int savejpegs = atoi(dbrow[col]); col++; + VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; + const char *encoderparams = dbrow[col] ? dbrow[col] : ""; col++; + bool record_audio = (*dbrow[col] != '0'); 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 ++; + Coord label_coord = Coord( atoi(dbrow[col]), atoi(dbrow[col+1]) ); col += 2; + int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int signal_check_color = strtol(dbrow[col][0] == '#' ? dbrow[col]+1 : dbrow[col], 0, 16); col++; + bool embed_exif = (*dbrow[col] != '0'); col++; + + Camera *camera = 0; + if ( type == "Local" ) { + + int extras = (deinterlacing>>24)&0xff; + + camera = new LocalCamera( + id, + device, + channel, + format, + v4l_multi_buffer, + v4l_captures_per_frame, + method, + width, + height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio, + extras + ); + } else if ( type == "Remote" ) { + if ( protocol == "http" ) { + camera = new RemoteCameraHttp( + id, + method, + host, + port, + path, + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); + } +#if HAVE_LIBAVFORMAT + else if ( protocol == "rtsp" ) { + camera = new RemoteCameraRtsp( + id, + method, + host, // Host + port, // Port + path, // Path + width, + height, + rtsp_describe, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); + } +#endif // HAVE_LIBAVFORMAT + else { + Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); + } + } else if ( type == "File" ) { + camera = new FileCamera( + id, + path.c_str(), + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); + } else if ( type == "Ffmpeg" ) { +#if HAVE_LIBAVFORMAT + camera = new FfmpegCamera( + id, + path, + method, + options, + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); +#endif // HAVE_LIBAVFORMAT + } else if ( type == "NVSocket" ) { + camera = new RemoteCameraNVSocket( + id, + host.c_str(), + port.c_str(), + path.c_str(), + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); + } else if ( type == "Libvlc" ) { +#if HAVE_LIBVLC + camera = new LibvlcCamera( + id, + path.c_str(), + method, + options, + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); +#else // HAVE_LIBVLC + Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); +#endif // HAVE_LIBVLC + } else if ( type == "cURL" ) { +#if HAVE_LIBCURL + camera = new cURLCamera( + id, + path.c_str(), + user.c_str(), + pass.c_str(), + width, + height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + record_audio + ); +#else // HAVE_LIBCURL + Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); +#endif // HAVE_LIBCURL + } else { + Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); + } // end if type + + Monitor *monitor = new Monitor( + id, + name, + server_id, + storage_id, + (int)function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + savejpegs, + videowriter, + encoderparams, + record_audio, + event_prefix, + label_format, + label_coord, + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + signal_check_color, + embed_exif, + purpose, + 0, + 0 + ); + camera->setMonitor(monitor); + Zone **zones = 0; + int n_zones = Zone::Load(monitor, zones); + monitor->AddZones(n_zones, zones); + monitor->AddPrivacyBitmask(zones); + Debug(1, "Loaded monitor %d(%s), %d zones", id, name, n_zones); + return monitor; +} + bool Monitor::connect() { - Debug(3, "Connecting to monitor. Purpose is %d", purpose ); + Debug(3, "Connecting to monitor. Purpose is %d", purpose ); #if ZM_MEM_MAPPED snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", staticConfig.PATH_MAP.c_str(), id ); map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); @@ -565,7 +895,7 @@ bool Monitor::connect() { struct timeval *shared_timestamps = (struct timeval *)((char *)video_store_data + sizeof(VideoStoreData)); unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); - + if ( ((unsigned long)shared_images % 64) != 0 ) { /* Align images buffer to nearest 64 byte boundary */ Debug(3,"Aligning shared memory images to the next 64 byte boundary"); @@ -1081,7 +1411,7 @@ void Monitor::DumpZoneImage( const char *zone_string ) { if(zone_image->Colours() == ZM_COLOUR_GRAY8) { zone_image->Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); } - + for( int i = 0; i < n_zones; i++ ) { if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zones[i]->Id() == exclude_id ) continue; @@ -1134,7 +1464,7 @@ bool Monitor::CheckSignal( const Image *image ) { static uint8_t red_val; static uint8_t green_val; static uint8_t blue_val; - static uint8_t grayscale_val; /* 8bit grayscale color */ + static uint8_t grayscale_val; /* 8bit grayscale color */ static Rgb colour_val; /* RGB32 color */ static int usedsubpixorder; @@ -1165,7 +1495,7 @@ bool Monitor::CheckSignal( const Image *image ) { if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width ) break; } - + if(colours == ZM_COLOUR_GRAY8) { if ( *(buffer+index) != grayscale_val ) return true; @@ -1313,7 +1643,7 @@ bool Monitor::Analyse() { bool signal_change = (signal != last_signal); Debug(3, "Motion detection is enabled signal(%d) signal_change(%d)", signal, signal_change); - + if ( trigger_data->trigger_state != TRIGGER_OFF ) { unsigned int score = 0; if ( Ready() ) { @@ -1408,14 +1738,14 @@ bool Monitor::Analyse() { if ( noteSet.size() > 0 ) noteSetMap[LINKED_CAUSE] = noteSet; } - + //TODO: What happens is the event closes and sets recording to false then recording to true again so quickly that our capture daemon never picks it up. Maybe need a refresh flag? if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) { if ( event ) { //TODO: We shouldn't have to do this every time. Not sure why it clears itself if this isn't here?? //snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile()); Debug( 3, "Detected new event at (%d.%d)", timestamp->tv_sec,timestamp->tv_usec ); - + if ( section_length ) { // TODO: Wouldn't this be clearer if we just did something like if now - event->start > section_length ? int section_mod = timestamp->tv_sec % section_length; @@ -1661,7 +1991,7 @@ bool Monitor::Analyse() { //Video Storage: activate only for supported cameras. Event::AddFrame knows whether or not we are recording video and saves frames accordingly //if((GetOptVideoWriter() == 2) && camera->SupportsNativeVideo()) { // I don't think this is required, and causes problems, as the event file hasn't been setup yet. - //Warning("In state TAPE, + //Warning("In state TAPE, //video_store_data->recording = event->StartTime(); //} if ( !(image_count%(frame_skip+1)) ) { @@ -1733,7 +2063,7 @@ void Monitor::Reload() { } int n_monitors = mysql_num_rows( result ); if ( n_monitors != 1 ) { - Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); + Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); return; } @@ -1773,7 +2103,7 @@ void Monitor::Reload() { ref_blend_perc = atoi(dbrow[index++]); alarm_ref_blend_perc = atoi(dbrow[index++]); track_motion = atoi(dbrow[index++]); - + if ( dbrow[index][0] == '#' ) signal_check_colour = strtol(dbrow[index]+1,0,16); @@ -1894,1011 +2224,90 @@ void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) { } } -#if ZM_HAS_V4L -int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'"; -; - if ( device[0] ) { - sql += " AND Device='"; - sql += device; - sql += "'"; - } - if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - Debug( 1, "Loading Local Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); +int Monitor::LoadMonitors(std::string sql, Monitor **&monitors, Purpose purpose) { + + Debug(1, "Loading Monitors with %s", sql.c_str()); + + MYSQL_RES *result = zmDbFetch(sql.c_str()); if ( !result ) { - Error( "Can't load local monitors: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + Error("Can't load local monitors: %s", mysql_error(&dbconn)); + return 0; } - int n_monitors = mysql_num_rows( result ); + 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++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - unsigned int storage_id = atoi(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++; - bool v4l_multi_buffer = config.v4l_multi_buffer; - if ( dbrow[col] ) { - if (*dbrow[col] == '0' ) { - v4l_multi_buffer = false; - } else if ( *dbrow[col] == '1' ) { - v4l_multi_buffer = true; - } - } - col++; - - int v4l_captures_per_frame = 0; - if ( dbrow[col] ) { - v4l_captures_per_frame = atoi(dbrow[col]); - } else { - v4l_captures_per_frame = config.captures_per_frame; - } - Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); - col++; - const char *method = dbrow[col] ? dbrow[col] : ""; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - - int savejpegs = atoi(dbrow[col]); col++; - VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; - bool record_audio = (*dbrow[col] != '0'); 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] ? dbrow[col] : ""; col++; - const char *label_format = dbrow[col] ? dbrow[col] : ""; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - 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 alarm_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); - else - signal_check_colour = strtol(dbrow[col],0,16); - col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int extras = (deinterlacing>>24)&0xff; - - Camera *camera = new LocalCamera( - id, - device, - channel, - format, - v4l_multi_buffer, - v4l_captures_per_frame, - method, - width, - height, - colours, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio, - extras - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - storage_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - savejpegs, - videowriter, - encoderparams, - record_audio, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - signal_check_colour, - embed_exif, - purpose, - 0, - 0 - ); - camera->setMonitor( monitors[i] ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + for( int i=0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) { + monitors[i] = Monitor::Load(dbrow, 1, purpose); } - if ( mysql_errno( &dbconn ) ) { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + if ( mysql_errno(&dbconn) ) { + Error("Can't fetch row: %s", mysql_error(&dbconn)); + return 0; } - // Yadda yadda - mysql_free_result( result ); + mysql_free_result(result); - return( n_monitors ); + return n_monitors; +} + +#if ZM_HAS_V4L +int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { + + std::string sql = load_monitor_sql + " WHERE Function != 'None' AND Type = 'Local'"; + + if ( device[0] ) + sql += " AND Device='" + std::string(device) + "'"; + if ( staticConfig.SERVER_ID ) + sql += stringtf(" AND ServerId=%d", staticConfig.SERVER_ID); + return LoadMonitors(sql, monitors, purpose); } #endif // ZM_HAS_V4L int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'"; - if ( staticConfig.SERVER_ID ) { + std::string sql = load_monitor_sql + " WHERE Function != 'None' AND Type = 'Remote'"; + if ( staticConfig.SERVER_ID ) sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - if ( protocol ) { + if ( protocol ) sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); - } - - Debug( 1, "Loading Remote Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - 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++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - unsigned int storage_id = atoi(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] ? dbrow[col] : ""; col++; - std::string method = dbrow[col] ? dbrow[col] : ""; col++; - std::string host = dbrow[col] ? dbrow[col] : ""; col++; - std::string port = dbrow[col] ? dbrow[col] : ""; col++; - std::string path = dbrow[col] ? dbrow[col] : ""; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - bool rtsp_describe = (dbrow[col] && *dbrow[col] != '0'); col++; - int savejpegs = atoi(dbrow[col]); col++; - VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; - bool record_audio = (*dbrow[col] != '0'); 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] ? dbrow[col] : ""; col++; - const char *label_format = dbrow[col] ? dbrow[col] : ""; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - 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 alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - Camera *camera = 0; - if ( protocol == "http" ) { - camera = new RemoteCameraHttp( - id, - method, - host, // Host - port, // Port - path, // Path - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - } -#if HAVE_LIBAVFORMAT - else if ( protocol == "rtsp" ) { - camera = new RemoteCameraRtsp( - id, - method, - host, // Host - port, // Port - path, // Path - width, - height, - rtsp_describe, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - } -#endif // HAVE_LIBAVFORMAT - else { - Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); - } - - monitors[i] = new Monitor( - id, - name.c_str(), - server_id, - storage_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - savejpegs, - videowriter, - encoderparams, - record_audio, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - RGB_WHITE, - embed_exif, - purpose, - 0, - 0 - ); - camera->setMonitor( monitors[i] ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( 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 LoadMonitors(sql, monitors, purpose); } int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'"; - if ( file[0] ) { - sql += " AND Path='"; - sql += file; - sql += "'"; - } + std::string sql = load_monitor_sql + " WHERE Function != 'None' AND Type = 'File'"; + if ( file[0] ) + sql += " AND Path='" + std::string(file) + "'"; if ( staticConfig.SERVER_ID ) { sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); } - Debug( 1, "Loading File Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - 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++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - unsigned int storage_id = atoi(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++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - - int savejpegs = atoi(dbrow[col]); col++; - VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col]; col++; - bool record_audio = (*dbrow[col] != '0'); 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] ? dbrow[col] : ""; col++; - const char *label_format = dbrow[col] ? dbrow[col] : ""; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - 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 alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - Camera *camera = new FileCamera( - id, - path, // File - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - storage_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - savejpegs, - videowriter, - encoderparams, - record_audio, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - embed_exif, - RGB_WHITE, - purpose, - 0, - 0 - ); - camera->setMonitor( monitors[i] ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( 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 LoadMonitors(sql, monitors, purpose); } #if HAVE_LIBAVFORMAT -int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'"; - if ( file[0] ) { - sql += " AND Path = '"; - sql += file; - sql += "'"; - } +int Monitor::LoadFfmpegMonitors(const char *file, Monitor **&monitors, Purpose purpose) { + std::string sql = load_monitor_sql + " WHERE Function != 'None' AND Type = 'Ffmpeg'"; + if ( file[0] ) + sql += " AND Path = '" + std::string(file) + "'"; + if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); + sql += stringtf(" AND ServerId=%d", staticConfig.SERVER_ID); } - Debug( 1, "Loading FFMPEG Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - if ( ! result ) { - Error( "Cannot load FfmpegMonitors" ); - 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++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - unsigned int storage_id = atoi(dbrow[col]); col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col] ? dbrow[col] : ""; col++; - - const char *path = dbrow[col]; col++; - const char *method = dbrow[col] ? dbrow[col] : ""; col++; - const char *options = dbrow[col] ? dbrow[col] : ""; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - - int savejpegs = atoi(dbrow[col]); col++; - VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; - bool record_audio = (*dbrow[col] != '0'); 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] ? dbrow[col] : ""; col++; - const char *label_format = dbrow[col] ? dbrow[col] : ""; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; - - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - double capture_fps = dbrow[col] ? atof(dbrow[col]) : 0;col++; - int capture_delay = capture_fps >0.0 ?int(DT_PREC_3/capture_fps):0; - double alarm_capture_fps = dbrow[col] ? atof(dbrow[col]) : 0; col++; - int alarm_capture_delay = alarm_capture_fps > 0.0 ?int(DT_PREC_3/alarm_capture_fps):0; - - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - Camera *camera = new FfmpegCamera( - id, - path, // File - method, - options, - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - storage_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - savejpegs, - videowriter, - encoderparams, - record_audio, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - embed_exif, - RGB_WHITE, - purpose, - 0, - 0 - ); - - camera->setMonitor( monitors[i] ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( 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 LoadMonitors(sql, monitors, purpose); } #endif // HAVE_LIBAVFORMAT -Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { - std::string sql = stringtf( "select Id, Name, ServerId, StorageId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); +Monitor *Monitor::Load(unsigned int p_id, bool load_zones, Purpose purpose) { + std::string sql = load_monitor_sql + stringtf(" WHERE Id=%d", p_id); zmDbRow dbrow; - if ( ! dbrow.fetch( sql.c_str() ) ) { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + if ( ! dbrow.fetch(sql.c_str()) ) { + Error("Can't use query result: %s", mysql_error(&dbconn)); + return NULL; } - Monitor *monitor = 0; - unsigned int col = 0; + Monitor *monitor = Monitor::Load(dbrow.mysql_row(), load_zones, purpose); - unsigned int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - unsigned int storage_id = dbrow[col] ? atoi(dbrow[col]) : 0; 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] ? dbrow[col] : ""; col++; - - std::string device = dbrow[col] ? dbrow[col] : ""; col++; - int channel = atoi(dbrow[col]); col++; - int format = atoi(dbrow[col]); col++; - - bool v4l_multi_buffer = config.v4l_multi_buffer; - if ( dbrow[col] ) { - if (*dbrow[col] == '0' ) { - v4l_multi_buffer = false; - } else if ( *dbrow[col] == '1' ) { - v4l_multi_buffer = true; - } - } - col++; - - int v4l_captures_per_frame = 0; - if ( dbrow[col] ) { - v4l_captures_per_frame = atoi(dbrow[col]); - } else { - v4l_captures_per_frame = config.captures_per_frame; - } - Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); - col++; - - std::string protocol = dbrow[col] ? dbrow[col] : ""; col++; - std::string method = dbrow[col] ? dbrow[col] : ""; col++; - std::string host = dbrow[col] ? dbrow[col] : ""; col++; - std::string port = dbrow[col] ? dbrow[col] : ""; col++; - std::string path = dbrow[col] ? dbrow[col] : ""; col++; - std::string options = dbrow[col] ? dbrow[col] : ""; col++; - std::string user = dbrow[col] ? dbrow[col] : ""; col++; - std::string pass = dbrow[col] ? dbrow[col] : ""; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - bool rtsp_describe = (dbrow[col] && *dbrow[col] != '0'); col++; - int savejpegs = atoi(dbrow[col]); col++; - VideoWriter videowriter = (VideoWriter)atoi(dbrow[col]); col++; - std::string encoderparams = dbrow[col] ? dbrow[col] : ""; col++; - bool record_audio = (*dbrow[col] != '0'); 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] ? dbrow[col] : ""; col++; - const char * label_format = dbrow[col] ? dbrow[col] : ""; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = 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 motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - 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 alarm_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); - else - signal_check_colour = strtol(dbrow[col],0,16); - col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int extras = (deinterlacing>>24)&0xff; - - Camera *camera = 0; - if ( type == "Local" ) { -#if ZM_HAS_V4L - camera = new LocalCamera( - id, - device.c_str(), - channel, - format, - v4l_multi_buffer, - v4l_captures_per_frame, - method, - width, - height, - colours, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio, - extras - ); -#else // ZM_HAS_V4L - Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id ); -#endif // ZM_HAS_V4L - } else if ( type == "NVSocket" ) { - camera = new RemoteCameraNVSocket( - id, - host.c_str(), - port.c_str(), - path.c_str(), - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - } else if ( type == "Remote" ) { - if ( protocol == "http" ) { - camera = new RemoteCameraHttp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - } else if ( protocol == "rtsp" ) { -#if HAVE_LIBAVFORMAT - camera = new RemoteCameraRtsp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - width, - height, - rtsp_describe, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); -#else // HAVE_LIBAVFORMAT - 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( - id, - path.c_str(), - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); - } else if ( type == "Ffmpeg" ) { -#if HAVE_LIBAVFORMAT - camera = new FfmpegCamera( - id, - path.c_str(), - method, - options, - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); -#else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); -#endif // HAVE_LIBAVFORMAT - } else if (type == "Libvlc") { -#if HAVE_LIBVLC - camera = new LibvlcCamera( - id, - path.c_str(), - method, - options, - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); -#else // HAVE_LIBVLC - Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); -#endif // HAVE_LIBVLC - } else if ( type == "cURL" ) { -#if HAVE_LIBCURL - camera = new cURLCamera( - id, - path.c_str(), - user.c_str(), - pass.c_str(), - width, - height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - record_audio - ); -#else // HAVE_LIBCURL - Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); -#endif // HAVE_LIBCURL - } else { - Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); - } - monitor = new Monitor( - id, - name.c_str(), - server_id, - storage_id, - function, - enabled, - linked_monitors.c_str(), - camera, - orientation, - deinterlacing, - savejpegs, - videowriter, - encoderparams, - record_audio, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - signal_check_colour, - embed_exif, - purpose, - 0, - 0 - - ); - - camera->setMonitor( monitor ); - - int n_zones = 0; - if ( load_zones ) { - Zone **zones = 0; - n_zones = Zone::Load( monitor, zones ); - monitor->AddZones( n_zones, zones ); - monitor->AddPrivacyBitmask( zones ); - } - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - return( monitor ); -} + return monitor; +} // end Monitor *Monitor::Load(unsigned int p_id, bool load_zones, Purpose purpose) /* Returns 0 on success, even if no new images are available (transient error) * Returns -1 on failure. @@ -2915,11 +2324,11 @@ int Monitor::Capture() { if ( deinterlacing_value == 4 ) { if ( FirstCapture != 1 ) { /* Copy the next image into the shared memory */ - capture_image->CopyBuffer(*(next_buffer.image)); + capture_image->CopyBuffer(*(next_buffer.image)); } - + /* Capture a new next image */ - + //Check if FFMPEG camera // Icon: I don't think we can support de-interlacing on ffmpeg input.... most of the time it will be h264 or mpeg4 if ( ( videowriter == H264PASSTHROUGH ) && camera->SupportsNativeVideo() ) { @@ -2950,7 +2359,7 @@ int Monitor::Capture() { captureResult = camera->Capture(*capture_image); } } -Debug(4, "Return from Capture (%d)", captureResult); +Debug(4, "Return from Capture (%d)", captureResult); if ( captureResult < 0 ) { // Unable to capture image for temporary reason // Fake a signal loss image @@ -2958,7 +2367,7 @@ Debug(4, "Return from Capture (%d)", captureResult); signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ capture_image->Fill(signalcolor); } else if ( captureResult > 0 ) { - + /* Deinterlacing */ if ( deinterlacing_value == 1 ) { capture_image->Deinterlace_Discard(); @@ -2971,7 +2380,7 @@ Debug(4, "Return from Capture (%d)", captureResult); } else if ( deinterlacing_value == 5 ) { capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); } - + if ( orientation != ROTATE_0 ) { switch ( orientation ) { case ROTATE_0 : { @@ -3192,7 +2601,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z } else { zone->ClearAlarm(); } - } + } } } @@ -3277,7 +2686,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z // 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; @@ -3312,25 +2721,25 @@ bool Monitor::DumpSettings( char *output, bool verbose ) { sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); } #endif // ZM_HAS_V4L - sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); - sprintf( output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); - 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), "Label Size : %d\n", label_size ); - 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?(double)DT_PREC_3/capture_delay:0.0 ); - sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?(double)DT_PREC_3/alarm_capture_delay:0.0 ); - sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); - sprintf( output+strlen(output), "Alarm Reference Blend %%ge : %d\n", alarm_ref_blend_perc ); - sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); - sprintf( output+strlen(output), "Function: %d - %s\n", function, + sprintf(output+strlen(output), "Colours : %d\n", camera->Colours() ); + sprintf(output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); + 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), "Label Size : %d\n", label_size ); + 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?(double)DT_PREC_3/capture_delay:0.0); + sprintf(output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?(double)DT_PREC_3/alarm_capture_delay:0.0); + sprintf(output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc); + sprintf(output+strlen(output), "Alarm Reference Blend %%ge : %d\n", alarm_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":( @@ -3338,26 +2747,20 @@ bool Monitor::DumpSettings( char *output, bool verbose ) { 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 ); + sprintf(output+strlen(output), "Zones : %d\n", n_zones ); for ( int i = 0; i < n_zones; i++ ) { - zones[i]->DumpSettings( output+strlen(output), verbose ); + zones[i]->DumpSettings(output+strlen(output), verbose); } - return( true ); -} // bool Monitor::DumpSettings( char *output, bool verbose ) + return true; +} // bool Monitor::DumpSettings(char *output, bool verbose) -unsigned int Monitor::Colours() const { return( camera->Colours() ); } -unsigned int Monitor::SubpixelOrder() const { return( camera->SubpixelOrder() ); } -int Monitor::PrimeCapture() { - return( camera->PrimeCapture() ); -} -int Monitor::PreCapture() { - return( camera->PreCapture() ); -} -int Monitor::PostCapture() { - return( camera->PostCapture() ); -} +unsigned int Monitor::Colours() const { return camera->Colours(); } +unsigned int Monitor::SubpixelOrder() const { return camera->SubpixelOrder(); } +int Monitor::PrimeCapture() const { return camera->PrimeCapture(); } +int Monitor::PreCapture() const { return camera->PreCapture(); } +int Monitor::PostCapture() const { return camera->PostCapture() ; } Monitor::Orientation Monitor::getOrientation() const { return orientation; } -Monitor::Snapshot *Monitor::getSnapshot() { +Monitor::Snapshot *Monitor::getSnapshot() const { return &image_buffer[ shared_data->last_write_index%image_buffer_count ]; } diff --git a/src/zm_monitor.h b/src/zm_monitor.h index d18cd1c13..fee44aba2 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -67,6 +67,15 @@ public: NODECT } Function; + typedef enum { + LOCAL, + REMOTE, + FILE, + FFMPEG, + LIBVLC, + CURL, + } CameraType; + typedef enum { ROTATE_0=1, ROTATE_90, @@ -228,6 +237,7 @@ protected: char name[64]; unsigned int server_id; // Id of the Server object unsigned int storage_id; // Id of the Storage Object, which currently will just provide a path, but in future may do more. + CameraType type; Function function; // What the monitor is doing bool enabled; // Whether the monitor is enabled or asleep unsigned int width; // Normally the same as the camera, but not if partly rotated @@ -238,7 +248,7 @@ protected: unsigned int deinterlacing; bool videoRecording; - int savejpegspref; + int savejpegs; VideoWriter videowriter; std::string encoderparams; std::vector encoderparamsvec; @@ -330,8 +340,6 @@ protected: int n_linked_monitors; MonitorLink **linked_monitors; - // This is the official SQL (and ordering of the fields) to load a Monitor. It will be used whereever a Monitor dbrow is needed. WHERE conditions can be appended - std::string load_monitor_sql = "SELECT Id, Name, ServerId, StorageId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, SaveJPEGs, VideoWriter, EncoderParameters, OutputCodec, Encoder, OutputContainer, RecordAudio, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPSLimit, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors"; public: explicit Monitor( int p_id ); @@ -433,22 +441,22 @@ public: unsigned int Colours() const; unsigned int SubpixelOrder() const; - int GetOptSaveJPEGs() const { return( savejpegspref ); } - VideoWriter GetOptVideoWriter() const { return( videowriter ); } - const std::vector* GetOptEncoderParams() const { return( &encoderparamsvec ); } + int GetOptSaveJPEGs() const { return savejpegs; } + VideoWriter GetOptVideoWriter() const { return videowriter; } + const std::vector* GetOptEncoderParams() const { return &encoderparamsvec; } uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; } void SetVideoWriterEventId( uint32_t p_event_id ) { video_store_data->current_event = p_event_id; } unsigned int GetPreEventCount() const { return pre_event_count; }; State GetState() const; int GetImage( int index=-1, int scale=100 ); - Snapshot *getSnapshot(); + Snapshot *getSnapshot() const; struct timeval GetTimestamp( int index=-1 ) const; void UpdateAdaptiveSkip(); useconds_t GetAnalysisRate(); - unsigned int GetAnalysisUpdateDelay() const { return( analysis_update_delay ); } - int GetCaptureDelay() const { return( capture_delay ); } - int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } + unsigned int GetAnalysisUpdateDelay() const { return analysis_update_delay; } + int GetCaptureDelay() const { return capture_delay; } + int GetAlarmCaptureDelay() const { return alarm_capture_delay; } unsigned int GetLastReadIndex() const; unsigned int GetLastWriteIndex() const; uint32_t GetLastEventId() const; @@ -456,13 +464,9 @@ public: void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); void ForceAlarmOff(); void CancelForced(); - TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); } - inline time_t getStartupTime() const { - return( shared_data->startup_time ); - } - inline void setStartupTime( time_t p_time ) { - shared_data->startup_time = p_time; - } + TriggerState GetTriggerState() const { return (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL); } + inline time_t getStartupTime() const { return shared_data->startup_time; } + inline void setStartupTime( time_t p_time ) { shared_data->startup_time = p_time; } void actionReload(); void actionEnable(); @@ -475,10 +479,10 @@ public: int actionColour( int p_colour=-1 ); int actionContrast( int p_contrast=-1 ); - int PrimeCapture(); - int PreCapture(); + int PrimeCapture() const; + int PreCapture() const; int Capture(); - int PostCapture(); + int PostCapture() const; unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); // DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info. @@ -496,15 +500,17 @@ public: bool DumpSettings( char *output, bool verbose ); void DumpZoneImage( const char *zone_string=0 ); + static int LoadMonitors(std::string sql, Monitor **&monitors, Purpose purpose); // Returns # of Monitors loaded, 0 on failure. #if ZM_HAS_V4L - static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ); + static int LoadLocalMonitors(const char *device, Monitor **&monitors, Purpose purpose); #endif // ZM_HAS_V4L - static int LoadRemoteMonitors( const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose ); - static int LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ); + static int LoadRemoteMonitors(const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose); + static int LoadFileMonitors(const char *file, Monitor **&monitors, Purpose purpose); #if HAVE_LIBAVFORMAT - static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); + static int LoadFfmpegMonitors(const char *file, Monitor **&monitors, Purpose purpose); #endif // HAVE_LIBAVFORMAT - static Monitor *Load( unsigned int id, bool load_zones, Purpose purpose ); + static Monitor *Load(unsigned int id, bool load_zones, Purpose purpose); + static Monitor *Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose); //void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y ); //void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 ); //void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 );