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;
|
int ret;
|
||||||
|
|
||||||
|
struct timeval video_buffer_duration = monitor->GetVideoBufferDuration();
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( !frameComplete ) {
|
while ( !frameComplete ) {
|
||||||
av_init_packet(&packet);
|
av_init_packet(&packet);
|
||||||
|
@ -920,6 +922,13 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
if ( packet.stream_index == mVideoStreamId ) {
|
if ( packet.stream_index == mVideoStreamId ) {
|
||||||
if ( keyframe ) {
|
if ( keyframe ) {
|
||||||
Debug(3, "Clearing queue");
|
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 (
|
if (
|
||||||
packetqueue->packet_count(mVideoStreamId)
|
packetqueue->packet_count(mVideoStreamId)
|
||||||
>=
|
>=
|
||||||
|
@ -933,7 +942,6 @@ int FfmpegCamera::CaptureAndRecord(
|
||||||
packetqueue->packet_count(mVideoStreamId)+1);
|
packetqueue->packet_count(mVideoStreamId)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
packetqueue->clearQueue(monitor->GetPreEventCount(), mVideoStreamId);
|
|
||||||
packetqueue->queuePacket(&packet);
|
packetqueue->queuePacket(&packet);
|
||||||
} else if ( packetqueue->size() ) {
|
} else if ( packetqueue->size() ) {
|
||||||
// it's a keyframe or we already have something in the queue
|
// it's a keyframe or we already have something in the queue
|
||||||
|
|
|
@ -338,6 +338,7 @@ Monitor::Monitor(
|
||||||
warmup_count( p_warmup_count ),
|
warmup_count( p_warmup_count ),
|
||||||
pre_event_count( p_pre_event_count ),
|
pre_event_count( p_pre_event_count ),
|
||||||
post_event_count( p_post_event_count ),
|
post_event_count( p_post_event_count ),
|
||||||
|
video_buffer_duration({0}),
|
||||||
stream_replay_buffer( p_stream_replay_buffer ),
|
stream_replay_buffer( p_stream_replay_buffer ),
|
||||||
section_length( p_section_length ),
|
section_length( p_section_length ),
|
||||||
min_section_length( p_min_section_length ),
|
min_section_length( p_min_section_length ),
|
||||||
|
@ -368,6 +369,12 @@ Monitor::Monitor(
|
||||||
privacy_bitmask( NULL ),
|
privacy_bitmask( NULL ),
|
||||||
event_delete_thread(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(name, p_name, sizeof(name)-1);
|
||||||
|
|
||||||
strncpy(event_prefix, p_event_prefix, sizeof(event_prefix)-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 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 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
|
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 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 section_length; // How long events should last in continuous modes
|
||||||
int min_section_length; // Minimum event length when using event_close_mode == ALARM
|
int min_section_length; // Minimum event length when using event_close_mode == ALARM
|
||||||
|
@ -467,7 +468,8 @@ public:
|
||||||
void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; }
|
void SetVideoWriterEventId( unsigned long long p_event_id ) { video_store_data->current_event = p_event_id; }
|
||||||
|
|
||||||
unsigned int GetPreEventCount() const { return pre_event_count; };
|
unsigned int GetPreEventCount() const { return pre_event_count; };
|
||||||
int GetImageBufferCount() const { return image_buffer_count; };
|
struct timeval GetVideoBufferDuration() const { return video_buffer_duration; };
|
||||||
|
int GetImageBufferCount() const { return image_buffer_count; };
|
||||||
State GetState() const;
|
State GetState() const;
|
||||||
int GetImage( int index=-1, int scale=100 );
|
int GetImage( int index=-1, int scale=100 );
|
||||||
Snapshot *getSnapshot() const;
|
Snapshot *getSnapshot() const;
|
||||||
|
|
|
@ -204,6 +204,72 @@ void zm_packetqueue::clearQueue() {
|
||||||
Debug(3, "Deleted (%d) packets", delete_count );
|
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() {
|
unsigned int zm_packetqueue::size() {
|
||||||
return pktQueue.size();
|
return pktQueue.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
bool popVideoPacket(ZMPacket* packet);
|
bool popVideoPacket(ZMPacket* packet);
|
||||||
bool popAudioPacket(ZMPacket* packet);
|
bool popAudioPacket(ZMPacket* packet);
|
||||||
unsigned int clearQueue(unsigned int video_frames_to_keep, int stream_id);
|
unsigned int clearQueue(unsigned int video_frames_to_keep, int stream_id);
|
||||||
|
unsigned int clearQueue(struct timeval *duration, int streamid);
|
||||||
void clearQueue();
|
void clearQueue();
|
||||||
void dumpQueue();
|
void dumpQueue();
|
||||||
unsigned int size();
|
unsigned int size();
|
||||||
|
|
Loading…
Reference in New Issue