Merge branch 'zma_to_thread' of github.com:ConnorTechnology/ZoneMinder into zma_to_thread

This commit is contained in:
Isaac Connor 2018-04-14 14:58:25 -04:00
commit c7deb91319
18 changed files with 571 additions and 581 deletions

View File

@ -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

View File

@ -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',

View File

@ -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 ;

View File

@ -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;

View File

@ -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.*,

View File

@ -679,7 +679,7 @@ sub Dump {
sub debug {
my $log = shift;
$log->logPrint(DEBUG, @_);
}
}
sub Debug( @ ) {
fetch()->logPrint(DEBUG, @_);

View File

@ -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 ) {

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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>