Merge branch 'zma_to_thread' of github.com:ConnorTechnology/ZoneMinder into zma_to_thread
This commit is contained in:
commit
c7deb91319
|
@ -60,7 +60,6 @@ FOR EACH ROW
|
|||
//
|
||||
|
||||
|
||||
delimiter //
|
||||
DROP TRIGGER IF EXISTS Events_Week_delete_trigger//
|
||||
CREATE TRIGGER Events_Week_delete_trigger BEFORE DELETE ON Events_Week
|
||||
FOR EACH ROW BEGIN
|
||||
|
|
|
@ -457,7 +457,8 @@ CREATE TABLE `Monitors` (
|
|||
`Deinterlacing` int(10) unsigned NOT NULL default '0',
|
||||
`SaveJPEGs` TINYINT NOT NULL DEFAULT '3' ,
|
||||
`VideoWriter` TINYINT NOT NULL DEFAULT '0',
|
||||
`OutputCodec` enum('h264','mjpeg','mpeg1','mpeg2'),
|
||||
`OutputCodec` int(10) unsigned NOT NULL default 0,
|
||||
`Encoder` enum('auto','h264','h264_omx','mjpeg','mpeg1','mpeg2'),
|
||||
`OutputContainer` enum('auto','mp4','mkv'),
|
||||
`EncoderParameters` TEXT,
|
||||
`RecordAudio` TINYINT NOT NULL DEFAULT '0',
|
||||
|
|
|
@ -176,8 +176,10 @@ BEGIN
|
|||
WHERE Id=OLD.MonitorId;
|
||||
END IF;
|
||||
END IF;
|
||||
ELSEIF ( NEW.Archived AND diff ) THEN
|
||||
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
|
||||
ELSE
|
||||
IF ( NEW.Archived AND diff ) THEN
|
||||
UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
IF ( diff ) THEN
|
||||
|
@ -185,7 +187,6 @@ BEGIN
|
|||
END IF;
|
||||
|
||||
END;
|
||||
|
||||
//
|
||||
|
||||
delimiter ;
|
||||
|
|
|
@ -10,3 +10,18 @@ SET @s = (SELECT IF(
|
|||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
||||
|
||||
ALTER TABLE `Monitors` MODIFY `OutputCodec` int(10) UNSIGNED NOT NULL default 0;
|
||||
|
||||
SET @s = (SELECT IF(
|
||||
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
|
||||
AND table_name = 'Monitors'
|
||||
AND column_name = 'Encoder'
|
||||
) > 0,
|
||||
"SELECT 'Column Encoder already exists in Monitors'",
|
||||
"ALTER TABLE `Monitors` ADD `Encoder` enum('auto','h264','h264_omx','mjpeg','mpeg1','mpeg2') AFTER `OutputCodec`"
|
||||
));
|
||||
|
||||
PREPARE stmt FROM @s;
|
||||
EXECUTE stmt;
|
||||
|
|
|
@ -130,8 +130,8 @@ sub Execute {
|
|||
}
|
||||
|
||||
sub Sql {
|
||||
my $self = $_[0];
|
||||
$$self{Sql} = shift if @_;;
|
||||
my $self = shift;
|
||||
$$self{Sql} = shift if @_;
|
||||
if ( ! $$self{Sql} ) {
|
||||
my $filter_expr = ZoneMinder::General::jsonDecode($self->{Query});
|
||||
my $sql = 'SELECT E.*,
|
||||
|
|
|
@ -679,7 +679,7 @@ sub Dump {
|
|||
sub debug {
|
||||
my $log = shift;
|
||||
$log->logPrint(DEBUG, @_);
|
||||
}
|
||||
}
|
||||
|
||||
sub Debug( @ ) {
|
||||
fetch()->logPrint(DEBUG, @_);
|
||||
|
|
|
@ -98,6 +98,7 @@ Event::Event(
|
|||
monitor->GetOptSaveJPEGs(),
|
||||
storage->SchemeString().c_str()
|
||||
);
|
||||
|
||||
db_mutex.lock();
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't insert event: %s. sql was (%s)", mysql_error(&dbconn), sql);
|
||||
|
@ -192,7 +193,7 @@ Event::Event(
|
|||
if ( monitor->GetOptVideoWriter() != 0 ) {
|
||||
std::string container = monitor->OutputContainer();
|
||||
if ( container == "auto" || container == "" ) {
|
||||
if ( monitor->OutputCodec() == "h264" ) {
|
||||
if ( monitor->OutputCodec() == AV_CODEC_ID_H264 ) {
|
||||
container = "mp4";
|
||||
} else {
|
||||
container = "mkv";
|
||||
|
@ -414,7 +415,7 @@ void Event::AddFrames(int n_frames, Image **images, struct timeval **timestamps)
|
|||
|
||||
void Event::AddFramesInternal(int n_frames, int start_frame, Image **images, struct timeval **timestamps) {
|
||||
static char sql[ZM_SQL_LGE_BUFSIZ];
|
||||
strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) );
|
||||
strncpy(sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql));
|
||||
int frameCount = 0;
|
||||
for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ ) {
|
||||
if ( timestamps[i]->tv_sec <= 0 ) {
|
||||
|
|
|
@ -461,3 +461,15 @@ void dumpPacket(AVPacket *pkt, const char *text) {
|
|||
pkt->duration);
|
||||
Debug(2, "%s:%d:%s: %s", __FILE__, __LINE__, text, b);
|
||||
}
|
||||
|
||||
void zm_free_codec( AVCodecContext **ctx ) {
|
||||
if ( *ctx ) {
|
||||
avcodec_close(*ctx);
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
// We allocate and copy in newer ffmpeg, so need to free it
|
||||
avcodec_free_context(ctx);
|
||||
#endif
|
||||
*ctx = NULL;
|
||||
audio_in_codec = NULL;
|
||||
} // end if
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ int FfmpegCamera::Capture(ZMPacket &zm_packet) {
|
|||
|
||||
// If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread.
|
||||
|
||||
if ( (ret = av_read_frame(mFormatContext, &packet)) < 0 ) {
|
||||
if ( (ret = av_read_frame( mFormatContext, &packet )) < 0 ) {
|
||||
if (
|
||||
// Check if EOF.
|
||||
(ret == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) ||
|
||||
|
@ -476,6 +476,6 @@ int FfmpegCamera::CloseFfmpeg() {
|
|||
}
|
||||
|
||||
return 0;
|
||||
} // end FfmpegCamera::Close
|
||||
} // end int FfmpegCamera::CloseFfmpeg()
|
||||
|
||||
#endif // HAVE_LIBAVFORMAT
|
||||
|
|
|
@ -163,6 +163,4 @@ AVFrame *FFmpeg_Input::get_frame(int stream_id, int frame_number) {
|
|||
break;
|
||||
} // end while frame_number > streams.frame_count
|
||||
return frame;
|
||||
} // end AVFrame *FFmpeg_Input::get_frame
|
||||
|
||||
|
||||
} // end AVFrame *FFmpeg_Input::get_frame
|
||||
|
|
|
@ -2132,6 +2132,7 @@ AVStream *LocalCamera::get_VideoStream() {
|
|||
AVFormatContext *oc = avformat_alloc_context();
|
||||
video_stream = avformat_new_stream( oc, NULL );
|
||||
if ( video_stream ) {
|
||||
video_stream->time_base = (AVRational){1, 1000000}; // microseconds as base frame rate
|
||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||
video_stream->codecpar->width = width;
|
||||
video_stream->codecpar->height = height;
|
||||
|
|
|
@ -71,7 +71,7 @@ std::string load_monitor_sql =
|
|||
"Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, " // V4L Settings
|
||||
"Protocol, Method, Options, User, Pass, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, "
|
||||
"SaveJPEGs, VideoWriter, EncoderParameters, "
|
||||
"OutputCodec, OutputContainer, "
|
||||
"OutputCodec, Encoder, OutputContainer, "
|
||||
"RecordAudio, "
|
||||
"Brightness, Contrast, Hue, Colour, "
|
||||
"EventPrefix, LabelFormat, LabelX, LabelY, LabelSize,"
|
||||
|
@ -292,7 +292,7 @@ Monitor::Monitor()
|
|||
colours(0),
|
||||
videowriter(DISABLED),
|
||||
encoderparams(""),
|
||||
output_codec(""),
|
||||
output_codec(0),
|
||||
output_container(""),
|
||||
record_audio(0),
|
||||
//event_prefix
|
||||
|
@ -460,7 +460,8 @@ void Monitor::Load(MYSQL_ROW dbrow, bool load_zones=true, Purpose p = QUERY) {
|
|||
/* Parse encoder parameters */
|
||||
ParseEncoderParameters(encoderparams.c_str(), &encoderparamsvec);
|
||||
|
||||
output_codec = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
output_codec = dbrow[col] ? atoi(dbrow[col]) : 0; col++;
|
||||
encoder = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
output_container = dbrow[col] ? dbrow[col] : ""; col++;
|
||||
record_audio = (*dbrow[col] != '0'); col++;
|
||||
|
||||
|
@ -883,25 +884,7 @@ bool Monitor::connect() {
|
|||
} // Monitor::connect
|
||||
|
||||
Monitor::~Monitor() {
|
||||
if ( videoStore ) {
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
}
|
||||
delete packetqueue;
|
||||
packetqueue = NULL;
|
||||
|
||||
if ( timestamps ) {
|
||||
delete[] timestamps;
|
||||
timestamps = 0;
|
||||
}
|
||||
if ( images ) {
|
||||
delete[] images;
|
||||
images = 0;
|
||||
}
|
||||
if ( privacy_bitmask ) {
|
||||
delete[] privacy_bitmask;
|
||||
privacy_bitmask = NULL;
|
||||
}
|
||||
if ( mem_ptr ) {
|
||||
if ( event ) {
|
||||
Info( "%s: image_count:%d - Closing event %llu, shutting down", name, image_count, event->Id() );
|
||||
|
@ -914,12 +897,17 @@ Monitor::~Monitor() {
|
|||
event_delete_thread = NULL;
|
||||
}
|
||||
}
|
||||
if ( event_delete_thread ) {
|
||||
event_delete_thread->join();
|
||||
delete event_delete_thread;
|
||||
event_delete_thread = NULL;
|
||||
}
|
||||
|
||||
if ( deinterlacing_value == 4 ) {
|
||||
delete next_buffer.image;
|
||||
}
|
||||
#if 1
|
||||
for ( int i = 0; i < image_buffer_count; i++ ) {
|
||||
for ( int i=0; i < image_buffer_count; i++ ) {
|
||||
delete image_buffer[i].image;
|
||||
}
|
||||
#endif
|
||||
|
@ -932,15 +920,15 @@ Monitor::~Monitor() {
|
|||
shared_data->last_read_time = 0;
|
||||
} else if ( purpose == CAPTURE ) {
|
||||
shared_data->valid = false;
|
||||
memset( mem_ptr, 0, mem_size );
|
||||
memset(mem_ptr, 0, mem_size);
|
||||
}
|
||||
|
||||
#if ZM_MEM_MAPPED
|
||||
if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 )
|
||||
Error( "Can't msync: %s", strerror(errno) );
|
||||
if ( munmap( mem_ptr, mem_size ) < 0 )
|
||||
Fatal( "Can't munmap: %s", strerror(errno) );
|
||||
close( map_fd );
|
||||
if ( msync(mem_ptr, mem_size, MS_SYNC) < 0 )
|
||||
Error("Can't msync: %s", strerror(errno));
|
||||
if ( munmap(mem_ptr, mem_size) < 0 )
|
||||
Fatal("Can't munmap: %s", strerror(errno));
|
||||
close(map_fd);
|
||||
|
||||
if ( purpose == CAPTURE ) {
|
||||
// How about we store this in the object on instantiation so that we don't have to do this again.
|
||||
|
@ -953,20 +941,41 @@ Monitor::~Monitor() {
|
|||
}
|
||||
#else // ZM_MEM_MAPPED
|
||||
struct shmid_ds shm_data;
|
||||
if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) {
|
||||
Error( "Can't shmctl: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
if ( shmctl(shm_id, IPC_STAT, &shm_data) < 0 ) {
|
||||
Error("Can't shmctl: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
if ( shm_data.shm_nattch <= 1 ) {
|
||||
if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) {
|
||||
Error( "Can't shmctl: %s", strerror(errno) );
|
||||
exit( -1 );
|
||||
if ( shmctl(shm_id, IPC_RMID, 0) < 0 ) {
|
||||
Error("Can't shmctl: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
#endif // ZM_MEM_MAPPED
|
||||
} // end if mem_ptr
|
||||
|
||||
for ( int i = 0; i < n_zones; i++ ) {
|
||||
if ( videoStore ) {
|
||||
delete videoStore;
|
||||
videoStore = NULL;
|
||||
}
|
||||
|
||||
if ( timestamps ) {
|
||||
delete[] timestamps;
|
||||
timestamps = 0;
|
||||
}
|
||||
if ( images ) {
|
||||
delete[] images;
|
||||
images = 0;
|
||||
}
|
||||
|
||||
delete packetqueue;
|
||||
packetqueue = NULL;
|
||||
|
||||
if ( privacy_bitmask ) {
|
||||
delete[] privacy_bitmask;
|
||||
privacy_bitmask = NULL;
|
||||
}
|
||||
for ( int i=0; i < n_zones; i++ ) {
|
||||
delete zones[i];
|
||||
}
|
||||
delete[] zones;
|
||||
|
@ -975,29 +984,29 @@ Monitor::~Monitor() {
|
|||
delete storage;
|
||||
}
|
||||
|
||||
void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) {
|
||||
for ( int i = 0; i < n_zones; i++ )
|
||||
void Monitor::AddZones(int p_n_zones, Zone *p_zones[]) {
|
||||
for ( int i=0; i < n_zones; i++ )
|
||||
delete zones[i];
|
||||
delete[] zones;
|
||||
n_zones = p_n_zones;
|
||||
zones = p_zones;
|
||||
}
|
||||
|
||||
void Monitor::AddPrivacyBitmask( Zone *p_zones[] ) {
|
||||
void Monitor::AddPrivacyBitmask(Zone *p_zones[]) {
|
||||
if ( privacy_bitmask ) {
|
||||
delete[] privacy_bitmask;
|
||||
privacy_bitmask = NULL;
|
||||
}
|
||||
Image *privacy_image = NULL;
|
||||
|
||||
for ( int i = 0; i < n_zones; i++ ) {
|
||||
for ( int i=0; i < n_zones; i++ ) {
|
||||
if ( p_zones[i]->IsPrivacy() ) {
|
||||
if ( !privacy_image ) {
|
||||
privacy_image = new Image( width, height, 1, ZM_SUBPIX_ORDER_NONE);
|
||||
privacy_image = new Image(width, height, 1, ZM_SUBPIX_ORDER_NONE);
|
||||
privacy_image->Clear();
|
||||
}
|
||||
privacy_image->Fill( 0xff, p_zones[i]->GetPolygon() );
|
||||
privacy_image->Outline( 0xff, p_zones[i]->GetPolygon() );
|
||||
privacy_image->Fill(0xff, p_zones[i]->GetPolygon());
|
||||
privacy_image->Outline(0xff, p_zones[i]->GetPolygon());
|
||||
}
|
||||
} // end foreach zone
|
||||
if ( privacy_image )
|
||||
|
@ -1550,15 +1559,15 @@ void Monitor::UpdateAnalysisFPS() {
|
|||
if ( new_analysis_fps != analysis_fps ) {
|
||||
analysis_fps = new_analysis_fps;
|
||||
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, analysis_fps, analysis_fps );
|
||||
char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO Monitor_Status (MonitorId,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, analysis_fps, analysis_fps);
|
||||
db_mutex.lock();
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
}
|
||||
db_mutex.unlock();
|
||||
last_analysis_fps_time = now.tv_sec;
|
||||
}
|
||||
last_analysis_fps_time = now.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1589,17 +1598,19 @@ bool Monitor::Analyse() {
|
|||
Debug(2, "Analysis index (%d), last_Write(%d)", index, shared_data->last_write_index);
|
||||
packets_processed += 1;
|
||||
|
||||
struct timeval *timestamp = snap->timestamp;
|
||||
Image *snap_image = snap->image;
|
||||
if ( snap->image_index == -1 ) {
|
||||
snap->unlock();
|
||||
Debug(2, "skipping because audio");
|
||||
// We want to skip, but if we return, we may sleep.
|
||||
//
|
||||
if ( ! packetqueue->increment_analysis_it() ) {
|
||||
Debug(2, "No more packets to analyse");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
struct timeval *timestamp = snap->timestamp;
|
||||
Image *snap_image = snap->image;
|
||||
|
||||
// signal is set by capture
|
||||
bool signal = shared_data->signal;
|
||||
|
@ -1727,6 +1738,19 @@ bool Monitor::Analyse() {
|
|||
// Create event
|
||||
event = new Event( this, *timestamp, "Continuous", noteSetMap );
|
||||
shared_data->last_event_id = event->Id();
|
||||
|
||||
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||
std::string alarm_cause="Continuous";
|
||||
for ( int i=0; i < n_zones; i++) {
|
||||
if (zones[i]->Alarmed()) {
|
||||
alarm_cause += std::string(zones[i]->Label());
|
||||
if (i < n_zones-1) {
|
||||
alarm_cause +=",";
|
||||
}
|
||||
}
|
||||
}
|
||||
alarm_cause = cause+" "+alarm_cause;
|
||||
strncpy( shared_data->alarm_cause,alarm_cause.c_str() , sizeof(shared_data->alarm_cause) );
|
||||
video_store_data->recording = event->StartTime();
|
||||
Info( "%s: %03d - Opening new event %llu, section start", name, analysis_image_count, event->Id() );
|
||||
/* To prevent cancelling out an existing alert\prealarm\alarm state */
|
||||
|
@ -1738,22 +1762,34 @@ bool Monitor::Analyse() {
|
|||
|
||||
if ( score ) {
|
||||
Debug(9, "Score: (%d)", score );
|
||||
if ( state == IDLE || state == TAPE || state == PREALARM ) {
|
||||
if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) {
|
||||
Info( "%s: %03d - Gone into alarm state", name, analysis_image_count );
|
||||
shared_data->state = state = ALARM;
|
||||
if ( ! event ) {
|
||||
event = new Event( this, *timestamp, cause, noteSetMap );
|
||||
shared_data->last_event_id = event->Id();
|
||||
}
|
||||
} else if ( state != PREALARM ) {
|
||||
Info( "%s: %03d - Gone into prealarm state", name, analysis_image_count );
|
||||
shared_data->state = state = PREALARM;
|
||||
}
|
||||
} else if ( state == ALERT ) {
|
||||
Info( "%s: %03d - Gone back into alarm state", name, analysis_image_count );
|
||||
if ( state == IDLE || state == TAPE || state == PREALARM ) {
|
||||
if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) {
|
||||
Info( "%s: %03d - Gone into alarm state", name, analysis_image_count );
|
||||
shared_data->state = state = ALARM;
|
||||
if ( ! event ) {
|
||||
// lets construct alarm cause. It will contain cause + names of zones alarmed
|
||||
std::string alarm_cause="";
|
||||
for ( int i=0; i < n_zones; i++) {
|
||||
if (zones[i]->Alarmed()) {
|
||||
alarm_cause += std::string(zones[i]->Label());
|
||||
if (i < n_zones-1) {
|
||||
alarm_cause +=",";
|
||||
}
|
||||
}
|
||||
}
|
||||
alarm_cause = cause+" "+alarm_cause;
|
||||
strncpy( shared_data->alarm_cause,alarm_cause.c_str() , sizeof(shared_data->alarm_cause) );
|
||||
event = new Event( this, *timestamp, cause, noteSetMap );
|
||||
shared_data->last_event_id = event->Id();
|
||||
}
|
||||
} else if ( state != PREALARM ) {
|
||||
Info( "%s: %03d - Gone into prealarm state", name, analysis_image_count );
|
||||
shared_data->state = state = PREALARM;
|
||||
}
|
||||
} else if ( state == ALERT ) {
|
||||
Info( "%s: %03d - Gone back into alarm state", name, analysis_image_count );
|
||||
shared_data->state = state = ALARM;
|
||||
}
|
||||
last_alarm_count = analysis_image_count;
|
||||
} else { // no score?
|
||||
if ( state == ALARM ) {
|
||||
|
@ -1817,9 +1853,14 @@ bool Monitor::Analyse() {
|
|||
// Alert means this frame has no motion, but we were alarmed and are still recording.
|
||||
if ( noteSetMap.size() > 0 )
|
||||
event->updateNotes( noteSetMap );
|
||||
} else if ( state == TAPE ) {
|
||||
if ( !(analysis_image_count%(frame_skip+1)) ) {
|
||||
}
|
||||
//} else if ( state == TAPE ) {
|
||||
//if ( !(analysis_image_count%(frame_skip+1)) ) {
|
||||
//if ( config.bulk_frame_interval > 1 ) {
|
||||
//event->AddFrame( snap_image, *timestamp, (event->Frames()<pre_event_count?0:-1) );
|
||||
//} else {
|
||||
//event->AddFrame( snap_image, *timestamp );
|
||||
//}
|
||||
//}
|
||||
}
|
||||
if ( function == MODECT || function == MOCORD ) {
|
||||
ref_image.Blend( *snap_image, ( state==ALARM ? alarm_ref_blend_perc : ref_blend_perc ) );
|
||||
|
@ -1921,12 +1962,12 @@ void Monitor::ReloadZones() {
|
|||
zones = 0;
|
||||
n_zones = Zone::Load(this, zones);
|
||||
//DumpZoneImage();
|
||||
}
|
||||
} // end void Monitor::ReloadZones()
|
||||
|
||||
void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
||||
Debug(1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors);
|
||||
if ( n_linked_monitors ) {
|
||||
for( int i = 0; i < n_linked_monitors; i++ ) {
|
||||
for( int i=0; i < n_linked_monitors; i++ ) {
|
||||
delete linked_monitors[i];
|
||||
}
|
||||
delete[] linked_monitors;
|
||||
|
@ -1938,6 +1979,7 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
|||
int n_link_ids = 0;
|
||||
unsigned int link_ids[256];
|
||||
|
||||
// This nasty code picks out strings of digits from p_linked_monitors and tries to load them.
|
||||
char link_id_str[8];
|
||||
char *dest_ptr = link_id_str;
|
||||
const char *src_ptr = p_linked_monitors;
|
||||
|
@ -1979,35 +2021,35 @@ void Monitor::ReloadLinkedMonitors(const char *p_linked_monitors) {
|
|||
linked_monitors = new MonitorLink *[n_link_ids];
|
||||
int count = 0;
|
||||
for ( int i = 0; i < n_link_ids; i++ ) {
|
||||
Debug( 1, "Checking linked monitor %d", link_ids[i] );
|
||||
Debug(1, "Checking linked monitor %d", link_ids[i]);
|
||||
|
||||
static char sql[ZM_SQL_SML_BUFSIZ];
|
||||
snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] );
|
||||
snprintf(sql, sizeof(sql), "SELECT Id, Name FROM Monitors WHERE Id = %d AND Function != 'None' AND Function != 'Monitor' AND Enabled = 1", link_ids[i] );
|
||||
db_mutex.lock();
|
||||
if ( mysql_query( &dbconn, sql ) ) {
|
||||
Error( "Can't run query: %s", mysql_error( &dbconn ) );
|
||||
if ( mysql_query(&dbconn, sql) ) {
|
||||
Error("Can't run query: %s", mysql_error(&dbconn));
|
||||
db_mutex.unlock();
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
MYSQL_RES *result = mysql_store_result( &dbconn );
|
||||
MYSQL_RES *result = mysql_store_result(&dbconn);
|
||||
db_mutex.unlock();
|
||||
if ( !result ) {
|
||||
Error( "Can't use query result: %s", mysql_error( &dbconn ) );
|
||||
exit( mysql_errno( &dbconn ) );
|
||||
Error("Can't use query result: %s", mysql_error(&dbconn));
|
||||
continue;
|
||||
}
|
||||
int n_monitors = mysql_num_rows( result );
|
||||
int n_monitors = mysql_num_rows(result);
|
||||
if ( n_monitors == 1 ) {
|
||||
MYSQL_ROW dbrow = mysql_fetch_row( result );
|
||||
Debug( 1, "Linking to monitor %d", link_ids[i] );
|
||||
linked_monitors[count++] = new MonitorLink( link_ids[i], dbrow[1] );
|
||||
MYSQL_ROW dbrow = mysql_fetch_row(result);
|
||||
Debug(1, "Linking to monitor %d", link_ids[i]);
|
||||
linked_monitors[count++] = new MonitorLink(link_ids[i], dbrow[1]);
|
||||
} else {
|
||||
Warning( "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] );
|
||||
Warning("Can't link to monitor %d, invalid id, function or not enabled", link_ids[i]);
|
||||
}
|
||||
mysql_free_result( result );
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} // end foreach n_link_id
|
||||
n_linked_monitors = count;
|
||||
}
|
||||
} // end if n_link_ids > 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2129,7 +2171,7 @@ int Monitor::Capture() {
|
|||
return 0;
|
||||
}
|
||||
} else {
|
||||
Debug(2,"Before capture");
|
||||
Debug(4, "Capturing");
|
||||
captureResult = camera->Capture(*packet);
|
||||
gettimeofday( packet->timestamp, NULL );
|
||||
if ( captureResult < 0 ) {
|
||||
|
@ -2589,18 +2631,17 @@ unsigned int Monitor::SubpixelOrder() const { return camera->SubpixelOrder(); }
|
|||
int Monitor::PrimeCapture() {
|
||||
int ret = camera->PrimeCapture();
|
||||
if ( ret == 0 ) {
|
||||
if ( packetqueue )
|
||||
delete packetqueue;
|
||||
video_stream_id = camera->get_VideoStreamId();
|
||||
packetqueue = new zm_packetqueue(image_buffer_count, video_stream_id);
|
||||
}
|
||||
Debug(2, "Video stream id is (%d), minimum_packets to keep in buffer(%d)", video_stream_id, pre_event_buffer_count);
|
||||
return ret;
|
||||
}
|
||||
int Monitor::PreCapture() {
|
||||
return camera->PreCapture();
|
||||
}
|
||||
int Monitor::PostCapture() {
|
||||
return camera->PostCapture();
|
||||
}
|
||||
|
||||
int Monitor::PreCapture() const { return camera->PreCapture(); }
|
||||
int Monitor::PostCapture() const { return camera->PostCapture() ; }
|
||||
Monitor::Orientation Monitor::getOrientation() const { return orientation; }
|
||||
|
||||
// Wait for camera to get an image, and then assign it as the base reference image. So this should be done as the first task in the analysis thread startup.
|
||||
|
|
|
@ -262,7 +262,8 @@ protected:
|
|||
int colours;
|
||||
VideoWriter videowriter;
|
||||
std::string encoderparams;
|
||||
std::string output_codec;
|
||||
int output_codec;
|
||||
std::string encoder;
|
||||
std::string output_container;
|
||||
std::vector<EncoderParameter_t> encoderparamsvec;
|
||||
_AVPIXELFORMAT imagePixFormat;
|
||||
|
@ -372,51 +373,6 @@ public:
|
|||
|
||||
// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info.
|
||||
//bool OurCheckAlarms( Zone *zone, const Image *pImage );
|
||||
Monitor(
|
||||
int p_id,
|
||||
const char *p_name,
|
||||
unsigned int p_server_id,
|
||||
unsigned int p_storage_id,
|
||||
int p_function,
|
||||
bool p_enabled,
|
||||
const char *p_linked_monitors,
|
||||
Camera *p_camera,
|
||||
int p_orientation,
|
||||
unsigned int p_deinterlacing,
|
||||
int p_savejpegs,
|
||||
int p_colours,
|
||||
VideoWriter p_videowriter,
|
||||
std::string &p_encoderparams,
|
||||
std::string &p_output_codec,
|
||||
std::string &p_output_container,
|
||||
bool p_record_audio,
|
||||
const char *p_event_prefix,
|
||||
const char *p_label_format,
|
||||
const Coord &p_label_coord,
|
||||
int label_size,
|
||||
int p_image_buffer_count,
|
||||
int p_warmup_count,
|
||||
int p_pre_event_count,
|
||||
int p_post_event_count,
|
||||
int p_stream_replay_buffer,
|
||||
int p_alarm_frame_count,
|
||||
int p_section_length,
|
||||
int p_frame_skip,
|
||||
int p_motion_frame_skip,
|
||||
double p_analysis_fps,
|
||||
unsigned int p_analysis_update_delay,
|
||||
int p_capture_delay,
|
||||
int p_alarm_capture_delay,
|
||||
int p_fps_report_interval,
|
||||
int p_ref_blend_perc,
|
||||
int p_alarm_ref_blend_perc,
|
||||
bool p_track_motion,
|
||||
Rgb p_signal_check_colour,
|
||||
bool p_embed_exif,
|
||||
Purpose p_purpose,
|
||||
int p_n_zones=0,
|
||||
Zone *p_zones[]=0
|
||||
);
|
||||
~Monitor();
|
||||
|
||||
void AddZones( int p_n_zones, Zone *p_zones[] );
|
||||
|
@ -486,7 +442,8 @@ public:
|
|||
VideoWriter GetOptVideoWriter() const { return videowriter; }
|
||||
const std::vector<EncoderParameter_t>* GetOptEncoderParams() const { return &encoderparamsvec; }
|
||||
const std::string &GetEncoderOptions() const { return encoderparams; }
|
||||
const std::string &OutputCodec() const { return output_codec; }
|
||||
const int OutputCodec() const { return output_codec; }
|
||||
const std::string &Encoder() const { return encoder; }
|
||||
const std::string &OutputContainer() const { return output_container; }
|
||||
|
||||
uint64_t GetVideoWriterEventId() const { return video_store_data->current_event; }
|
||||
|
@ -510,7 +467,7 @@ 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 ); }
|
||||
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 get_ref_image();
|
||||
|
@ -527,9 +484,9 @@ public:
|
|||
int actionContrast( int p_contrast=-1 );
|
||||
|
||||
int PrimeCapture();
|
||||
int PreCapture();
|
||||
int PreCapture() const;
|
||||
int Capture();
|
||||
int PostCapture();
|
||||
int PostCapture() const;
|
||||
|
||||
void CheckAction();
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) {
|
|||
// If we can never queue the same packet, then they can never go past
|
||||
if ( zm_packet->image_index == first_video_packet_index ) {
|
||||
Debug(2, "queuing packet that is already on the queue(%d)", zm_packet->image_index );
|
||||
ZMPacket *p;
|
||||
ZMPacket *p = NULL;;
|
||||
while ( pktQueue.size() && (p = pktQueue.front()) && ( p->image_index != zm_packet->image_index ) ) {
|
||||
if ( ( analysis_it != pktQueue.end() ) && ( *analysis_it == p ) ) {
|
||||
Debug(2, "Increasing analysis_it");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,15 @@ class VideoStore;
|
|||
class VideoStore {
|
||||
private:
|
||||
|
||||
struct CodecData {
|
||||
const int codec_id;
|
||||
const char *codec_codec;
|
||||
const char *codec_name;
|
||||
const enum AVPixelFormat pix_fmt;
|
||||
|
||||
};
|
||||
static struct CodecData codec_data[];
|
||||
|
||||
Monitor *monitor;
|
||||
AVOutputFormat *out_format;
|
||||
AVFormatContext *oc;
|
||||
|
@ -89,6 +98,7 @@ public:
|
|||
int writeAudioFramePacket( ZMPacket *pkt );
|
||||
int writePacket( ZMPacket *pkt );
|
||||
int write_packets( zm_packetqueue &queue );
|
||||
void flush_codecs();
|
||||
};
|
||||
|
||||
#endif //havelibav
|
||||
|
|
|
@ -15,7 +15,8 @@ private $defaults = array(
|
|||
'Height' => null,
|
||||
'Orientation' => null,
|
||||
'AnalysisFPSLimit' => null,
|
||||
'OutputCodec' => 'h264',
|
||||
'OutputCodec' => '0',
|
||||
'Encoder' => 'auto',
|
||||
'OutputContainer' => 'auto',
|
||||
'ZoneCount' => 0,
|
||||
'Triggers' => null,
|
||||
|
|
|
@ -471,13 +471,21 @@ $videowriteropts = array(
|
|||
'X264 Encode' => 1,
|
||||
'H264 Camera Passthrough' => 2
|
||||
);
|
||||
$videowriter_codecs = array(
|
||||
'' => translate('Disabled'),
|
||||
$videowriter_encoders = array(
|
||||
'' => translate('Auto'),
|
||||
'h264_omx' => 'h264_omx',
|
||||
'h264' => 'h264',
|
||||
'mjpeg' => 'mjpeg',
|
||||
'mpeg1' => 'mpeg1',
|
||||
'mpeg2' => 'mpeg2',
|
||||
);
|
||||
$videowriter_codecs = array(
|
||||
'0' => translate('Disabled'),
|
||||
'220' => 'h264',
|
||||
'8' => 'mjpeg',
|
||||
'1' => 'mpeg1',
|
||||
'2' => 'mpeg2',
|
||||
);
|
||||
$videowriter_containers = array(
|
||||
'' => translate('Auto'),
|
||||
'mp4' => 'mp4',
|
||||
|
@ -610,6 +618,7 @@ if ( $tab != 'storage' ) {
|
|||
<input type="hidden" name="newMonitor[SaveJPEGs]" value="<?php echo validHtmlStr($monitor->SaveJPEGs()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[VideoWriter]" value="<?php echo validHtmlStr($monitor->VideoWriter()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[OutputCodec]" value="<?php echo validHtmlStr($monitor->OutputCodec()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[Encoder]" value="<?php echo validHtmlStr($monitor->Encoder()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[OutputContainer]" value="<?php echo validHtmlStr($monitor->OutputContainer()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[EncoderParameters]" value="<?php echo validHtmlStr($monitor->EncoderParameters()) ?>"/>
|
||||
<input type="hidden" name="newMonitor[RecordAudio]" value="<?php echo validHtmlStr($monitor->RecordAudio()) ?>"/>
|
||||
|
@ -916,6 +925,7 @@ if ( $monitor->Type() == 'Local' ) {
|
|||
<tr><td><?php echo translate('SaveJPEGs') ?></td><td><select name="newMonitor[SaveJPEGs]"><?php foreach ( $savejpegopts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->SaveJPEGs() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('VideoWriter') ?></td><td><select name="newMonitor[VideoWriter]"><?php foreach ( $videowriteropts as $name => $value ) { ?><option value="<?php echo $value ?>"<?php if ( $value == $monitor->VideoWriter() ) { ?> selected="selected"<?php } ?>><?php echo $name ?></option><?php } ?></select></td></tr>
|
||||
<tr><td><?php echo translate('OutputCodec') ?></td><td><?php echo htmlSelect( 'newMonitor[OutputCodec]', $videowriter_codecs, $monitor->OutputCodec() );?></td></tr>
|
||||
<tr><td><?php echo translate('Encoder') ?></td><td><?php echo htmlSelect( 'newMonitor[Encoder]', $videowriter_encoders, $monitor->Encoder() );?></td></tr>
|
||||
<tr><td><?php echo translate('OutputContainer') ?></td><td><?php echo htmlSelect( 'newMonitor[OutputContainer]', $videowriter_containers, $monitor->OutputContainer() );?></td></tr>
|
||||
<tr><td><?php echo translate('OptionalEncoderParam') ?></td><td><textarea name="newMonitor[EncoderParameters]" rows="4" cols="36"><?php echo validHtmlStr($monitor->EncoderParameters()) ?></textarea></td></tr>
|
||||
<tr><td><?php echo translate('RecordAudio') ?></td><td><input type="checkbox" name="newMonitor[RecordAudio]" value="1"<?php if ( $monitor->RecordAudio() ) { ?> checked="checked"<?php } ?>/></td></tr>
|
||||
|
|
Loading…
Reference in New Issue