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/>.
2021-01-07 22:43:53 +08:00
// PacketQueue must know about all iterators and manage them
2017-05-17 00:04:56 +08:00
# include "zm_packetqueue.h"
2021-02-04 11:47:28 +08:00
2017-05-17 00:04:56 +08:00
# include "zm_ffmpeg.h"
2021-02-04 11:47:28 +08:00
# include "zm_packet.h"
2019-02-26 22:45:40 +08:00
# include "zm_signal.h"
2017-08-24 03:05:44 +08:00
# include <sys/time.h>
2017-05-17 00:04:56 +08:00
2021-02-01 10:30:12 +08:00
PacketQueue : : PacketQueue ( ) :
video_stream_id ( - 1 ) ,
max_video_packet_count ( - 1 ) ,
2021-03-27 02:26:37 +08:00
pre_event_video_packet_count ( - 1 ) ,
2021-02-01 10:30:12 +08:00
max_stream_id ( - 1 ) ,
packet_counts ( nullptr ) ,
2021-03-23 00:04:32 +08:00
deleting ( false ) ,
keep_keyframes ( false )
2020-12-22 23:20:44 +08:00
{
2017-05-17 00:04:56 +08:00
}
2021-02-01 10:30:12 +08:00
/* Assumes queue is empty when adding streams
* Assumes first stream added will be the video stream
*/
2021-03-03 22:52:13 +08:00
int PacketQueue : : addStream ( ) {
2021-02-03 03:22:38 +08:00
deleting = false ;
2021-03-03 22:52:13 +08:00
if ( max_stream_id = = - 1 ) {
video_stream_id = 0 ;
max_stream_id = 0 ;
} else {
max_stream_id + + ;
2020-12-10 04:01:24 +08:00
}
2021-03-03 22:52:13 +08:00
if ( packet_counts ) delete [ ] packet_counts ;
packet_counts = new int [ max_stream_id + 1 ] ;
for ( int i = 0 ; i < = max_stream_id ; + + i )
packet_counts [ i ] = 0 ;
return max_stream_id ;
2021-02-01 10:30:12 +08:00
}
2020-12-10 04:01:24 +08:00
2021-02-01 10:30:12 +08:00
PacketQueue : : ~ PacketQueue ( ) {
clear ( ) ;
2021-03-18 00:48:42 +08:00
if ( packet_counts ) {
2021-02-01 23:25:48 +08:00
delete [ ] packet_counts ;
packet_counts = nullptr ;
}
2021-03-18 00:48:42 +08:00
while ( ! iterators . empty ( ) ) {
2021-02-01 23:25:48 +08:00
packetqueue_iterator * it = iterators . front ( ) ;
iterators . pop_front ( ) ;
delete it ;
}
2021-01-07 22:43:53 +08:00
Debug ( 4 , " Done in destructor " ) ;
2017-05-17 00:04:56 +08:00
}
2021-01-07 22:43:53 +08:00
/* Enqueues the given packet. Will maintain the it pointer and image packet counts.
2018-08-18 04:06:03 +08:00
* If we have reached our max image packet count , it will pop off as many packets as are needed .
* Thus it will ensure that the same packet never gets queued twice .
*/
2021-02-01 10:30:12 +08:00
bool PacketQueue : : queuePacket ( ZMPacket * add_packet ) {
2021-01-19 22:46:08 +08:00
Debug ( 4 , " packetqueue queuepacket %p %d " , add_packet , add_packet - > image_index ) ;
2021-02-11 03:11:00 +08:00
if ( iterators . empty ( ) ) {
Debug ( 4 , " No iterators so no one needs us to queue packets. " ) ;
return false ;
}
if ( ! packet_counts [ video_stream_id ] and ! add_packet - > keyframe ) {
Debug ( 4 , " No video keyframe so no one needs us to queue packets. " ) ;
return false ;
}
2021-03-27 05:01:45 +08:00
{
std : : unique_lock < std : : mutex > lck ( mutex ) ;
if ( add_packet - > packet . stream_index = = video_stream_id ) {
if ( ( max_video_packet_count > 0 ) and ( packet_counts [ video_stream_id ] > max_video_packet_count ) ) {
Warning ( " You have set the video packets in the queue to %d. The queue is full. Either Analysis is not keeping up or your camera's keyframe interval is larger than this setting. We are dropping packets. " ) ;
if ( add_packet - > keyframe ) {
// Have a new keyframe, so delete everything
while ( ( * pktQueue . begin ( ) ! = add_packet ) and ( packet_counts [ video_stream_id ] > max_video_packet_count ) ) {
ZMPacket * zm_packet = * pktQueue . begin ( ) ;
ZMLockedPacket * lp = new ZMLockedPacket ( zm_packet ) ;
if ( ! lp - > trylock ( ) ) {
Debug ( 1 , " Found locked packet when trying to free up video packets. Can't continue " ) ;
//delete lp;
break ;
}
delete lp ;
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
if ( * ( * iterator_it ) = = zm_packet ) {
Debug ( 1 , " Bumping IT because it is at the front that we are deleting " ) ;
+ + ( * iterators_it ) ;
}
} // end foreach iterator
pktQueue . pop_front ( ) ;
packet_counts [ zm_packet - > packet . stream_index ] - = 1 ;
Debug ( 1 , " Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d " ,
zm_packet - > packet . stream_index , zm_packet - > image_index , zm_packet - > keyframe , packet_counts [ video_stream_id ] , max_video_packet_count , pktQueue . size ( ) ) ;
delete zm_packet ;
} // end while
}
} // end if too many video packets
if ( ( max_video_packet_count > 0 ) and ( packet_counts [ video_stream_id ] > max_video_packet_count ) ) {
Error ( " Unable to free up older packets. Not queueing this video packet. " ) ;
return false ;
}
} // end if this packet is a video packet
pktQueue . push_back ( add_packet ) ;
packet_counts [ add_packet - > packet . stream_index ] + = 1 ;
Debug ( 2 , " packet counts for %d is %d " ,
add_packet - > packet . stream_index ,
packet_counts [ add_packet - > packet . stream_index ] ) ;
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
if ( * iterator_it = = pktQueue . end ( ) ) {
Debug ( 4 , " pointing it %p to back " , iterator_it ) ;
- - ( * iterator_it ) ;
}
} // end foreach iterator
} // end lock scope
2021-02-19 08:25:40 +08:00
// We signal on every packet because someday we may analyze sound
Debug ( 4 , " packetqueue queuepacket, unlocked signalling " ) ;
condition . notify_all ( ) ;
return true ;
} // end bool PacketQueue::queuePacket(ZMPacket* zm_packet)
2021-01-07 22:43:53 +08:00
2021-02-19 08:25:40 +08:00
void PacketQueue : : clearPackets ( ZMPacket * add_packet ) {
2021-01-07 22:43:53 +08:00
// Only do queueCleaning if we are adding a video keyframe, so that we guarantee that there is one.
// No good. Have to satisfy two conditions:
// 1. packetqueue starts with a video keyframe
// 2. Have minimum # of video packets
// 3. No packets can be locked
// 4. No iterator can point to one of the packets
//
// So start at the beginning, counting video packets until the next keyframe.
// Then if deleting those packets doesn't break 1 and 2, then go ahead and delete them.
2021-03-23 00:04:32 +08:00
if ( keep_keyframes and ! (
2021-02-19 08:25:40 +08:00
add_packet - > packet . stream_index = = video_stream_id
2021-03-23 00:04:32 +08:00
and
add_packet - > keyframe
and
2021-03-27 02:26:37 +08:00
( packet_counts [ video_stream_id ] > pre_event_video_packet_count )
2021-03-23 00:04:32 +08:00
and
* ( pktQueue . begin ( ) ) ! = add_packet
)
2021-01-07 22:43:53 +08:00
) {
2021-03-27 02:26:37 +08:00
Debug ( 3 , " stream index %d ?= video_stream_id %d, keyframe %d, keep_keyframes %d, counts %d > pre_event_count %d at begin %d " ,
add_packet - > packet . stream_index , video_stream_id , add_packet - > keyframe , keep_keyframes , packet_counts [ video_stream_id ] , pre_event_video_packet_count ,
2021-03-04 20:46:39 +08:00
( * ( pktQueue . begin ( ) ) ! = add_packet )
) ;
2021-02-19 08:25:40 +08:00
return ;
}
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2021-03-23 09:31:09 +08:00
// If ananlysis_it isn't at the end, we need to keep that many additional packets
int tail_count = 0 ;
if ( pktQueue . back ( ) ! = add_packet ) {
Debug ( 1 , " Ours is not the back " ) ;
packetqueue_iterator it = pktQueue . end ( ) ;
- - it ;
while ( * it ! = add_packet ) {
if ( ( * it ) - > packet . stream_index = = video_stream_id )
+ + tail_count ;
- - it ;
}
}
Debug ( 1 , " Tail count is %d " , tail_count ) ;
2021-03-23 00:04:32 +08:00
if ( ! keep_keyframes ) {
// If not doing passthrough, we don't care about starting with a keyframe so logic is simpler
2021-03-27 02:26:37 +08:00
while ( ( * pktQueue . begin ( ) ! = add_packet ) and ( packet_counts [ video_stream_id ] > pre_event_video_packet_count + tail_count ) ) {
2021-03-23 00:04:32 +08:00
ZMPacket * zm_packet = * pktQueue . begin ( ) ;
ZMLockedPacket * lp = new ZMLockedPacket ( zm_packet ) ;
if ( ! lp - > trylock ( ) ) break ;
delete lp ;
pktQueue . pop_front ( ) ;
packet_counts [ zm_packet - > packet . stream_index ] - = 1 ;
Debug ( 1 , " Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d " ,
2021-03-27 02:26:37 +08:00
zm_packet - > packet . stream_index , zm_packet - > image_index , zm_packet - > keyframe , packet_counts [ video_stream_id ] , pre_event_video_packet_count , pktQueue . size ( ) ) ;
2021-03-23 00:04:32 +08:00
delete zm_packet ;
} // end while
return ;
}
2021-02-19 08:25:40 +08:00
packetqueue_iterator it = pktQueue . begin ( ) ;
packetqueue_iterator next_front = pktQueue . begin ( ) ;
2021-03-05 23:02:12 +08:00
int video_packets_to_delete = 0 ; // This is a count of how many packets we will delete so we know when to stop looking
2021-02-19 08:25:40 +08:00
// First packet is special because we know it is a video keyframe and only need to check for lock
ZMPacket * zm_packet = * it ;
2021-03-16 05:05:30 +08:00
ZMLockedPacket * lp = new ZMLockedPacket ( zm_packet ) ;
2021-03-22 00:28:33 +08:00
if ( lp - > trylock ( ) ) {
2021-02-19 08:25:40 +08:00
+ + it ;
2021-03-16 05:05:30 +08:00
delete lp ;
2021-02-19 08:25:40 +08:00
// Since we have many packets in the queue, we should NOT be pointing at end so don't need to test for that
2021-03-22 00:28:33 +08:00
while ( * it ! = add_packet ) {
2021-02-19 08:25:40 +08:00
zm_packet = * it ;
2021-03-16 05:05:30 +08:00
lp = new ZMLockedPacket ( zm_packet ) ;
2021-03-22 00:28:33 +08:00
if ( ! lp - > trylock ( ) ) break ;
2021-03-16 05:05:30 +08:00
delete lp ;
2021-02-01 23:25:48 +08:00
2021-03-22 00:28:33 +08:00
if ( is_there_an_iterator_pointing_to_packet ( zm_packet ) ) {
2021-02-20 04:56:42 +08:00
Warning ( " Found iterator at beginning of queue. Some thread isn't keeping up " ) ;
2021-02-19 08:25:40 +08:00
break ;
}
2021-02-03 03:22:38 +08:00
2021-03-22 00:28:33 +08:00
if ( zm_packet - > packet . stream_index = = video_stream_id ) {
if ( zm_packet - > keyframe ) {
2021-03-05 23:02:12 +08:00
Debug ( 3 , " Have a video keyframe so setting next front to it " ) ;
2021-02-19 08:25:40 +08:00
next_front = it ;
2021-01-07 22:43:53 +08:00
}
2021-03-05 23:02:12 +08:00
+ + video_packets_to_delete ;
2021-03-22 00:28:33 +08:00
Debug ( 4 , " Counted %d video packets. Which would leave %d in packetqueue tail count is %d " ,
video_packets_to_delete , packet_counts [ video_stream_id ] - video_packets_to_delete , tail_count ) ;
2021-03-27 02:26:37 +08:00
if ( packet_counts [ video_stream_id ] - video_packets_to_delete < = pre_event_video_packet_count + tail_count ) {
2021-03-05 23:02:12 +08:00
break ;
}
2021-01-07 22:43:53 +08:00
}
2021-02-19 08:25:40 +08:00
it + + ;
} // end while
} // end if first packet not locked
2021-02-24 02:12:09 +08:00
Debug ( 1 , " Resulting pointing at latest packet? %d, next front points to begin? %d " ,
2021-02-19 08:25:40 +08:00
( * it = = add_packet ) ,
( next_front = = pktQueue . begin ( ) )
) ;
if ( next_front ! = pktQueue . begin ( ) ) {
while ( pktQueue . begin ( ) ! = next_front ) {
ZMPacket * zm_packet = * pktQueue . begin ( ) ;
if ( ! zm_packet ) {
Error ( " NULL zm_packet in queue " ) ;
continue ;
}
2018-08-18 04:06:03 +08:00
2021-02-19 08:25:40 +08:00
Debug ( 1 , " Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%d " ,
2021-03-27 02:26:37 +08:00
zm_packet - > packet . stream_index , zm_packet - > image_index , zm_packet - > keyframe , packet_counts [ video_stream_id ] , pre_event_video_packet_count , pktQueue . size ( ) ) ;
2021-02-19 08:25:40 +08:00
pktQueue . pop_front ( ) ;
packet_counts [ zm_packet - > packet . stream_index ] - = 1 ;
delete zm_packet ;
}
} // end if have at least max_video_packet_count video packets remaining
2020-12-10 04:01:24 +08:00
// We signal on every packet because someday we may analyze sound
2017-05-17 00:04:56 +08:00
2021-02-19 08:25:40 +08:00
return ;
} // end voidPacketQueue::clearPackets(ZMPacket* zm_packet)
2017-05-17 00:04:56 +08:00
2021-03-16 05:05:30 +08:00
ZMLockedPacket * PacketQueue : : popPacket ( ) {
2020-12-16 05:01:18 +08:00
Debug ( 4 , " pktQueue size %d " , pktQueue . size ( ) ) ;
2017-05-17 00:04:56 +08:00
if ( pktQueue . empty ( ) ) {
2020-08-26 07:45:48 +08:00
return nullptr ;
2017-05-17 00:04:56 +08:00
}
2020-12-16 05:01:18 +08:00
Debug ( 4 , " poPacket Mutex locking " ) ;
2021-03-27 02:26:37 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2017-05-17 00:04:56 +08:00
2021-01-07 22:43:53 +08:00
ZMPacket * zm_packet = pktQueue . front ( ) ;
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
if ( * ( * iterator_it ) = = zm_packet ) {
Debug ( 4 , " Bumping it because it is at the front that we are deleting " ) ;
+ + ( * iterators_it ) ;
}
} // end foreach iterator
2021-03-16 05:05:30 +08:00
ZMLockedPacket * lp = new ZMLockedPacket ( zm_packet ) ;
lp - > lock ( ) ;
2017-12-01 03:37:36 +08:00
2017-05-17 00:04:56 +08:00
pktQueue . pop_front ( ) ;
2021-01-07 22:43:53 +08:00
packet_counts [ zm_packet - > packet . stream_index ] - = 1 ;
2020-12-22 23:20:44 +08:00
2021-03-16 05:05:30 +08:00
return lp ;
2020-12-10 04:01:24 +08:00
} // popPacket
2017-05-17 00:04:56 +08:00
2020-12-22 23:20:44 +08:00
/* Keeps frames_to_keep frames of the provided stream, which theoretically is the video stream
* Basically it starts at the end , moving backwards until it finds the minimum video frame .
* Then it should probably move forward to find a keyframe . The first video frame must always be a keyframe .
* So really frames_to_keep is a maximum which isn ' t so awesome . . maybe we should go back farther to find the keyframe in which case
* frames_to_keep in a minimum
*/
2021-02-01 10:30:12 +08:00
unsigned int PacketQueue : : clear ( unsigned int frames_to_keep , int stream_id ) {
2018-08-18 04:06:03 +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
if ( pktQueue . empty ( ) ) {
return 0 ;
}
2020-12-22 23:20:44 +08:00
// If size is <= frames_to_keep since it could contain audio, we can't possibly do anything
2018-02-16 03:08:21 +08:00
if ( pktQueue . size ( ) < = frames_to_keep ) {
return 0 ;
}
2021-02-01 10:30:12 +08:00
Debug ( 5 , " Locking in clear " ) ;
2021-03-27 02:26:37 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2020-12-22 23:20:44 +08:00
2021-01-07 22:43:53 +08:00
packetqueue_iterator it = pktQueue . end ( ) - - ; // point to last element instead of end
2020-12-22 23:20:44 +08:00
ZMPacket * zm_packet = nullptr ;
while ( ( it ! = pktQueue . begin ( ) ) and frames_to_keep ) {
zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
Debug ( 3 , " Looking at packet with stream index (%d) with keyframe(%d), Image_index(%d) frames_to_keep is (%d) " ,
av_packet - > stream_index , zm_packet - > keyframe , zm_packet - > image_index , frames_to_keep ) ;
// Want frames_to_keep video keyframes. Otherwise, we may not have enough
if ( av_packet - > stream_index = = stream_id ) {
frames_to_keep - - ;
}
it - - ;
}
// Either at beginning or frames_to_keep == 0
if ( it = = pktQueue . begin ( ) ) {
if ( frames_to_keep ) {
Warning ( " Couldn't remove any packets, needed %d " , frames_to_keep ) ;
}
mutex . unlock ( ) ;
return 0 ;
}
int delete_count = 0 ;
// Else not at beginning, are pointing at packet before the last video packet
while ( pktQueue . begin ( ) ! = it ) {
Debug ( 4 , " Deleting a packet from the front, count is (%d), queue size is %d " ,
delete_count , pktQueue . size ( ) ) ;
zm_packet = pktQueue . front ( ) ;
2021-01-07 22:43:53 +08:00
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
if ( * ( * iterator_it ) = = zm_packet ) {
Debug ( 4 , " Bumping it because it is at the front that we are deleting " ) ;
+ + ( * iterators_it ) ;
}
} // end foreach iterator
2020-12-22 23:20:44 +08:00
packet_counts [ zm_packet - > packet . stream_index ] - - ;
pktQueue . pop_front ( ) ;
2021-01-07 22:43:53 +08:00
//if ( zm_packet->image_index == -1 )
2020-12-22 23:20:44 +08:00
delete zm_packet ;
delete_count + = 1 ;
} // while our iterator is not the first packet
Debug ( 3 , " Deleted %d packets, %d remaining " , delete_count , pktQueue . size ( ) ) ;
2017-05-17 00:04:56 +08:00
return delete_count ;
2021-02-01 10:30:12 +08:00
} // end unsigned int PacketQueue::clear( unsigned int frames_to_keep, int stream_id )
2017-05-17 00:04:56 +08:00
2021-02-01 10:30:12 +08:00
void PacketQueue : : clear ( ) {
deleting = true ;
2021-03-18 00:48:42 +08:00
condition . notify_all ( ) ;
2021-02-01 10:30:12 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2021-03-12 02:48:52 +08:00
while ( ! pktQueue . empty ( ) ) {
2021-02-01 10:30:12 +08:00
ZMPacket * packet = pktQueue . front ( ) ;
// Someone might have this packet, but not for very long and since we have locked the queue they won't be able to get another one
2021-03-17 22:07:03 +08:00
ZMLockedPacket * lp = new ZMLockedPacket ( packet ) ;
lp - > lock ( ) ;
2017-05-17 00:04:56 +08:00
pktQueue . pop_front ( ) ;
2021-03-17 22:07:03 +08:00
delete lp ;
2021-02-01 10:30:12 +08:00
delete packet ;
}
2021-01-07 22:43:53 +08:00
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
* iterator_it = pktQueue . begin ( ) ;
} // end foreach iterator
2021-03-04 20:46:39 +08:00
if ( packet_counts ) delete [ ] packet_counts ;
packet_counts = nullptr ;
max_stream_id = - 1 ;
2021-02-01 10:30:12 +08:00
condition . notify_all ( ) ;
2017-05-17 00:04:56 +08:00
}
2019-11-02 05:29:55 +08:00
// clear queue keeping only specified duration of video -- return number of pkts removed
2021-02-01 10:30:12 +08:00
unsigned int PacketQueue : : clear ( struct timeval * duration , int streamId ) {
2019-11-02 05:29:55 +08:00
2020-05-03 06:03:42 +08:00
if ( pktQueue . empty ( ) ) {
2019-11-02 05:29:55 +08:00
return 0 ;
}
2021-02-01 10:30:12 +08:00
Debug ( 4 , " Locking in clear " ) ;
2021-03-27 02:26:37 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2020-12-10 04:01:24 +08:00
2019-11-02 05:29:55 +08:00
struct timeval keep_from ;
2020-12-10 04:01:24 +08:00
std : : list < ZMPacket * > : : reverse_iterator it = pktQueue . rbegin ( ) ;
2019-11-02 05:29:55 +08:00
2020-05-03 06:03:42 +08:00
struct timeval * t = ( * it ) - > timestamp ;
timersub ( t , duration , & keep_from ) ;
2019-11-02 05:29:55 +08:00
+ + it ;
2020-12-10 04:01:24 +08:00
Debug ( 3 , " Looking for frame before queue keep time with stream id (%d), queue has %d packets " ,
2019-11-02 05:29:55 +08:00
streamId , pktQueue . size ( ) ) ;
for ( ; it ! = pktQueue . rend ( ) ; + + it ) {
ZMPacket * zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
2020-12-10 04:01:24 +08:00
if (
( av_packet - > stream_index = = streamId )
and
timercmp ( zm_packet - > timestamp , & keep_from , < = )
) {
2019-11-02 05:29:55 +08:00
Debug ( 3 , " Found frame before keep time with stream index %d at %d.%d " ,
av_packet - > stream_index ,
2020-05-03 06:03:42 +08:00
zm_packet - > timestamp - > tv_sec ,
zm_packet - > timestamp - > tv_usec ) ;
2019-11-02 05:29:55 +08:00
break ;
}
}
2020-12-10 04:01:24 +08:00
if ( it = = pktQueue . rend ( ) ) {
2019-11-02 05:29:55 +08:00
Debug ( 1 , " Didn't find a frame before queue preserve time. keeping all " ) ;
2020-12-10 04:01:24 +08:00
mutex . unlock ( ) ;
2019-11-02 05:29:55 +08:00
return 0 ;
}
Debug ( 3 , " Looking for keyframe " ) ;
for ( ; it ! = pktQueue . rend ( ) ; + + it ) {
ZMPacket * zm_packet = * it ;
AVPacket * av_packet = & ( zm_packet - > packet ) ;
2020-12-10 04:01:24 +08:00
if (
( av_packet - > flags & AV_PKT_FLAG_KEY )
and
( av_packet - > stream_index = = streamId )
) {
2019-11-02 05:29:55 +08:00
Debug ( 3 , " Found keyframe before start with stream index %d at %d.%d " ,
av_packet - > stream_index ,
2020-05-03 06:03:42 +08:00
zm_packet - > timestamp - > tv_sec ,
zm_packet - > timestamp - > tv_usec ) ;
2019-11-02 05:29:55 +08:00
break ;
}
}
if ( it = = pktQueue . rend ( ) ) {
Debug ( 1 , " Didn't find a keyframe before event starttime. keeping all " ) ;
return 0 ;
}
unsigned int deleted_frames = 0 ;
2020-08-26 07:45:48 +08:00
ZMPacket * zm_packet = nullptr ;
2020-12-10 04:01:24 +08:00
while ( distance ( it , pktQueue . rend ( ) ) > 1 ) {
2019-11-02 05:29:55 +08:00
zm_packet = pktQueue . front ( ) ;
2021-01-07 22:43:53 +08:00
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
if ( * ( * iterator_it ) = = zm_packet ) {
Debug ( 4 , " Bumping it because it is at the front that we are deleting " ) ;
+ + ( * iterators_it ) ;
}
} // end foreach iterator
2019-11-02 05:29:55 +08:00
pktQueue . pop_front ( ) ;
packet_counts [ zm_packet - > packet . stream_index ] - = 1 ;
2021-03-27 02:26:37 +08:00
delete zm_packet ;
2019-11-02 05:29:55 +08:00
deleted_frames + = 1 ;
}
Debug ( 3 , " Deleted %d frames " , deleted_frames ) ;
return deleted_frames ;
}
2021-02-01 10:30:12 +08:00
unsigned int PacketQueue : : size ( ) {
2017-05-17 00:04:56 +08:00
return pktQueue . size ( ) ;
}
2021-02-01 10:30:12 +08:00
int PacketQueue : : packet_count ( int stream_id ) {
2021-02-19 02:43:58 +08:00
if ( stream_id < 0 or stream_id > max_stream_id ) {
2021-02-24 02:12:09 +08:00
Error ( " Invalid stream_id %d max is %d " , stream_id , max_stream_id ) ;
2021-02-19 02:43:58 +08:00
return - 1 ;
}
2018-10-15 22:51:56 +08:00
return packet_counts [ stream_id ] ;
2021-02-20 01:44:20 +08:00
} // end int PacketQueue::packet_count(int stream_id)
2017-05-17 00:04:56 +08:00
2020-12-22 23:20:44 +08:00
2021-01-07 22:43:53 +08:00
// Returns a packet. Packet will be locked
2021-03-16 05:05:30 +08:00
ZMLockedPacket * PacketQueue : : get_packet ( packetqueue_iterator * it ) {
2021-03-18 00:48:42 +08:00
if ( deleting or zm_terminate )
2021-01-27 01:23:44 +08:00
return nullptr ;
2017-12-01 03:37:36 +08:00
2021-01-19 22:46:08 +08:00
Debug ( 4 , " Locking in get_packet using it %p queue end? %d, packet %p " ,
* it , ( * it = = pktQueue . end ( ) ) , * ( * it ) ) ;
2020-12-10 04:01:24 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2021-01-07 22:43:53 +08:00
Debug ( 4 , " Have Lock in get_packet " ) ;
2020-12-10 04:01:24 +08:00
2021-01-14 23:31:29 +08:00
while ( ( ! pktQueue . size ( ) ) or ( * it = = pktQueue . end ( ) ) ) {
2021-01-07 22:43:53 +08:00
if ( deleting or zm_terminate )
return nullptr ;
2021-01-14 23:31:29 +08:00
Debug ( 2 , " waiting. Queue size %d it == end? %d " , pktQueue . size ( ) , ( * it = = pktQueue . end ( ) ) ) ;
2020-12-10 04:01:24 +08:00
condition . wait ( lck ) ;
2019-02-25 23:21:43 +08:00
}
2021-03-18 00:48:42 +08:00
if ( deleting or zm_terminate )
2020-12-15 23:14:19 +08:00
return nullptr ;
2017-12-01 03:37:36 +08:00
2021-02-01 00:42:51 +08:00
Debug ( 4 , " get_packet using it %p queue end? %d, packet %p " ,
* it , ( * it = = pktQueue . end ( ) ) , * ( * it ) ) ;
2021-01-07 22:43:53 +08:00
ZMPacket * p = * ( * it ) ;
if ( ! p ) {
Error ( " Null p?! " ) ;
return nullptr ;
}
2021-03-16 05:05:30 +08:00
ZMLockedPacket * lp = new ZMLockedPacket ( p ) ;
2021-01-19 22:46:08 +08:00
Debug ( 3 , " get_packet %p image_index: %d, about to lock packet " , p , p - > image_index ) ;
2021-03-16 05:05:30 +08:00
while ( ! ( zm_terminate or deleting ) and ! lp - > trylock ( ) ) {
2021-03-16 03:08:43 +08:00
Debug ( 3 , " waiting on index %d. Queue size %d it == end? %d " ,
p - > image_index , pktQueue . size ( ) , ( * it = = pktQueue . end ( ) ) ) ;
ZM_DUMP_PACKET ( p - > packet , " " ) ;
2020-12-10 04:01:24 +08:00
condition . wait ( lck ) ;
}
2021-03-18 00:48:42 +08:00
if ( deleting or zm_terminate ) {
// packet may have been deleted so we can't delete the lp FIXME
return nullptr ;
}
2020-09-26 04:20:19 +08:00
Debug ( 2 , " Locked packet, unlocking packetqueue mutex " ) ;
2021-03-16 05:05:30 +08:00
return lp ;
} // end ZMLockedPacket *PacketQueue::get_packet(it)
2021-01-07 22:43:53 +08:00
2021-02-01 10:30:12 +08:00
bool PacketQueue : : increment_it ( packetqueue_iterator * it ) {
2021-01-19 22:46:08 +08:00
Debug ( 2 , " Incrementing %p, queue size %d, end? %d " , it , pktQueue . size ( ) , ( ( * it ) = = pktQueue . end ( ) ) ) ;
if ( ( * it ) = = pktQueue . end ( ) ) {
2021-01-07 22:43:53 +08:00
return false ;
}
+ + ( * it ) ;
if ( * it ! = pktQueue . end ( ) ) {
2021-01-19 22:46:08 +08:00
Debug ( 2 , " Incrementing %p, %p still not at end %p, so returning true " , it , * it , pktQueue . end ( ) ) ;
2021-01-07 22:43:53 +08:00
return true ;
2020-12-10 04:01:24 +08:00
}
2021-01-07 22:43:53 +08:00
return false ;
2021-02-01 10:30:12 +08:00
} // end bool PacketQueue::increment_it(packetqueue_iterator *it)
2020-12-10 04:01:24 +08:00
2021-01-07 22:43:53 +08:00
// Increment it only considering packets for a given stream
2021-02-01 10:30:12 +08:00
bool PacketQueue : : increment_it ( packetqueue_iterator * it , int stream_id ) {
2021-01-07 22:43:53 +08:00
Debug ( 2 , " Incrementing %p, queue size %d, end? %d " , it , pktQueue . size ( ) , ( * it = = pktQueue . end ( ) ) ) ;
if ( * it = = pktQueue . end ( ) ) {
2017-12-01 03:37:36 +08:00
return false ;
}
2019-06-21 03:14:20 +08:00
2021-01-28 00:48:19 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2021-01-07 22:43:53 +08:00
do {
+ + ( * it ) ;
} while ( ( * it ! = pktQueue . end ( ) ) and ( ( * ( * it ) ) - > packet . stream_index ! = stream_id ) ) ;
if ( * it ! = pktQueue . end ( ) ) {
Debug ( 2 , " Incrementing %p, still not at end, so incrementing " , it ) ;
return true ;
}
return false ;
2021-02-01 10:30:12 +08:00
} // end bool PacketQueue::increment_it(packetqueue_iterator *it)
2020-12-22 23:20:44 +08:00
2021-02-03 03:22:38 +08:00
packetqueue_iterator * PacketQueue : : get_event_start_packet_it (
packetqueue_iterator snapshot_it ,
2020-12-22 23:20:44 +08:00
unsigned int pre_event_count
) {
2021-02-19 05:59:17 +08:00
std : : unique_lock < std : : mutex > lck ( mutex ) ;
2021-02-03 03:22:38 +08:00
packetqueue_iterator * it = new packetqueue_iterator ;
iterators . push_back ( it ) ;
* it = snapshot_it ;
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( ( * ( * it ) ) - > packet , " " ) ;
2020-12-22 23:20:44 +08:00
// Step one count back pre_event_count frames as the minimum
// Do not assume that snapshot_it is video
// snapshot it might already point to the beginning
2021-03-05 23:02:12 +08:00
while ( ( ( * it ) ! = pktQueue . begin ( ) ) and pre_event_count ) {
2021-02-03 03:22:38 +08:00
Debug ( 1 , " Previous packet pre_event_count %d stream_index %d keyframe %d " ,
pre_event_count , ( * ( * it ) ) - > packet . stream_index , ( * ( * it ) ) - > keyframe ) ;
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( ( * ( * it ) ) - > packet , " " ) ;
2021-02-03 03:22:38 +08:00
if ( ( * ( * it ) ) - > packet . stream_index = = video_stream_id ) {
2020-12-22 23:20:44 +08:00
pre_event_count - - ;
2021-01-27 01:23:44 +08:00
if ( ! pre_event_count )
break ;
2020-12-22 23:20:44 +08:00
}
2021-02-03 03:22:38 +08:00
( * it ) - - ;
2020-12-22 23:20:44 +08:00
}
2021-01-27 01:23:44 +08:00
// it either points to beginning or we have seen pre_event_count video packets.
2021-02-03 03:22:38 +08:00
if ( ( * it ) = = pktQueue . begin ( ) ) {
2020-12-22 23:20:44 +08:00
Debug ( 1 , " Hit begin " ) ;
// hit end, the first packet in the queue should ALWAYS be a video keyframe.
// So we should be able to return it.
2021-01-07 22:43:53 +08:00
if ( pre_event_count ) {
2021-02-03 03:22:38 +08:00
if ( ( * ( * it ) ) - > image_index < ( int ) pre_event_count ) {
2021-01-12 06:18:14 +08:00
// probably just starting up
Debug ( 1 , " Hit end of packetqueue before satisfying pre_event_count. Needed %d more video frames " , pre_event_count ) ;
} else {
Warning ( " Hit end of packetqueue before satisfying pre_event_count. Needed %d more video frames " , pre_event_count ) ;
}
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( ( * ( * it ) ) - > packet , " " ) ;
2021-01-07 22:43:53 +08:00
}
2020-12-22 23:20:44 +08:00
return it ;
}
2021-01-27 01:23:44 +08:00
// Not at beginning, so must be pointing at a video keyframe or maybe pre_event_count == 0
2021-02-03 03:22:38 +08:00
if ( ( * ( * it ) ) - > keyframe ) {
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( ( * ( * it ) ) - > packet , " Found video keyframe, Returning " ) ;
2020-12-22 23:20:44 +08:00
return it ;
}
2021-02-08 09:58:00 +08:00
while ( - - ( * it ) ! = pktQueue . begin ( ) ) {
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( ( * ( * it ) ) - > packet , " No keyframe " ) ;
2021-02-08 09:58:00 +08:00
if ( ( ( * ( * it ) ) - > packet . stream_index = = video_stream_id ) and ( * ( * it ) ) - > keyframe )
2021-01-27 01:23:44 +08:00
return it ; // Success
2020-12-22 23:20:44 +08:00
}
2021-02-03 03:22:38 +08:00
if ( ! ( * ( * it ) ) - > keyframe ) {
2021-01-27 01:23:44 +08:00
Warning ( " Hit end of packetqueue before satisfying pre_event_count. Needed %d more video frames " , pre_event_count ) ;
2020-12-22 23:20:44 +08:00
}
return it ;
2021-02-03 03:22:38 +08:00
} // end packetqueue_iterator *PacketQueue::get_event_start_packet_it
2020-12-22 23:20:44 +08:00
2021-02-01 10:30:12 +08:00
void PacketQueue : : dumpQueue ( ) {
2019-06-21 03:14:20 +08:00
std : : list < ZMPacket * > : : reverse_iterator it ;
for ( it = pktQueue . rbegin ( ) ; it ! = pktQueue . rend ( ) ; + + it ) {
ZMPacket * zm_packet = * it ;
2021-02-06 21:46:28 +08:00
ZM_DUMP_PACKET ( zm_packet - > packet , " " ) ;
2019-06-21 03:14:20 +08:00
}
}
2021-01-07 22:43:53 +08:00
/* Returns an iterator to the first video keyframe in the queue.
* nullptr if no keyframe video packet exists .
*/
2021-02-01 10:30:12 +08:00
packetqueue_iterator * PacketQueue : : get_video_it ( bool wait ) {
2021-01-07 22:43:53 +08:00
packetqueue_iterator * it = new packetqueue_iterator ;
iterators . push_back ( it ) ;
std : : unique_lock < std : : mutex > lck ( mutex ) ;
* it = pktQueue . begin ( ) ;
if ( wait ) {
while ( ( ( ! pktQueue . size ( ) ) or ( * it = = pktQueue . end ( ) ) ) and ! zm_terminate and ! deleting ) {
2021-03-17 22:07:03 +08:00
Debug ( 2 , " waiting for packets in queue. Queue size %d it == end? %d " , pktQueue . size ( ) , ( * it = = pktQueue . end ( ) ) ) ;
2021-01-07 22:43:53 +08:00
condition . wait ( lck ) ;
* it = pktQueue . begin ( ) ;
}
if ( deleting or zm_terminate ) {
2021-02-01 23:25:48 +08:00
free_it ( it ) ;
2021-01-07 22:43:53 +08:00
delete it ;
return nullptr ;
}
}
while ( * it ! = pktQueue . end ( ) ) {
ZMPacket * zm_packet = * ( * it ) ;
2021-03-16 03:08:43 +08:00
if ( ! zm_packet ) {
2021-01-07 22:43:53 +08:00
Error ( " Null zmpacket in queue!? " ) ;
2021-02-01 23:25:48 +08:00
free_it ( it ) ;
2021-01-07 22:43:53 +08:00
return nullptr ;
}
Debug ( 1 , " Packet keyframe %d for stream %d, so returning the it to it " ,
zm_packet - > keyframe , zm_packet - > packet . stream_index ) ;
2021-03-16 03:08:43 +08:00
if ( zm_packet - > keyframe and ( zm_packet - > packet . stream_index = = video_stream_id ) ) {
2021-01-07 22:43:53 +08:00
Debug ( 1 , " Found a keyframe for stream %d, so returning the it to it " , video_stream_id ) ;
return it ;
}
+ + ( * it ) ;
}
Debug ( 1 , " DIdn't Found a keyframe for stream %d, so returning the it to it " , video_stream_id ) ;
return it ;
2021-03-16 03:08:43 +08:00
} // get video_it
2021-02-01 23:25:48 +08:00
void PacketQueue : : free_it ( packetqueue_iterator * it ) {
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
if ( * iterators_it = = it ) {
iterators . erase ( iterators_it ) ;
break ;
}
}
}
2021-02-03 03:22:38 +08:00
bool PacketQueue : : is_there_an_iterator_pointing_to_packet ( ZMPacket * zm_packet ) {
for (
std : : list < packetqueue_iterator * > : : iterator iterators_it = iterators . begin ( ) ;
iterators_it ! = iterators . end ( ) ;
+ + iterators_it
) {
packetqueue_iterator * iterator_it = * iterators_it ;
if ( * iterator_it = = pktQueue . end ( ) ) {
continue ;
}
Debug ( 4 , " Checking iterator %p == packet ? %d " , ( * iterator_it ) , ( * ( * iterator_it ) = = zm_packet ) ) ;
// Have to check each iterator and make sure it doesn't point to the packet we are about to delete
if ( * ( * iterator_it ) = = zm_packet ) {
return true ;
}
} // end foreach iterator
return false ;
}
2021-03-12 02:48:52 +08:00
void PacketQueue : : setMaxVideoPackets ( int p ) {
max_video_packet_count = p ;
Debug ( 1 , " Setting max_video_packet_count to %d " , p ) ;
2021-03-27 02:26:37 +08:00
if ( max_video_packet_count < 0 )
max_video_packet_count = 0 ;
}
void PacketQueue : : setPreEventVideoPackets ( int p ) {
pre_event_video_packet_count = p ;
Debug ( 1 , " Setting pre_event_video_packet_count to %d " , p ) ;
if ( pre_event_video_packet_count < 1 )
pre_event_video_packet_count = 1 ;
2021-03-12 02:48:52 +08:00
// We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue
}