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

This commit is contained in:
Isaac Connor 2017-12-03 11:00:52 -05:00
commit 5f01313ff6
7 changed files with 85 additions and 48 deletions

View File

@ -437,6 +437,8 @@ void Event::AddPacket( ZMPacket *packet, int score, Image *alarm_image ) {
Debug(2, "No video keyframe yet, not writing");
}
//FIXME if it fails, we should write a jpeg
} else {
Debug(2,"AddPacket but no videostore?!");
}
if ( have_video_keyframe && ( packet->codec_type == AVMEDIA_TYPE_VIDEO ) ) {
AddFrame( packet->image, *packet->timestamp, score, alarm_image );

View File

@ -1919,7 +1919,6 @@ int LocalCamera::PreCapture() {
int LocalCamera::Capture( ZMPacket &zm_packet ) {
// We assume that the avpacket is allocated, and just needs to be filled
Debug( 3, "Capturing" );
static uint8_t* buffer = NULL;
int buffer_bytesused = 0;
int capture_frame = -1;
@ -1954,7 +1953,7 @@ int LocalCamera::Capture( ZMPacket &zm_packet ) {
}
return -1;
}
Debug(3, "Captured a frame");
Debug(5, "Captured a frame");
v4l2_data.bufptr = &vid_buf;
capture_frame = v4l2_data.bufptr->index;

View File

@ -353,8 +353,10 @@ Monitor::Monitor(
event_count = 0;
image_count = 0;
analysis_image_count = 0;
// How many frames we need to have before we start analysing
ready_count = warmup_count;
first_alarm_count = 0;
last_alarm_count = 0;
state = IDLE;
last_signal = false;
@ -411,6 +413,7 @@ Monitor::Monitor(
}
memset( mem_ptr, 0, mem_size );
shared_data->size = sizeof(SharedData);
Debug( 1, "shared.size=%d", shared_data->size );
shared_data->active = enabled;
shared_data->signal = false;
shared_data->state = IDLE;
@ -451,7 +454,8 @@ Monitor::Monitor(
start_time = last_fps_time = time( 0 );
event = 0;
last_section_mod =0;
last_section_mod = 0;
pre_event_buffer_count = pre_event_count + alarm_frame_count + warmup_count- 1;
Debug( 1, "Monitor %s\
function: %d\
@ -459,7 +463,9 @@ Monitor::Monitor(
IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, ARBP = %d, FM = %d",
name,
function, label_format, label_coord.X(), label_coord.Y(), label_size,
image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion
image_buffer_count, warmup_count,
pre_event_count, post_event_count, alarm_frame_count,
fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion
);
n_linked_monitors = 0;
@ -563,7 +569,6 @@ bool Monitor::connect() {
/* Allocate a buffer for the next image */
next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder());
}
pre_event_buffer_count = pre_event_count + alarm_frame_count - 1;
Debug(3, "Success connecting");
return true;
@ -752,8 +757,9 @@ unsigned int Monitor::GetLastWriteIndex() const {
}
uint32_t Monitor::GetLastEventId() const {
Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%d)",
Debug(2, "mem_ptr(%x), size(%d) State(%d) last_read_index(%d) last_read_time(%d) last_event(%d)",
mem_ptr,
shared_data->size,
shared_data->state,
shared_data->last_read_index,
shared_data->last_read_time,
@ -777,7 +783,7 @@ double Monitor::GetFPS() const {
}
struct timeval time1 = *snap1->timestamp;
int image_count = image_buffer_count;
int fps_image_count = image_buffer_count;
int index2 = (index1+1)%image_buffer_count;
Debug(2, "index2(%d)", index2);
@ -791,7 +797,7 @@ double Monitor::GetFPS() const {
}
index2 = (index2+1)%image_buffer_count;
snap2 = &image_buffer[ index2 ];
image_count--;
fps_image_count--;
}
struct timeval time2 = *snap2->timestamp;
@ -799,10 +805,11 @@ double Monitor::GetFPS() const {
if ( ! time_diff ) {
return 0.0;
}
double curr_fps = image_count/time_diff;
double curr_fps = fps_image_count/time_diff;
if ( curr_fps < 0.0 ) {
Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count );
Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d",
curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count );
return 0.0;
}
return curr_fps;
@ -1239,13 +1246,11 @@ bool Monitor::Analyse() {
// if have event, sent frames until we find a video packet, at which point do analysis. Adaptive skip should only affect which frames we do analysis on.
// If do have an event, then analysis_it should point to the head of the queue, because we would have emptied it on event creation.
unsigned int index = ( shared_data->last_read_index + 1 ) % image_buffer_count;
int packets_processed = 0;
ZMPacket *snap;
while ( ( snap = packetqueue->get_analysis_packet() ) && ( snap->score == -1 ) ) {
unsigned int index = snap->image_index;
Debug(2, "Analysis index (%d), last_Write(%d)", index, shared_data->last_write_index);
packets_processed += 1;
@ -1294,7 +1299,7 @@ bool Monitor::Analyse() {
if ( !signal ) {
signalText = "Lost";
if ( event ) {
Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() );
Info( "%s: %03d - Closing event %d, signal loss", name, analysis_image_count, event->Id() );
closeEvent();
last_section_mod = 0;
}
@ -1374,7 +1379,7 @@ bool Monitor::Analyse() {
Debug( 3, "Section length (%d) Last Section Mod(%d), tv_sec(%d) new section mod(%d)", section_length, last_section_mod, timestamp->tv_sec, section_mod );
// This is not clear, but basically due to pauses, etc we might not get section_mod == 0
if ( section_mod < last_section_mod ) {
Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() );
Info( "%s: %03d - Closing event %d, section end forced ", name, analysis_image_count, event->Id() );
closeEvent();
last_section_mod = 0;
} else {
@ -1388,7 +1393,7 @@ bool Monitor::Analyse() {
event = new Event( this, *timestamp, "Continuous", noteSetMap );
shared_data->last_event_id = event->Id();
video_store_data->recording = event->StartTime();
Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() );
Info( "%s: %03d - Opening new event %d, section start", name, analysis_image_count, event->Id() );
/* To prevent cancelling out an existing alert\prealarm\alarm state */
if ( state == IDLE ) {
shared_data->state = state = TAPE;
@ -1400,32 +1405,36 @@ bool Monitor::Analyse() {
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, image_count );
Info( "%s: %03d - Gone into alarm state", name, analysis_image_count );
shared_data->state = state = ALARM;
if ( (function != MOCORD && state != ALERT) ) {
if ( event ) {
Error("Already ahve evnet!");
} else {
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, image_count );
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, image_count );
Info( "%s: %03d - Gone back into alarm state", name, analysis_image_count );
shared_data->state = state = ALARM;
}
last_alarm_count = image_count;
last_alarm_count = analysis_image_count;
} else { // no score?
if ( state == ALARM ) {
Info( "%s: %03d - Gone into alert state", name, image_count );
Info( "%s: %03d - Gone into alert state", name, analysis_image_count );
shared_data->state = state = ALERT;
} else if ( state == ALERT ) {
if ( image_count-last_alarm_count > post_event_count ) {
Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() );
if ( analysis_image_count-last_alarm_count > post_event_count ) {
Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, analysis_image_count, event->Id(), event->Frames(), event->AlarmFrames() );
//if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE )
if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) {
shared_data->state = state = IDLE;
Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" );
Info( "%s: %03d - Closing event %d, alarm end%s", name, analysis_image_count, event->Id(), (function==MOCORD)?", section truncated":"" );
closeEvent();
} else {
shared_data->state = state = TAPE;
@ -1478,7 +1487,7 @@ bool Monitor::Analyse() {
if ( noteSetMap.size() > 0 )
event->updateNotes( noteSetMap );
} else if ( state == TAPE ) {
if ( !(image_count%(frame_skip+1)) ) {
if ( !(analysis_image_count%(frame_skip+1)) ) {
}
}
if ( function == MODECT || function == MOCORD ) {
@ -1489,11 +1498,12 @@ bool Monitor::Analyse() {
} else {
Debug(3,"Not ready?");
return false;
}
} else {
Debug(3, "trigger == off");
if ( event ) {
Info( "%s: %03d - Closing event %d, trigger off", name, image_count, event->Id() );
Info( "%s: %03d - Closing event %d, trigger off", name, analysis_image_count, event->Id() );
closeEvent();
}
shared_data->state = state = IDLE;
@ -1501,24 +1511,32 @@ bool Monitor::Analyse() {
} // end if ( trigger_data->trigger_state != TRIGGER_OFF )
if ( event ) {
int last_write = shared_data->last_write_index;
int written = 0;
ZMPacket *queued_packet;
//popPacket will increment analysis_it if neccessary, so this will write out all packets in queue
// We can't just loop here forever, because we may be capturing just as fast, and never leave the loop.
// Only loop until we hit the analysis index
while ( ( queued_packet = packetqueue->popPacket() ) ) {
Debug(2,"adding packet (%x) (%d)", queued_packet, queued_packet->image_index );
Debug(2,"adding packet (%d) qp lwindex(%d), written(%d)", queued_packet->image_index, last_write, written );
event->AddPacket( queued_packet );
written ++;
if ( queued_packet->image_index == -1 ) {
delete queued_packet;
queued_packet = NULL;
} else if ( snap == queued_packet ) {
packetqueue->increment_analysis_it();
break;
}
// encoding can take a long time, so
shared_data->last_read_time = time(NULL);
} // end while write out queued_packets
queued_packet = NULL;
} else {
packetqueue->increment_analysis_it();
}
shared_data->last_read_index = snap->image_index;
struct timeval now;
gettimeofday(&now, NULL);
shared_data->last_read_time = now.tv_sec;
shared_data->last_read_time = time(NULL);
analysis_image_count++;
} // end while not at end of packetqueue
if ( packets_processed > 0 )
@ -2736,6 +2754,7 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) {
int Monitor::Capture() {
static int FirstCapture = 1; // Used in de-interlacing to indicate whether this is the even or odd image
GetLastEventId();
unsigned int index = image_count % image_buffer_count;
if ( (index == shared_data->last_read_index) && (function > MONITOR) ) {
@ -2750,7 +2769,6 @@ int Monitor::Capture() {
}
ZMPacket *packet = &image_buffer[index];
Debug(2,"Reset index(%d) of (%d)", index, image_buffer_count );
packet->reset();
Image* capture_image = packet->image;
int captureResult = 0;
@ -2771,7 +2789,6 @@ int Monitor::Capture() {
}
} else {
captureResult = camera->Capture(*packet);
Debug(2, "Reset timestamp");
gettimeofday( packet->timestamp, NULL );
if ( captureResult < 0 ) {
// Unable to capture image for temporary reason
@ -2804,7 +2821,6 @@ int Monitor::Capture() {
return 1;
}
Debug(2, "Have video packet");
packet->codec_type = camera->get_VideoStream()->codecpar->codec_type;
if ( packet->packet.size && ! packet->in_frame ) {
@ -2816,8 +2832,11 @@ int Monitor::Capture() {
// Have an av_packet,
mutex.lock();
if ( packetqueue->video_packet_count || packet->keyframe || event ) {
Debug(2, "Have video packet for index (%d)", index );
//Debug(2, "Queueing video packet");
packetqueue->queuePacket( packet );
} else {
Debug(2, "Not queiing video packet for index (%d)", index );
}
mutex.unlock();
} else {
@ -3110,7 +3129,7 @@ unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &z
shared_data->alarm_x = alarm_centre.X();
shared_data->alarm_y = alarm_centre.Y();
Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count );
Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, analysis_image_count );
} else {
shared_data->alarm_x = shared_data->alarm_y = -1;
}
@ -3192,9 +3211,9 @@ int Monitor::PrimeCapture() {
int ret = camera->PrimeCapture();
if ( ret == 0 ) {
video_stream_id = camera->get_VideoStreamId();
packetqueue = new zm_packetqueue( pre_event_buffer_count, video_stream_id );
packetqueue = new zm_packetqueue( image_buffer_count, video_stream_id );
}
Debug(2, "Video stream id is (%d)", 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() {

View File

@ -100,7 +100,7 @@ protected:
typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode;
/* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */
/* sizeof(SharedData) expected to be 344 bytes on 32bit and 64bit */
typedef struct {
uint32_t size; /* +0 */
uint32_t last_write_index; /* +4 */
@ -425,9 +425,15 @@ public:
return( event_prefix );
}
inline bool Ready() {
if ( function <= MONITOR )
if ( function <= MONITOR ) {
Error("Should not be calling Ready if the function doesn't include motion detection");
return( false );
return( image_count > ready_count );
}
if ( image_count > ready_count ) {
return true;
}
Debug(2, "Not ready because image_count(%d) <= ready_count(%d)", image_count, ready_count );
return false;
}
inline bool Active() {
if ( function <= MONITOR )

View File

@ -183,6 +183,7 @@ int RemoteCameraNVSocket::PrimeCapture() {
Disconnect();
return -1;
}
mVideoStreamId=0;
return 0;
}
@ -207,6 +208,7 @@ int RemoteCameraNVSocket::Capture( ZMPacket &zm_packet ) {
}
zm_packet.image->Assign( width, height, colours, subpixelorder, buffer, imagesize );
zm_packet.keyframe = 1;
return 1;
}
@ -232,9 +234,8 @@ AVStream *RemoteCameraNVSocket::get_VideoStream() {
} else {
Error("Can't create video stream");
}
} else {
Debug(2,"Have videostream");
} else {
Debug(5,"Have videostream");
}
Debug(2,"Get videoStream");
return video_stream;
}

View File

@ -46,7 +46,7 @@ VideoStore::VideoStore(
packets_written = 0;
frame_count = 0;
av_register_all();
FFMPEGInit();
Info("Opening video storage stream %s format: %s", filename, format);
@ -976,7 +976,8 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
} else if ( zm_packet->image ) {
Debug(2,"Have an image, convert it");
//Go straight to out frame
swscale.Convert(zm_packet->image,
swscale.Convert(
zm_packet->image,
zm_packet->buffer,
codec_imgsize,
(AVPixelFormat)zm_packet->image->AVPixFormat(),
@ -997,10 +998,18 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
if ( ! video_last_pts ) {
video_last_pts = zm_packet->timestamp->tv_sec*1000000 + zm_packet->timestamp->tv_usec;
Debug(2, "No video_lsat_pts, set to (%d)", video_last_pts );
zm_packet->out_frame->pts = 0;
} else {
zm_packet->out_frame->pts = ( zm_packet->timestamp->tv_sec*1000000 + zm_packet->timestamp->tv_usec ) - video_last_pts;
}
if ( zm_packet->keyframe ) {
Debug(2, "Setting keyframe");
zm_packet->out_frame->key_frame =1;
Debug(2, "Setting keyframe (%d)", zm_packet->out_frame->key_frame );
} else {
Debug(2, "Not Setting keyframe");
}
// Do this to allow the encoder to choose whether to use I/P/B frame
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -1040,6 +1049,7 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
return 0;
}
#endif
opkt.dts = opkt.pts;
} else {
AVPacket *ipkt = &zm_packet->packet;
@ -1058,7 +1068,7 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) {
}
opkt.duration = 0;
Debug(3, "dts:%" PRId64 ", pts:%" PRId64 ", keyframe:%d", opkt.dts, opkt.pts, opkt.flags & AV_PKT_FLAG_KEY );
Debug(3, "dts:%" PRId64 ", pts:%" PRId64 ", keyframe:%d", opkt.dts, opkt.pts, opkt.flags & AV_PKT_FLAG_KEY );
write_video_packet( opkt );
zm_av_packet_unref(&opkt);

View File

@ -222,7 +222,7 @@ Warning("Not Using snapshot" . $event->Path().'/snapshot.jpg' );
$imgHtml = '<img id="thumbnail'.$event->id().'" src="'.$imgSrc.'" alt="'. validHtmlStr('Event '.$event->Id()) .'" style="width:'. validInt($thumbData['Width']) .'px;height:'. validInt( $thumbData['Height'] ).'px;" onmouseover="this.src=\''.$streamSrc.'\';" onmouseout="this.src=\''.$imgSrc.'\';"/>';
echo makePopupLink(
'?view=frame&amp;eid='.$event->Id().'&amp;fid='.$thumbData['FrameId'],
'?view=frame&amp;eid='.$event->Id().'&amp;fid='.( isset($thumbData['FrameId']) ? $thumbData['FrameId'] : 'snapshot' ),
'zmImage',
array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ),
$imgHtml