2017-05-17 00:04:56 +08:00
//ZoneMinder Packet Queue Implementation Class
//Copyright 2016 Steve Gilvarry
//
//This file is part of ZoneMinder.
//
//ZoneMinder is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//ZoneMinder is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with ZoneMinder. If not, see <http://www.gnu.org/licenses/>.
# include "zm_packetqueue.h"
# include "zm_ffmpeg.h"
2017-08-24 03:05:44 +08:00
# include <sys/time.h>
2017-05-17 00:04:56 +08:00
2018-10-15 22:51:56 +08:00
zm_packetqueue : : zm_packetqueue ( int p_max_stream_id ) {
max_stream_id = p_max_stream_id ;
packet_counts = new int [ max_stream_id + 1 ] ;
for ( int i = 0 ; i < = max_stream_id ; + + i )
2018-10-15 23:13:10 +08:00
packet_counts [ i ] = 0 ;
2017-05-17 00:04:56 +08:00
}
zm_packetqueue : : ~ zm_packetqueue ( ) {
2017-08-01 03:49:27 +08:00
clearQueue ( ) ;
2018-10-15 22:51:56 +08:00
delete [ ] packet_counts ;
packet_counts = NULL ;
2017-05-17 00:04:56 +08:00
}
2018-10-15 22:51:56 +08:00
bool zm_packetqueue : : queuePacket ( ZMPacket * zm_packet ) {
pktQueue . push_back ( zm_packet ) ;
packet_counts [ zm_packet - > packet . stream_index ] + = 1 ;
2017-05-17 00:04:56 +08:00
return true ;
}
2018-10-15 22:51:56 +08:00
bool zm_packetqueue : : queuePacket ( AVPacket * av_packet ) {
2017-05-17 00:04:56 +08:00
2018-10-15 22:51:56 +08:00
ZMPacket * zm_packet = new ZMPacket ( av_packet ) ;
2017-05-17 00:04:56 +08:00
2018-10-15 22:51:56 +08:00
pktQueue . push_back ( zm_packet ) ;
packet_counts [ zm_packet - > packet . stream_index ] + = 1 ;
2017-05-17 00:04:56 +08:00
return true ;
}
ZMPacket * zm_packetqueue : : popPacket ( ) {
if ( pktQueue . empty ( ) ) {
return NULL ;
}
ZMPacket * packet = pktQueue . front ( ) ;
pktQueue . pop_front ( ) ;
2018-10-15 22:51:56 +08:00
packet_counts [ packet - > packet . stream_index ] - = 1 ;
2017-05-17 00:04:56 +08:00
return packet ;
}
2018-10-15 22:51:56 +08:00
unsigned int zm_packetqueue : : clearQueue ( unsigned int frames_to_keep , int stream_id ) {
2017-05-17 00:04:56 +08:00
2018-10-15 22:51:56 +08:00
Debug ( 3 , " Clearing all but %d frames, queue has %d " , frames_to_keep , pktQueue . size ( ) ) ;
2017-05-17 00:04:56 +08:00
frames_to_keep + = 1 ;
if ( pktQueue . empty ( ) ) {
Debug ( 3 , " Queue is empty " ) ;
return 0 ;
}
2017-08-24 03:05:44 +08:00
std : : list < ZMPacket * > : : reverse_iterator it ;
2017-05-17 00:04:56 +08:00
ZMPacket * packet = NULL ;
for ( it = pktQueue . rbegin ( ) ; it ! = pktQueue . rend ( ) & & frames_to_keep ; + + it ) {
ZMPacket * zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
2018-10-15 22:51:56 +08:00
Debug ( 4 , " Looking at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d) " ,
av_packet - > stream_index , ( av_packet - > flags & AV_PKT_FLAG_KEY ) , frames_to_keep ) ;
2017-05-17 00:04:56 +08:00
// Want frames_to_keep video keyframes. Otherwise, we may not have enough
2018-01-08 02:39:13 +08:00
if ( ( av_packet - > stream_index = = stream_id ) ) {
//&& ( av_packet->flags & AV_PKT_FLAG_KEY ) ) {
2017-05-17 00:04:56 +08:00
frames_to_keep - - ;
}
}
2018-01-08 02:39:13 +08:00
2018-10-15 22:51:56 +08:00
// Make sure we start on a keyframe
2018-01-08 02:39:13 +08:00
for ( ; it ! = pktQueue . rend ( ) ; + + it ) {
ZMPacket * zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
2018-10-15 22:51:56 +08:00
Debug ( 5 , " Looking for keyframe at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d) " ,
av_packet - > stream_index , ( av_packet - > flags & AV_PKT_FLAG_KEY ) , frames_to_keep ) ;
2018-01-08 02:39:13 +08:00
// Want frames_to_keep video keyframes. Otherwise, we may not have enough
if ( ( av_packet - > stream_index = = stream_id ) & & ( av_packet - > flags & AV_PKT_FLAG_KEY ) ) {
2018-10-15 22:51:56 +08:00
Debug ( 4 , " Found keyframe at packet with stream index (%d) with keyframe (%d), frames_to_keep is (%d) " ,
av_packet - > stream_index , ( av_packet - > flags & AV_PKT_FLAG_KEY ) , frames_to_keep ) ;
2018-01-08 02:39:13 +08:00
break ;
}
}
2017-06-01 08:44:43 +08:00
if ( frames_to_keep ) {
2018-10-15 22:51:56 +08:00
Debug ( 3 , " Hit end of queue, still need (%d) video frames " , frames_to_keep ) ;
2018-01-17 23:01:48 +08:00
}
if ( it ! = pktQueue . rend ( ) ) {
// We want to keep this packet, so advance to the next
2018-04-12 23:29:35 +08:00
+ + it ;
2017-06-01 08:44:43 +08:00
}
2017-05-17 00:04:56 +08:00
unsigned int delete_count = 0 ;
while ( it ! = pktQueue . rend ( ) ) {
2018-10-15 22:51:56 +08:00
Debug ( 4 , " Deleting a packet from the front, count is (%d) " , delete_count ) ;
2017-05-17 00:04:56 +08:00
packet = pktQueue . front ( ) ;
pktQueue . pop_front ( ) ;
2018-10-15 22:51:56 +08:00
packet_counts [ packet - > packet . stream_index ] - = 1 ;
2017-05-17 00:04:56 +08:00
delete packet ;
delete_count + = 1 ;
}
2018-10-15 22:51:56 +08:00
packet = NULL ; // tidy up for valgrind
Debug ( 3 , " Deleted %d packets, %d remaining " , delete_count , pktQueue . size ( ) ) ;
2017-05-17 00:04:56 +08:00
return delete_count ;
} // end unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream_id )
void zm_packetqueue : : clearQueue ( ) {
ZMPacket * packet = NULL ;
2018-09-14 04:18:28 +08:00
int delete_count = 0 ;
2019-01-17 04:20:17 +08:00
while ( ! pktQueue . empty ( ) ) {
2017-05-17 00:04:56 +08:00
packet = pktQueue . front ( ) ;
2018-10-15 22:51:56 +08:00
packet_counts [ packet - > packet . stream_index ] - = 1 ;
2017-05-17 00:04:56 +08:00
pktQueue . pop_front ( ) ;
delete packet ;
2018-09-14 04:18:28 +08:00
delete_count + = 1 ;
2017-05-17 00:04:56 +08:00
}
2018-09-14 04:18:28 +08:00
Debug ( 3 , " Deleted (%d) packets " , delete_count ) ;
2017-05-17 00:04:56 +08:00
}
unsigned int zm_packetqueue : : size ( ) {
return pktQueue . size ( ) ;
}
2018-10-15 22:51:56 +08:00
int zm_packetqueue : : packet_count ( int stream_id ) {
return packet_counts [ stream_id ] ;
} // end int zm_packetqueue::packet_count( int stream_id )
2017-05-17 00:04:56 +08:00
void zm_packetqueue : : clear_unwanted_packets ( timeval * recording_started , int mVideoStreamId ) {
// Need to find the keyframe <= recording_started. Can get rid of audio packets.
2018-10-15 22:51:56 +08:00
if ( pktQueue . empty ( ) )
2017-05-17 00:04:56 +08:00
return ;
// Step 1 - find keyframe < recording_started.
// Step 2 - pop packets until we get to the packet in step 2
2017-08-24 03:05:44 +08:00
std : : list < ZMPacket * > : : reverse_iterator it ;
2017-05-17 00:04:56 +08:00
2019-01-15 03:00:45 +08:00
Debug ( 3 , " Looking for keyframe after start recording stream id (%d) " , mVideoStreamId ) ;
2017-05-17 00:04:56 +08:00
for ( it = pktQueue . rbegin ( ) ; 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 = = mVideoStreamId )
& &
2019-01-15 03:00:45 +08:00
timercmp ( & ( zm_packet - > timestamp ) , recording_started , < = )
2017-05-17 00:04:56 +08:00
) {
2019-01-15 03:00:45 +08:00
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 ) ;
2017-05-17 00:04:56 +08:00
break ;
}
}
if ( it = = pktQueue . rend ( ) ) {
2018-01-22 10:27:44 +08:00
Debug ( 1 , " Didn't find a keyframe before event starttime. keeping all " ) ;
2017-05-17 00:04:56 +08:00
return ;
}
2017-06-01 08:44:43 +08:00
ZMPacket * zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
Debug ( 3 , " Found packet before start with stream index (%d) with keyframe (%d), distance(%d), size(%d) " ,
av_packet - > stream_index ,
( av_packet - > flags & AV_PKT_FLAG_KEY ) ,
distance ( it , pktQueue . rend ( ) ) ,
pktQueue . size ( ) ) ;
unsigned int deleted_frames = 0 ;
2017-05-17 00:04:56 +08:00
ZMPacket * packet = NULL ;
2019-01-15 03:00:45 +08:00
while ( distance ( it , pktQueue . rend ( ) ) > 1 ) {
2017-06-01 08:44:43 +08:00
//while ( pktQueue.rend() != it ) {
2017-05-17 00:04:56 +08:00
packet = pktQueue . front ( ) ;
pktQueue . pop_front ( ) ;
2018-10-15 22:51:56 +08:00
packet_counts [ packet - > packet . stream_index ] - = 1 ;
2017-05-17 00:04:56 +08:00
delete packet ;
2017-06-01 08:44:43 +08:00
deleted_frames + = 1 ;
}
2018-10-15 22:51:56 +08:00
packet = NULL ; // tidy up for valgrind
2017-06-01 08:44:43 +08:00
zm_packet = pktQueue . front ( ) ;
av_packet = & ( zm_packet - > packet ) ;
if ( ( ! ( av_packet - > flags & AV_PKT_FLAG_KEY ) ) | | ( av_packet - > stream_index ! = mVideoStreamId ) ) {
2019-01-15 03:00:45 +08:00
Error ( " 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 ( ) ) ;
2017-06-01 08:44:43 +08:00
} else {
2019-01-15 03:00:45 +08:00
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 ( ) ) ;
2017-05-17 00:04:56 +08:00
}
2018-10-15 22:51:56 +08:00
} // end void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVideoStreamId )