2022-12-02 14:43:06 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
2022-12-02 14:43:06 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
2022-12-02 14:43:06 +08:00
*
2023-12-09 16:23:51 +08:00
* Use of this source code is governed by MIT - like license that can be found in the
2022-12-02 14:43:06 +08:00
* LICENSE file in the root of the source tree . All contributing project authors
* may be found in the AUTHORS file in the root of the source tree .
*/
# ifndef ZLMEDIAKIT_PACKET_CACHE_H_
# define ZLMEDIAKIT_PACKET_CACHE_H_
2022-11-29 11:07:13 +08:00
# include "Common/config.h"
# include "Util/List.h"
namespace mediakit {
2024-09-19 14:53:50 +08:00
// / 缓存刷新策略类 [AUTO-TRANSLATED:bd941d15]
// / Cache refresh strategy class
2022-11-29 11:07:13 +08:00
class FlushPolicy {
public :
bool isFlushAble ( bool is_video , bool is_key , uint64_t new_stamp , size_t cache_size ) ;
private :
2024-09-19 14:53:50 +08:00
// 音视频的最后时间戳 [AUTO-TRANSLATED:957d18ed]
// Last timestamp of audio and video
2022-11-29 11:07:13 +08:00
uint64_t _last_stamp [ 2 ] = { 0 , 0 } ;
} ;
2024-09-19 14:53:50 +08:00
// / 合并写缓存模板 [AUTO-TRANSLATED:25cde944]
// / Merge write cache template
// / \tparam packet 包类型 [AUTO-TRANSLATED:43085d9b]
// / \tparam packet Packet type
// / \tparam policy 刷新缓存策略 [AUTO-TRANSLATED:c5ac29a7]
// / \tparam policy Refresh cache strategy
// / \tparam packet_list 包缓存类型 [AUTO-TRANSLATED:a434e7fe]
// / \tparam packet_list Packet cache type
2022-11-29 11:07:13 +08:00
template < typename packet , typename policy = FlushPolicy , typename packet_list = toolkit : : List < std : : shared_ptr < packet > > >
class PacketCache {
public :
PacketCache ( ) { _cache = std : : make_shared < packet_list > ( ) ; }
virtual ~ PacketCache ( ) = default ;
void inputPacket ( uint64_t stamp , bool is_video , std : : shared_ptr < packet > pkt , bool key_pos ) {
bool flag = flushImmediatelyWhenCloseMerge ( ) ;
if ( ! flag & & _policy . isFlushAble ( is_video , key_pos , stamp , _cache - > size ( ) ) ) {
flush ( ) ;
}
2024-09-19 14:53:50 +08:00
// 追加数据到最后 [AUTO-TRANSLATED:e24ccfb6]
// Append data to the end
2022-11-29 11:07:13 +08:00
_cache - > emplace_back ( std : : move ( pkt ) ) ;
if ( key_pos ) {
_key_pos = key_pos ;
}
if ( flag ) {
flush ( ) ;
}
}
void flush ( ) {
if ( _cache - > empty ( ) ) {
return ;
}
onFlush ( std : : move ( _cache ) , _key_pos ) ;
_cache = std : : make_shared < packet_list > ( ) ;
_key_pos = false ;
}
virtual void clearCache ( ) {
_cache - > clear ( ) ;
}
virtual void onFlush ( std : : shared_ptr < packet_list > , bool key_pos ) = 0 ;
private :
bool flushImmediatelyWhenCloseMerge ( ) {
2024-09-19 14:53:50 +08:00
// 一般的协议关闭合并写时, 立即刷新缓存, 这样可以减少一帧的延时, 但是rtp例外 [AUTO-TRANSLATED:54eba701]
// Generally, when the protocol closes the merge write, the cache is refreshed immediately, which can reduce the delay of one frame, but RTP is an exception.
// 因为rtp的包很小, 一个RtpPacket包中也不是完整的一帧图像, 所以在关闭合并写时, [AUTO-TRANSLATED:b219082d]
// Because the RTP packet is very small, and a RtpPacket does not contain a complete frame of image, so when closing the merge write,
// 还是有必要缓冲一帧的rtp(也就是时间戳相同的rtp)再输出,这样虽然会增加一帧的延时 [AUTO-TRANSLATED:27c7ee8b]
// It is still necessary to buffer one frame of RTP (that is, RTP with the same timestamp) before outputting. Although this will increase the delay of one frame,
// 但是却对性能提升很大,这样做还是比较划算的 [AUTO-TRANSLATED:80eab719]
// But it greatly improves performance, so it is still worthwhile to do so.
2022-11-29 11:07:13 +08:00
GET_CONFIG ( int , mergeWriteMS , General : : kMergeWriteMS ) ;
GET_CONFIG ( int , rtspLowLatency , Rtsp : : kLowLatency ) ;
2023-12-09 16:23:51 +08:00
return std : : is_same < packet , RtpPacket > : : value ? rtspLowLatency : ( mergeWriteMS < = 0 ) ;
2022-11-29 11:07:13 +08:00
}
private :
bool _key_pos = false ;
policy _policy ;
std : : shared_ptr < packet_list > _cache ;
} ;
}
2022-12-02 14:43:06 +08:00
# endif //ZLMEDIAKIT_PACKET_CACHE_H_