Properly compute video buffer length when analysis fps is set
Currently the number of video frames kept in the buffer is set as the pre_event_count. This falls short when the capture fps is larger than the analysis fps. Fix by computing the retained video duration as pre_event_count/analysis_fps No change if analysis fps is not set. Signed-off-by: Selva Nair <selva.nair@gmail.com>
This commit is contained in:
parent
c3250dea00
commit
2e7fad68d1
|
@ -744,6 +744,8 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
}
|
||||
int ret;
|
||||
|
||||
struct timeval video_buffer_duration = monitor->GetVideoBufferDuration();
|
||||
|
||||
int frameComplete = false;
|
||||
while ( !frameComplete ) {
|
||||
av_init_packet(&packet);
|
||||
|
@ -920,6 +922,13 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
if ( packet.stream_index == mVideoStreamId ) {
|
||||
if ( keyframe ) {
|
||||
Debug(3, "Clearing queue");
|
||||
if (video_buffer_duration.tv_sec > 0 || video_buffer_duration.tv_usec > 0) {
|
||||
packetqueue->clearQueue(&video_buffer_duration, mVideoStreamId);
|
||||
}
|
||||
else {
|
||||
packetqueue->clearQueue(monitor->GetPreEventCount(), mVideoStreamId);
|
||||
}
|
||||
|
||||
if (
|
||||
packetqueue->packet_count(mVideoStreamId)
|
||||
>=
|
||||
|
@ -933,7 +942,6 @@ int FfmpegCamera::CaptureAndRecord(
|
|||
packetqueue->packet_count(mVideoStreamId)+1);
|
||||
}
|
||||
|
||||
packetqueue->clearQueue(monitor->GetPreEventCount(), mVideoStreamId);
|
||||
packetqueue->queuePacket(&packet);
|
||||
} else if ( packetqueue->size() ) {
|
||||
// it's a keyframe or we already have something in the queue
|
||||
|
|
|
@ -338,6 +338,7 @@ Monitor::Monitor(
|
|||
warmup_count( p_warmup_count ),
|
||||
pre_event_count( p_pre_event_count ),
|
||||
post_event_count( p_post_event_count ),
|
||||
video_buffer_duration({0}),
|
||||
stream_replay_buffer( p_stream_replay_buffer ),
|
||||
section_length( p_section_length ),
|
||||
min_section_length( p_min_section_length ),
|
||||
|
@ -368,6 +369,12 @@ Monitor::Monitor(
|
|||
privacy_bitmask( NULL ),
|
||||
event_delete_thread(NULL)
|
||||
{
|
||||
if (analysis_fps > 0.0) {
|
||||
uint64_t usec = round(1000000*pre_event_count/analysis_fps);
|
||||
video_buffer_duration.tv_sec = usec/1000000;
|
||||
video_buffer_duration.tv_usec = usec % 1000000;
|
||||
}
|
||||
|
||||
strncpy(name, p_name, sizeof(name)-1);
|
||||
|
||||
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-1);
|
||||
|
|
|
@ -273,6 +273,7 @@ protected:
|
|||
int warmup_count; // How many images to process before looking for events
|
||||
int pre_event_count; // How many images to hold and prepend to an alarm event
|
||||
int post_event_count; // How many unalarmed images must occur before the alarm state is reset
|
||||
struct timeval video_buffer_duration; // How long a video segment to keep in buffer (set only if analysis fps != 0 )
|
||||
int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now
|
||||
int section_length; // How long events should last in continuous modes
|
||||
int min_section_length; // Minimum event length when using event_close_mode == ALARM
|
||||
|
@ -467,6 +468,7 @@ public:
|
|||
void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; }
|
||||
|
||||
unsigned int GetPreEventCount() const { return pre_event_count; };
|
||||
struct timeval GetVideoBufferDuration() const { return video_buffer_duration; };
|
||||
int GetImageBufferCount() const { return image_buffer_count; };
|
||||
State GetState() const;
|
||||
int GetImage( int index=-1, int scale=100 );
|
||||
|
|
|
@ -204,6 +204,72 @@ void zm_packetqueue::clearQueue() {
|
|||
Debug(3, "Deleted (%d) packets", delete_count );
|
||||
}
|
||||
|
||||
// clear queue keeping only specified duration of video -- return number of pkts removed
|
||||
unsigned int zm_packetqueue::clearQueue(struct timeval *duration, int streamId) {
|
||||
|
||||
if (pktQueue.empty()) {
|
||||
return 0;
|
||||
}
|
||||
struct timeval keep_from;
|
||||
std::list<ZMPacket *>::reverse_iterator it;
|
||||
it = pktQueue.rbegin();
|
||||
|
||||
timersub(&(*it)->timestamp, duration, &keep_from);
|
||||
++it;
|
||||
|
||||
Debug(3, "Looking for frame before queue keep time with stream id (%d), queue has %d packets",
|
||||
streamId, pktQueue.size());
|
||||
for ( ; it != pktQueue.rend(); ++it) {
|
||||
ZMPacket *zm_packet = *it;
|
||||
AVPacket *av_packet = &(zm_packet->packet);
|
||||
if (av_packet->stream_index == streamId
|
||||
&& timercmp( &zm_packet->timestamp, &keep_from, <= )) {
|
||||
Debug(3, "Found frame before keep time with stream index %d at %d.%d",
|
||||
av_packet->stream_index,
|
||||
zm_packet->timestamp.tv_sec,
|
||||
zm_packet->timestamp.tv_usec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it == pktQueue.rend()) {
|
||||
Debug(1, "Didn't find a frame before queue preserve time. keeping all");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Debug(3, "Looking for keyframe");
|
||||
for ( ; it != pktQueue.rend(); ++it) {
|
||||
ZMPacket *zm_packet = *it;
|
||||
AVPacket *av_packet = &(zm_packet->packet);
|
||||
if (av_packet->flags & AV_PKT_FLAG_KEY
|
||||
&& av_packet->stream_index == streamId) {
|
||||
Debug(3, "Found keyframe before start with stream index %d at %d.%d",
|
||||
av_packet->stream_index,
|
||||
zm_packet->timestamp.tv_sec,
|
||||
zm_packet->timestamp.tv_usec );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( it == pktQueue.rend() ) {
|
||||
Debug(1, "Didn't find a keyframe before event starttime. keeping all" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int deleted_frames = 0;
|
||||
ZMPacket *zm_packet = NULL;
|
||||
while (distance(it, pktQueue.rend()) > 1) {
|
||||
zm_packet = pktQueue.front();
|
||||
pktQueue.pop_front();
|
||||
packet_counts[zm_packet->packet.stream_index] -= 1;
|
||||
delete zm_packet;
|
||||
deleted_frames += 1;
|
||||
}
|
||||
zm_packet = NULL;
|
||||
Debug(3, "Deleted %d frames", deleted_frames);
|
||||
|
||||
return deleted_frames;
|
||||
}
|
||||
|
||||
unsigned int zm_packetqueue::size() {
|
||||
return pktQueue.size();
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
bool popVideoPacket(ZMPacket* packet);
|
||||
bool popAudioPacket(ZMPacket* packet);
|
||||
unsigned int clearQueue(unsigned int video_frames_to_keep, int stream_id);
|
||||
unsigned int clearQueue(struct timeval *duration, int streamid);
|
||||
void clearQueue();
|
||||
void dumpQueue();
|
||||
unsigned int size();
|
||||
|
|
Loading…
Reference in New Issue