From f0ffa34c4d766e726a08c78948959add7d3c8e20 Mon Sep 17 00:00:00 2001 From: APHW2 MFGENG Date: Tue, 28 Nov 2017 12:58:20 -0800 Subject: [PATCH 1/5] set videostreamid --- src/zm_remote_camera_nvsocket.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zm_remote_camera_nvsocket.cpp b/src/zm_remote_camera_nvsocket.cpp index ae5eb3faa..d6e7c7401 100644 --- a/src/zm_remote_camera_nvsocket.cpp +++ b/src/zm_remote_camera_nvsocket.cpp @@ -183,6 +183,7 @@ int RemoteCameraNVSocket::PrimeCapture() { Disconnect(); return -1; } + mVideoStreamId=0; return 0; } From 128ae823312b29786094dc9156bcb3eff82e4c4e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 1 Dec 2017 10:33:10 -0500 Subject: [PATCH 2/5] add a debug for when in addpacket and no videostore --- src/zm_event.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zm_event.cpp b/src/zm_event.cpp index c312c4c2f..f59ce4c97 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -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 ); From 2e3fda488e126e54dc04aca94e3f41c5dd46f113 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 1 Dec 2017 14:33:51 -0500 Subject: [PATCH 3/5] more debug --- src/zm_local_camera.cpp | 3 +-- src/zm_monitor.cpp | 57 ++++++++++++++++++++++++----------------- src/zm_monitor.h | 12 ++++++--- src/zm_videostore.cpp | 9 +++++-- 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index a7e951be2..72aa669c8 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -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; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 1ac336888..18234459d 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -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; @@ -1236,6 +1243,7 @@ bool Monitor::Analyse() { Warning("SHouldn't be doing Analyze when not Enabled"); return false; } + GetLastEventId(); // 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. @@ -1294,7 +1302,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 +1382,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 +1396,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 +1408,32 @@ 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) ) { 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 +1486,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 +1497,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; @@ -3110,7 +3119,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; } @@ -3194,7 +3203,7 @@ int Monitor::PrimeCapture() { video_stream_id = camera->get_VideoStreamId(); packetqueue = new zm_packetqueue( pre_event_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() { diff --git a/src/zm_monitor.h b/src/zm_monitor.h index b0128c423..13a215e48 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -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 ) diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index cb7908892..c4f599182 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -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,6 +998,7 @@ 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; @@ -1040,6 +1042,9 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) { return 0; } #endif + opkt.dts = opkt.pts; + if ( zm_packet->keyframe ) + opkt.flags |= AV_PKT_FLAG_KEY; } else { AVPacket *ipkt = &zm_packet->packet; @@ -1058,7 +1063,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); From b87e45912531c16e59e4dee72545e2bd41db04ea Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 1 Dec 2017 14:48:30 -0500 Subject: [PATCH 4/5] still corrupting memory --- src/zm_monitor.cpp | 1 + src/zm_videostore.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 18234459d..9c18bf179 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2745,6 +2745,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) ) { diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index c4f599182..a7cadfbb3 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -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); From 4a9c31a15d679667544e946de99da44d5dd12372 Mon Sep 17 00:00:00 2001 From: APHW2 MFGENG Date: Fri, 1 Dec 2017 15:42:19 -0800 Subject: [PATCH 5/5] wip --- src/zm_monitor.cpp | 35 +++++++++++++++++++----------- src/zm_remote_camera_nvsocket.cpp | 6 ++--- src/zm_videostore.cpp | 9 ++++++-- web/skins/classic/views/events.php | 2 +- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 9c18bf179..e0c71572a 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1243,17 +1243,14 @@ bool Monitor::Analyse() { Warning("SHouldn't be doing Analyze when not Enabled"); return false; } - GetLastEventId(); // 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; @@ -1411,8 +1408,12 @@ bool Monitor::Analyse() { 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, analysis_image_count ); @@ -1510,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 ) @@ -2760,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; @@ -2781,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 @@ -2814,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 ) { @@ -2826,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 { @@ -3202,7 +3211,7 @@ 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), minimum_packets to keep in buffer(%d)", video_stream_id, pre_event_buffer_count ); return ret; diff --git a/src/zm_remote_camera_nvsocket.cpp b/src/zm_remote_camera_nvsocket.cpp index d6e7c7401..1ba91942b 100644 --- a/src/zm_remote_camera_nvsocket.cpp +++ b/src/zm_remote_camera_nvsocket.cpp @@ -208,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; } @@ -233,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; } diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index a7cadfbb3..573c96970 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -1003,6 +1003,13 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) { } 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) @@ -1043,8 +1050,6 @@ int VideoStore::writeVideoFramePacket( ZMPacket * zm_packet ) { } #endif opkt.dts = opkt.pts; - if ( zm_packet->keyframe ) - opkt.flags |= AV_PKT_FLAG_KEY; } else { AVPacket *ipkt = &zm_packet->packet; diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 0166fb6b1..cd8103afc 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -222,7 +222,7 @@ Warning("Not Using snapshot" . $event->Path().'/snapshot.jpg' ); $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; echo makePopupLink( - '?view=frame&eid='.$event->Id().'&fid='.$thumbData['FrameId'], + '?view=frame&eid='.$event->Id().'&fid='.( isset($thumbData['FrameId']) ? $thumbData['FrameId'] : 'snapshot' ), 'zmImage', array( 'image', reScale( $event->Width(), $scale ), reScale( $event->Height(), $scale ) ), $imgHtml