diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 4fc4c7b2b..dab9af809 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -428,12 +428,14 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st } void Event::AddPacket( ZMPacket *packet, int score, Image *alarm_image ) { - frames++; if ( videoStore ) { have_video_keyframe = have_video_keyframe || ( packet->codec_type == AVMEDIA_TYPE_VIDEO && ( packet->packet.flags & AV_PKT_FLAG_KEY ) ); - if ( have_video_keyframe ) + if ( have_video_keyframe ) { videoStore->writePacket( packet ); + } else { + Debug(2, "No video keyframe yet, not writing"); + } //FIXME if it fails, we should write a jpeg } if ( packet->codec_type == AVMEDIA_TYPE_VIDEO ) { diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index f8b6d6241..f99e56561 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -148,7 +148,7 @@ int FfmpegCamera::PrimeCapture() { } return 0; #else - return OpenFfmpeg(); + return ! OpenFfmpeg(); #endif } @@ -206,6 +206,9 @@ int FfmpegCamera::PostCapture() { int FfmpegCamera::OpenFfmpeg() { Debug ( 2, "OpenFfmpeg called." ); + uint32_t last_event_id = monitor->GetLastEventId() ; + uint32_t video_writer_event_id = monitor->GetVideoWriterEventId(); + Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id ); int ret; @@ -249,6 +252,9 @@ int FfmpegCamera::OpenFfmpeg() { //FIXME can speed up initial analysis but need sensible parameters... //mFormatContext->probesize = 32; //mFormatContext->max_analyze_duration = 32; + last_event_id = monitor->GetLastEventId() ; + video_writer_event_id = monitor->GetVideoWriterEventId(); + Debug(2, "last_event(%d), our current (%d), mpath (%s)", last_event_id, video_writer_event_id, mPath.c_str() ); if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) != 0 ) #endif @@ -263,6 +269,10 @@ int FfmpegCamera::OpenFfmpeg() { Warning( "Option %s not recognized by ffmpeg", e->key); } + last_event_id = monitor->GetLastEventId() ; + video_writer_event_id = monitor->GetVideoWriterEventId(); + Debug(2, "last_event(%d), our current (%d)", last_event_id, video_writer_event_id ); + mIsOpening = false; Debug ( 1, "Opened input" ); @@ -430,7 +440,7 @@ int FfmpegCamera::OpenFfmpeg() { } } // end if have audio stream - Debug ( 1, "Opened codec" ); + Debug ( 1, "Opened audio codec" ); if ( (unsigned int)mVideoCodecContext->width != width || (unsigned int)mVideoCodecContext->height != height ) { Warning( "Monitor dimensions are %dx%d but camera is sending %dx%d", width, height, mVideoCodecContext->width, mVideoCodecContext->height ); @@ -478,12 +488,16 @@ int FfmpegCamera::CloseFfmpeg() { if ( mVideoCodecContext ) { avcodec_close(mVideoCodecContext); +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) avcodec_free_context(&mVideoCodecContext); +#endif mVideoCodecContext = NULL; // Freed by av_close_input_file } if ( mAudioCodecContext ) { avcodec_close(mAudioCodecContext); +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) avcodec_free_context(&mAudioCodecContext); +#endif mAudioCodecContext = NULL; // Freed by av_close_input_file } @@ -535,6 +549,5 @@ void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx) { return NULL; } } -} // end void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx) - +} #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index e9477dcbd..2b2af06b9 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -63,7 +63,12 @@ #define MAP_LOCKED 0 #endif -Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) { +Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : + id( p_id ), + shared_data(NULL), + trigger_data(NULL), + video_store_data(NULL) +{ strncpy( name, p_name, sizeof(name) ); #if ZM_MEM_MAPPED @@ -446,6 +451,7 @@ Monitor::Monitor( start_time = last_fps_time = time( 0 ); event = 0; + last_section_mod =0; Debug( 1, "Monitor %s\ function: %d\ @@ -749,7 +755,14 @@ unsigned int Monitor::GetLastWriteIndex() const { return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 ); } -unsigned int Monitor::GetLastEvent() const { +uint32_t Monitor::GetLastEventId() const { + Debug(2, "mem_ptr(%x), State(%d) last_read_index(%d) last_read_time(%d) last_event(%d)", + mem_ptr, + shared_data->state, + shared_data->last_read_index, + shared_data->last_read_time, + shared_data->last_event_id + ); return( shared_data->last_event_id ); } @@ -1226,7 +1239,6 @@ bool Monitor::Analyse() { return false; } - // 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. // Keeps minimum video frames. This should be ok, because we SHOULD be staying close to the head of the queue in analysis @@ -1237,8 +1249,6 @@ bool Monitor::Analyse() { mutex.unlock(); } } - - // 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; @@ -1246,43 +1256,28 @@ bool Monitor::Analyse() { Debug(2, "PacketQueue is empty" ); return false; } - Debug(2, "PacketQueue size (%d)", packetqueue.size() ); - - // The idea is that iterator_id never gets to the end. - -// analysis_it is == end when queue is empty? - Debug(2, "Analysis index (%d), last_Write(%d)", index, shared_data->last_write_index ); - if ( analysis_it == packetqueue.pktQueue.end() ) { - Debug(2, "Analysis index (%d), last_Write(%d), at end of queue", index, shared_data->last_write_index ); - analysis_it = packetqueue.pktQueue.begin(); - return false; - } - std::list::iterator next_it = analysis_it; - Debug(2, "next_it (%x)", next_it ); - ++next_it; struct timeval now; - gettimeofday( &now, NULL ); + gettimeofday(&now, NULL); int packets_processed = 0; - // Move to next packet. - while ( ( index != shared_data->last_write_index ) && ( next_it != packetqueue.pktQueue.end() ) ) { - analysis_it = next_it; - ++next_it; - Debug(2, "Analysis index (%d), last_Write(%d), *it: (%x) (%d)", index, shared_data->last_write_index, *analysis_it, (*analysis_it)->image_index ); + + ZMPacket *snap; + while ( ( snap = packetqueue.get_analysis_packet() ) && ( snap->score == -1 ) ) { + Debug(2, "Analysis index (%d), last_Write(%d)", index, shared_data->last_write_index); packets_processed += 1; - ZMPacket *snap = *analysis_it; struct timeval *timestamp = snap->timestamp; Image *snap_image = snap->image; Debug(2, "Analysing image (%d)", snap->image_index ); if ( snap->image_index == -1 ) { Debug(2, "skipping because audio"); + if ( ! packetqueue.increment_analysis_it() ) { + Debug(2, "No more packets to analyse"); + break; + } continue; } - - int last_section_mod = 0; - // signal is set by capture bool signal = shared_data->signal; bool signal_change = (signal != last_signal); @@ -1393,7 +1388,7 @@ bool Monitor::Analyse() { if ( section_length ) { // TODO: Wouldn't this be clearer if we just did something like if now - event->start > section_length ? int section_mod = timestamp->tv_sec % section_length; - Debug( 3, "Section length (%d) Last Section Mod(%d), new section mod(%d)", section_length, last_section_mod, section_mod ); + 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() ); @@ -1427,18 +1422,6 @@ bool Monitor::Analyse() { if ( (function != MOCORD && state != ALERT) ) { event = new Event( this, *timestamp, cause, noteSetMap ); shared_data->last_event_id = event->Id(); - mutex.lock(); - std::list::iterator it = packetqueue.pktQueue.begin(); - while( packetqueue.size() && ( it != analysis_it ) ) { - ZMPacket *queued_packet = packetqueue.popPacket(); - event->AddPacket( queued_packet ); - if ( queued_packet->image_index == -1 ) { - delete queued_packet; - } - it = packetqueue.pktQueue.begin(); - } - mutex.unlock(); - // The analysis packet will be added below. } } else if ( state != PREALARM ) { Info( "%s: %03d - Gone into prealarm state", name, image_count ); @@ -1473,6 +1456,9 @@ bool Monitor::Analyse() { Event::EmptyPreAlarmFrames(); } // end if score or not + // Flag the packet so we don't analyse it again + snap->score = score; + if ( state == PREALARM || state == ALARM ) { if ( config.create_analysis_images ) { bool got_anal_image = false; @@ -1502,45 +1488,14 @@ bool Monitor::Analyse() { } // end foreach zone } // analsys_images or record stats - mutex.lock(); - ZMPacket *pack = packetqueue.popPacket(); - mutex.unlock(); - event->AddPacket( pack, score ); - if ( pack->image_index == -1 ) { - delete pack; - pack = NULL; - } - if ( noteSetMap.size() > 0 ) event->updateNotes( noteSetMap ); } else if ( state == ALERT ) { // Alert means this frame has no motion, but we were alarmed and are still recording. - mutex.lock(); - ZMPacket *pack = packetqueue.popPacket(); - mutex.unlock(); - event->AddPacket( pack, score ); - if ( pack->image_index == -1 ) { - delete pack; - pack = NULL; - } if ( noteSetMap.size() > 0 ) event->updateNotes( noteSetMap ); } else if ( state == TAPE ) { if ( !(image_count%(frame_skip+1)) ) { - mutex.lock(); - ZMPacket *pack = packetqueue.popPacket(); -Debug(2,"adding packet (%x)", pack ); -Debug(2,"adding packet (%x) (%d)", pack, pack->image_index ); - mutex.unlock(); - if ( config.bulk_frame_interval > 1 ) { - event->AddPacket( pack, (event->Frames()AddPacket( pack ); - } - if ( pack->image_index == -1 ) { - delete pack; - pack = NULL; - } } } if ( function == MODECT || function == MOCORD ) { @@ -1562,15 +1517,29 @@ Debug(2,"adding packet (%x) (%d)", pack, pack->image_index ); last_section_mod = 0; } // end if ( trigger_data->trigger_state != TRIGGER_OFF ) + if ( event ) { + ZMPacket *queued_packet; + //popPacket will increment analysis_it if neccessary, so this will write out all packets in queue + while ( ( queued_packet = packetqueue.popPacket() ) ) { + Debug(2,"adding packet (%x) (%d)", queued_packet, queued_packet->image_index ); + event->AddPacket( queued_packet ); + if ( queued_packet->image_index == -1 ) { + delete queued_packet; + queued_packet = NULL; + } + } // end while write out queued_packets + } else { + packetqueue.increment_analysis_it(); + } + shared_data->last_read_index = snap->image_index; shared_data->last_read_time = now.tv_sec; analysis_image_count++; } // end while not at end of packetqueue - //mutex.unlock(); -if ( packets_processed > 0 ) - return true; -return false; -} + if ( packets_processed > 0 ) + return true; + return false; +} // end Monitor::Analyze void Monitor::Reload() { Debug( 1, "Reloading monitor %s", name ); @@ -2780,7 +2749,6 @@ Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) { * Returns -1 on failure. */ int Monitor::Capture() { - Debug(2,"Capture::Lock"); mutex.lock(); static int FirstCapture = 1; // Used in de-interlacing to indicate whether this is the even or odd image @@ -2857,19 +2825,19 @@ int Monitor::Capture() { packet->codec_type = camera->get_VideoStream()->codecpar->codec_type; if ( packet->packet.size && ! packet->in_frame ) { - Debug(2,"About to decode"); + //Debug(2,"About to decode"); if ( packet->decode( camera->get_VideoCodecContext() ) ) { - Debug(2,"Getimage"); + //Debug(2,"Getimage"); packet->get_image(); } // Have an av_packet, if ( packetqueue.video_packet_count || ( packet->packet.flags & AV_PKT_FLAG_KEY ) || event ) { - Debug(2, "Queueing packet"); + //Debug(2, "Queueing video packet"); packetqueue.queuePacket( packet ); } } else { // Non-avpackets are all keyframes. - Debug(2, "Queueing packet"); + //Debug(2, "Queueing video packet"); packetqueue.queuePacket( packet ); } @@ -3256,6 +3224,7 @@ void Monitor::get_ref_image() { ( shared_data->last_write_index == (unsigned int)image_buffer_count ) && ( shared_data->last_write_time == 0 ) + && ! zm_terminate ) { Warning( "Waiting for capture daemon" ); usleep( 100000 ); diff --git a/src/zm_monitor.h b/src/zm_monitor.h index d0866b34d..063ecb9a9 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -292,6 +292,7 @@ protected: int first_alarm_count; int last_alarm_count; bool last_signal; + int last_section_mod; int buffer_count; int prealarm_count; State state; @@ -454,7 +455,6 @@ public: const std::string &OutputCodec() const { return output_codec; } const std::string &OutputContainer() const { return output_container; } - uint32_t GetLastEventId() const { return shared_data->last_event_id; } uint32_t GetVideoWriterEventId() const { return video_store_data->current_event; } void SetVideoWriterEventId( uint32_t p_event_id ) { video_store_data->current_event = p_event_id; } @@ -470,7 +470,7 @@ public: int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } unsigned int GetLastReadIndex() const; unsigned int GetLastWriteIndex() const; - unsigned int GetLastEvent() const; + uint32_t GetLastEventId() const; double GetFPS() const; void UpdateAnalysisFPS(); void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); diff --git a/src/zm_packet.cpp b/src/zm_packet.cpp index ec6702aa6..9dbd93aca 100644 --- a/src/zm_packet.cpp +++ b/src/zm_packet.cpp @@ -36,6 +36,7 @@ ZMPacket::ZMPacket( ) { timestamp = NULL; analysis_image = NULL; image_index = -1; + score = -1; } ZMPacket::ZMPacket( ZMPacket &p ) { @@ -53,6 +54,7 @@ ZMPacket::ZMPacket( ZMPacket &p ) { *timestamp = *p.timestamp; analysis_image = NULL; image_index = -1; + score = -1; } ZMPacket::~ZMPacket() { @@ -103,6 +105,7 @@ void ZMPacket::reset() { timestamp = NULL; } #endif + score = -1; } int ZMPacket::decode( AVCodecContext *ctx ) { diff --git a/src/zm_packet.h b/src/zm_packet.h index 7fb3ee7c0..d0d85645b 100644 --- a/src/zm_packet.h +++ b/src/zm_packet.h @@ -44,6 +44,7 @@ class ZMPacket { struct timeval *timestamp; AVMediaType codec_type; int image_index; + public: AVPacket *av_packet() { return &packet; } AVPacket *set_packet( AVPacket *p ) ; diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index f1ce41ec7..12d1aeef0 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -26,6 +26,7 @@ zm_packetqueue::zm_packetqueue() { video_packet_count = 0; + analysis_it = pktQueue.begin(); } zm_packetqueue::~zm_packetqueue() { @@ -37,6 +38,12 @@ bool zm_packetqueue::queuePacket( ZMPacket* zm_packet ) { if ( zm_packet->codec_type == AVMEDIA_TYPE_VIDEO ) video_packet_count += 1; + if ( analysis_it == pktQueue.end() ) { + // ANalsys_it should only point to end when queue it empty + Debug(2,"pointing analysis_it to begining"); + analysis_it = pktQueue.begin(); + } + return true; } @@ -46,6 +53,9 @@ ZMPacket* zm_packetqueue::popPacket( ) { } ZMPacket *packet = pktQueue.front(); + if ( *analysis_it == packet ) + analysis_it ++; + pktQueue.pop_front(); if ( packet->codec_type == AVMEDIA_TYPE_VIDEO ) video_packet_count -= 1; @@ -108,6 +118,8 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream Debug(4, "Deleting a packet from the front, count is (%d)", delete_count ); packet = pktQueue.front(); + if ( *analysis_it == packet ) + analysis_it ++; if ( packet->codec_type == AVMEDIA_TYPE_VIDEO ) video_packet_count -= 1; pktQueue.pop_front(); @@ -129,6 +141,7 @@ void zm_packetqueue::clearQueue() { delete packet; } video_packet_count = 0; + analysis_it = pktQueue.begin(); } unsigned int zm_packetqueue::size() { @@ -195,4 +208,31 @@ void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVi } else { Debug(1, "Done looking for keyframe. Deleted %d frames. Remaining frames in queue: %d stream of head packet is (%d), keyframe (%d), distance(%d), packets(%d)", deleted_frames, pktQueue.size(), av_packet->stream_index, ( av_packet->flags & AV_PKT_FLAG_KEY ), distance( it, pktQueue.rend() ), pktQueue.size() ); } -} +} // end void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVideoStreamId ) + +// Returns a packet to analyse or NULL +ZMPacket *zm_packetqueue::get_analysis_packet() { + + if ( ! pktQueue.size() ) + return NULL; + if ( analysis_it == pktQueue.end() ) + return NULL; + + Debug(2, "Distance from head: (%d)", std::distance( pktQueue.begin(), analysis_it ) ); + Debug(2, "Distance from end: (%d)", std::distance( analysis_it, pktQueue.end() ) ); + + return *analysis_it; +} // end ZMPacket *zm_packetqueue::get_analysis_packet() + +// The idea is that analsys_it will only be == end() if the queue is empty +// probvlem here is that we don't want to analyse a packet twice. Maybe we can flag the packet analysed +bool zm_packetqueue::increment_analysis_it( ) { + // We do this instead of distance becuase distance will traverse the entire list in the worst case + std::list::iterator next_it = analysis_it; + next_it ++; + if ( next_it == pktQueue.end() ) { + return false; + } + analysis_it = next_it; + return true; +} // end bool zm_packetqueue::increment_analysis_it( ) diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index 7c386e3fc..d48869c18 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -31,6 +31,12 @@ extern "C" { } class zm_packetqueue { + public: // For now just to ease development + std::list pktQueue; + std::list::iterator analysis_it; + + int video_packet_count; // keep track of how many video packets we have, because we shouldn't have more than image_buffer_count + public: zm_packetqueue(); virtual ~zm_packetqueue(); @@ -41,8 +47,10 @@ public: unsigned int size(); unsigned int get_video_packet_count(); void clear_unwanted_packets( timeval *recording, int mVideoStreamId ); - std::list pktQueue; - int video_packet_count; // keep track of how many video packets we have, because we shouldn't have more than image_buffer_count + + // Functions to manage the analysis frame logic + bool increment_analysis_it(); + ZMPacket *get_analysis_packet(); }; #endif /* ZM_PACKETQUEUE_H */ diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 8c488194b..8cc444b6d 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -69,8 +69,8 @@ void StreamBase::updateFrameRate( double fps ) { while( effective_fps > maxfps ) { effective_fps /= 2.0; frame_mod *= 2; - } Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); + } } bool StreamBase::checkCommandQueue() { diff --git a/src/zm_thread.cpp b/src/zm_thread.cpp index 9728796be..1232ac5f0 100644 --- a/src/zm_thread.cpp +++ b/src/zm_thread.cpp @@ -70,7 +70,7 @@ void Mutex::lock() { if ( pthread_mutex_lock( &mMutex ) < 0 ) throw ThreadException( stringtf( "Unable to lock pthread mutex: %s", strerror(errno) ) ); - Debug(3, "Lock"); + //Debug(3, "Lock"); } void Mutex::lock( int secs ) @@ -91,7 +91,7 @@ void Mutex::unlock() { if ( pthread_mutex_unlock( &mMutex ) < 0 ) throw ThreadException( stringtf( "Unable to unlock pthread mutex: %s", strerror(errno) ) ); - Debug(3, "unLock"); + //Debug(3, "unLock"); } bool Mutex::locked() diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 3356466bb..4bdd5430a 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -43,10 +43,11 @@ VideoStore::VideoStore( filename = filename_in; format = format_in; - av_register_all(); packets_written = 0; frame_count = 0; + av_register_all(); + Info("Opening video storage stream %s format: %s", filename, format); ret = avformat_alloc_output_context2(&oc, NULL, NULL, filename); @@ -359,6 +360,7 @@ Error("Codec not set"); converted_in_samples = NULL; audio_out_codec = NULL; + audio_in_codec = NULL; audio_in_ctx = NULL; audio_out_stream = NULL; out_frame = NULL; @@ -635,18 +637,35 @@ Debug(3, "dts:%d, pts:%d, keyframe:%d", pkt.dts, pkt.pts, keyframe ); // allocation/de-allocation constantly, or whether we can just re-use it. // Just do a file open/close/writeheader/etc. // What if we were only doing audio recording? -// Used by both audio and video conversions - if ( in_frame ) { - av_frame_free(&in_frame); - in_frame = NULL; - } - if ( audio_in_ctx ) { - avcodec_free_context(&audio_in_ctx); - audio_in_ctx = NULL; + if (video_out_stream) { +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + // We allocate and copy in newer ffmpeg, so need to free it + avcodec_free_context(&video_in_ctx); +#endif + video_in_ctx=NULL; + + avcodec_close(video_out_ctx); +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) + avcodec_free_context(&video_out_ctx); +#endif + video_out_ctx = NULL; + Debug(4, "Success freeing video_out_ctx"); } if ( audio_out_stream ) { + if ( audio_in_codec ) { + avcodec_close(audio_in_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(&audio_in_ctx); +#endif + audio_in_ctx = NULL; + audio_in_codec = NULL; + } // end if audio_in_codec + avcodec_close(audio_out_ctx); +#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) avcodec_free_context(&audio_out_ctx); +#endif audio_out_ctx = NULL; #ifdef HAVE_LIBAVRESAMPLE if ( resample_ctx ) { diff --git a/src/zm_videostore.h b/src/zm_videostore.h index e11517ef3..d63e56360 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -18,8 +18,6 @@ class VideoStore; class VideoStore { private: - unsigned int packets_written; - unsigned int frame_count; AVOutputFormat *out_format; AVFormatContext *oc; @@ -41,10 +39,13 @@ int audio_in_stream_index; AVFrame *out_frame; AVCodecContext *video_in_ctx; + AVCodec *audio_in_codec; AVCodecContext *audio_in_ctx; int ret; SWScale swscale; + unsigned int packets_written; + unsigned int frame_count; // The following are used when encoding the audio stream to AAC AVCodec *audio_out_codec; diff --git a/src/zmu.cpp b/src/zmu.cpp index 46ba35ac6..4c94d0b51 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -514,10 +514,10 @@ int main( int argc, char *argv[] ) { } if ( function & ZMU_EVENT ) { if ( verbose ) - printf( "Last event id: %d\n", monitor->GetLastEvent() ); + printf( "Last event id: %d\n", monitor->GetLastEventId() ); else { if ( have_output ) printf( "%c", separator ); - printf( "%d", monitor->GetLastEvent() ); + printf( "%d", monitor->GetLastEventId() ); have_output = true; } } @@ -712,7 +712,7 @@ int main( int argc, char *argv[] ) { tv.tv_sec, tv.tv_usec/10000, monitor->GetLastReadIndex(), monitor->GetLastWriteIndex(), - monitor->GetLastEvent(), + monitor->GetLastEventId(), monitor->GetFPS() ); delete monitor; diff --git a/web/ajax/stream.php b/web/ajax/stream.php index 5c653d068..1f0245a69 100644 --- a/web/ajax/stream.php +++ b/web/ajax/stream.php @@ -116,7 +116,9 @@ switch ( $data['type'] ) { case MSG_DATA_WATCH : { $data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg ); + Logger::Debug("FPS: " . $data['fps'] ); $data['fps'] = round( $data['fps'], 2 ); + Logger::Debug("FPS: " . $data['fps'] ); $data['rate'] /= RATE_BASE; $data['delay'] = round( $data['delay'], 2 ); $data['zoom'] = round( $data['zoom']/SCALE_BASE, 1 ); diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php index afdfd7bd6..55819329c 100644 --- a/web/includes/csrf/csrf-magic.php +++ b/web/includes/csrf/csrf-magic.php @@ -189,21 +189,21 @@ function csrf_check($fatal = true) { $tokens = ''; do { if (!isset($_POST[$name])) { -Logger::Debug("POST[$name] is not set"); +#Logger::Debug("POST[$name] is not set"); break; -} else { -Logger::Debug("POST[$name] is set as " . $_POST[$name] ); +#} else { +#Logger::Debug("POST[$name] is set as " . $_POST[$name] ); } // we don't regenerate a token and check it because some token creation // schemes are volatile. $tokens = $_POST[$name]; if (!csrf_check_tokens($tokens)) { -Logger::Debug("Failed checking tokens"); +#Logger::Debug("Failed checking tokens"); break; -} else { -Logger::Debug("Token passed"); +#} else { +#Logger::Debug("Token passed"); } $ok = true; } while (false); @@ -308,27 +308,27 @@ function csrf_check_tokens($tokens) { * Checks if a token is valid. */ function csrf_check_token($token) { -Logger::Debug("Checking CSRF token $token"); +#Logger::Debug("Checking CSRF token $token"); if (strpos($token, ':') === false) { -Logger::Debug("Checking CSRF token $token bad because no :"); +#Logger::Debug("Checking CSRF token $token bad because no :"); return false; } list($type, $value) = explode(':', $token, 2); if (strpos($value, ',') === false) { -Logger::Debug("Checking CSRF token $token bad because no ,"); +#Logger::Debug("Checking CSRF token $token bad because no ,"); return false; } list($x, $time) = explode(',', $token, 2); if ($GLOBALS['csrf']['expires']) { if (time() > $time + $GLOBALS['csrf']['expires']) { -Logger::Debug("Checking CSRF token $token bad because expired"); +#Logger::Debug("Checking CSRF token $token bad because expired"); return false; } } switch ($type) { case 'sid': { - Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) ); + #Logger::Debug("Checking sid: $value === " . csrf_hash(session_id(), $time) ); return $value === csrf_hash(session_id(), $time); } case 'cookie': @@ -341,7 +341,7 @@ return false; Logger::Debug("Checking key: no key set" ); return false; } - Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) ); + #Logger::Debug("Checking sid: $value === " . csrf_hash($GLOBALS['csrf']['key'], $time) ); return $value === csrf_hash($GLOBALS['csrf']['key'], $time); // We could disable these 'weaker' checks if 'key' was set, but // that doesn't make me feel good then about the cookie-based diff --git a/web/index.php b/web/index.php index 845540327..eb406ceb3 100644 --- a/web/index.php +++ b/web/index.php @@ -195,7 +195,7 @@ isset($action) || $action = NULL; if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $view != 'video' && $request != 'control' && $view != 'frames') { require_once( 'includes/csrf/csrf-magic.php' ); - Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); + #Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); csrf_check(); } diff --git a/web/js/logger.js b/web/js/logger.js index 9cbe50268..6bd465c8a 100644 --- a/web/js/logger.js +++ b/web/js/logger.js @@ -50,7 +50,10 @@ function logReport( level, message, file, line ) if ( !debugReq ) { - debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+Browser.Platform.name; + if ( Browser ) + debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown'); + else + debugParms = "view=request&request=log&task=create&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown"; debugReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain' } ); } var requestParms = debugParms; diff --git a/web/skins/classic/css/flat/views/montagereview.css b/web/skins/classic/css/flat/views/montagereview.css index 743df40a1..6f8feddf3 100644 --- a/web/skins/classic/css/flat/views/montagereview.css +++ b/web/skins/classic/css/flat/views/montagereview.css @@ -4,7 +4,7 @@ display: inline-flex; border: 1px solid black; width: 25%; - padding: 9px; + padding: 4px; } #ScaleDiv label, #SpeedDiv label { diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 561f7e6c2..03457f38f 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -42,7 +42,7 @@ function evaluateLoadTimes() { imageLoadTimesEvaluated=0; setSpeed(speedIndex); $('fps').innerHTML="Display refresh rate is " + (1000 / currentDisplayInterval).toFixed(1) + " per second, avgFrac=" + avgFrac.toFixed(3) + "."; -} +} // end evaluateLoadTimes() // time is seconds since epoch function SetImageSource( monId, time ) { @@ -465,12 +465,12 @@ function setSpeed( speed_index ) { playSecsperInterval = Math.floor( 1000 * currentSpeed * currentDisplayInterval ) / 1000000; console.log("playSecsPerInterval: " + playSecsperInterval + " = currentspeed:" + currentSpeed + " * " + currentDisplayInterval + " /1000"); showSpeed(speed_index); - if ( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update + if ( timerInterval != currentDisplayInterval || currentSpeed == 0 ) timerFire(); // if the timer isn't firing we need to trigger it to update } function setLive(value) { liveMode = value; - redrawScreen(); + changeDateTime(); } @@ -510,16 +510,12 @@ function clicknav(minSecs,maxSecs,live) {// we use the current time if we can if ( live == 1 ) liveStr="&live=1"; - var fitStr="&fit=0"; - if ( fitMode == 1 ) - fitStr="&fit=1"; - var zoomStr=""; for ( var i=0; i < numMonitors; i++ ) if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1 zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2); - var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; + var uri = "?view=" + currentView + '&fit='+(fitMode==1?'1':'0') + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; window.location = uri; } // end function clicknav diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index d6943dac5..69d9c3d22 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -31,14 +31,18 @@ var groupStr=; // Because we might not have time as the criteria, figure out the min/max time when we run the query -$minTimeSecs = strtotime('2036-01-01 01:01:01'); -$maxTimeSecs = strtotime('1950-01-01 01:01:01'); +if ( ! $maxTimeSecs ) +$maxTimeSecs = time(); +if ( ! $minTimeSecs ) +$minTimeSecs = strtotime('2010-01-01 01:01:01'); // This builds the list of events that are eligible from this range $index = 0; $anyAlarms = false; +if ( ! $initialModeIsLive ) { + $result = dbQuery( $eventsSql ); if ( ! $result ) { Fatal('SQL-ERR'); @@ -81,6 +85,7 @@ if ( !isset($minTime) || !isset($maxTime) ) { $minTime = strftime($minTimeSecs); } else { $minTimeSecs = strtotime($minTime); + $maxTimeSecs = strtotime($maxTime); } @@ -136,6 +141,7 @@ if ( $mId > 0 ) { } echo "var maxScore=$maxScore;\n"; // used to skip frame load if we find no alarms. +} // end if initialmodeislive echo "var monitorName = [];\n"; echo "var monitorLoading = [];\n"; echo "var monitorImageObject = [];\n"; diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 69a5c2921..37add6ddc 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -106,6 +106,7 @@ if ( !isset($_REQUEST['minTime']) && !isset($_REQUEST['maxTime']) ) { $time = time(); $maxTime = strftime("%FT%T",$time); $minTime = strftime("%FT%T",$time - 3600); + Logger::Debug("Defaulting to $minTime to $maxTime"); } if ( isset($_REQUEST['minTime']) ) $minTime = validHtmlStr($_REQUEST['minTime']); @@ -113,7 +114,7 @@ if ( isset($_REQUEST['minTime']) ) if ( isset($_REQUEST['maxTime']) ) $maxTime = validHtmlStr($_REQUEST['maxTime']); -// AS a special case a "all" is passed in as an exterme interval - if so , clear them here and let the database query find them +// AS a special case a "all" is passed in as an extreme interval - if so, clear them here and let the database query find them if ( (strtotime($maxTime) - strtotime($minTime))/(365*24*3600) > 30 ) { // test years @@ -161,6 +162,7 @@ $eventsSql .= ' GROUP BY E.Id,E.Name,E.StartTime,E.Length,E.Frames,E.MaxScore,E. if ( isset($minTime) && isset($maxTime) ) { $minTimeSecs = strtotime($minTime); $maxTimeSecs = strtotime($maxTime); + Logger::Debug("Min/max time secs: $minTimeSecs $maxTimeSecs"); $eventsSql .= " HAVING CalcEndTimeSecs > '" . $minTimeSecs . "' AND StartTimeSecs < '" . $maxTimeSecs . "'"; $frameSql .= " AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'"; } @@ -190,31 +192,31 @@ xhtmlHeaders(__FILE__, translate('MontageReview') );
- - - x + + + x
- - - fps + + + fps
- - - - - - - - - + + + + + + + + +
- - - - + + + +