/* * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * * Use of this source code is governed by MIT-like license that can be found in the * 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_ #include "Common/config.h" #include "Util/List.h" namespace mediakit { // / 缓存刷新策略类 [AUTO-TRANSLATED:bd941d15] // / Cache refresh strategy class class FlushPolicy { public: bool isFlushAble(bool is_video, bool is_key, uint64_t new_stamp, size_t cache_size); private: // 音视频的最后时间戳 [AUTO-TRANSLATED:957d18ed] // Last timestamp of audio and video uint64_t _last_stamp[2] = { 0, 0 }; }; // / 合并写缓存模板 [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 template > > class PacketCache { public: PacketCache() { _cache = std::make_shared(); } virtual ~PacketCache() = default; void inputPacket(uint64_t stamp, bool is_video, std::shared_ptr pkt, bool key_pos) { bool flag = flushImmediatelyWhenCloseMerge(); if (!flag && _policy.isFlushAble(is_video, key_pos, stamp, _cache->size())) { flush(); } // 追加数据到最后 [AUTO-TRANSLATED:e24ccfb6] // Append data to the end _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(); _key_pos = false; } virtual void clearCache() { _cache->clear(); } virtual void onFlush(std::shared_ptr, bool key_pos) = 0; private: bool flushImmediatelyWhenCloseMerge() { // 一般的协议关闭合并写时,立即刷新缓存,这样可以减少一帧的延时,但是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. GET_CONFIG(int, mergeWriteMS, General::kMergeWriteMS); GET_CONFIG(int, rtspLowLatency, Rtsp::kLowLatency); return std::is_same::value ? rtspLowLatency : (mergeWriteMS <= 0); } private: bool _key_pos = false; policy _policy; std::shared_ptr _cache; }; } #endif //ZLMEDIAKIT_PACKET_CACHE_H_