Merge branch 'zma_to_thread' of github.com:ConnorTechnology/ZoneMinder into zma_to_thread
This commit is contained in:
commit
5f01313ff6
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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&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
|
||||
|
|
Loading…
Reference in New Issue