From aa2ff01d9fc5ec616c5413ce4970b230d3d52c47 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 13:25:32 +0800 Subject: [PATCH 01/31] first commit for srt intergrate --- CMakeLists.txt | 10 + conf/config.ini | 8 + server/main.cpp | 31 +++ srt/Ack.cpp | 74 ++++++ srt/Ack.hpp | 96 ++++++++ srt/Common.hpp | 54 ++++ srt/HSExt.cpp | 127 ++++++++++ srt/HSExt.hpp | 128 ++++++++++ srt/Packet.cpp | 574 +++++++++++++++++++++++++++++++++++++++++++ srt/Packet.hpp | 317 ++++++++++++++++++++++++ srt/PacketQueue.cpp | 126 ++++++++++ srt/PacketQueue.hpp | 44 ++++ srt/SrtSession.cpp | 137 +++++++++++ srt/SrtSession.hpp | 31 +++ srt/SrtTransport.cpp | 465 +++++++++++++++++++++++++++++++++++ srt/SrtTransport.hpp | 143 +++++++++++ srt/Statistic.cpp | 76 ++++++ srt/Statistic.hpp | 43 ++++ 18 files changed, 2484 insertions(+) create mode 100644 srt/Ack.cpp create mode 100644 srt/Ack.hpp create mode 100644 srt/Common.hpp create mode 100644 srt/HSExt.cpp create mode 100644 srt/HSExt.hpp create mode 100644 srt/Packet.cpp create mode 100644 srt/Packet.hpp create mode 100644 srt/PacketQueue.cpp create mode 100644 srt/PacketQueue.hpp create mode 100644 srt/SrtSession.cpp create mode 100644 srt/SrtSession.hpp create mode 100644 srt/SrtTransport.cpp create mode 100644 srt/SrtTransport.hpp create mode 100644 srt/Statistic.cpp create mode 100644 srt/Statistic.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ffaf764..dd155379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ option(ENABLE_FFMPEG "Enable FFmpeg" true) option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" true) option(ENABLE_API_STATIC_LIB "Enable mk_api static lib" false) option(USE_SOLUTION_FOLDERS "Enable solution dir supported" ON) +option(ENABLE_SRT "Enable SRT" true) # ---------------------------------------------------------------------------- # Solution folders: # ---------------------------------------------------------------------------- @@ -486,6 +487,15 @@ if (ENABLE_WEBRTC) endif () endif () +if (ENABLE_SRT) + add_definitions(-DENABLE_SRT) + include_directories(./srt) + file(GLOB SRC_SRT_LIST ./srt/*.cpp ./srt/*.h ./srt/*.hpp) + add_library(srt ${SRC_SRT_LIST}) + list(APPEND LINK_LIB_LIST srt) + message(STATUS "srt 功能已开启") +endif() + #添加c库 if (ENABLE_API) add_subdirectory(api) diff --git a/conf/config.ini b/conf/config.ini index 2c36c22b..7a199215 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -284,6 +284,14 @@ preferredCodecA=PCMU,PCMA,opus,mpeg4-generic #以下范例为所有支持的视频codec preferredCodecV=H264,H265,AV1X,VP9,VP8 +[srt] +#srt播放推流、播放超时时间,单位秒 +timeoutSec=5 +#srt udp服务器监听端口号,所有srt客户端将通过该端口传输srt数据, +#该端口是多线程的,同时支持客户端网络切换导致的连接迁移 +port=9000 + + [rtsp] #rtsp专有鉴权方式是采用base64还是md5方式 authBasic=0 diff --git a/server/main.cpp b/server/main.cpp index f2dd1f61..f98e9640 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -32,6 +32,11 @@ #include "../webrtc/WebRtcSession.h" #endif +#if defined(ENABLE_SRT) +#include "../srt/SrtSession.hpp" +#include "../srt/SrtTransport.hpp" +#endif + #if defined(ENABLE_VERSION) #include "version.h" #endif @@ -284,6 +289,24 @@ int start_main(int argc,char *argv[]) { uint16_t rtcPort = mINI::Instance()[RTC::kPort]; #endif//defined(ENABLE_WEBRTC) + +#if defined(ENABLE_SRT) + auto srtSrv = std::make_shared(); + srtSrv->setOnCreateSocket([](const EventPoller::Ptr &poller, const Buffer::Ptr &buf, struct sockaddr *, int) { + if (!buf) { + return Socket::createSocket(poller, false); + } + auto new_poller = SRT::SrtSession::queryPoller(buf); + if (!new_poller) { + //握手第一阶段 + return Socket::createSocket(poller, false); + } + return Socket::createSocket(new_poller, false); + }); + + uint16_t srtPort = mINI::Instance()[SRT::kPort]; +#endif //defined(ENABLE_SRT) + try { //rtsp服务器,端口默认554 if (rtspPort) { rtspSrv->start(rtspPort); } @@ -313,6 +336,14 @@ int start_main(int argc,char *argv[]) { if (rtcPort) { rtcSrv->start(rtcPort); } #endif//defined(ENABLE_WEBRTC) + +#if defined(ENABLE_SRT) + // srt udp服务器 + if(srtPort){ + srtSrv->start(srtPort); + } +#endif//defined(ENABLE_SRT) + } catch (std::exception &ex) { WarnL << "端口占用或无权限:" << ex.what() << endl; ErrorL << "程序启动失败,请修改配置文件中端口号后重试!" << endl; diff --git a/srt/Ack.cpp b/srt/Ack.cpp new file mode 100644 index 00000000..7a61971e --- /dev/null +++ b/srt/Ack.cpp @@ -0,0 +1,74 @@ +#include "Ack.hpp" +#include "Common.hpp" + +namespace SRT { +bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { + if(len < ACK_CIF_SIZE + ControlPacket::HEADER_SIZE){ + return false; + } + + _data = BufferRaw::create(); + _data->assign((char *)(buf), len); + ControlPacket::loadHeader(); + ack_number = loadUint32(type_specific_info); + uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; + + last_ack_pkt_seq_number = loadUint32(ptr); + ptr += 4; + + rtt = loadUint32(ptr); + ptr += 4; + + rtt_variance = loadUint32(ptr); + ptr += 4; + + available_buf_size = loadUint32(ptr); + ptr += 4; + + pkt_recv_rate = loadUint32(ptr); + ptr += 4; + + estimated_link_capacity = loadUint32(ptr); + ptr += 4; + + recv_rate = loadUint32(ptr); + ptr += 4; + + return true; +} +bool ACKPacket::storeToData() { + _data = BufferRaw::create(); + _data->setCapacity(HEADER_SIZE + ACK_CIF_SIZE); + _data->setSize(HEADER_SIZE + ACK_CIF_SIZE); + control_type = ControlPacket::ACK; + sub_type = 0; + + storeUint32(type_specific_info,ack_number); + storeToHeader(); + + uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; + + storeUint32(ptr,last_ack_pkt_seq_number); + ptr += 4; + + storeUint32(ptr,rtt); + ptr += 4; + + storeUint32(ptr,rtt_variance); + ptr += 4; + + storeUint32(ptr,pkt_recv_rate); + ptr += 4; + + storeUint32(ptr,available_buf_size); + ptr += 4; + + storeUint32(ptr,estimated_link_capacity); + ptr += 4; + + storeUint32(ptr,recv_rate); + ptr += 4; + + return true; +} +} // namespace \ No newline at end of file diff --git a/srt/Ack.hpp b/srt/Ack.hpp new file mode 100644 index 00000000..15a026db --- /dev/null +++ b/srt/Ack.hpp @@ -0,0 +1,96 @@ +#ifndef ZLMEDIAKIT_SRT_ACK_H +#define ZLMEDIAKIT_SRT_ACK_H +#include "Packet.hpp" + + +namespace SRT{ +/* +0 1 2 3 +0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type | Reserved | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Acknowledgement Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+- CIF -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Last Acknowledged Packet Sequence Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| RTT | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| RTT Variance | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Available Buffer Size | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Packets Receiving Rate | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Estimated Link Capacity | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Receiving Rate | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 13: ACK control packet + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-ack-acknowledgment +*/ +class ACKPacket : public ControlPacket +{ +public: + using Ptr = std::shared_ptr; + ACKPacket() = default; + ~ACKPacket() = default; + + enum{ + ACK_CIF_SIZE = 7*4 + }; + + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + + uint32_t ack_number; + + uint32_t last_ack_pkt_seq_number; + uint32_t rtt; + uint32_t rtt_variance; + uint32_t available_buf_size; + uint32_t pkt_recv_rate; + uint32_t estimated_link_capacity; + uint32_t recv_rate; +}; + + +class ACKACKPacket : public ControlPacket{ +public: + using Ptr = std::shared_ptr; + ACKACKPacket() = default; + ~ACKACKPacket() = default; + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override{ + if(len < ControlPacket::HEADER_SIZE){ + return false; + } + _data = BufferRaw::create(); + _data->assign((char *)(buf), len); + ControlPacket::loadHeader(); + ack_number = loadUint32(type_specific_info); + return true; + } + bool storeToData() override{ + _data = BufferRaw::create(); + _data->setCapacity(HEADER_SIZE); + _data->setSize(HEADER_SIZE ); + control_type = ControlPacket::ACKACK; + sub_type = 0; + + storeUint32(type_specific_info,ack_number); + storeToHeader(); + return true; + } + + uint32_t ack_number; + +}; + +} //namespace SRT +#endif // ZLMEDIAKIT_SRT_ACK_H \ No newline at end of file diff --git a/srt/Common.hpp b/srt/Common.hpp new file mode 100644 index 00000000..cfb80240 --- /dev/null +++ b/srt/Common.hpp @@ -0,0 +1,54 @@ +#ifndef ZLMEDIAKIT_SRT_COMMON_H +#define ZLMEDIAKIT_SRT_COMMON_H +#include + +namespace SRT +{ +using SteadyClock = std::chrono::steady_clock; +using TimePoint = std::chrono::time_point; + +using Microseconds = std::chrono::microseconds; +using Milliseconds = std::chrono::milliseconds; + +inline int64_t DurationCountMicroseconds( SteadyClock::duration dur){ + return std::chrono::duration_cast(dur).count(); +} + +inline uint32_t loadUint32(uint8_t *ptr) { + return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; +} +inline uint16_t loadUint16(uint8_t *ptr) { + return ptr[0] << 8 | ptr[1]; +} + +inline void storeUint32(uint8_t *buf, uint32_t val) { + buf[0] = val >> 24; + buf[1] = (val >> 16) & 0xff; + buf[2] = (val >> 8) & 0xff; + buf[3] = val & 0xff; +} + +inline void storeUint16(uint8_t *buf, uint16_t val) { + buf[0] = (val >> 8) & 0xff; + buf[1] = val & 0xff; +} + +inline void storeUint32LE(uint8_t *buf, uint32_t val) { + buf[0] = val & 0xff; + buf[1] = (val >> 8) & 0xff; + buf[2] = (val >> 16) & 0xff; + buf[3] = (val >>24) & 0xff; +} + +inline void storeUint16LE(uint8_t *buf, uint16_t val) { + buf[0] = val & 0xff; + buf[1] = (val>>8) & 0xff; +} + +inline uint32_t srtVersion(int major, int minor, int patch) +{ + return patch + minor*0x100 + major*0x10000; +} +} // namespace SRT + +#endif //ZLMEDIAKIT_SRT_COMMON_H \ No newline at end of file diff --git a/srt/HSExt.cpp b/srt/HSExt.cpp new file mode 100644 index 00000000..5398e48e --- /dev/null +++ b/srt/HSExt.cpp @@ -0,0 +1,127 @@ +#include "HSExt.hpp" + +namespace SRT { +bool HSExtMessage::loadFromData(uint8_t *buf, size_t len) { + if(buf == NULL || len != HSEXT_MSG_SIZE){ + return false; + } + + _data = BufferRaw::create(); + _data->assign((char*)buf,len); + extension_length = 3; + HSExt::loadHeader(); + + assert(extension_type == SRT_CMD_HSREQ || extension_type == SRT_CMD_HSRSP); + + uint8_t* ptr = (uint8_t*)_data->data()+4; + srt_version = loadUint32(ptr); + ptr += 4; + + srt_flag = loadUint32(ptr); + ptr += 4; + + recv_tsbpd_delay = loadUint16(ptr); + ptr += 2; + + send_tsbpd_delay = loadUint16(ptr); + ptr += 2; + + return true; + + } + std::string HSExtMessage::dump(){ + _StrPrinter printer; + printer << "srt version : "<; + uint16_t extension_type; + uint16_t extension_length; + virtual bool loadFromData(uint8_t *buf, size_t len) = 0; + virtual bool storeToData() = 0; + virtual std::string dump() = 0; + ///////Buffer override/////// + char *data() const override { + if (_data) { + return _data->data(); + } + return nullptr; + }; + size_t size() const override { + if (_data) { + return _data->size(); + } + return 0; + }; + +protected: + void loadHeader() { + uint8_t *ptr = (uint8_t *)_data->data(); + extension_type = loadUint16(ptr); + ptr += 2; + extension_length = loadUint16(ptr); + ptr += 2; + } + void storeHeader() { + uint8_t *ptr = (uint8_t *)_data->data(); + SRT::storeUint16(ptr, extension_type); + ptr += 2; + storeUint16(ptr, extension_length); + } + +protected: + BufferRaw::Ptr _data; +}; + +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| SRT Version | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| SRT Flags | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Receiver TSBPD Delay | Sender TSBPD Delay | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 6: Handshake Extension Message structure + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-handshake-extension-message + +*/ +class HSExtMessage : public HSExt { +public: + using Ptr = std::shared_ptr; + enum { + HS_EXT_MSG_TSBPDSND = 0x00000001, + HS_EXT_MSG_TSBPDRCV = 0x00000002, + HS_EXT_MSG_CRYPT = 0x00000004, + HS_EXT_MSG_TLPKTDROP = 0x00000008, + HS_EXT_MSG_PERIODICNAK = 0x00000010, + HS_EXT_MSG_REXMITFLG = 0x00000020, + HS_EXT_MSG_STREAM = 0x00000040, + HS_EXT_MSG_PACKET_FILTER = 0x00000080 + }; + enum { HSEXT_MSG_SIZE = 16 }; + HSExtMessage() = default; + ~HSExtMessage() = default; + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + std::string dump() override; + uint32_t srt_version; + uint32_t srt_flag; + uint16_t recv_tsbpd_delay; + uint16_t send_tsbpd_delay; +}; + +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | +| Stream ID | + ... +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 7: Stream ID Extension Message + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-stream-id-extension-message +*/ +class HSExtStreamID : public HSExt { +public: + using Ptr = std::shared_ptr; + HSExtStreamID() = default; + ~HSExtStreamID() = default; + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + std::string dump() override; + std::string streamid; +}; +} // namespace SRT +#endif // ZLMEDIAKIT_SRT_HS_EXT_H \ No newline at end of file diff --git a/srt/Packet.cpp b/srt/Packet.cpp new file mode 100644 index 00000000..af4b3772 --- /dev/null +++ b/srt/Packet.cpp @@ -0,0 +1,574 @@ + +#include "sys/socket.h" +#include "netdb.h" + +#include +#include "Util/logger.h" +#include "Util/MD5.h" + +#include "Packet.hpp" + + + +namespace SRT { + + +const size_t DataPacket::HEADER_SIZE; +const size_t ControlPacket::HEADER_SIZE; +const size_t HandshakePacket::HS_CONTENT_MIN_SIZE; + +bool DataPacket::isDataPacket(uint8_t *buf, size_t len) { + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + if (!(buf[0] & 0x80)) { + return true; + } + return false; +} + +uint32_t DataPacket::getSocketID(uint8_t *buf, size_t len){ + uint8_t *ptr = buf; + ptr += 12; + return loadUint32(ptr); +} + +bool DataPacket::loadFromData(uint8_t *buf, size_t len) { + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + uint8_t *ptr = buf; + f = ptr[0] >> 7; + packet_seq_number = loadUint32(ptr)&0x7fffffff; + ptr += 4; + + PP = ptr[0] >> 6; + O = (ptr[0] & 0x20) >> 5; + KK = (ptr[0] & 0x18) >> 3; + R = (ptr[0] & 0x04) >> 2; + msg_number = (ptr[0] & 0x03) << 24 | ptr[1] << 12 | ptr[2] << 8 | ptr[3]; + ptr += 4; + + timestamp = loadUint32(ptr); + ptr += 4; + + dst_socket_id = loadUint32(ptr); + ptr += 4; + + _data = BufferRaw::create(); + _data->assign((char *)(buf), len); + return true; +} + +bool DataPacket::storeToData(uint8_t *buf, size_t len) { + _data = BufferRaw::create(); + _data->setCapacity(len + HEADER_SIZE); + _data->setSize(len + HEADER_SIZE); + + uint8_t *ptr = (uint8_t *)_data->data(); + + ptr[0] = packet_seq_number >> 24; + ptr[1] = (packet_seq_number >> 16) & 0xff; + ptr[2] = (packet_seq_number >> 8) & 0xff; + ptr[3] = packet_seq_number & 0xff; + ptr += 4; + + ptr[0] = PP << 6; + ptr[0] |= O << 5; + ptr[0] |= KK << 3; + ptr[0] |= R << 2; + ptr[0] |= (msg_number & 0xff000000) >> 24; + ptr[1] = (msg_number & 0xff0000) >> 16; + ptr[2] = (msg_number & 0xff00) >> 8; + ptr[3] = msg_number & 0xff; + ptr += 4; + + storeUint32(ptr, timestamp); + ptr += 4; + + storeUint32(ptr, dst_socket_id); + ptr += 4; + + memcpy(ptr, buf, len); + return true; +} + +char *DataPacket::data() const { + if (!_data) + return nullptr; + return _data->data(); +} +size_t DataPacket::size() const { + if (!_data) { + return 0; + } + return _data->size(); +} + +char *DataPacket::payloadData() { + if (!_data) + return nullptr; + return _data->data() + HEADER_SIZE; +} +size_t DataPacket::payloadSize() { + if (!_data) { + return 0; + } + return _data->size() - HEADER_SIZE; +} + + + +bool ControlPacket::isControlPacket(uint8_t *buf, size_t len) { + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + if (buf[0] & 0x80) { + return true; + } + return false; +} + +uint16_t ControlPacket::getControlType(uint8_t *buf, size_t len) { + uint8_t *ptr = buf; + uint16_t control_type = (ptr[0] & 0x7f) << 8 | ptr[1]; + return control_type; +} + +bool ControlPacket::loadHeader() { + uint8_t *ptr = (uint8_t *)_data->data(); + f = ptr[0] >> 7; + control_type = (ptr[0] & 0x7f) << 8 | ptr[1]; + ptr += 2; + + sub_type = loadUint16(ptr); + ptr += 2; + + type_specific_info[0] = ptr[0]; + type_specific_info[1] = ptr[1]; + type_specific_info[2] = ptr[2]; + type_specific_info[3] = ptr[3]; + ptr += 4; + + timestamp = loadUint32(ptr); + ptr += 4; + + dst_socket_id = loadUint32(ptr); + ptr += 4; + return true; +} +bool ControlPacket::storeToHeader() { + uint8_t *ptr = (uint8_t *)_data->data(); + ptr[0] = 0x80; + ptr[0] |= control_type >> 8; + ptr[1] = control_type & 0xff; + ptr += 2; + + storeUint16(ptr, sub_type); + ptr += 2; + + ptr[0] = type_specific_info[0]; + ptr[1] = type_specific_info[1]; + ptr[2] = type_specific_info[2]; + ptr[3] = type_specific_info[3]; + ptr += 4; + + storeUint32(ptr, timestamp); + ptr += 4; + + storeUint32(ptr, dst_socket_id); + ptr += 4; + return true; +} + +char *ControlPacket::data() const { + if (!_data) + return nullptr; + return _data->data(); +} +size_t ControlPacket::size() const { + if (!_data) { + return 0; + } + return _data->size(); +} +uint32_t ControlPacket::getSocketID(uint8_t *buf, size_t len){ + return loadUint32(buf+12); +} +bool HandshakePacket::loadFromData(uint8_t *buf, size_t len) { + if(HEADER_SIZE+HS_CONTENT_MIN_SIZE > len){ + ErrorL << "size too smalle " << encryption_field; + return false; + } + _data = BufferRaw::create(); + _data->assign((char *)(buf), len); + ControlPacket::loadHeader(); + + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; + // parse CIF + version = loadUint32(ptr); + ptr += 4; + + encryption_field = loadUint16(ptr); + ptr += 2; + + extension_field = loadUint16(ptr); + ptr += 2; + + initial_packet_sequence_number = loadUint32(ptr); + ptr += 4; + + mtu = loadUint32(ptr); + ptr += 4; + + max_flow_window_size = loadUint32(ptr); + ptr += 4; + + handshake_type = loadUint32(ptr); + ptr += 4; + + srt_socket_id = loadUint32(ptr); + ptr += 4; + + syn_cookie = loadUint32(ptr); + ptr += 4; + + memcpy(peer_ip_addr, ptr, sizeof(peer_ip_addr) * sizeof(peer_ip_addr[0])); + ptr += sizeof(peer_ip_addr) * sizeof(peer_ip_addr[0]); + + if (encryption_field != NO_ENCRYPTION) { + ErrorL << "not support encryption " << encryption_field; + } + + if(extension_field == 0){ + return true; + } + + if(len == HEADER_SIZE+HS_CONTENT_MIN_SIZE){ + //ErrorL << "extension filed not exist " << extension_field; + return true; + } + + return loadExtMessage(ptr,len-HS_CONTENT_MIN_SIZE-HEADER_SIZE); +} +bool HandshakePacket::loadExtMessage(uint8_t *buf,size_t len){ + uint8_t* ptr = buf; + ext_list.clear(); + uint16_t type; + uint16_t length; + HSExt::Ptr ext; + while(ptr(); + break; + case HSExt::SRT_CMD_SID: + ext = std::make_shared(); + break; + default: + WarnL<<"not support ext "<loadFromData(ptr,length*4+4)){ + ext_list.push_back(std::move(ext)); + }else{ + WarnL<<"parse HS EXT failed type="<ss_family == AF_INET){ + struct sockaddr_in * ipv4 = (struct sockaddr_in *)addr; + //抓包 奇怪好像是小头端??? + storeUint32LE(peer_ip_addr,ipv4->sin_addr.s_addr); + }else{ + const sockaddr_in6* ipv6 = (struct sockaddr_in6 *)addr; + memcpy(peer_ip_addr,ipv6->sin6_addr.s6_addr,sizeof(peer_ip_addr)*sizeof(peer_ip_addr[0])); + } +} +uint32_t HandshakePacket::generateSynCookie(struct sockaddr_storage* addr,TimePoint ts,uint32_t current_cookie, int correction ){ + + static std::atomic distractor{0}; + uint32_t rollover = distractor.load() + 10; + + for (;;) + { + // SYN cookie + char clienthost[NI_MAXHOST]; + char clientport[NI_MAXSERV]; + getnameinfo((struct sockaddr*)addr, + sizeof(struct sockaddr_storage), + clienthost, + sizeof(clienthost), + clientport, + sizeof(clientport), + NI_NUMERICHOST | NI_NUMERICSERV); + int64_t timestamp = (DurationCountMicroseconds(SteadyClock::now() - ts) / 60000000) + distractor.load() + + correction; // secret changes every one minute + std::stringstream cookiestr; + cookiestr << clienthost << ":" << clientport << ":" << timestamp; + union { + unsigned char cookie[16]; + uint32_t cookie_val; + }; + MD5 md5(cookiestr.str()); + memcpy(cookie,md5.rawdigest().c_str(),16); + + if (cookie_val != current_cookie) + return cookie_val; + + ++distractor; + + // This is just to make the loop formally breakable, + // but this is virtually impossible to happen. + if (distractor == rollover) + return cookie_val; + } +} + +bool KeepLivePacket::loadFromData(uint8_t *buf, size_t len){ + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + _data = BufferRaw::create(); + _data->assign((char*)buf,len); + + return loadHeader(); +} +bool KeepLivePacket::storeToData(){ + control_type = ControlPacket::KEEPALIVE; + sub_type = 0; + + _data = BufferRaw::create(); + _data->setCapacity(HEADER_SIZE); + _data->setSize(HEADER_SIZE); + return storeToHeader(); +} + +bool NAKPacket::loadFromData(uint8_t *buf, size_t len) { + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + _data = BufferRaw::create(); + _data->assign((char*)buf,len); + loadHeader(); + + uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t* end = (uint8_t*)_data->data()+_data->size(); + LostPair lost; + while (ptrsetCapacity(HEADER_SIZE+cif_size); + _data->setSize(HEADER_SIZE+cif_size); + + storeToHeader(); + + uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + + for(auto it : lost_list){ + if(it.first+1 ==it.second){ + storeUint32(ptr,it.first); + ptr[0] = ptr[0]&0x7f; + ptr += 4; + }else{ + storeUint32(ptr,it.first); + ptr[0] |= 0x80; + + storeUint32(ptr+4,it.second-1); + //ptr[4] = ptr[4]&0x7f; + + ptr += 8; + } + } + + return true; +} + +size_t NAKPacket::getCIFSize(){ + size_t size = 0; + for(auto it : lost_list){ + if(it.first+1 ==it.second){ + size += 4; + }else{ + size += 8; + } + } + return size; +} + +std::string NAKPacket::dump(){ + _StrPrinter printer; + for (auto it : lost_list) { + printer<<"[ "<assign((char*)buf,len); + loadHeader(); + + uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + + first_pkt_seq_num = loadUint32(ptr); + ptr += 4; + + last_pkt_seq_num = loadUint32(ptr); + ptr += 4; + return true; +} +bool MsgDropReqPacket::storeToData() { + control_type = DROPREQ; + sub_type = 0; + _data = BufferRaw::create(); + _data->setCapacity(HEADER_SIZE+8); + _data->setSize(HEADER_SIZE+8); + + storeToHeader(); + + uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + + storeUint32(ptr,first_pkt_seq_num); + ptr += 4; + + storeUint32(ptr,last_pkt_seq_num); + ptr += 4; + return true; +} +} // namespace SRT \ No newline at end of file diff --git a/srt/Packet.hpp b/srt/Packet.hpp new file mode 100644 index 00000000..f2fbc98a --- /dev/null +++ b/srt/Packet.hpp @@ -0,0 +1,317 @@ +#ifndef ZLMEDIAKIT_SRT_PACKET_H +#define ZLMEDIAKIT_SRT_PACKET_H + +#include +#include + +#include "Network/Buffer.h" + +#include "Common.hpp" +#include "HSExt.hpp" + +namespace SRT { + +using namespace toolkit; +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|0| Packet Sequence Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|P P|O|K K|R| Message Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++ Data + +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 3: Data packet structure + reference https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-packet-structure +*/ +class DataPacket : public Buffer { +public: + using Ptr = std::shared_ptr; + DataPacket() = default; + ~DataPacket() = default; + + static const size_t HEADER_SIZE = 16; + static bool isDataPacket(uint8_t *buf, size_t len); + static uint32_t getSocketID(uint8_t *buf, size_t len); + bool loadFromData(uint8_t *buf, size_t len); + bool storeToData(uint8_t *buf, size_t len); + + ///////Buffer override/////// + char *data() const override; + size_t size() const override; + + char *payloadData(); + size_t payloadSize(); + + uint8_t f; + uint32_t packet_seq_number; + uint8_t PP; + uint8_t O; + uint8_t KK; + uint8_t R; + uint32_t msg_number; + uint32_t timestamp; + uint32_t dst_socket_id; + +private: + BufferRaw::Ptr _data; +}; +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type | Subtype | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type-specific Information | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+- CIF -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++ Control Information Field + +| | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 4: Control packet structure + reference https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-control-packets +*/ +class ControlPacket : public Buffer { +public: + using Ptr = std::shared_ptr; + static const size_t HEADER_SIZE = 16; + static bool isControlPacket(uint8_t *buf, size_t len); + static uint16_t getControlType(uint8_t *buf, size_t len); + static uint32_t getSocketID(uint8_t *buf, size_t len); + + ControlPacket() = default; + virtual ~ControlPacket() = default; + virtual bool loadFromData(uint8_t *buf, size_t len) = 0; + virtual bool storeToData() = 0; + + bool loadHeader(); + bool storeToHeader(); + + ///////Buffer override/////// + char *data() const override; + size_t size() const override; + + enum { + HANDSHAKE = 0x0000, + KEEPALIVE = 0x0001, + ACK = 0x0002, + NAK = 0x0003, + CONGESTIONWARNING = 0x0004, + SHUTDOWN = 0x0005, + ACKACK = 0x0006, + DROPREQ = 0x0007, + PEERERROR = 0x0008, + USERDEFINEDTYPE = 0x7FFF + }; + + uint32_t sub_type : 16; + uint32_t control_type : 15; + uint32_t f : 1; + uint8_t type_specific_info[4]; + uint32_t timestamp; + uint32_t dst_socket_id; + +protected: + BufferRaw::Ptr _data; +}; + +/** + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Version | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Encryption Field | Extension Field | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Initial Packet Sequence Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Maximum Transmission Unit Size | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Maximum Flow Window Size | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Handshake Type | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| SRT Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| SYN Cookie | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++ + +| | ++ Peer IP Address + +| | ++ + +| | ++=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +| Extension Type | Extension Length | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| | ++ Extension Contents + +| | ++=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + Figure 5: Handshake packet structure + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-handshake + */ +class HandshakePacket : public ControlPacket { +public: + using Ptr = std::shared_ptr; + enum { NO_ENCRYPTION = 0, AES_128 = 1, AES_196 = 2, AES_256 = 3 }; + static const size_t HS_CONTENT_MIN_SIZE = 48; + enum { + HS_TYPE_DONE = 0xFFFFFFFD, + HS_TYPE_AGREEMENT = 0xFFFFFFFE, + HS_TYPE_CONCLUSION = 0xFFFFFFFF, + HS_TYPE_WAVEHAND = 0x00000000, + HS_TYPE_INDUCTION = 0x00000001 + }; + + enum { HS_EXT_FILED_HSREQ = 0x00000001, HS_EXT_FILED_KMREQ = 0x00000002, HS_EXT_FILED_CONFIG = 0x00000004 }; + + + + HandshakePacket() = default; + ~HandshakePacket() = default; + + static bool isHandshakePacket(uint8_t *buf, size_t len); + static uint32_t getHandshakeType(uint8_t *buf, size_t len); + static uint32_t getSynCookie(uint8_t *buf, size_t len); + static uint32_t generateSynCookie(struct sockaddr_storage* addr,TimePoint ts,uint32_t current_cookie = 0, int correction = 0); + + void assignPeerIP(struct sockaddr_storage* addr); + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + + uint32_t version; + uint16_t encryption_field; + uint16_t extension_field; + uint32_t initial_packet_sequence_number; + uint32_t mtu; + uint32_t max_flow_window_size; + uint32_t handshake_type; + uint32_t srt_socket_id; + uint32_t syn_cookie; + uint8_t peer_ip_addr[16]; + + std::vector ext_list; +private: + bool loadExtMessage(uint8_t *buf,size_t len); + bool storeExtMessage(); + size_t getExtSize(); +}; +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type | Reserved | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type-specific Information | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 12: Keep-Alive control packet + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-keep-alive +*/ +class KeepLivePacket : public ControlPacket +{ +public: + using Ptr = std::shared_ptr; + KeepLivePacket() = default; + ~KeepLivePacket() = default; + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; +}; + +/* +An SRT NAK packet is formatted as follows: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type | Reserved | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type-specific Information | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+- CIF (Loss List) -+-+-+-+-+-+-+-+-+-+-+-+ +|0| Lost packet sequence number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Range of lost packets from sequence number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|0| Up to sequence number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +|0| Lost packet sequence number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 14: NAK control packet + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-nak-control-packet +*/ +class NAKPacket : public ControlPacket +{ +public: + using Ptr = std::shared_ptr; + using LostPair = std::pair; + NAKPacket() = default; + ~NAKPacket() = default; + std::string dump(); + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + + std::list lost_list; +private: + size_t getCIFSize(); +}; + + +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type = 7 | Reserved = 0 | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Message Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| First Packet Sequence Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Last Packet Sequence Number | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 18: Drop Request control packet + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-message-drop-request +*/ +class MsgDropReqPacket : public ControlPacket +{ + public: + using Ptr = std::shared_ptr; + MsgDropReqPacket() = default; + ~MsgDropReqPacket() = default; + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override; + bool storeToData() override; + + uint32_t first_pkt_seq_num; + uint32_t last_pkt_seq_num; +}; + +} // namespace SRT + +#endif //ZLMEDIAKIT_SRT_PACKET_H \ No newline at end of file diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp new file mode 100644 index 00000000..ea342277 --- /dev/null +++ b/srt/PacketQueue.cpp @@ -0,0 +1,126 @@ +#include "PacketQueue.hpp" + +namespace SRT { +PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency) + : _pkt_expected_seq(init_seq) + , _pkt_cap(max_size) + , _pkt_lantency(lantency) { + } + +bool PacketQueue::inputPacket(DataPacket::Ptr pkt) { + if (pkt->packet_seq_number < _pkt_expected_seq) { + // TOO later drop this packet + return false; + } + + _pkt_map[pkt->packet_seq_number] = pkt; + + return true; +} + +std::list PacketQueue::tryGetPacket() { + std::list re; + while (_pkt_map.find(_pkt_expected_seq) != _pkt_map.end()) { + re.push_back(_pkt_map[_pkt_expected_seq]); + _pkt_map.erase(_pkt_expected_seq); + _pkt_expected_seq++; + } + + while (_pkt_map.size() > _pkt_cap) { + // force pop some packet + auto it = _pkt_map.begin(); + re.push_back(it->second); + _pkt_expected_seq = it->second->packet_seq_number + 1; + _pkt_map.erase(it); + } + + while (timeLantency() > _pkt_lantency) { + auto it = _pkt_map.begin(); + re.push_back(it->second); + _pkt_expected_seq = it->second->packet_seq_number + 1; + _pkt_map.erase(it); + } + + return std::move(re); +} + + +bool PacketQueue::dropForRecv(uint32_t first,uint32_t last){ + if(first >= last){ + return false; + } + + if(_pkt_expected_seq <= last){ + _pkt_expected_seq = last+1; + return true; + } + + return false; +} +uint32_t PacketQueue::timeLantency() { + if (_pkt_map.empty()) { + return 0; + } + + auto first = _pkt_map.begin()->second; + auto last = _pkt_map.rbegin()->second; + + return last->timestamp - first->timestamp; +} + +std::list PacketQueue::getLostSeq() { + std::list re; + if(_pkt_map.empty()){ + return re; + } + + if(getExpectedSize() == getSize()){ + return re; + } + + PacketQueue::LostPair lost; + lost.first = 0; + lost.second = 0; + + uint32_t i = _pkt_expected_seq; + bool finish = true; + for(i = _pkt_expected_seq;i<=_pkt_map.rbegin()->first;++i){ + if(_pkt_map.find(i) == _pkt_map.end()){ + if(finish){ + finish = false; + lost.first = i; + lost.second = i+1; + }else{ + lost.second = i+1; + } + }else{ + + if(!finish){ + finish = true; + re.push_back(lost); + } + } + } + + return re; +} + +size_t PacketQueue::getSize(){ + return _pkt_map.size(); +} + +size_t PacketQueue::getExpectedSize() { + if(_pkt_map.empty()){ + return 0; + } + return _pkt_map.rbegin()->first - _pkt_expected_seq+1; +} + +size_t PacketQueue::getAvailableBufferSize(){ + return _pkt_cap - getExpectedSize(); +} + +uint32_t PacketQueue::getExpectedSeq(){ + return _pkt_expected_seq; +} +} // namespace SRT \ No newline at end of file diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp new file mode 100644 index 00000000..05996647 --- /dev/null +++ b/srt/PacketQueue.hpp @@ -0,0 +1,44 @@ +#ifndef ZLMEDIAKIT_SRT_PACKET_QUEUE_H +#define ZLMEDIAKIT_SRT_PACKET_QUEUE_H +#include +#include +#include +#include +#include + +#include "Packet.hpp" + +namespace SRT{ + +class PacketQueue +{ +public: + using Ptr = std::shared_ptr; + using LostPair = std::pair; + + PacketQueue(uint32_t max_size,uint32_t init_seq,uint32_t lantency); + ~PacketQueue() = default; + bool inputPacket(DataPacket::Ptr pkt); + std::list tryGetPacket(); + uint32_t timeLantency(); + std::list getLostSeq(); + + size_t getSize(); + size_t getExpectedSize(); + size_t getAvailableBufferSize(); + uint32_t getExpectedSeq(); + + bool dropForRecv(uint32_t first,uint32_t last); + + +private: + std::map _pkt_map; + + uint32_t _pkt_expected_seq = 0; + uint32_t _pkt_cap; + uint32_t _pkt_lantency; +}; + +} + +#endif //ZLMEDIAKIT_SRT_PACKET_QUEUE_H \ No newline at end of file diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp new file mode 100644 index 00000000..a20246d4 --- /dev/null +++ b/srt/SrtSession.cpp @@ -0,0 +1,137 @@ +#include "SrtSession.hpp" +#include "Packet.hpp" +#include "SrtTransport.hpp" + +#include "Common/config.h" + +namespace SRT { +using namespace mediakit; + +SrtSession::SrtSession(const Socket::Ptr &sock) + : UdpSession(sock) { + socklen_t addr_len = sizeof(_peer_addr); + getpeername(sock->rawFD(), (struct sockaddr *)&_peer_addr, &addr_len); +} + +SrtSession::~SrtSession() { + InfoP(this); +} + +EventPoller::Ptr SrtSession::queryPoller(const Buffer::Ptr &buffer) { + uint8_t* data = (uint8_t*)buffer->data(); + size_t size = buffer->size(); + + if(DataPacket::isDataPacket(data,size)){ + uint32_t socket_id = DataPacket::getSocketID(data,size); + auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); + return trans ? trans->getPoller() : nullptr; + } + + if(HandshakePacket::isHandshakePacket(data,size)){ + auto type = HandshakePacket::getHandshakeType(data,size); + if(type == HandshakePacket::HS_TYPE_INDUCTION){ + // 握手第一阶段 + return nullptr; + }else if(type == HandshakePacket::HS_TYPE_CONCLUSION){ + // 握手第二阶段 + uint32_t sync_cookie = HandshakePacket::getSynCookie(data,size); + auto trans = SrtTransportManager::Instance().getHandshakeItem(std::to_string(sync_cookie)); + return trans ? trans->getPoller() : nullptr; + }else{ + WarnL<<" not reach there"; + } + }else{ + uint32_t socket_id = ControlPacket::getSocketID(data,size); + auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); + return trans ? trans->getPoller() : nullptr; + } + return nullptr; +} + +void SrtSession::onRecv(const Buffer::Ptr &buffer) { + uint8_t* data = (uint8_t*)buffer->data(); + size_t size = buffer->size(); + + if (_find_transport) { + //只允许寻找一次transport + _find_transport = false; + + if (DataPacket::isDataPacket(data, size)) { + uint32_t socket_id = DataPacket::getSocketID(data, size); + auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); + if(trans){ + _transport = std::move(trans); + }else{ + WarnL<<" data packet not find transport "; + } + } + + if (HandshakePacket::isHandshakePacket(data, size)) { + auto type = HandshakePacket::getHandshakeType(data, size); + if (type == HandshakePacket::HS_TYPE_INDUCTION) { + // 握手第一阶段 + _transport = std::make_shared(getPoller()); + + } else if (type == HandshakePacket::HS_TYPE_CONCLUSION) { + // 握手第二阶段 + uint32_t sync_cookie = HandshakePacket::getSynCookie(data, size); + auto trans = SrtTransportManager::Instance().getHandshakeItem(std::to_string(sync_cookie)); + if (trans) { + _transport = std::move(trans); + } else { + WarnL << " hanshake packet not find transport "; + } + } else { + WarnL << " not reach there"; + } + } else { + uint32_t socket_id = ControlPacket::getSocketID(data, size); + auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); + if(trans){ + _transport = std::move(trans); + }else{ + WarnL << " not find transport"; + } + } + + if(_transport){ + _transport->setSession(shared_from_this()); + } + InfoP(this); + } + _ticker.resetTime(); + + if(_transport){ + _transport->inputSockData(data,size,&_peer_addr); + }else{ + WarnL<< "ingore data"; + } +} + +void SrtSession::onError(const SockException &err) { + // udp链接超时,但是srt链接不一定超时,因为可能存在udp链接迁移的情况 + //在udp链接迁移时,新的SrtSession对象将接管SrtSession对象的生命周期 + //本SrtSession对象将在超时后自动销毁 + WarnP(this) << err.what(); + + if (!_transport) { + return; + } + + // 防止互相引用导致不释放 + auto transport = std::move(_transport); + getPoller()->async([transport,err] { + //延时减引用,防止使用transport对象时,销毁对象 + transport->onShutdown(err); + }, false); +} + +void SrtSession::onManager() { + GET_CONFIG(float, timeoutSec, kTimeOutSec); + if (_ticker.elapsedTime() > timeoutSec*1000) { + shutdown(SockException(Err_timeout, "srt connection timeout")); + return; + } +} + +} // namespace SRT \ No newline at end of file diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp new file mode 100644 index 00000000..9478f1b9 --- /dev/null +++ b/srt/SrtSession.hpp @@ -0,0 +1,31 @@ +#ifndef ZLMEDIAKIT_SRT_SESSION_H +#define ZLMEDIAKIT_SRT_SESSION_H + +#include "Network/Session.h" +#include "SrtTransport.hpp" + +namespace SRT { + +using namespace toolkit; + +class SrtSession : public UdpSession { +public: + SrtSession(const Socket::Ptr &sock); + ~SrtSession() override; + + void onRecv(const Buffer::Ptr &) override; + void onError(const SockException &err) override; + void onManager() override; + + static EventPoller::Ptr queryPoller(const Buffer::Ptr &buffer); + +private: + bool _find_transport = true; + Ticker _ticker; + struct sockaddr_storage _peer_addr; + SrtTransport::Ptr _transport; + +}; + +} // namespace SRT +#endif //ZLMEDIAKIT_SRT_SESSION_H \ No newline at end of file diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp new file mode 100644 index 00000000..4086ffe2 --- /dev/null +++ b/srt/SrtTransport.cpp @@ -0,0 +1,465 @@ +#include "Util/onceToken.h" + +#include "SrtTransport.hpp" +#include "Packet.hpp" +#include "Ack.hpp" +namespace SRT { +#define SRT_FIELD "srt." +//srt 超时时间 +const std::string kTimeOutSec = SRT_FIELD"timeoutSec"; +//srt 单端口udp服务器 +const std::string kPort = SRT_FIELD"port"; + +static std::atomic s_srt_socket_id_generate{125}; +//////////// SrtTransport ////////////////////////// +SrtTransport::SrtTransport(const EventPoller::Ptr &poller) + : _poller(poller) { + _start_timestamp = SteadyClock::now(); + _socket_id = s_srt_socket_id_generate.fetch_add(1); + } + +SrtTransport::~SrtTransport(){ + TraceL<<" "; +} +const EventPoller::Ptr &SrtTransport::getPoller() const { + return _poller; +} + +void SrtTransport::setSession(Session::Ptr session) { + _history_sessions.emplace(session.get(), session); + if (_selected_session) { + InfoL << "srt network changed: " << _selected_session->get_peer_ip() << ":" + << _selected_session->get_peer_port() << " -> " << session->get_peer_ip() << ":" + << session->get_peer_port() << ", id:" << _selected_session->getIdentifier(); + } + _selected_session = session; +} +const Session::Ptr &SrtTransport::getSession() const { + return _selected_session; +} + +void SrtTransport::switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr){ + BufferRaw::Ptr tmp = BufferRaw::create(); + struct sockaddr_storage tmp_addr = *addr; + tmp->assign((char*)buf,len); + auto trans = SrtTransportManager::Instance().getItem(std::to_string(socketid)); + if(trans){ + trans->getPoller()->async([tmp,tmp_addr,trans]{ + trans->inputSockData((uint8_t*)tmp->data(),tmp->size(),(struct sockaddr_storage*)&tmp_addr); + }); + } +} + +void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr) { + using srt_control_handler = void (SrtTransport::*)(uint8_t* buf,int len,struct sockaddr_storage *addr); + static std::unordered_map s_control_functions; + static onceToken token([]() { + s_control_functions.emplace(ControlPacket::HANDSHAKE, &SrtTransport::handleHandshake); + s_control_functions.emplace(ControlPacket::KEEPALIVE, &SrtTransport::handleKeeplive); + s_control_functions.emplace(ControlPacket::ACK, &SrtTransport::handleACK); + s_control_functions.emplace(ControlPacket::NAK, &SrtTransport::handleNAK); + s_control_functions.emplace(ControlPacket::CONGESTIONWARNING, &SrtTransport::handleCongestionWarning); + s_control_functions.emplace(ControlPacket::SHUTDOWN, &SrtTransport::handleShutDown); + s_control_functions.emplace(ControlPacket::ACKACK, &SrtTransport::handleACKACK); + s_control_functions.emplace(ControlPacket::DROPREQ, &SrtTransport::handleDropReq); + s_control_functions.emplace(ControlPacket::PEERERROR, &SrtTransport::handlePeerError); + s_control_functions.emplace(ControlPacket::USERDEFINEDTYPE, &SrtTransport::handleUserDefinedType); + }); + auto now = SteadyClock::now(); + // 处理srt数据 + if (DataPacket::isDataPacket(buf, len)) { + uint32_t socketId = DataPacket::getSocketID(buf,len); + if(socketId == _socket_id){ + _pkt_recv_rate_context.inputPacket(now); + _estimated_link_capacity_context.inputPacket(now); + _recv_rate_context.inputPacket(now, len); + + handleDataPacket(buf, len, addr); + }else{ + switchToOtherTransport(buf,len,socketId,addr); + } + } else { + if (ControlPacket::isControlPacket(buf, len)) { + uint32_t socketId = ControlPacket::getSocketID(buf,len); + uint16_t type = ControlPacket::getControlType(buf,len); + if(type != ControlPacket::HANDSHAKE && socketId != _socket_id && _socket_id != 0){ + // socket id not same + switchToOtherTransport(buf,len,socketId,addr); + return; + } + _pkt_recv_rate_context.inputPacket(now); + _estimated_link_capacity_context.inputPacket(now); + _recv_rate_context.inputPacket(now, len); + + auto it = s_control_functions.find(type); + if (it == s_control_functions.end()) { + WarnL<<" not support type ignore" << ControlPacket::getControlType(buf,len); + return; + }else{ + (this->*(it->second))(buf,len,addr); + } + } else { + // not reach + WarnL << "not reach this"; + } + } +} + +void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockaddr_storage *addr) { + // Induction Phase + TraceL << getIdentifier() << " Induction Phase "; + if (_handleshake_res) { + TraceL << getIdentifier() << " Induction handle repeate "; + sendControlPacket(_handleshake_res, true); + return; + } + + _init_seq_number = pkt.initial_packet_sequence_number; + _max_window_size = pkt.max_flow_window_size; + _mtu = pkt.mtu; + + _peer_socket_id = pkt.srt_socket_id; + HandshakePacket::Ptr res = std::make_shared(); + res->dst_socket_id = _peer_socket_id; + res->timestamp = DurationCountMicroseconds(_start_timestamp.time_since_epoch()); + res->mtu = _mtu; + res->max_flow_window_size = _max_window_size; + res->initial_packet_sequence_number = _init_seq_number; + res->version = 5; + res->encryption_field = HandshakePacket::NO_ENCRYPTION; + res->extension_field = 0x4A17; + res->handshake_type = HandshakePacket::HS_TYPE_INDUCTION; + res->srt_socket_id = _peer_socket_id; + res->syn_cookie = HandshakePacket::generateSynCookie(addr, _start_timestamp); + _sync_cookie = res->syn_cookie; + memcpy(res->peer_ip_addr, pkt.peer_ip_addr, sizeof(pkt.peer_ip_addr) * sizeof(pkt.peer_ip_addr[0])); + _handleshake_res = res; + res->storeToData(); + + registerSelfHandshake(); + sendControlPacket(res, true); +} +void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockaddr_storage *addr) { + if(!_handleshake_res){ + ErrorL<<"must Induction Phase for handleshake "; + return; + } + + if (_handleshake_res->handshake_type == HandshakePacket::HS_TYPE_INDUCTION) { + // first + HSExtMessage::Ptr req; + HSExtStreamID::Ptr sid; + + for (auto ext : pkt.ext_list) { + //TraceL << getIdentifier() << " ext " << ext->dump(); + if (!req) { + req = std::dynamic_pointer_cast(ext); + } + if(!sid){ + sid = std::dynamic_pointer_cast(ext); + } + } + if(sid){ + _stream_id = sid->streamid; + } + TraceL << getIdentifier() << " CONCLUSION Phase "; + HandshakePacket::Ptr res = std::make_shared(); + res->dst_socket_id = _peer_socket_id; + res->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); + res->mtu = _mtu; + res->max_flow_window_size = _max_window_size; + res->initial_packet_sequence_number = _init_seq_number; + res->version = 5; + res->encryption_field = HandshakePacket::NO_ENCRYPTION; + res->extension_field = HandshakePacket::HS_EXT_FILED_HSREQ; + res->handshake_type = HandshakePacket::HS_TYPE_CONCLUSION; + res->srt_socket_id = _socket_id; + res->syn_cookie = 0; + res->assignPeerIP(addr); + HSExtMessage::Ptr ext = std::make_shared(); + ext->extension_type = HSExt::SRT_CMD_HSRSP; + ext->srt_version = srtVersion(1, 5, 0); + ext->srt_flag = req->srt_flag; + ext->recv_tsbpd_delay = ext->send_tsbpd_delay = req->recv_tsbpd_delay; + res->ext_list.push_back(std::move(ext)); + res->storeToData(); + _handleshake_res = res; + unregisterSelfHandshake(); + registerSelf(); + sendControlPacket(res, true); + TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<recv_tsbpd_delay; + _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); + onHandShakeFinished(_stream_id); + } else { + TraceL << getIdentifier() << " CONCLUSION handle repeate "; + sendControlPacket(_handleshake_res, true); + } +} +void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ + HandshakePacket pkt; + assert(pkt.loadFromData(buf,len)); + + if(pkt.handshake_type == HandshakePacket::HS_TYPE_INDUCTION){ + handleHandshakeInduction(pkt,addr); + }else if(pkt.handshake_type == HandshakePacket::HS_TYPE_CONCLUSION){ + handleHandshakeConclusion(pkt,addr); + }else{ + WarnL<<" not support handshake type = "<< pkt.handshake_type; + } + _ack_ticker.resetTime(); + _nak_ticker.resetTime(); +} +void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; +} +void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; + auto now = SteadyClock::now(); + ACKPacket ack; + ack.loadFromData(buf,len); + + ACKACKPacket::Ptr pkt = std::make_shared(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(now -_start_timestamp); + pkt->ack_number = ack.ack_number; + pkt->storeToData(); + sendControlPacket(pkt,true); +} +void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; +} +void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; +} +void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; + onShutdown(SockException(Err_shutdown, "peer close connection")); +} +void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr){ + MsgDropReqPacket pkt; + pkt.loadFromData(buf,len); + TraceL<<"drop "<dropForRecv(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num); +} +void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; +} + +void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ + //TraceL; + auto now = SteadyClock::now(); + ACKACKPacket::Ptr pkt = std::make_shared(); + pkt->loadFromData(buf,len); + + uint32_t rtt = DurationCountMicroseconds(now - _ack_send_timestamp[pkt->ack_number]); + _rtt_variance = 3*_rtt_variance/4+abs(_rtt - rtt); + _rtt = 7*rtt/8+_rtt/8; + + _ack_send_timestamp.erase(pkt->ack_number); +} + +void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr){ + TraceL; +} + +void SrtTransport::sendACKPacket() { + ACKPacket::Ptr pkt=std::make_shared(); + auto now = SteadyClock::now(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->ack_number = ++_ack_number_count; + pkt->last_ack_pkt_seq_number = _recv_buf->getExpectedSeq(); + pkt->rtt = _rtt; + pkt->rtt_variance = _rtt_variance; + pkt->available_buf_size = _recv_buf->getAvailableBufferSize(); + pkt->pkt_recv_rate = _pkt_recv_rate_context.getPacketRecvRate(); + pkt->estimated_link_capacity = _estimated_link_capacity_context.getEstimatedLinkCapacity(); + pkt->recv_rate = _recv_rate_context.getRecvRate(); + pkt->storeToData(); + _ack_send_timestamp[pkt->ack_number] = now; + sendControlPacket(pkt,true); +} +void SrtTransport::sendLightACKPacket() { + ACKPacket::Ptr pkt=std::make_shared(); + auto now = SteadyClock::now(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->ack_number = 0; + pkt->last_ack_pkt_seq_number = _recv_buf->getExpectedSeq(); + pkt->rtt = 0; + pkt->rtt_variance = 0; + pkt->available_buf_size = 0; + pkt->pkt_recv_rate = 0; + pkt->estimated_link_capacity = 0; + pkt->recv_rate = 0; + pkt->storeToData(); + sendControlPacket(pkt,true); + +} + +void SrtTransport::sendNAKPacket(std::list& lost_list){ + NAKPacket::Ptr pkt = std::make_shared(); + auto now = SteadyClock::now(); + + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->lost_list = lost_list; + + pkt->storeToData(); + + //TraceL<<"send NAK "<dump(); + sendControlPacket(pkt,true); +} +void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ + DataPacket::Ptr pkt = std::make_shared(); + pkt->loadFromData(buf,len); + if(_ack_ticker.elapsedTime()>=10){ + _light_ack_pkt_count = 0; + _ack_ticker.resetTime(); + // send a ack per 10 ms for receiver + sendACKPacket(); + }else{ + if(_light_ack_pkt_count >= 64){ + // for high bitrate stream send light ack + // TODO + sendLightACKPacket(); + } + _light_ack_pkt_count = 0; + } + + _light_ack_pkt_count++; + + //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ + " PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; +#if 1 + _recv_buf->inputPacket(pkt); +#else + if(pkt->packet_seq_number%100 == 0){ + // drop + TraceL<<"drop packet"; + TraceL<<"expected size "<<_recv_buf->getExpectedSize()<<" real size="<<_recv_buf->getSize(); + }else{ + _recv_buf->inputPacket(pkt); + } +#endif + //TraceL<<" data number size "<20 && _nak_ticker.elapsedTime()>nak_interval){ + auto lost = _recv_buf->getLostSeq(); + if(!lost.empty()){ + sendNAKPacket(lost); + //TraceL<<"send NAK"; + } + _nak_ticker.resetTime(); + } + auto list = _recv_buf->tryGetPacket(); + + for(auto data : list){ + onSRTData(std::move(data)); + } +} + +void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { + pkt->storeToData((uint8_t*)buf,len); + sendPacket(pkt,flush); +} +void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { + sendPacket(pkt,flush); +} +void SrtTransport::sendPacket(Buffer::Ptr pkt,bool flush){ + if(_selected_session){ + auto tmp = _packet_pool.obtain2(); + tmp->assign(pkt->data(),pkt->size()); + _selected_session->setSendFlushFlag(flush); + _selected_session->send(std::move(tmp)); + }else{ + WarnL<<"not reach this"; + } +} +std::string SrtTransport::getIdentifier(){ + return _selected_session ? _selected_session->getIdentifier() : ""; +} + +void SrtTransport::registerSelfHandshake() { + SrtTransportManager::Instance().addHandshakeItem(std::to_string(_sync_cookie),shared_from_this()); +} +void SrtTransport::unregisterSelfHandshake() { + if(_sync_cookie == 0){ + return; + } + SrtTransportManager::Instance().removeHandshakeItem(std::to_string(_sync_cookie)); +} + +void SrtTransport::registerSelf() { + if(_socket_id == 0){ + return; + } + SrtTransportManager::Instance().addItem(std::to_string(_socket_id),shared_from_this()); + +} +void SrtTransport::unregisterSelf() { + SrtTransportManager::Instance().removeItem(std::to_string(_socket_id)); +} + +void SrtTransport::onShutdown(const SockException &ex){ + WarnL << ex.what(); + unregisterSelfHandshake(); + unregisterSelf(); + for (auto &pr : _history_sessions) { + auto session = pr.second.lock(); + if (session) { + session->shutdown(ex); + } + } +} +//////////// SrtTransportManager ////////////////////////// +SrtTransportManager &SrtTransportManager::Instance() { + static SrtTransportManager s_instance; + return s_instance; +} + +void SrtTransportManager::addItem(const std::string &key, const SrtTransport::Ptr &ptr) { + std::lock_guard lck(_mtx); + _map[key] = ptr; +} + +SrtTransport::Ptr SrtTransportManager::getItem(const std::string &key) { + if (key.empty()) { + return nullptr; + } + std::lock_guard lck(_mtx); + auto it = _map.find(key); + if (it == _map.end()) { + return nullptr; + } + return it->second.lock(); +} + +void SrtTransportManager::removeItem(const std::string &key) { + std::lock_guard lck(_mtx); + _map.erase(key); +} + +void SrtTransportManager::addHandshakeItem(const std::string &key, const SrtTransport::Ptr &ptr) { + std::lock_guard lck(_handshake_mtx); + _handshake_map[key] = ptr; +} +void SrtTransportManager::removeHandshakeItem(const std::string &key) { + std::lock_guard lck(_handshake_mtx); + _handshake_map.erase(key); +} +SrtTransport::Ptr SrtTransportManager::getHandshakeItem(const std::string &key) { + if (key.empty()) { + return nullptr; + } + std::lock_guard lck(_handshake_mtx); + auto it = _handshake_map.find(key); + if (it == _handshake_map.end()) { + return nullptr; + } + return it->second.lock(); +} + + +} // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp new file mode 100644 index 00000000..5ecd24ca --- /dev/null +++ b/srt/SrtTransport.hpp @@ -0,0 +1,143 @@ +#ifndef ZLMEDIAKIT_SRT_TRANSPORT_H +#define ZLMEDIAKIT_SRT_TRANSPORT_H + +#include +#include +#include +#include + +#include "Network/Session.h" +#include "Poller/EventPoller.h" +#include "Util/TimeTicker.h" + +#include "Common.hpp" +#include "Packet.hpp" +#include "PacketQueue.hpp" +#include "Statistic.hpp" + +namespace SRT { +using namespace toolkit; + +extern const std::string kPort; +extern const std::string kTimeOutSec; + +class SrtTransport : public std::enable_shared_from_this { +public: + friend class SrtSession; + using Ptr = std::shared_ptr; + + SrtTransport(const EventPoller::Ptr &poller); + virtual ~SrtTransport(); + const EventPoller::Ptr &getPoller() const; + void setSession(Session::Ptr session); + const Session::Ptr &getSession() const; + /** + * socket收到udp数据 + * @param buf 数据指针 + * @param len 数据长度 + * @param addr 数据来源地址 + */ + void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr); + + std::string getIdentifier(); + + void unregisterSelfHandshake(); + void unregisterSelf(); +protected: + virtual void onHandShakeFinished(std::string& streamid){}; + virtual void onSRTData(DataPacket::Ptr pkt){}; + virtual void onShutdown(const SockException &ex); + +private: + void registerSelfHandshake(); + void registerSelf(); + + void switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr); + + void handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleHandshakeInduction(HandshakePacket& pkt,struct sockaddr_storage *addr); + void handleHandshakeConclusion(HandshakePacket& pkt,struct sockaddr_storage *addr); + + void handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr); + void handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr); + + void sendNAKPacket(std::list& lost_list); + void sendACKPacket(); + void sendLightACKPacket(); +protected: + void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); + void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); + void sendPacket(Buffer::Ptr pkt,bool flush = true); +private: + //当前选中的udp链接 + Session::Ptr _selected_session; + //链接迁移前后使用过的udp链接 + std::unordered_map > _history_sessions; + + EventPoller::Ptr _poller; + + uint32_t _peer_socket_id; + uint32_t _socket_id = 0; + + TimePoint _start_timestamp; + + uint32_t _mtu = 1500; + uint32_t _max_window_size = 8192; + uint32_t _init_seq_number = 0; + + std::string _stream_id; + uint32_t _sync_cookie = 0; + + PacketQueue::Ptr _recv_buf; + uint32_t _rtt = 100*1000; + uint32_t _rtt_variance =50*1000; + uint32_t _light_ack_pkt_count = 0; + uint32_t _ack_number_count = 0; + Ticker _ack_ticker; + std::map _ack_send_timestamp; + + PacketRecvRateContext _pkt_recv_rate_context; + EstimatedLinkCapacityContext _estimated_link_capacity_context; + RecvRateContext _recv_rate_context; + + Ticker _nak_ticker; + + //保持发送的握手消息,防止丢失重发 + HandshakePacket::Ptr _handleshake_res; + + ResourcePool _packet_pool; + +}; + +class SrtTransportManager { +public: + static SrtTransportManager &Instance(); + SrtTransport::Ptr getItem(const std::string &key); + void addItem(const std::string &key, const SrtTransport::Ptr &ptr); + void removeItem(const std::string &key); + + void addHandshakeItem(const std::string &key, const SrtTransport::Ptr &ptr); + void removeHandshakeItem(const std::string &key); + SrtTransport::Ptr getHandshakeItem(const std::string &key); +private: + SrtTransportManager() = default; + +private: + std::mutex _mtx; + std::unordered_map> _map; + + std::mutex _handshake_mtx; + std::unordered_map> _handshake_map; +}; + +} // namespace SRT + +#endif // ZLMEDIAKIT_SRT_TRANSPORT_H \ No newline at end of file diff --git a/srt/Statistic.cpp b/srt/Statistic.cpp new file mode 100644 index 00000000..8728ccdc --- /dev/null +++ b/srt/Statistic.cpp @@ -0,0 +1,76 @@ +#include + +#include "Statistic.hpp" +namespace SRT { +void PacketRecvRateContext::inputPacket(TimePoint ts) { + if(_pkt_map.size()>100){ + _pkt_map.erase(_pkt_map.begin()); + } + _pkt_map.emplace(ts,ts); +} +uint32_t PacketRecvRateContext::getPacketRecvRate() { + if(_pkt_map.size()<2){ + return 0; + } + + auto first = _pkt_map.begin(); + auto last = _pkt_map.rbegin(); + double dur = DurationCountMicroseconds(last->first - first->first)/1000000.0; + double rate = _pkt_map.size()/dur; + return (uint32_t)rate; +} + +void EstimatedLinkCapacityContext::inputPacket(TimePoint ts) { + if(_pkt_map.size()>16){ + _pkt_map.erase(_pkt_map.begin()); + } + _pkt_map.emplace(ts,ts); +} +uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { + decltype(_pkt_map.begin()) next; + std::vector tmp; + + for(auto it = _pkt_map.begin();it != _pkt_map.end();++it){ + next = it; + ++next; + if(next != _pkt_map.end()){ + tmp.push_back(next->first -it->first); + }else{ + break; + } + } + std::sort(tmp.begin(),tmp.end()); + if(tmp.empty()){ + return 0; + } + + double dur =DurationCountMicroseconds(tmp[tmp.size()/2])/1e6; + + return (uint32_t)(1.0/dur); + +} + +void RecvRateContext::inputPacket(TimePoint ts, size_t size ) { + if (_pkt_map.size() > 100) { + _pkt_map.erase(_pkt_map.begin()); + } + _pkt_map.emplace(ts, size); +} +uint32_t RecvRateContext::getRecvRate() { + if(_pkt_map.size()<2){ + return 0; + } + + auto first = _pkt_map.begin(); + auto last = _pkt_map.rbegin(); + double dur = DurationCountMicroseconds(last->first - first->first)/1000000.0; + + size_t bytes = 0; + for(auto it : _pkt_map){ + bytes += it.second; + } + double rate = (double)bytes/dur; + return (uint32_t)rate; +} + +} // namespace SRT \ No newline at end of file diff --git a/srt/Statistic.hpp b/srt/Statistic.hpp new file mode 100644 index 00000000..283d4546 --- /dev/null +++ b/srt/Statistic.hpp @@ -0,0 +1,43 @@ +#ifndef ZLMEDIAKIT_SRT_STATISTIC_H +#define ZLMEDIAKIT_SRT_STATISTIC_H +#include + +#include "Common.hpp" +#include "Packet.hpp" + +namespace SRT { +class PacketRecvRateContext { +public: + PacketRecvRateContext() = default; + ~PacketRecvRateContext() = default; + void inputPacket(TimePoint ts); + uint32_t getPacketRecvRate(); +private: + std::map _pkt_map; + +}; + +class EstimatedLinkCapacityContext { +public: + EstimatedLinkCapacityContext() = default; + ~EstimatedLinkCapacityContext() = default; + void inputPacket(TimePoint ts); + uint32_t getEstimatedLinkCapacity(); +private: + std::map _pkt_map; +}; + +class RecvRateContext { +public: + RecvRateContext() = default; + ~RecvRateContext() = default; + void inputPacket(TimePoint ts,size_t size); + uint32_t getRecvRate(); +private: + std::map _pkt_map; +}; + + + +} // namespace SRT +#endif // ZLMEDIAKIT_SRT_STATISTIC_H \ No newline at end of file From 1891c4e391249011b04fff4c94f6ea551556903f Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 15:02:07 +0800 Subject: [PATCH 02/31] add srt push type --- src/Common/MediaSource.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/MediaSource.h b/src/Common/MediaSource.h index dd6d3572..6d3f5d82 100644 --- a/src/Common/MediaSource.h +++ b/src/Common/MediaSource.h @@ -45,6 +45,7 @@ enum class MediaOriginType : uint8_t { mp4_vod, device_chn, rtc_push, + srt_push }; std::string getOriginTypeString(MediaOriginType type); From 9fadc22c80f6113635f9fe15493f5e32d86f5409 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 16:47:53 +0800 Subject: [PATCH 03/31] srt can push but bandwith estimate has error --- srt/SrtSession.cpp | 4 +- srt/SrtTransport.cpp | 4 +- srt/SrtTransport.hpp | 4 +- srt/SrtTransportImp.cpp | 220 ++++++++++++++++++++++++++++++++++++++++ srt/SrtTransportImp.hpp | 73 +++++++++++++ 5 files changed, 299 insertions(+), 6 deletions(-) create mode 100644 srt/SrtTransportImp.cpp create mode 100644 srt/SrtTransportImp.hpp diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index a20246d4..ed7f4547 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -1,6 +1,6 @@ #include "SrtSession.hpp" #include "Packet.hpp" -#include "SrtTransport.hpp" +#include "SrtTransportImp.hpp" #include "Common/config.h" @@ -70,7 +70,7 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { auto type = HandshakePacket::getHandshakeType(data, size); if (type == HandshakePacket::HS_TYPE_INDUCTION) { // 握手第一阶段 - _transport = std::make_shared(getPoller()); + _transport = std::make_shared(getPoller()); } else if (type == HandshakePacket::HS_TYPE_CONCLUSION) { // 握手第二阶段 diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 4086ffe2..b86869b9 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -189,7 +189,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad sendControlPacket(res, true); TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<recv_tsbpd_delay; _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); - onHandShakeFinished(_stream_id); + onHandShakeFinished(_stream_id,addr); } else { TraceL << getIdentifier() << " CONCLUSION handle repeate "; sendControlPacket(_handleshake_res, true); @@ -356,7 +356,7 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora auto list = _recv_buf->tryGetPacket(); for(auto data : list){ - onSRTData(std::move(data)); + onSRTData(std::move(data),addr); } } diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 5ecd24ca..c67212a2 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -44,8 +44,8 @@ public: void unregisterSelfHandshake(); void unregisterSelf(); protected: - virtual void onHandShakeFinished(std::string& streamid){}; - virtual void onSRTData(DataPacket::Ptr pkt){}; + virtual void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr){}; + virtual void onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr){}; virtual void onShutdown(const SockException &ex); private: diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp new file mode 100644 index 00000000..2367c881 --- /dev/null +++ b/srt/SrtTransportImp.cpp @@ -0,0 +1,220 @@ +#include +#include "Util/util.h" + +#include "SrtTransportImp.hpp" + +namespace SRT { +SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) + : SrtTransport(poller) {} + +SrtTransportImp::~SrtTransportImp() { + InfoP(this); +} + +void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_storage *addr) { + + // TODO parse streamid like this zlmediakit.com/live/test?token=1213444&type=pusher + if(!_addr){ + _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); + } + + _media_info.parse("srt://"+streamid); + + auto params = Parser::parseArgs(_media_info._param_strs); + if(params["type"] == "push"){ + _is_pusher = true; + _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this); + emitOnPublish(); + }else{ + _is_pusher = false; + } +} +void SrtTransportImp::onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) { + if(!_is_pusher){ + WarnP(this)<<"this is a player data ignore"; + return; + } + if(!_addr){ + _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); + } + if (_decoder) { + _decoder->input(reinterpret_cast(pkt->payloadData()), pkt->payloadSize()); + }else{ + WarnP(this)<<" not reach this"; + } +} +void SrtTransportImp::onShutdown(const SockException &ex) { + SrtTransport::onShutdown(ex); +} + +bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force){ + if (!force && totalReaderCount(sender)) { + return false; + } + std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" + << sender.getApp() << "/" << sender.getId() << " " << force; + weak_ptr weak_self = static_pointer_cast(shared_from_this()); + getPoller()->async([weak_self, err]() { + auto strong_self = weak_self.lock(); + if (strong_self) { + strong_self->onShutdown(SockException(Err_shutdown, err)); + //主动关闭推流,那么不延时注销 + strong_self->_muxer = nullptr; + } + }); + return true; +} +// 播放总人数 +int SrtTransportImp::totalReaderCount(mediakit::MediaSource &sender){ + return _muxer ? _muxer->totalReaderCount() : sender.readerCount(); +} +// 获取媒体源类型 +mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const{ + return MediaOriginType::srt_push; +} +// 获取媒体源url或者文件路径 +std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const{ + return _media_info._full_url; +} +// 获取媒体源客户端相关信息 +std::shared_ptr SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const{ + return static_pointer_cast(getSession()); +} + +void SrtTransportImp::emitOnPublish() { + std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); + Broadcast::PublishAuthInvoker invoker = [weak_self](const std::string &err, const ProtocolOption &option) { + auto strong_self = weak_self.lock(); + if (!strong_self) { + return; + } + if (err.empty()) { + strong_self->_muxer = std::make_shared(strong_self->_media_info._vhost, + strong_self->_media_info._app, + strong_self->_media_info._streamid, 0.0f, + option); + strong_self->_muxer->setMediaListener(strong_self); + strong_self->doCachedFunc(); + InfoP(strong_self) << "允许 srt 推流"; + } else { + WarnP(strong_self) << "禁止 srt 推流:" << err; + strong_self->onShutdown(SockException(Err_refused,err)); + } + }; + + //触发推流鉴权事件 + auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::rtp_push, _media_info, invoker, static_cast(*this)); + if (!flag) { + //该事件无人监听,默认不鉴权 + invoker("", ProtocolOption()); + } +} + + +void SrtTransportImp::emitOnPlay(){ + std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); + Broadcast::AuthInvoker invoker = [weak_self](const string &err){ + auto strong_self = weak_self.lock(); + if (!strong_self) { + return; + } + strong_self->getPoller()->async([strong_self,err]{ + if(err != ""){ + strong_self->onShutdown(SockException(Err_refused,err)); + }else{ + strong_self->doPlay(); + } + }); + }; + + auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); + if(!flag){ + doPlay(); + } +} +void SrtTransportImp::doPlay(){ + +} +std::string SrtTransportImp::get_peer_ip() { + if (!_addr) { + return "::"; + } + return SockUtil::inet_ntoa((sockaddr *)_addr.get()); +} + +uint16_t SrtTransportImp::get_peer_port() { + if (!_addr) { + return 0; + } + return SockUtil::inet_port((sockaddr *)_addr.get()); +} + +std::string SrtTransportImp::get_local_ip() { + auto s = getSession(); + if (s) { + return s->get_local_ip(); + } + return "::"; +} + +uint16_t SrtTransportImp::get_local_port() { + auto s = getSession(); + if (s) { + return s->get_local_port(); + } + return 0; +} + +std::string SrtTransportImp::getIdentifier() const { + return _media_info._streamid; +} + +bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) { + if (_muxer) { + return _muxer->inputFrame(frame); + } + if (_cached_func.size() > 200) { + WarnL << "cached frame of track(" << frame->getCodecName() << ") is too much, now dropped"; + return false; + } + auto frame_cached = Frame::getCacheAbleFrame(frame); + lock_guard lck(_func_mtx); + _cached_func.emplace_back([this, frame_cached]() { + _muxer->inputFrame(frame_cached); + }); + return true; +} + +bool SrtTransportImp::addTrack(const Track::Ptr &track) { + if (_muxer) { + return _muxer->addTrack(track); + } + + lock_guard lck(_func_mtx); + _cached_func.emplace_back([this, track]() { + _muxer->addTrack(track); + }); + return true; +} + +void SrtTransportImp::addTrackCompleted() { + if (_muxer) { + _muxer->addTrackCompleted(); + } else { + lock_guard lck(_func_mtx); + _cached_func.emplace_back([this]() { + _muxer->addTrackCompleted(); + }); + } +} + +void SrtTransportImp::doCachedFunc() { + lock_guard lck(_func_mtx); + for (auto &func : _cached_func) { + func(); + } + _cached_func.clear(); +} + + +} // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp new file mode 100644 index 00000000..31f932b5 --- /dev/null +++ b/srt/SrtTransportImp.hpp @@ -0,0 +1,73 @@ +#ifndef ZLMEDIAKIT_SRT_TRANSPORT_IMP_H +#define ZLMEDIAKIT_SRT_TRANSPORT_IMP_H + +#include "Common/MultiMediaSourceMuxer.h" +#include "Rtp/Decoder.h" +#include "SrtTransport.hpp" + +namespace SRT { + using namespace toolkit; + using namespace mediakit; + using namespace std; +class SrtTransportImp + : public SrtTransport + , public toolkit::SockInfo + , public MediaSinkInterface + , public mediakit::MediaSourceEvent { +public: + SrtTransportImp(const EventPoller::Ptr &poller); + ~SrtTransportImp(); + + /// SockInfo override + std::string get_local_ip() override; + uint16_t get_local_port() override; + std::string get_peer_ip() override; + uint16_t get_peer_port() override; + std::string getIdentifier() const override; + +protected: + ///////SrtTransport override/////// + void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr) override; + void onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) override; + void onShutdown(const SockException &ex) override; + + ///////MediaSourceEvent override/////// + // 关闭 + bool close(mediakit::MediaSource &sender, bool force) override; + // 播放总人数 + int totalReaderCount(mediakit::MediaSource &sender) override; + // 获取媒体源类型 + mediakit::MediaOriginType getOriginType(mediakit::MediaSource &sender) const override; + // 获取媒体源url或者文件路径 + std::string getOriginUrl(mediakit::MediaSource &sender) const override; + // 获取媒体源客户端相关信息 + std::shared_ptr getOriginSock(mediakit::MediaSource &sender) const override; + + bool inputFrame(const Frame::Ptr &frame) override; + bool addTrack(const Track::Ptr & track) override; + void addTrackCompleted() override; + void resetTracks() override {}; + +private: + void emitOnPublish(); + void emitOnPlay(); + + void doPlay(); + void doCachedFunc(); + +private: + bool _is_pusher = true; + MediaInfo _media_info; + + std::unique_ptr _addr; + + // for pusher + MultiMediaSourceMuxer::Ptr _muxer; + DecoderImp::Ptr _decoder; + std::recursive_mutex _func_mtx; + std::deque > _cached_func; +}; + +} // namespace SRT + +#endif // ZLMEDIAKIT_SRT_TRANSPORT_IMP_H From ddc5b59a6558a80a0a23f32a55fdbab01b45210f Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 17:49:43 +0800 Subject: [PATCH 04/31] some change --- srt/SrtTransport.cpp | 51 +++++++++++++++++++++++++++----------------- srt/SrtTransport.hpp | 1 + srt/Statistic.cpp | 7 +++++- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index b86869b9..467cc16f 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -263,6 +263,10 @@ void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storag } void SrtTransport::sendACKPacket() { + if(_last_ack_pkt_seq_num == _recv_buf->getExpectedSeq()){ + return; + } + ACKPacket::Ptr pkt=std::make_shared(); auto now = SteadyClock::now(); pkt->dst_socket_id = _peer_socket_id; @@ -277,9 +281,14 @@ void SrtTransport::sendACKPacket() { pkt->recv_rate = _recv_rate_context.getRecvRate(); pkt->storeToData(); _ack_send_timestamp[pkt->ack_number] = now; + _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; sendControlPacket(pkt,true); + TraceL<<"send ack"; } void SrtTransport::sendLightACKPacket() { + if(_last_ack_pkt_seq_num == _recv_buf->getExpectedSeq()){ + return; + } ACKPacket::Ptr pkt=std::make_shared(); auto now = SteadyClock::now(); pkt->dst_socket_id = _peer_socket_id; @@ -293,8 +302,9 @@ void SrtTransport::sendLightACKPacket() { pkt->estimated_link_capacity = 0; pkt->recv_rate = 0; pkt->storeToData(); + _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; sendControlPacket(pkt,true); - + TraceL<<"send light ack"; } void SrtTransport::sendNAKPacket(std::list& lost_list){ @@ -307,27 +317,12 @@ void SrtTransport::sendNAKPacket(std::list& lost_list){ pkt->storeToData(); - //TraceL<<"send NAK "<dump(); + TraceL<<"send NAK "<dump(); sendControlPacket(pkt,true); } void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ DataPacket::Ptr pkt = std::make_shared(); pkt->loadFromData(buf,len); - if(_ack_ticker.elapsedTime()>=10){ - _light_ack_pkt_count = 0; - _ack_ticker.resetTime(); - // send a ack per 10 ms for receiver - sendACKPacket(); - }else{ - if(_light_ack_pkt_count >= 64){ - // for high bitrate stream send light ack - // TODO - sendLightACKPacket(); - } - _light_ack_pkt_count = 0; - } - - _light_ack_pkt_count++; //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ " PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; @@ -343,6 +338,11 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora } #endif //TraceL<<" data number size "<tryGetPacket(); + + for(auto data : list){ + onSRTData(std::move(data),addr); + } auto nak_interval = (_rtt+_rtt_variance*4)/2/1000; if(_nak_ticker.elapsedTime()>20 && _nak_ticker.elapsedTime()>nak_interval){ @@ -353,11 +353,22 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora } _nak_ticker.resetTime(); } - auto list = _recv_buf->tryGetPacket(); - for(auto data : list){ - onSRTData(std::move(data),addr); + if(_ack_ticker.elapsedTime()>=10){ + _light_ack_pkt_count = 0; + _ack_ticker.resetTime(); + // send a ack per 10 ms for receiver + sendACKPacket(); + }else{ + if(_light_ack_pkt_count >= 64){ + // for high bitrate stream send light ack + // TODO + sendLightACKPacket(); + TraceL<<"send light ack"; + } + _light_ack_pkt_count = 0; } + _light_ack_pkt_count++; } void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index c67212a2..6e9f4b7d 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -101,6 +101,7 @@ private: uint32_t _rtt_variance =50*1000; uint32_t _light_ack_pkt_count = 0; uint32_t _ack_number_count = 0; + uint32_t _last_ack_pkt_seq_num = 0; Ticker _ack_ticker; std::map _ack_send_timestamp; diff --git a/srt/Statistic.cpp b/srt/Statistic.cpp index 8728ccdc..c836b56e 100644 --- a/srt/Statistic.cpp +++ b/srt/Statistic.cpp @@ -41,9 +41,14 @@ uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { } std::sort(tmp.begin(),tmp.end()); if(tmp.empty()){ - return 0; + return 1000; } + if(tmp.size()<16){ + return 1000; + } + return 1000; + double dur =DurationCountMicroseconds(tmp[tmp.size()/2])/1e6; return (uint32_t)(1.0/dur); From 7038924c6f56240d4e22bbd5c6a70f194f86c206 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 18:05:24 +0800 Subject: [PATCH 05/31] for srt set recv buf --- srt/SrtSession.cpp | 4 +++- srt/SrtSession.hpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index ed7f4547..47b0b11f 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -47,7 +47,9 @@ EventPoller::Ptr SrtSession::queryPoller(const Buffer::Ptr &buffer) { } return nullptr; } - +void SrtSession::attachServer(const toolkit::Server &server){ + SockUtil::setRecvBuf(getSock()->rawFD(),1024 * 1024); +} void SrtSession::onRecv(const Buffer::Ptr &buffer) { uint8_t* data = (uint8_t*)buffer->data(); size_t size = buffer->size(); diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp index 9478f1b9..401aae3c 100644 --- a/srt/SrtSession.hpp +++ b/srt/SrtSession.hpp @@ -16,7 +16,7 @@ public: void onRecv(const Buffer::Ptr &) override; void onError(const SockException &err) override; void onManager() override; - + void attachServer(const toolkit::Server &server) override; static EventPoller::Ptr queryPoller(const Buffer::Ptr &buffer); private: From 7606dd7110c729dd4ef70d5d7b755a0df963c760 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 20:18:34 +0800 Subject: [PATCH 06/31] for srt push fix ack paramter error result in pkt lost --- srt/Ack.cpp | 9 +++++ srt/Ack.hpp | 2 +- srt/Common.hpp | 36 ++++++++++++++++++++ srt/SrtTransport.cpp | 79 ++++++++++++++++++++++++-------------------- srt/SrtTransport.hpp | 13 ++++---- srt/Statistic.cpp | 51 ++++++++++++++++++---------- srt/Statistic.hpp | 21 +++++++----- 7 files changed, 142 insertions(+), 69 deletions(-) diff --git a/srt/Ack.cpp b/srt/Ack.cpp index 7a61971e..7be5a08d 100644 --- a/srt/Ack.cpp +++ b/srt/Ack.cpp @@ -71,4 +71,13 @@ bool ACKPacket::storeToData() { return true; } + +std::string ACKPacket::dump(){ + _StrPrinter printer; + printer << "last_ack_pkt_seq_number="<(); res->dst_socket_id = _peer_socket_id; - res->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); + res->timestamp = DurationCountMicroseconds(_now - _start_timestamp); res->mtu = _mtu; res->max_flow_window_size = _max_window_size; res->initial_packet_sequence_number = _init_seq_number; @@ -194,6 +197,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad TraceL << getIdentifier() << " CONCLUSION handle repeate "; sendControlPacket(_handleshake_res, true); } + _last_ack_pkt_seq_num = _init_seq_number; } void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ HandshakePacket pkt; @@ -206,21 +210,29 @@ void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storag }else{ WarnL<<" not support handshake type = "<< pkt.handshake_type; } - _ack_ticker.resetTime(); - _nak_ticker.resetTime(); + _ack_ticker.resetTime(_now); + _nak_ticker.resetTime(_now); } void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; + sendKeepLivePacket(); } + + void SrtTransport::sendKeepLivePacket(){ + KeepLivePacket::Ptr pkt = std::make_shared(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->storeToData(); + sendControlPacket(pkt,true); + } void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; - auto now = SteadyClock::now(); ACKPacket ack; ack.loadFromData(buf,len); ACKACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); pkt->ack_number = ack.ack_number; pkt->storeToData(); sendControlPacket(pkt,true); @@ -247,13 +259,12 @@ void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_ void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ //TraceL; - auto now = SteadyClock::now(); ACKACKPacket::Ptr pkt = std::make_shared(); pkt->loadFromData(buf,len); - uint32_t rtt = DurationCountMicroseconds(now - _ack_send_timestamp[pkt->ack_number]); - _rtt_variance = 3*_rtt_variance/4+abs(_rtt - rtt); - _rtt = 7*rtt/8+_rtt/8; + uint32_t rtt = DurationCountMicroseconds(_now - _ack_send_timestamp[pkt->ack_number]); + _rtt_variance = (3*_rtt_variance+abs(_rtt - rtt))/4; + _rtt = (7*rtt+_rtt)/8; _ack_send_timestamp.erase(pkt->ack_number); } @@ -268,31 +279,30 @@ void SrtTransport::sendACKPacket() { } ACKPacket::Ptr pkt=std::make_shared(); - auto now = SteadyClock::now(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = ++_ack_number_count; pkt->last_ack_pkt_seq_number = _recv_buf->getExpectedSeq(); pkt->rtt = _rtt; pkt->rtt_variance = _rtt_variance; pkt->available_buf_size = _recv_buf->getAvailableBufferSize(); - pkt->pkt_recv_rate = _pkt_recv_rate_context.getPacketRecvRate(); - pkt->estimated_link_capacity = _estimated_link_capacity_context.getEstimatedLinkCapacity(); - pkt->recv_rate = _recv_rate_context.getRecvRate(); + pkt->pkt_recv_rate = _pkt_recv_rate_context->getPacketRecvRate(); + pkt->estimated_link_capacity = _estimated_link_capacity_context->getEstimatedLinkCapacity(); + pkt->recv_rate = _recv_rate_context->getRecvRate(); pkt->storeToData(); - _ack_send_timestamp[pkt->ack_number] = now; + _ack_send_timestamp[pkt->ack_number] = _now; _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; sendControlPacket(pkt,true); - TraceL<<"send ack"; + //TraceL<<"send ack "<dump(); } void SrtTransport::sendLightACKPacket() { if(_last_ack_pkt_seq_num == _recv_buf->getExpectedSeq()){ return; } ACKPacket::Ptr pkt=std::make_shared(); - auto now = SteadyClock::now(); + pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = 0; pkt->last_ack_pkt_seq_number = _recv_buf->getExpectedSeq(); pkt->rtt = 0; @@ -304,15 +314,14 @@ void SrtTransport::sendLightACKPacket() { pkt->storeToData(); _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; sendControlPacket(pkt,true); - TraceL<<"send light ack"; + TraceL<<"send ack "<dump(); } void SrtTransport::sendNAKPacket(std::list& lost_list){ NAKPacket::Ptr pkt = std::make_shared(); - auto now = SteadyClock::now(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(now - _start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->lost_list = lost_list; pkt->storeToData(); @@ -325,7 +334,7 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora pkt->loadFromData(buf,len); //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ - " PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; + //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; #if 1 _recv_buf->inputPacket(pkt); #else @@ -344,19 +353,19 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora onSRTData(std::move(data),addr); } - auto nak_interval = (_rtt+_rtt_variance*4)/2/1000; - if(_nak_ticker.elapsedTime()>20 && _nak_ticker.elapsedTime()>nak_interval){ + auto nak_interval = (_rtt+_rtt_variance*4)/2; + if(_nak_ticker.elapsedTime(_now)>20*1000 && _nak_ticker.elapsedTime(_now)>nak_interval){ auto lost = _recv_buf->getLostSeq(); if(!lost.empty()){ sendNAKPacket(lost); //TraceL<<"send NAK"; } - _nak_ticker.resetTime(); + _nak_ticker.resetTime(_now); } - if(_ack_ticker.elapsedTime()>=10){ + if(_ack_ticker.elapsedTime(_now)>10*1000){ _light_ack_pkt_count = 0; - _ack_ticker.resetTime(); + _ack_ticker.resetTime(_now); // send a ack per 10 ms for receiver sendACKPacket(); }else{ diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 6e9f4b7d..6d2b9e48 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -8,7 +8,6 @@ #include "Network/Session.h" #include "Poller/EventPoller.h" -#include "Util/TimeTicker.h" #include "Common.hpp" #include "Packet.hpp" @@ -72,6 +71,7 @@ private: void sendNAKPacket(std::list& lost_list); void sendACKPacket(); void sendLightACKPacket(); + void sendKeepLivePacket(); protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); @@ -87,6 +87,7 @@ private: uint32_t _peer_socket_id; uint32_t _socket_id = 0; + TimePoint _now; TimePoint _start_timestamp; uint32_t _mtu = 1500; @@ -102,14 +103,14 @@ private: uint32_t _light_ack_pkt_count = 0; uint32_t _ack_number_count = 0; uint32_t _last_ack_pkt_seq_num = 0; - Ticker _ack_ticker; + UTicker _ack_ticker; std::map _ack_send_timestamp; - PacketRecvRateContext _pkt_recv_rate_context; - EstimatedLinkCapacityContext _estimated_link_capacity_context; - RecvRateContext _recv_rate_context; + std::shared_ptr _pkt_recv_rate_context; + std::shared_ptr _estimated_link_capacity_context; + std::shared_ptr _recv_rate_context; - Ticker _nak_ticker; + UTicker _nak_ticker; //保持发送的握手消息,防止丢失重发 HandshakePacket::Ptr _handleshake_res; diff --git a/srt/Statistic.cpp b/srt/Statistic.cpp index c836b56e..9fc13cd5 100644 --- a/srt/Statistic.cpp +++ b/srt/Statistic.cpp @@ -2,33 +2,47 @@ #include "Statistic.hpp" namespace SRT { -void PacketRecvRateContext::inputPacket(TimePoint ts) { +void PacketRecvRateContext::inputPacket(TimePoint& ts) { if(_pkt_map.size()>100){ _pkt_map.erase(_pkt_map.begin()); } - _pkt_map.emplace(ts,ts); + auto tmp = DurationCountMicroseconds(ts - _start); + _pkt_map.emplace(tmp,tmp); } uint32_t PacketRecvRateContext::getPacketRecvRate() { - if(_pkt_map.size()<2){ - return 0; + if (_pkt_map.size() < 2) { + return 50000; + } + int64_t dur = 1000; + for (auto it = _pkt_map.begin(); it != _pkt_map.end(); ++it) { + auto next = it; + ++next; + if (next != _pkt_map.end()) { + if ((next->first - it->first) < dur) { + dur = next->first - it->first; + } + } else { + break; + } } - auto first = _pkt_map.begin(); - auto last = _pkt_map.rbegin(); - double dur = DurationCountMicroseconds(last->first - first->first)/1000000.0; - double rate = _pkt_map.size()/dur; - return (uint32_t)rate; + double rate = 1e6 / (double)dur; + if(rate <=1000){ + return 50000; + } + return rate; } -void EstimatedLinkCapacityContext::inputPacket(TimePoint ts) { - if(_pkt_map.size()>16){ +void EstimatedLinkCapacityContext::inputPacket(TimePoint& ts) { + if (_pkt_map.size() > 16) { _pkt_map.erase(_pkt_map.begin()); } - _pkt_map.emplace(ts,ts); + auto tmp = DurationCountMicroseconds(ts - _start); + _pkt_map.emplace(tmp, tmp); } uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { decltype(_pkt_map.begin()) next; - std::vector tmp; + std::vector tmp; for(auto it = _pkt_map.begin();it != _pkt_map.end();++it){ next = it; @@ -47,19 +61,20 @@ uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { if(tmp.size()<16){ return 1000; } - return 1000; - double dur =DurationCountMicroseconds(tmp[tmp.size()/2])/1e6; + double dur =tmp[0]/1e6; return (uint32_t)(1.0/dur); } -void RecvRateContext::inputPacket(TimePoint ts, size_t size ) { +void RecvRateContext::inputPacket(TimePoint& ts, size_t size ) { if (_pkt_map.size() > 100) { _pkt_map.erase(_pkt_map.begin()); } - _pkt_map.emplace(ts, size); + auto tmp = DurationCountMicroseconds(ts - _start); + + _pkt_map.emplace(tmp, tmp); } uint32_t RecvRateContext::getRecvRate() { if(_pkt_map.size()<2){ @@ -68,7 +83,7 @@ uint32_t RecvRateContext::getRecvRate() { auto first = _pkt_map.begin(); auto last = _pkt_map.rbegin(); - double dur = DurationCountMicroseconds(last->first - first->first)/1000000.0; + double dur = (last->first - first->first)/1000000.0; size_t bytes = 0; for(auto it : _pkt_map){ diff --git a/srt/Statistic.hpp b/srt/Statistic.hpp index 283d4546..4524aebe 100644 --- a/srt/Statistic.hpp +++ b/srt/Statistic.hpp @@ -8,33 +8,36 @@ namespace SRT { class PacketRecvRateContext { public: - PacketRecvRateContext() = default; + PacketRecvRateContext(TimePoint start):_start(start){}; ~PacketRecvRateContext() = default; - void inputPacket(TimePoint ts); + void inputPacket(TimePoint& ts); uint32_t getPacketRecvRate(); private: - std::map _pkt_map; + std::map _pkt_map; + TimePoint _start; }; class EstimatedLinkCapacityContext { public: - EstimatedLinkCapacityContext() = default; + EstimatedLinkCapacityContext(TimePoint start):_start(start){}; ~EstimatedLinkCapacityContext() = default; - void inputPacket(TimePoint ts); + void inputPacket(TimePoint& ts); uint32_t getEstimatedLinkCapacity(); private: - std::map _pkt_map; + std::map _pkt_map; + TimePoint _start; }; class RecvRateContext { public: - RecvRateContext() = default; + RecvRateContext(TimePoint start):_start(start){}; ~RecvRateContext() = default; - void inputPacket(TimePoint ts,size_t size); + void inputPacket(TimePoint& ts,size_t size); uint32_t getRecvRate(); private: - std::map _pkt_map; + std::map _pkt_map; + TimePoint _start; }; From 18f4870cfe7253ee4531adf18aa87102af4eac26 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 20:26:53 +0800 Subject: [PATCH 07/31] emit push is srt --- srt/SrtTransportImp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 2367c881..0d8f90cc 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -103,7 +103,7 @@ void SrtTransportImp::emitOnPublish() { }; //触发推流鉴权事件 - auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::rtp_push, _media_info, invoker, static_cast(*this)); + auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::srt_push, _media_info, invoker, static_cast(*this)); if (!flag) { //该事件无人监听,默认不鉴权 invoker("", ProtocolOption()); From b9f66ca1ec00ecd4dfb9454402e8b131eb7bd3e8 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 20:38:35 +0800 Subject: [PATCH 08/31] add srt push string --- src/Common/MediaSource.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/MediaSource.cpp b/src/Common/MediaSource.cpp index 6b395c18..a3244565 100644 --- a/src/Common/MediaSource.cpp +++ b/src/Common/MediaSource.cpp @@ -38,6 +38,7 @@ string getOriginTypeString(MediaOriginType type){ SWITCH_CASE(mp4_vod); SWITCH_CASE(device_chn); SWITCH_CASE(rtc_push); + SWITCH_CASE(srt_push); default : return "unknown"; } } From 82da99eef3bd494bd46577591a6c9d48b76e1ef3 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 21:17:01 +0800 Subject: [PATCH 09/31] add shutdown packet and flow report --- srt/Packet.hpp | 27 +++++++++++++++++++++++++++ srt/SrtTransport.cpp | 9 +++++++++ srt/SrtTransport.hpp | 3 ++- srt/SrtTransportImp.cpp | 12 ++++++++++++ srt/SrtTransportImp.hpp | 8 ++++++-- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/srt/Packet.hpp b/srt/Packet.hpp index f2fbc98a..ddc784fd 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -5,6 +5,7 @@ #include #include "Network/Buffer.h" +#include "Util/logger.h" #include "Common.hpp" #include "HSExt.hpp" @@ -312,6 +313,32 @@ class MsgDropReqPacket : public ControlPacket uint32_t last_pkt_seq_num; }; +class ShutDownPacket : public ControlPacket +{ +public: + using Ptr = std::shared_ptr; + ShutDownPacket() = default; + ~ShutDownPacket() = default; + ///////ControlPacket override/////// + bool loadFromData(uint8_t *buf, size_t len) override { + if (len < HEADER_SIZE) { + WarnL << "data size" << len << " less " << HEADER_SIZE; + return false; + } + _data = BufferRaw::create(); + _data->assign((char *)buf, len); + + return loadHeader(); + }; + bool storeToData() override { + control_type = ControlPacket::SHUTDOWN; + sub_type = 0; + _data = BufferRaw::create(); + _data->setCapacity(HEADER_SIZE); + _data->setSize(HEADER_SIZE); + return storeToHeader(); + }; +}; } // namespace SRT #endif //ZLMEDIAKIT_SRT_PACKET_H \ No newline at end of file diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 354d36f4..b9fef358 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -329,6 +329,14 @@ void SrtTransport::sendNAKPacket(std::list& lost_list){ TraceL<<"send NAK "<dump(); sendControlPacket(pkt,true); } + +void SrtTransport::sendShutDown(){ + ShutDownPacket::Ptr pkt = std::make_shared(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); + pkt->storeToData(); + sendControlPacket(pkt,true); +} void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ DataPacket::Ptr pkt = std::make_shared(); pkt->loadFromData(buf,len); @@ -423,6 +431,7 @@ void SrtTransport::unregisterSelf() { } void SrtTransport::onShutdown(const SockException &ex){ + sendShutDown(); WarnL << ex.what(); unregisterSelfHandshake(); unregisterSelf(); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 6d2b9e48..02ff395e 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -36,7 +36,7 @@ public: * @param len 数据长度 * @param addr 数据来源地址 */ - void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr); + virtual void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr); std::string getIdentifier(); @@ -72,6 +72,7 @@ private: void sendACKPacket(); void sendLightACKPacket(); void sendKeepLivePacket(); + void sendShutDown(); protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 0d8f90cc..9d06659c 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -9,6 +9,18 @@ SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) SrtTransportImp::~SrtTransportImp() { InfoP(this); + uint64_t duration = _alive_ticker.createdTime() / 1000; + WarnP(this) << "srt 推流器(" + << _media_info._vhost << "/" + << _media_info._app << "/" + << _media_info._streamid + << ")断开,耗时(s):" << duration; + + //流量统计事件广播 + GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold); + if (_total_bytes >= iFlowThreshold * 1024) { + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport, _media_info, _total_bytes, duration, false, static_cast(*this)); + } } void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_storage *addr) { diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 31f932b5..a1f3b65b 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -17,7 +17,10 @@ class SrtTransportImp public: SrtTransportImp(const EventPoller::Ptr &poller); ~SrtTransportImp(); - + void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr){ + SrtTransport::inputSockData(buf,len,addr); + _total_bytes += len; + } /// SockInfo override std::string get_local_ip() override; uint16_t get_local_port() override; @@ -58,7 +61,8 @@ private: private: bool _is_pusher = true; MediaInfo _media_info; - + uint64_t _total_bytes = 0; + Ticker _alive_ticker; std::unique_ptr _addr; // for pusher From 7f65e082f53a81b8eebcd6de5c9d10952611857e Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Fri, 3 Jun 2022 22:47:52 +0800 Subject: [PATCH 10/31] can build prepare for play ts stream by srt --- srt/Packet.cpp | 28 +++++++++++++++++ srt/Packet.hpp | 1 + srt/PacketQueue.cpp | 29 +++++++++++++++++- srt/PacketQueue.hpp | 4 +++ srt/SrtTransport.cpp | 68 +++++++++++++++++++++++++++++++++++++++++ srt/SrtTransport.hpp | 7 +++++ srt/SrtTransportImp.cpp | 65 +++++++++++++++++++++++++++++++++++++++ srt/SrtTransportImp.hpp | 7 +++-- 8 files changed, 206 insertions(+), 3 deletions(-) diff --git a/srt/Packet.cpp b/srt/Packet.cpp index af4b3772..3cf40584 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -61,7 +61,35 @@ bool DataPacket::loadFromData(uint8_t *buf, size_t len) { _data->assign((char *)(buf), len); return true; } +bool DataPacket::storeToHeader(){ + if (!_data || _data->size() < HEADER_SIZE) { + WarnL << "data size less " << HEADER_SIZE; + return false; + } + uint8_t *ptr = (uint8_t *)_data->data(); + ptr[0] = packet_seq_number >> 24; + ptr[1] = (packet_seq_number >> 16) & 0xff; + ptr[2] = (packet_seq_number >> 8) & 0xff; + ptr[3] = packet_seq_number & 0xff; + ptr += 4; + + ptr[0] = PP << 6; + ptr[0] |= O << 5; + ptr[0] |= KK << 3; + ptr[0] |= R << 2; + ptr[0] |= (msg_number & 0xff000000) >> 24; + ptr[1] = (msg_number & 0xff0000) >> 16; + ptr[2] = (msg_number & 0xff00) >> 8; + ptr[3] = msg_number & 0xff; + ptr += 4; + + storeUint32(ptr, timestamp); + ptr += 4; + + storeUint32(ptr, dst_socket_id); + ptr += 4; +} bool DataPacket::storeToData(uint8_t *buf, size_t len) { _data = BufferRaw::create(); _data->setCapacity(len + HEADER_SIZE); diff --git a/srt/Packet.hpp b/srt/Packet.hpp index ddc784fd..b34aae29 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -43,6 +43,7 @@ public: static uint32_t getSocketID(uint8_t *buf, size_t len); bool loadFromData(uint8_t *buf, size_t len); bool storeToData(uint8_t *buf, size_t len); + bool storeToHeader(); ///////Buffer override/////// char *data() const override; diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index ea342277..20181262 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -51,12 +51,39 @@ bool PacketQueue::dropForRecv(uint32_t first,uint32_t last){ } if(_pkt_expected_seq <= last){ - _pkt_expected_seq = last+1; + for(uint32_t i =first;i<=last;++i){ + if(_pkt_map.find(i) != _pkt_map.end()){ + _pkt_map.erase(i); + } + } + _pkt_expected_seq = last+1; return true; } return false; } + +bool PacketQueue::dropForSend(uint32_t num){ + if(num <= _pkt_expected_seq){ + return false; + } + + for(uint32_t i =_pkt_expected_seq;i< num;++i){ + if(_pkt_map.find(i) != _pkt_map.end()){ + _pkt_map.erase(i); + } + } + _pkt_expected_seq = num; + return true; +} + +DataPacket::Ptr PacketQueue::findPacketBySeq(uint32_t seq){ + auto it = _pkt_map.find(seq); + if(it != _pkt_map.end()){ + return it->second; + } + return nullptr; +} uint32_t PacketQueue::timeLantency() { if (_pkt_map.empty()) { return 0; diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp index 05996647..2ba8467b 100644 --- a/srt/PacketQueue.hpp +++ b/srt/PacketQueue.hpp @@ -29,6 +29,10 @@ public: uint32_t getExpectedSeq(); bool dropForRecv(uint32_t first,uint32_t last); + + bool dropForSend(uint32_t num); + + DataPacket::Ptr findPacketBySeq(uint32_t seq); private: diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index b9fef358..bc185717 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -192,6 +192,8 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad sendControlPacket(res, true); TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<recv_tsbpd_delay; _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); + _send_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); + _send_packet_seq_number = _init_seq_number; onHandShakeFinished(_stream_id,addr); } else { TraceL << getIdentifier() << " CONCLUSION handle repeate "; @@ -235,10 +237,33 @@ void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *add pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); pkt->ack_number = ack.ack_number; pkt->storeToData(); + _send_buf->dropForSend(ack.last_ack_pkt_seq_number); sendControlPacket(pkt,true); +} +void SrtTransport::sendMsgDropReq(uint32_t first ,uint32_t last){ + } void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; + NAKPacket pkt; + pkt.loadFromData(buf,len); + bool empty = false; + + for(auto it : pkt.lost_list){ + empty = true; + for(uint32_t i=it.first;ifindPacketBySeq(i); + if(data){ + data->R = 1; + data->storeToHeader(); + sendPacket(data,true); + empty = false; + } + } + if(empty){ + sendMsgDropReq(it.first,it.second-1); + } + } } void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; @@ -391,6 +416,7 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { pkt->storeToData((uint8_t*)buf,len); sendPacket(pkt,flush); + _send_buf->inputPacket(pkt); } void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { sendPacket(pkt,flush); @@ -442,6 +468,48 @@ void SrtTransport::onShutdown(const SockException &ex){ } } } +size_t SrtTransport::getPayloadSize(){ + size_t ret = (_mtu - 28 -16)/188*188; + return ret; +} +void SrtTransport::onSendData(const Buffer::Ptr &buffer, bool flush){ + DataPacket::Ptr pkt; + size_t payloadSize = getPayloadSize(); + size_t size = buffer->size(); + char* ptr = buffer->data(); + char* end = buffer->data()+size; + + while(ptr < end && size >=payloadSize){ + pkt = std::make_shared(); + pkt->f = 0; + pkt->packet_seq_number = _send_packet_seq_number++; + pkt->PP = 3; + pkt->O = 0; + pkt->KK = 0; + pkt->R = 0; + pkt->msg_number = _send_msg_number++; + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); + sendDataPacket(pkt,ptr,(int)payloadSize,flush); + ptr += payloadSize; + size -= payloadSize; + } + + if(size >0 && ptr (); + pkt->f = 0; + pkt->packet_seq_number = _send_packet_seq_number++; + pkt->PP = 3; + pkt->O = 0; + pkt->KK = 0; + pkt->R = 0; + pkt->msg_number = _send_msg_number++; + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); + sendDataPacket(pkt,ptr,(int)size,flush); + } + +} //////////// SrtTransportManager ////////////////////////// SrtTransportManager &SrtTransportManager::Instance() { static SrtTransportManager s_instance; diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 02ff395e..892a85c4 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -37,6 +37,7 @@ public: * @param addr 数据来源地址 */ virtual void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr); + virtual void onSendData(const Buffer::Ptr &buffer, bool flush); std::string getIdentifier(); @@ -73,6 +74,9 @@ private: void sendLightACKPacket(); void sendKeepLivePacket(); void sendShutDown(); + void sendMsgDropReq(uint32_t first ,uint32_t last); + + size_t getPayloadSize(); protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); @@ -97,7 +101,10 @@ private: std::string _stream_id; uint32_t _sync_cookie = 0; + uint32_t _send_packet_seq_number = 0; + uint32_t _send_msg_number = 1; + PacketQueue::Ptr _send_buf; PacketQueue::Ptr _recv_buf; uint32_t _rtt = 100*1000; uint32_t _rtt_variance =50*1000; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 9d06659c..e2b1c903 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -145,7 +145,72 @@ void SrtTransportImp::emitOnPlay(){ } } void SrtTransportImp::doPlay(){ + //鉴权结果回调 + weak_ptr weak_self = dynamic_pointer_cast(shared_from_this()); + auto onRes = [weak_self](const string &err) { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } + if (!err.empty()) { + //播放鉴权失败 + strong_self->onShutdown(SockException(Err_refused, err)); + return; + } + + //异步查找直播流 + MediaInfo info = strong_self->_media_info; + info._schema = TS_SCHEMA; + MediaSource::findAsync(info, strong_self->getSession(), [weak_self](const MediaSource::Ptr &src) { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } + if (!src) { + //未找到该流 + strong_self->onShutdown(SockException(Err_shutdown)); + } else { + auto ts_src = dynamic_pointer_cast(src); + assert(ts_src); + ts_src->pause(false); + strong_self->_ts_reader = ts_src->getRing()->attach(strong_self->getPoller()); + strong_self->_ts_reader->setDetachCB([weak_self]() { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } + strong_self->onShutdown(SockException(Err_shutdown)); + }); + strong_self->_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } + size_t i = 0; + auto size = ts_list->size(); + ts_list->for_each([&](const TSPacket::Ptr &ts) { strong_self->onSendData(ts, ++i == size); }); + }); + }; + + }); + }; + + Broadcast::AuthInvoker invoker = [weak_self, onRes](const string &err) { + if (auto strongSelf = weak_self.lock()) { + strongSelf->getPoller()->async([onRes, err]() { onRes(err); }); + } + }; + + auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); + if (!flag) { + //该事件无人监听,默认不鉴权 + onRes(""); + } } std::string SrtTransportImp::get_peer_ip() { if (!_addr) { diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index a1f3b65b..80106d2d 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -1,10 +1,12 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_IMP_H #define ZLMEDIAKIT_SRT_TRANSPORT_IMP_H - +#include #include "Common/MultiMediaSourceMuxer.h" #include "Rtp/Decoder.h" +#include "TS/TSMediaSource.h" #include "SrtTransport.hpp" + namespace SRT { using namespace toolkit; using namespace mediakit; @@ -64,7 +66,8 @@ private: uint64_t _total_bytes = 0; Ticker _alive_ticker; std::unique_ptr _addr; - + // for player + TSMediaSource::RingType::RingReader::Ptr _ts_reader; // for pusher MultiMediaSourceMuxer::Ptr _muxer; DecoderImp::Ptr _decoder; From 6237dd48dc639a81cd5799865b03fcd45cd9f8df Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 10:11:28 +0800 Subject: [PATCH 11/31] add commet and remove compile warn --- srt/Packet.cpp | 1 + srt/Packet.hpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/srt/Packet.cpp b/srt/Packet.cpp index 3cf40584..085c56a0 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -89,6 +89,7 @@ bool DataPacket::storeToHeader(){ storeUint32(ptr, dst_socket_id); ptr += 4; + return true; } bool DataPacket::storeToData(uint8_t *buf, size_t len) { _data = BufferRaw::create(); diff --git a/srt/Packet.hpp b/srt/Packet.hpp index b34aae29..2118113d 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -314,6 +314,22 @@ class MsgDropReqPacket : public ControlPacket uint32_t last_pkt_seq_num; }; +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+- SRT Header +-+-+-+-+-+-+-+-+-+-+-+-+-+ +|1| Control Type | Reserved | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Type-specific Information | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Timestamp | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Destination Socket ID | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Figure 16: Shutdown control packet + https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-shutdown + +*/ class ShutDownPacket : public ControlPacket { public: From 91aa9c494cedbd16a95853171baa4054086261f6 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 11:23:18 +0800 Subject: [PATCH 12/31] srt can play stream --- srt/HSExt.cpp | 2 + srt/SrtTransport.cpp | 18 ++++++-- srt/SrtTransport.hpp | 4 +- srt/SrtTransportImp.cpp | 99 ++++++++++++++++------------------------- srt/SrtTransportImp.hpp | 8 ++++ 5 files changed, 64 insertions(+), 67 deletions(-) diff --git a/srt/HSExt.cpp b/srt/HSExt.cpp index 5398e48e..20a5b89c 100644 --- a/srt/HSExt.cpp +++ b/srt/HSExt.cpp @@ -80,6 +80,8 @@ bool HSExtStreamID::loadFromData(uint8_t *buf, size_t len) { streamid.push_back(*(ptr)); ptr+=4; } + char zero = 0x00; + streamid.erase(streamid.find_first_of(zero),streamid.size()); return true; } diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index bc185717..f06361c5 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -228,9 +228,11 @@ void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage sendControlPacket(pkt,true); } void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - TraceL; + //TraceL; ACKPacket ack; - ack.loadFromData(buf,len); + if(!ack.loadFromData(buf,len)){ + return; + } ACKACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; @@ -239,9 +241,16 @@ void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *add pkt->storeToData(); _send_buf->dropForSend(ack.last_ack_pkt_seq_number); sendControlPacket(pkt,true); + //TraceL<<"ack number "<(); + pkt->dst_socket_id = _peer_socket_id; + pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->first_pkt_seq_num = first; + pkt->last_pkt_seq_num = last; + pkt->storeToData(); + sendControlPacket(pkt,true); } void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; @@ -472,7 +481,8 @@ size_t SrtTransport::getPayloadSize(){ size_t ret = (_mtu - 28 -16)/188*188; return ret; } -void SrtTransport::onSendData(const Buffer::Ptr &buffer, bool flush){ +void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ + //TraceL; DataPacket::Ptr pkt; size_t payloadSize = getPayloadSize(); size_t size = buffer->size(); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 892a85c4..0cf93b35 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -37,7 +37,7 @@ public: * @param addr 数据来源地址 */ virtual void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr); - virtual void onSendData(const Buffer::Ptr &buffer, bool flush); + virtual void onSendTSData(const Buffer::Ptr &buffer, bool flush); std::string getIdentifier(); @@ -80,7 +80,7 @@ private: protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); - void sendPacket(Buffer::Ptr pkt,bool flush = true); + virtual void sendPacket(Buffer::Ptr pkt,bool flush = true); private: //当前选中的udp链接 Session::Ptr _selected_session; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index e2b1c903..b5d72344 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -10,7 +10,7 @@ SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) SrtTransportImp::~SrtTransportImp() { InfoP(this); uint64_t duration = _alive_ticker.createdTime() / 1000; - WarnP(this) << "srt 推流器(" + WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info._vhost << "/" << _media_info._app << "/" << _media_info._streamid @@ -39,6 +39,7 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_ emitOnPublish(); }else{ _is_pusher = false; + emitOnPlay(); } } void SrtTransportImp::onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) { @@ -145,72 +146,48 @@ void SrtTransportImp::emitOnPlay(){ } } void SrtTransportImp::doPlay(){ - //鉴权结果回调 - weak_ptr weak_self = dynamic_pointer_cast(shared_from_this()); - auto onRes = [weak_self](const string &err) { + //异步查找直播流 + std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); + + MediaInfo info = _media_info; + info._schema = TS_SCHEMA; + MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) { auto strong_self = weak_self.lock(); if (!strong_self) { //本对象已经销毁 + TraceL<<"本对象已经销毁"; return; } - - if (!err.empty()) { - //播放鉴权失败 - strong_self->onShutdown(SockException(Err_refused, err)); - return; - } - - //异步查找直播流 - MediaInfo info = strong_self->_media_info; - info._schema = TS_SCHEMA; - MediaSource::findAsync(info, strong_self->getSession(), [weak_self](const MediaSource::Ptr &src) { - auto strong_self = weak_self.lock(); - if (!strong_self) { - //本对象已经销毁 - return; - } - if (!src) { - //未找到该流 + if (!src) { + //未找到该流 + TraceL<<"未找到该流"; + strong_self->onShutdown(SockException(Err_shutdown)); + } else { + TraceL<<"找到该流"; + auto ts_src = dynamic_pointer_cast(src); + assert(ts_src); + ts_src->pause(false); + strong_self->_ts_reader = ts_src->getRing()->attach(strong_self->getPoller()); + strong_self->_ts_reader->setDetachCB([weak_self]() { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } strong_self->onShutdown(SockException(Err_shutdown)); - } else { - auto ts_src = dynamic_pointer_cast(src); - assert(ts_src); - ts_src->pause(false); - strong_self->_ts_reader = ts_src->getRing()->attach(strong_self->getPoller()); - strong_self->_ts_reader->setDetachCB([weak_self]() { - auto strong_self = weak_self.lock(); - if (!strong_self) { - //本对象已经销毁 - return; - } - strong_self->onShutdown(SockException(Err_shutdown)); - }); - strong_self->_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) { - auto strong_self = weak_self.lock(); - if (!strong_self) { - //本对象已经销毁 - return; - } - size_t i = 0; - auto size = ts_list->size(); - ts_list->for_each([&](const TSPacket::Ptr &ts) { strong_self->onSendData(ts, ++i == size); }); - }); - }; - - }); - }; - - Broadcast::AuthInvoker invoker = [weak_self, onRes](const string &err) { - if (auto strongSelf = weak_self.lock()) { - strongSelf->getPoller()->async([onRes, err]() { onRes(err); }); - } - }; - - auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); - if (!flag) { - //该事件无人监听,默认不鉴权 - onRes(""); - } + }); + strong_self->_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) { + auto strong_self = weak_self.lock(); + if (!strong_self) { + //本对象已经销毁 + return; + } + size_t i = 0; + auto size = ts_list->size(); + ts_list->for_each([&](const TSPacket::Ptr &ts) { strong_self->onSendTSData(ts, ++i == size); }); + }); + }; + }); } std::string SrtTransportImp::get_peer_ip() { if (!_addr) { diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 80106d2d..8abe2b40 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -23,6 +23,9 @@ public: SrtTransport::inputSockData(buf,len,addr); _total_bytes += len; } + void onSendTSData(const Buffer::Ptr &buffer, bool flush){ + SrtTransport::onSendTSData(buffer,flush); + } /// SockInfo override std::string get_local_ip() override; uint16_t get_local_port() override; @@ -36,6 +39,11 @@ protected: void onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) override; void onShutdown(const SockException &ex) override; + void sendPacket(Buffer::Ptr pkt,bool flush = true) override{ + _total_bytes += pkt->size(); + SrtTransport::sendPacket(pkt,flush); + }; + ///////MediaSourceEvent override/////// // 关闭 bool close(mediakit::MediaSource &sender, bool force) override; From af9bd2dd0a81ee52bd7ddfc31b2019e3ff6ced18 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 12:03:56 +0800 Subject: [PATCH 13/31] fix streamid zero error --- srt/HSExt.cpp | 4 +++- srt/SrtSession.cpp | 3 +++ srt/SrtTransport.cpp | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/srt/HSExt.cpp b/srt/HSExt.cpp index 20a5b89c..ab4d4ff2 100644 --- a/srt/HSExt.cpp +++ b/srt/HSExt.cpp @@ -81,7 +81,9 @@ bool HSExtStreamID::loadFromData(uint8_t *buf, size_t len) { ptr+=4; } char zero = 0x00; - streamid.erase(streamid.find_first_of(zero),streamid.size()); + if(streamid.back() == zero){ + streamid.erase(streamid.find_first_of(zero),streamid.size()); + } return true; } diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index 47b0b11f..17a2eff0 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -10,7 +10,10 @@ using namespace mediakit; SrtSession::SrtSession(const Socket::Ptr &sock) : UdpSession(sock) { socklen_t addr_len = sizeof(_peer_addr); + memset(&_peer_addr,0,addr_len); + TraceL<<"before addr len "<rawFD(), (struct sockaddr *)&_peer_addr, &addr_len); + TraceL<<"after addr len "< +#include "Util/onceToken.h" #include "SrtTransport.hpp" #include "Packet.hpp" @@ -297,7 +298,7 @@ void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage * pkt->loadFromData(buf,len); uint32_t rtt = DurationCountMicroseconds(_now - _ack_send_timestamp[pkt->ack_number]); - _rtt_variance = (3*_rtt_variance+abs(_rtt - rtt))/4; + _rtt_variance = (3*_rtt_variance+abs((long)(_rtt - rtt)))/4; _rtt = (7*rtt+_rtt)/8; _ack_send_timestamp.erase(pkt->ack_number); From cd6b0ee0c434d4b3b9392be0511463c5f8b3c3c8 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 12:22:55 +0800 Subject: [PATCH 14/31] fix peer ip error --- srt/Packet.cpp | 12 +++++++++--- srt/SrtSession.cpp | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/srt/Packet.cpp b/srt/Packet.cpp index 085c56a0..38c5c147 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -419,9 +419,15 @@ void HandshakePacket::assignPeerIP(struct sockaddr_storage* addr){ struct sockaddr_in * ipv4 = (struct sockaddr_in *)addr; //抓包 奇怪好像是小头端??? storeUint32LE(peer_ip_addr,ipv4->sin_addr.s_addr); - }else{ - const sockaddr_in6* ipv6 = (struct sockaddr_in6 *)addr; - memcpy(peer_ip_addr,ipv6->sin6_addr.s6_addr,sizeof(peer_ip_addr)*sizeof(peer_ip_addr[0])); + }else if(addr->ss_family == AF_INET6){ + if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) { + struct in_addr addr4; + memcpy(&addr4, 12 + (char *)&(((struct sockaddr_in6 *)addr)->sin6_addr), 4); + storeUint32LE(peer_ip_addr,addr4.s_addr); + }else{ + const sockaddr_in6* ipv6 = (struct sockaddr_in6 *)addr; + memcpy(peer_ip_addr,ipv6->sin6_addr.s6_addr,sizeof(peer_ip_addr)*sizeof(peer_ip_addr[0])); + } } } uint32_t HandshakePacket::generateSynCookie(struct sockaddr_storage* addr,TimePoint ts,uint32_t current_cookie, int correction ){ diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index 17a2eff0..978e28da 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -11,9 +11,9 @@ SrtSession::SrtSession(const Socket::Ptr &sock) : UdpSession(sock) { socklen_t addr_len = sizeof(_peer_addr); memset(&_peer_addr,0,addr_len); - TraceL<<"before addr len "<rawFD(), (struct sockaddr *)&_peer_addr, &addr_len); - TraceL<<"after addr len "< Date: Sat, 4 Jun 2022 13:30:59 +0800 Subject: [PATCH 15/31] check stream id --- srt/SrtTransport.cpp | 16 +++++++++++----- srt/SrtTransportImp.cpp | 8 +++++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 082cdb8f..619c6377 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -153,6 +153,8 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad // first HSExtMessage::Ptr req; HSExtStreamID::Ptr sid; + uint32_t srt_flag = 0xbf; + uint16_t delay = 120; for (auto ext : pkt.ext_list) { //TraceL << getIdentifier() << " ext " << ext->dump(); @@ -166,6 +168,10 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad if(sid){ _stream_id = sid->streamid; } + if(req){ + srt_flag = req->srt_flag; + delay = req->recv_tsbpd_delay; + } TraceL << getIdentifier() << " CONCLUSION Phase "; HandshakePacket::Ptr res = std::make_shared(); res->dst_socket_id = _peer_socket_id; @@ -183,17 +189,17 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad HSExtMessage::Ptr ext = std::make_shared(); ext->extension_type = HSExt::SRT_CMD_HSRSP; ext->srt_version = srtVersion(1, 5, 0); - ext->srt_flag = req->srt_flag; - ext->recv_tsbpd_delay = ext->send_tsbpd_delay = req->recv_tsbpd_delay; + ext->srt_flag = srt_flag; + ext->recv_tsbpd_delay = ext->send_tsbpd_delay = delay; res->ext_list.push_back(std::move(ext)); res->storeToData(); _handleshake_res = res; unregisterSelfHandshake(); registerSelf(); sendControlPacket(res, true); - TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<recv_tsbpd_delay; - _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); - _send_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, req->recv_tsbpd_delay*1e6); + TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<(res->max_flow_window_size,_init_seq_number, delay*1e6); + _send_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, delay*1e6); _send_packet_seq_number = _init_seq_number; onHandShakeFinished(_stream_id,addr); } else { diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index b5d72344..5bae174a 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -25,10 +25,16 @@ SrtTransportImp::~SrtTransportImp() { void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_storage *addr) { - // TODO parse streamid like this zlmediakit.com/live/test?token=1213444&type=pusher + // TODO parse streamid like this zlmediakit.com/live/test?token=1213444&type=push if(!_addr){ _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); } + _is_pusher = false; + TraceL<<" stream id "< Date: Sat, 4 Jun 2022 13:31:15 +0800 Subject: [PATCH 16/31] add srt usage for zlm --- srt/srt.md | 25 +++++++++++++++++++++++++ srt/srt_en.md | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 srt/srt.md create mode 100644 srt/srt_en.md diff --git a/srt/srt.md b/srt/srt.md new file mode 100644 index 00000000..2d504720 --- /dev/null +++ b/srt/srt.md @@ -0,0 +1,25 @@ +## 特性 +- NACK(重传) +- listener 支持 +- 推流只支持ts推流 +- 拉流只支持ts拉流 +- 协议实现 [参考](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html) +- 版本支持(>=1.3.0) +- fec与加密没有实现 + +## 使用 + +zlm中的srt更加streamid 来确定是推流还是拉流,来确定vhost,app,streamid(ZLM中的) +srt中的streamid 为 `//?type=& =` + +- OBS 推流地址 + + `srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test?type=push` +- ffmpeg 推流 + + `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid="__defaultVhost__/live/test?type=push"` +- ffplay 拉流 + + `ffplay -i srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test` + +- vlc 不支持,因为无法指定streamid[参考](https://github.com/Haivision/srt/issues/1015) \ No newline at end of file diff --git a/srt/srt_en.md b/srt/srt_en.md new file mode 100644 index 00000000..c4ef2b1d --- /dev/null +++ b/srt/srt_en.md @@ -0,0 +1,24 @@ +## feature +- NACK support +- listener support +- push stream payload must ts +- pull stream payload is ts +- protocol impliment [reference](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html) +- version support (>=1.3.0) +- fec and encriyped not support + +## usage + +zlm get vhost,app,streamid and push or play by streamid of srt like this `//?type=& =` + +- OBS push stream url + + `srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test?type=push` +- ffmpeg push + + `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid="__defaultVhost__/live/test?type=push"` +- ffplay pull + + `ffplay -i srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test` + +- vlc not support ,because can't set stream id [reference](https://github.com/Haivision/srt/issues/1015) \ No newline at end of file From 9a57353470c812746288a7823efd300be7797048 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 13:31:36 +0800 Subject: [PATCH 17/31] add srt on readme --- README.md | 2 +- README_en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da0cd2e4..f8ece25a 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ - 支持rtp扩展解析 - 支持GOP缓冲,webrtc播放秒开 - 支持datachannel - +- [SRT支持](./srt/srt.md) - 其他 - 支持丰富的restful api以及web hook事件 - 支持简单的telnet调试 diff --git a/README_en.md b/README_en.md index f0f09470..a1d958d1 100644 --- a/README_en.md +++ b/README_en.md @@ -61,7 +61,7 @@ - Support simulcast - Support rtx/nack - Support transport-cc rtcp/rtp ext - +- [SRT support](./srt/srt_en.md) - Others - Support stream proxy by ffmpeg. - RESTful http api and http hook event api. From 086146a3446817ca9ccd9cd1b201dd4c612d9700 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 14:05:51 +0800 Subject: [PATCH 18/31] try fix windows build error --- srt/Packet.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/srt/Packet.cpp b/srt/Packet.cpp index 38c5c147..18ad279c 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -1,6 +1,16 @@  -#include "sys/socket.h" -#include "netdb.h" +#if defined(_WIN32) +#include +#include +#include +#pragma comment (lib, "Ws2_32.lib") +#pragma comment(lib,"Iphlpapi.lib") +#else +#include +#include +#endif // defined(_WIN32) + + #include #include "Util/logger.h" From 71ce31d5c07fb7d23068a7adfd8c6feb11490f75 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 20:51:49 +0800 Subject: [PATCH 19/31] for some optimize and anti pkt lost and force pop packet when too late --- srt/Packet.hpp | 2 ++ srt/PacketQueue.cpp | 41 +++++++++++++++++++++++++------ srt/PacketQueue.hpp | 4 +++ srt/SrtSession.cpp | 2 +- srt/SrtTransport.cpp | 54 +++++++++++++++++++++++++++++++---------- srt/SrtTransport.hpp | 9 ++++++- srt/SrtTransportImp.cpp | 5 +--- srt/SrtTransportImp.hpp | 6 ++++- 8 files changed, 95 insertions(+), 28 deletions(-) diff --git a/srt/Packet.hpp b/srt/Packet.hpp index 2118113d..bab6df0c 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -62,6 +62,8 @@ public: uint32_t timestamp; uint32_t dst_socket_id; + TimePoint get_ts; // recv or send time + private: BufferRaw::Ptr _data; }; diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 20181262..7cf5f73d 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -20,16 +20,20 @@ bool PacketQueue::inputPacket(DataPacket::Ptr pkt) { std::list PacketQueue::tryGetPacket() { std::list re; - while (_pkt_map.find(_pkt_expected_seq) != _pkt_map.end()) { - re.push_back(_pkt_map[_pkt_expected_seq]); - _pkt_map.erase(_pkt_expected_seq); + auto it = _pkt_map.find(_pkt_expected_seq); + while ( it != _pkt_map.end()) { + re.push_back(it->second); + _last_pop_ts = it->second->get_ts; + _pkt_map.erase(it); _pkt_expected_seq++; + it = _pkt_map.find(_pkt_expected_seq); } while (_pkt_map.size() > _pkt_cap) { // force pop some packet - auto it = _pkt_map.begin(); + it = _pkt_map.begin(); re.push_back(it->second); + _last_pop_ts = it->second->get_ts; _pkt_expected_seq = it->second->packet_seq_number + 1; _pkt_map.erase(it); } @@ -37,11 +41,12 @@ std::list PacketQueue::tryGetPacket() { while (timeLantency() > _pkt_lantency) { auto it = _pkt_map.begin(); re.push_back(it->second); + _last_pop_ts = it->second->get_ts; _pkt_expected_seq = it->second->packet_seq_number + 1; _pkt_map.erase(it); } - return std::move(re); + return re; } @@ -67,10 +72,12 @@ bool PacketQueue::dropForSend(uint32_t num){ if(num <= _pkt_expected_seq){ return false; } - + decltype(_pkt_map.end()) it; for(uint32_t i =_pkt_expected_seq;i< num;++i){ - if(_pkt_map.find(i) != _pkt_map.end()){ - _pkt_map.erase(i); + it = _pkt_map.find(i); + if(it != _pkt_map.end()){ + _last_pop_ts = it->second->get_ts; + _pkt_map.erase(it); } } _pkt_expected_seq = num; @@ -84,6 +91,24 @@ DataPacket::Ptr PacketQueue::findPacketBySeq(uint32_t seq){ } return nullptr; } +uint32_t PacketQueue::timeLantencyFrom(TimePoint now){ + return DurationCountMicroseconds(now - _last_pop_ts); +} + +std::list PacketQueue::tryGetPacketByNow(TimePoint now){ + std::list re; + auto it = _pkt_map.begin(); + while(it !=_pkt_map.end()){ + if(DurationCountMicroseconds(now-it->second->get_ts)>=_pkt_lantency){ + re.push_back(it->second); + _pkt_expected_seq = it->second->packet_seq_number+1; + _last_pop_ts = it->second->get_ts; + _pkt_map.erase(it); + } + it++; + } + return re; +} uint32_t PacketQueue::timeLantency() { if (_pkt_map.empty()) { return 0; diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp index 2ba8467b..06036d75 100644 --- a/srt/PacketQueue.hpp +++ b/srt/PacketQueue.hpp @@ -21,6 +21,8 @@ public: bool inputPacket(DataPacket::Ptr pkt); std::list tryGetPacket(); uint32_t timeLantency(); + uint32_t timeLantencyFrom(TimePoint now); + std::list tryGetPacketByNow(TimePoint now); std::list getLostSeq(); size_t getSize(); @@ -41,6 +43,8 @@ private: uint32_t _pkt_expected_seq = 0; uint32_t _pkt_cap; uint32_t _pkt_lantency; + + TimePoint _last_pop_ts; }; } diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index 978e28da..fe8cfc13 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -109,7 +109,7 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { if(_transport){ _transport->inputSockData(data,size,&_peer_addr); }else{ - WarnL<< "ingore data"; + //WarnL<< "ingore data"; } } diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 619c6377..4d5ac60e 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -201,6 +201,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, delay*1e6); _send_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, delay*1e6); _send_packet_seq_number = _init_seq_number; + _buf_delay = delay; onHandShakeFinished(_stream_id,addr); } else { TraceL << getIdentifier() << " CONCLUSION handle repeate "; @@ -208,6 +209,33 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad } _last_ack_pkt_seq_num = _init_seq_number; } +void SrtTransport::bufCheckInterval(){ + if(isPusher()){ + if(_recv_buf->timeLantencyFrom(_now) > (_buf_delay*1e6)){ + auto list = _recv_buf->tryGetPacketByNow(_now); + for(auto data : list){ + onSRTData(std::move(data)); + } + if(!list.empty()){ + sendACKPacket(); + _light_ack_pkt_count = 0; + _ack_ticker.resetTime(_now); + } + + auto nak_interval = (_rtt+_rtt_variance*4)/2; + if(nak_interval >= 20*1000){ + nak_interval = 20*1000; + } + if(_nak_ticker.elapsedTime(_now)>nak_interval || list.empty()){ + auto lost = _recv_buf->getLostSeq(); + if(!lost.empty()){ + sendNAKPacket(lost); + } + _nak_ticker.resetTime(_now); + } + } + } +} void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ HandshakePacket pkt; assert(pkt.loadFromData(buf,len)); @@ -223,7 +251,7 @@ void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storag _nak_ticker.resetTime(_now); } void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr){ - TraceL; + //TraceL; sendKeepLivePacket(); } @@ -260,7 +288,7 @@ void SrtTransport::sendMsgDropReq(uint32_t first ,uint32_t last){ sendControlPacket(pkt,true); } void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - TraceL; + //TraceL; NAKPacket pkt; pkt.loadFromData(buf,len); bool empty = false; @@ -291,7 +319,7 @@ void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr){ MsgDropReqPacket pkt; pkt.loadFromData(buf,len); - TraceL<<"drop "<dropForRecv(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num); } void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr){ @@ -315,10 +343,6 @@ void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storag } void SrtTransport::sendACKPacket() { - if(_last_ack_pkt_seq_num == _recv_buf->getExpectedSeq()){ - return; - } - ACKPacket::Ptr pkt=std::make_shared(); pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); @@ -337,9 +361,6 @@ void SrtTransport::sendACKPacket() { //TraceL<<"send ack "<dump(); } void SrtTransport::sendLightACKPacket() { - if(_last_ack_pkt_seq_num == _recv_buf->getExpectedSeq()){ - return; - } ACKPacket::Ptr pkt=std::make_shared(); pkt->dst_socket_id = _peer_socket_id; @@ -367,7 +388,7 @@ void SrtTransport::sendNAKPacket(std::list& lost_list){ pkt->storeToData(); - TraceL<<"send NAK "<dump(); + //TraceL<<"send NAK "<dump(); sendControlPacket(pkt,true); } @@ -381,6 +402,8 @@ void SrtTransport::sendShutDown(){ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ DataPacket::Ptr pkt = std::make_shared(); pkt->loadFromData(buf,len); + + pkt->get_ts = _now; //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; @@ -399,11 +422,14 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora auto list = _recv_buf->tryGetPacket(); for(auto data : list){ - onSRTData(std::move(data),addr); + onSRTData(std::move(data)); } auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(_nak_ticker.elapsedTime(_now)>20*1000 && _nak_ticker.elapsedTime(_now)>nak_interval){ + if(nak_interval >= 20*1000){ + nak_interval = 20*1000; + } + if(_nak_ticker.elapsedTime(_now)>nak_interval || list.empty()){ auto lost = _recv_buf->getLostSeq(); if(!lost.empty()){ sendNAKPacket(lost); @@ -427,6 +453,8 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora _light_ack_pkt_count = 0; } _light_ack_pkt_count++; + + bufCheckInterval(); } void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 0cf93b35..af19060e 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -8,6 +8,7 @@ #include "Network/Session.h" #include "Poller/EventPoller.h" +#include "Poller/Timer.h" #include "Common.hpp" #include "Packet.hpp" @@ -45,8 +46,11 @@ public: void unregisterSelf(); protected: virtual void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr){}; - virtual void onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr){}; + virtual void onSRTData(DataPacket::Ptr pkt){}; virtual void onShutdown(const SockException &ex); + virtual bool isPusher(){ + return true; + }; private: void registerSelfHandshake(); @@ -76,6 +80,8 @@ private: void sendShutDown(); void sendMsgDropReq(uint32_t first ,uint32_t last); + void bufCheckInterval(); + size_t getPayloadSize(); protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); @@ -105,6 +111,7 @@ private: uint32_t _send_msg_number = 1; PacketQueue::Ptr _send_buf; + uint32_t _buf_delay = 120; PacketQueue::Ptr _recv_buf; uint32_t _rtt = 100*1000; uint32_t _rtt_variance =50*1000; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 5bae174a..b12e6e7c 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -48,13 +48,10 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_ emitOnPlay(); } } -void SrtTransportImp::onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) { +void SrtTransportImp::onSRTData(DataPacket::Ptr pkt) { if(!_is_pusher){ WarnP(this)<<"this is a player data ignore"; return; - } - if(!_addr){ - _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); } if (_decoder) { _decoder->input(reinterpret_cast(pkt->payloadData()), pkt->payloadSize()); diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 8abe2b40..36a07e01 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -36,7 +36,7 @@ public: protected: ///////SrtTransport override/////// void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr) override; - void onSRTData(DataPacket::Ptr pkt,struct sockaddr_storage *addr) override; + void onSRTData(DataPacket::Ptr pkt) override; void onShutdown(const SockException &ex) override; void sendPacket(Buffer::Ptr pkt,bool flush = true) override{ @@ -44,6 +44,10 @@ protected: SrtTransport::sendPacket(pkt,flush); }; + bool isPusher() override{ + return _is_pusher; + } + ///////MediaSourceEvent override/////// // 关闭 bool close(mediakit::MediaSource &sender, bool force) override; From adaffcc2459523f56ef54b883b3221103ebbb6e6 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 22:09:56 +0800 Subject: [PATCH 20/31] prevent pkt seq cycle and time stamp cycle --- srt/PacketQueue.cpp | 73 ++++++++++++++++++++++---------------------- srt/PacketQueue.hpp | 6 +--- srt/SrtTransport.cpp | 27 +--------------- 3 files changed, 38 insertions(+), 68 deletions(-) diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 7cf5f73d..e9b51505 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -1,6 +1,10 @@ #include "PacketQueue.hpp" namespace SRT { + +inline uint32_t genExpectedSeq(uint32_t seq){ + return 0x7fffffff&seq; +} PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency) : _pkt_expected_seq(init_seq) , _pkt_cap(max_size) @@ -23,27 +27,28 @@ std::list PacketQueue::tryGetPacket() { auto it = _pkt_map.find(_pkt_expected_seq); while ( it != _pkt_map.end()) { re.push_back(it->second); - _last_pop_ts = it->second->get_ts; _pkt_map.erase(it); - _pkt_expected_seq++; + _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq+1); it = _pkt_map.find(_pkt_expected_seq); } while (_pkt_map.size() > _pkt_cap) { - // force pop some packet - it = _pkt_map.begin(); - re.push_back(it->second); - _last_pop_ts = it->second->get_ts; - _pkt_expected_seq = it->second->packet_seq_number + 1; - _pkt_map.erase(it); + // 防止回环 + it = _pkt_map.find(_pkt_expected_seq); + if(it != _pkt_map.end()){ + re.push_back(it->second); + _pkt_map.erase(it); + } + _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } while (timeLantency() > _pkt_lantency) { - auto it = _pkt_map.begin(); - re.push_back(it->second); - _last_pop_ts = it->second->get_ts; - _pkt_expected_seq = it->second->packet_seq_number + 1; - _pkt_map.erase(it); + it = _pkt_map.find(_pkt_expected_seq); + if(it != _pkt_map.end()){ + re.push_back(it->second); + _pkt_map.erase(it); + } + _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } return re; @@ -61,7 +66,7 @@ bool PacketQueue::dropForRecv(uint32_t first,uint32_t last){ _pkt_map.erase(i); } } - _pkt_expected_seq = last+1; + _pkt_expected_seq =genExpectedSeq(last+1); return true; } @@ -76,11 +81,10 @@ bool PacketQueue::dropForSend(uint32_t num){ for(uint32_t i =_pkt_expected_seq;i< num;++i){ it = _pkt_map.find(i); if(it != _pkt_map.end()){ - _last_pop_ts = it->second->get_ts; _pkt_map.erase(it); } } - _pkt_expected_seq = num; + _pkt_expected_seq =genExpectedSeq(num); return true; } @@ -91,33 +95,26 @@ DataPacket::Ptr PacketQueue::findPacketBySeq(uint32_t seq){ } return nullptr; } -uint32_t PacketQueue::timeLantencyFrom(TimePoint now){ - return DurationCountMicroseconds(now - _last_pop_ts); -} -std::list PacketQueue::tryGetPacketByNow(TimePoint now){ - std::list re; - auto it = _pkt_map.begin(); - while(it !=_pkt_map.end()){ - if(DurationCountMicroseconds(now-it->second->get_ts)>=_pkt_lantency){ - re.push_back(it->second); - _pkt_expected_seq = it->second->packet_seq_number+1; - _last_pop_ts = it->second->get_ts; - _pkt_map.erase(it); - } - it++; - } - return re; -} uint32_t PacketQueue::timeLantency() { if (_pkt_map.empty()) { return 0; } - auto first = _pkt_map.begin()->second; - auto last = _pkt_map.rbegin()->second; + auto first = _pkt_map.begin()->second->timestamp; + auto last = _pkt_map.rbegin()->second->timestamp; + uint32_t dur; + if(last>first){ + dur = last - first; + }else{ + dur = first - last; + } - return last->timestamp - first->timestamp; + if(dur > 0x80000000){ + dur = 0xffffffff - dur; + } + + return dur; } std::list PacketQueue::getLostSeq() { @@ -136,7 +133,7 @@ std::list PacketQueue::getLostSeq() { uint32_t i = _pkt_expected_seq; bool finish = true; - for(i = _pkt_expected_seq;i<=_pkt_map.rbegin()->first;++i){ + for(i = _pkt_expected_seq;i<=_pkt_map.rbegin()->first;){ if(_pkt_map.find(i) == _pkt_map.end()){ if(finish){ finish = false; @@ -152,6 +149,7 @@ std::list PacketQueue::getLostSeq() { re.push_back(lost); } } + i = genExpectedSeq(i+1); } return re; @@ -175,4 +173,5 @@ size_t PacketQueue::getAvailableBufferSize(){ uint32_t PacketQueue::getExpectedSeq(){ return _pkt_expected_seq; } + } // namespace SRT \ No newline at end of file diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp index 06036d75..d213f2d5 100644 --- a/srt/PacketQueue.hpp +++ b/srt/PacketQueue.hpp @@ -21,8 +21,6 @@ public: bool inputPacket(DataPacket::Ptr pkt); std::list tryGetPacket(); uint32_t timeLantency(); - uint32_t timeLantencyFrom(TimePoint now); - std::list tryGetPacketByNow(TimePoint now); std::list getLostSeq(); size_t getSize(); @@ -35,8 +33,6 @@ public: bool dropForSend(uint32_t num); DataPacket::Ptr findPacketBySeq(uint32_t seq); - - private: std::map _pkt_map; @@ -44,7 +40,7 @@ private: uint32_t _pkt_cap; uint32_t _pkt_lantency; - TimePoint _last_pop_ts; + }; } diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 4d5ac60e..4b58b07e 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -210,31 +210,6 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad _last_ack_pkt_seq_num = _init_seq_number; } void SrtTransport::bufCheckInterval(){ - if(isPusher()){ - if(_recv_buf->timeLantencyFrom(_now) > (_buf_delay*1e6)){ - auto list = _recv_buf->tryGetPacketByNow(_now); - for(auto data : list){ - onSRTData(std::move(data)); - } - if(!list.empty()){ - sendACKPacket(); - _light_ack_pkt_count = 0; - _ack_ticker.resetTime(_now); - } - - auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval >= 20*1000){ - nak_interval = 20*1000; - } - if(_nak_ticker.elapsedTime(_now)>nak_interval || list.empty()){ - auto lost = _recv_buf->getLostSeq(); - if(!lost.empty()){ - sendNAKPacket(lost); - } - _nak_ticker.resetTime(_now); - } - } - } } void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ HandshakePacket pkt; @@ -454,7 +429,7 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora } _light_ack_pkt_count++; - bufCheckInterval(); + //bufCheckInterval(); } void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { From 6f05cf803d4f11a5494c1ab33d7f834980f10292 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 4 Jun 2022 22:42:28 +0800 Subject: [PATCH 21/31] prevent cycle for time lantency and available size --- srt/PacketQueue.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index e9b51505..2ee6db9a 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -111,6 +111,7 @@ uint32_t PacketQueue::timeLantency() { } if(dur > 0x80000000){ + //WarnL<<"cycle dur "<first - _pkt_expected_seq+1; + auto size = _pkt_map.rbegin()->first - _pkt_expected_seq+1; + if(size >= _pkt_cap){ + // 回环 + //WarnL<<"cycle size "< Date: Sun, 5 Jun 2022 11:07:42 +0800 Subject: [PATCH 22/31] fix timelatency not take effect and avoid buffer is liner avoid cycle --- srt/PacketQueue.cpp | 173 ++++++++++++++++++++++++---------------- srt/PacketQueue.hpp | 39 +++++---- srt/PacketSendQueue.cpp | 77 ++++++++++++++++++ srt/PacketSendQueue.hpp | 29 +++++++ srt/SrtTransport.cpp | 89 ++++++++++++++------- srt/SrtTransport.hpp | 3 +- 6 files changed, 290 insertions(+), 120 deletions(-) create mode 100644 srt/PacketSendQueue.cpp create mode 100644 srt/PacketSendQueue.hpp diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 2ee6db9a..340f94d0 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -2,31 +2,62 @@ namespace SRT { +#define MAX_SEQ 0x7fffffff +#define MAX_TS 0xffffffff inline uint32_t genExpectedSeq(uint32_t seq){ - return 0x7fffffff&seq; + return MAX_SEQ & seq; +} +inline bool isSeqEdge(uint32_t seq,uint32_t cap){ + if(seq >(MAX_SEQ - cap)){ + return true; + } + return false; +} + +inline bool isTSCycle(uint32_t first,uint32_t second){ + uint32_t diff; + if(first>second){ + diff = first - second; + }else{ + diff = second - first; + } + + if(diff > (MAX_TS>>1)){ + return true; + }else{ + return false; + } } PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency) : _pkt_expected_seq(init_seq) , _pkt_cap(max_size) , _pkt_lantency(lantency) { - } - -bool PacketQueue::inputPacket(DataPacket::Ptr pkt) { - if (pkt->packet_seq_number < _pkt_expected_seq) { - // TOO later drop this packet - return false; - } - - _pkt_map[pkt->packet_seq_number] = pkt; - - return true; } +void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt){ -std::list PacketQueue::tryGetPacket() { - std::list re; + if (_pkt_expected_seq <= pkt->packet_seq_number) { + auto diff = pkt->packet_seq_number - _pkt_expected_seq; + if(diff >= (MAX_SEQ>>1)){ + TraceL << "drop packet too later for cycle "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + return; + }else{ + _pkt_map.emplace(pkt->packet_seq_number, pkt); + } + } else { + auto diff = _pkt_expected_seq - pkt->packet_seq_number; + if(diff >= (MAX_SEQ>>1)){ + _pkt_map.emplace(pkt->packet_seq_number, pkt); + TraceL<<" cycle packet "<<"expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + }else{ + TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + } + } +} +bool PacketQueue::inputPacket(DataPacket::Ptr pkt,std::list& out) { + tryInsertPkt(pkt); auto it = _pkt_map.find(_pkt_expected_seq); while ( it != _pkt_map.end()) { - re.push_back(it->second); + out.push_back(it->second); _pkt_map.erase(it); _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq+1); it = _pkt_map.find(_pkt_expected_seq); @@ -36,64 +67,37 @@ std::list PacketQueue::tryGetPacket() { // 防止回环 it = _pkt_map.find(_pkt_expected_seq); if(it != _pkt_map.end()){ - re.push_back(it->second); + out.push_back(it->second); _pkt_map.erase(it); } _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } - while (timeLantency() > _pkt_lantency) { + while (timeLantency() > _pkt_lantency) { it = _pkt_map.find(_pkt_expected_seq); if(it != _pkt_map.end()){ - re.push_back(it->second); + out.push_back(it->second); _pkt_map.erase(it); } _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } - return re; -} - - -bool PacketQueue::dropForRecv(uint32_t first,uint32_t last){ - if(first >= last){ - return false; - } - - if(_pkt_expected_seq <= last){ - for(uint32_t i =first;i<=last;++i){ - if(_pkt_map.find(i) != _pkt_map.end()){ - _pkt_map.erase(i); - } - } - _pkt_expected_seq =genExpectedSeq(last+1); - return true; - } - - return false; -} - -bool PacketQueue::dropForSend(uint32_t num){ - if(num <= _pkt_expected_seq){ - return false; - } - decltype(_pkt_map.end()) it; - for(uint32_t i =_pkt_expected_seq;i< num;++i){ - it = _pkt_map.find(i); - if(it != _pkt_map.end()){ - _pkt_map.erase(it); - } - } - _pkt_expected_seq =genExpectedSeq(num); return true; } -DataPacket::Ptr PacketQueue::findPacketBySeq(uint32_t seq){ - auto it = _pkt_map.find(seq); - if(it != _pkt_map.end()){ - return it->second; +bool PacketQueue::drop(uint32_t first, uint32_t last,std::list& out){ + uint32_t end = genExpectedSeq(last+1); + decltype(_pkt_map.end()) it; + for(uint32_t i =_pkt_expected_seq;i< end;){ + it = _pkt_map.find(i); + if(it != _pkt_map.end()){ + out.push_back(it->second); + _pkt_map.erase(it); + } + i = genExpectedSeq(i+1); } - return nullptr; + _pkt_expected_seq = end; + return true; } uint32_t PacketQueue::timeLantency() { @@ -111,8 +115,8 @@ uint32_t PacketQueue::timeLantency() { } if(dur > 0x80000000){ - //WarnL<<"cycle dur "< PacketQueue::getLostSeq() { return re; } + uint32_t end = 0; + uint32_t first,last; + + first = _pkt_map.begin()->second->packet_seq_number; + last = _pkt_map.rbegin()->second->packet_seq_number; + if ((last - first) > (MAX_SEQ >> 1)) { + TraceL << " cycle seq first " << first << " last " << last << " size " << _pkt_map.size(); + end = first; + } else { + end = last; + } PacketQueue::LostPair lost; lost.first = 0; lost.second = 0; uint32_t i = _pkt_expected_seq; bool finish = true; - for(i = _pkt_expected_seq;i<=_pkt_map.rbegin()->first;){ + for(i = _pkt_expected_seq;i<=end;){ if(_pkt_map.find(i) == _pkt_map.end()){ if(finish){ finish = false; @@ -144,7 +159,6 @@ std::list PacketQueue::getLostSeq() { lost.second = i+1; } }else{ - if(!finish){ finish = true; re.push_back(lost); @@ -164,21 +178,42 @@ size_t PacketQueue::getExpectedSize() { if(_pkt_map.empty()){ return 0; } - auto size = _pkt_map.rbegin()->first - _pkt_expected_seq+1; - if(size >= _pkt_cap){ - // 回环 - //WarnL<<"cycle size "<first; + uint32_t min = _pkt_map.begin()->first; + if((max-min)>=(MAX_SEQ>>1)){ + TraceL<<"cycle "<<"expected seq "<<_pkt_expected_seq<<" min "< size){ + return _pkt_cap - size; + } + + if(_pkt_cap > _pkt_map.size()){ + return _pkt_cap - _pkt_map.size(); + } + WarnL<<" cap "<<_pkt_cap<<" expected size "<second->packet_seq_number; + printer<<" last:"<<_pkt_map.rbegin()->second->packet_seq_number; + printer<<" latency:"< +#include #include #include -#include -#include #include +#include -#include "Packet.hpp" +namespace SRT { -namespace SRT{ - -class PacketQueue -{ +// for recv +class PacketQueue { public: using Ptr = std::shared_ptr; - using LostPair = std::pair; + using LostPair = std::pair; - PacketQueue(uint32_t max_size,uint32_t init_seq,uint32_t lantency); + PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency); ~PacketQueue() = default; - bool inputPacket(DataPacket::Ptr pkt); - std::list tryGetPacket(); + bool inputPacket(DataPacket::Ptr pkt,std::list& out); + uint32_t timeLantency(); std::list getLostSeq(); @@ -28,21 +28,20 @@ public: size_t getAvailableBufferSize(); uint32_t getExpectedSeq(); - bool dropForRecv(uint32_t first,uint32_t last); + bool drop(uint32_t first, uint32_t last,std::list& out); - bool dropForSend(uint32_t num); - - DataPacket::Ptr findPacketBySeq(uint32_t seq); + std::string dump(); private: - std::map _pkt_map; + void tryInsertPkt(DataPacket::Ptr pkt); +private: + + std::map _pkt_map; uint32_t _pkt_expected_seq = 0; uint32_t _pkt_cap; uint32_t _pkt_lantency; - - }; -} +} // namespace SRT -#endif //ZLMEDIAKIT_SRT_PACKET_QUEUE_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_PACKET_QUEUE_H \ No newline at end of file diff --git a/srt/PacketSendQueue.cpp b/srt/PacketSendQueue.cpp new file mode 100644 index 00000000..9ea11aaf --- /dev/null +++ b/srt/PacketSendQueue.cpp @@ -0,0 +1,77 @@ +#include "PacketSendQueue.hpp" + +namespace SRT { + +PacketSendQueue::PacketSendQueue(uint32_t max_size, uint32_t lantency) + : _pkt_cap(max_size) + , _pkt_lantency(lantency) {} +bool PacketSendQueue::drop(uint32_t num) { + decltype(_pkt_cache.begin()) it; + for (it = _pkt_cache.begin(); it != _pkt_cache.end(); ++it) { + if ((*it)->packet_seq_number == num) { + break; + } + } + if (it != _pkt_cache.end()) { + _pkt_cache.erase(_pkt_cache.begin(), it); + } + return true; +} +bool PacketSendQueue::inputPacket(DataPacket::Ptr pkt) { + _pkt_cache.push_back(pkt); + while (_pkt_cache.size() > _pkt_cap) { + _pkt_cache.pop_front(); + } + while (timeLantency() > _pkt_lantency) { + _pkt_cache.pop_front(); + } + return true; +} + +std::list PacketSendQueue::findPacketBySeq(uint32_t start, uint32_t end) { + std::list re; + decltype(_pkt_cache.begin()) it; + for (it = _pkt_cache.begin(); it != _pkt_cache.end(); ++it) { + if ((*it)->packet_seq_number == start) { + break; + } + } + + if (start == end) { + if (it != _pkt_cache.end()) { + re.push_back(*it); + } + return re; + } + + for (; it != _pkt_cache.end(); ++it) { + re.push_back(*it); + if ((*it)->packet_seq_number == end) { + break; + } + } + return re; +} + +uint32_t PacketSendQueue::timeLantency() { + if (_pkt_cache.empty()) { + return 0; + } + auto first = _pkt_cache.front()->timestamp; + auto last = _pkt_cache.back()->timestamp; + uint32_t dur; + + if (last > first) { + dur = last - first; + } else { + dur = first - last; + } + if (dur > (0x01 << 31)) { + TraceL << "cycle timeLantency " << dur; + dur = 0xffffffff - dur; + } + + return dur; +} + +} // namespace SRT \ No newline at end of file diff --git a/srt/PacketSendQueue.hpp b/srt/PacketSendQueue.hpp new file mode 100644 index 00000000..86fa86f1 --- /dev/null +++ b/srt/PacketSendQueue.hpp @@ -0,0 +1,29 @@ +#ifndef ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H +#define ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H +#include "Packet.hpp" +#include +#include +#include +#include +#include +#include +namespace SRT { +class PacketSendQueue { +public: + using Ptr = std::shared_ptr; + using LostPair = std::pair; + PacketSendQueue(uint32_t max_size, uint32_t lantency); + ~PacketSendQueue() = default; + bool drop(uint32_t num); + bool inputPacket(DataPacket::Ptr pkt); + std::list findPacketBySeq(uint32_t start,uint32_t end); +private: + uint32_t timeLantency(); +private: + std::list _pkt_cache; + uint32_t _pkt_cap; + uint32_t _pkt_lantency; +}; +} // namespace SRT + +#endif // ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H \ No newline at end of file diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 4b58b07e..c23614b1 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -198,8 +198,8 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad registerSelf(); sendControlPacket(res, true); TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<(res->max_flow_window_size,_init_seq_number, delay*1e6); - _send_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, delay*1e6); + _recv_buf = std::make_shared(res->max_flow_window_size,_init_seq_number, delay*1e3); + _send_buf = std::make_shared(res->max_flow_window_size, delay*1e3); _send_packet_seq_number = _init_seq_number; _buf_delay = delay; onHandShakeFinished(_stream_id,addr); @@ -249,7 +249,7 @@ void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *add pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); pkt->ack_number = ack.ack_number; pkt->storeToData(); - _send_buf->dropForSend(ack.last_ack_pkt_seq_number); + _send_buf->drop(ack.last_ack_pkt_seq_number); sendControlPacket(pkt,true); //TraceL<<"ack number "<findPacketBySeq(i); - if(data){ - data->R = 1; - data->storeToHeader(); - sendPacket(data,true); - empty = false; - } + auto re_list = _send_buf->findPacketBySeq(it.first,it.second-1); + for(auto pkt : re_list){ + pkt->R = 1; + pkt->storeToHeader(); + sendPacket(pkt,flush); + empty = false; } if(empty){ sendMsgDropReq(it.first,it.second-1); @@ -294,8 +296,45 @@ void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr){ MsgDropReqPacket pkt; pkt.loadFromData(buf,len); + std::list list; //TraceL<<"drop "<dropForRecv(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num); + _recv_buf->drop(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num,list); + if(list.empty()){ + return; + } + + for(auto data : list){ + onSRTData(std::move(data)); + } + + auto nak_interval = (_rtt+_rtt_variance*4)/2; + if(nak_interval >= 20*1000){ + nak_interval = 20*1000; + } + if(_nak_ticker.elapsedTime(_now)>nak_interval){ + auto lost = _recv_buf->getLostSeq(); + if(!lost.empty()){ + sendNAKPacket(lost); + } + _nak_ticker.resetTime(_now); + } + + if(_ack_ticker.elapsedTime(_now)>10*1000){ + _light_ack_pkt_count = 0; + _ack_ticker.resetTime(_now); + // send a ack per 10 ms for receiver + sendACKPacket(); + }else{ + if(_light_ack_pkt_count >= 64){ + // for high bitrate stream send light ack + // TODO + sendLightACKPacket(); + TraceL<<"send light ack"; + } + _light_ack_pkt_count = 0; + } + _light_ack_pkt_count++; + } void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr){ TraceL; @@ -379,32 +418,23 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora pkt->loadFromData(buf,len); pkt->get_ts = _now; - + std::list list; //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; -#if 1 - _recv_buf->inputPacket(pkt); -#else - if(pkt->packet_seq_number%100 == 0){ - // drop - TraceL<<"drop packet"; - TraceL<<"expected size "<<_recv_buf->getExpectedSize()<<" real size="<<_recv_buf->getSize(); - }else{ - _recv_buf->inputPacket(pkt); - } -#endif - //TraceL<<" data number size "<tryGetPacket(); - + _recv_buf->inputPacket(pkt,list); for(auto data : list){ onSRTData(std::move(data)); } + if(list.empty()){ + //TraceL<<_recv_buf->dump(); + } + auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval >= 20*1000){ + if(nak_interval <= 20*1000){ nak_interval = 20*1000; } - if(_nak_ticker.elapsedTime(_now)>nak_interval || list.empty()){ + if(_nak_ticker.elapsedTime(_now)>nak_interval){ auto lost = _recv_buf->getLostSeq(); if(!lost.empty()){ sendNAKPacket(lost); @@ -428,7 +458,6 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora _light_ack_pkt_count = 0; } _light_ack_pkt_count++; - //bufCheckInterval(); } diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index af19060e..b9aeca5b 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -13,6 +13,7 @@ #include "Common.hpp" #include "Packet.hpp" #include "PacketQueue.hpp" +#include "PacketSendQueue.hpp" #include "Statistic.hpp" namespace SRT { @@ -110,7 +111,7 @@ private: uint32_t _send_packet_seq_number = 0; uint32_t _send_msg_number = 1; - PacketQueue::Ptr _send_buf; + PacketSendQueue::Ptr _send_buf; uint32_t _buf_delay = 120; PacketQueue::Ptr _recv_buf; uint32_t _rtt = 100*1000; From 3cca4015c5f0d83b090d87f266507fe7f74df907 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sun, 5 Jun 2022 12:13:28 +0800 Subject: [PATCH 23/31] fix rtt and rtt variance --- srt/SrtTransport.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index c23614b1..a754a81e 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -308,7 +308,7 @@ void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage } auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval >= 20*1000){ + if(nak_interval <= 20*1000){ nak_interval = 20*1000; } if(_nak_ticker.elapsedTime(_now)>nak_interval){ @@ -346,9 +346,11 @@ void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage * pkt->loadFromData(buf,len); uint32_t rtt = DurationCountMicroseconds(_now - _ack_send_timestamp[pkt->ack_number]); - _rtt_variance = (3*_rtt_variance+abs((long)(_rtt - rtt)))/4; + _rtt_variance = (3*_rtt_variance+abs((long)_rtt - (long)rtt))/4; _rtt = (7*rtt+_rtt)/8; + + //TraceL<<" rtt:"<<_rtt<<" rtt variance:"<<_rtt_variance; _ack_send_timestamp.erase(pkt->ack_number); } @@ -426,19 +428,22 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora onSRTData(std::move(data)); } - if(list.empty()){ - //TraceL<<_recv_buf->dump(); - } - auto nak_interval = (_rtt+_rtt_variance*4)/2; if(nak_interval <= 20*1000){ nak_interval = 20*1000; } + + if(list.empty()){ + //TraceL<<_recv_buf->dump()<<" nake interval:"<nak_interval){ auto lost = _recv_buf->getLostSeq(); if(!lost.empty()){ sendNAKPacket(lost); //TraceL<<"send NAK"; + }else{ + //TraceL<<"lost is empty"; } _nak_ticker.resetTime(_now); } From b8806657cd78484c6e833092ad6c9d28445f2853 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sun, 5 Jun 2022 14:09:35 +0800 Subject: [PATCH 24/31] for srt lantency calculate when handshake --- srt/PacketQueue.cpp | 2 +- srt/SrtTransport.cpp | 7 ++++--- srt/SrtTransport.hpp | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 340f94d0..7cfb4781 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -49,7 +49,7 @@ void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt){ _pkt_map.emplace(pkt->packet_seq_number, pkt); TraceL<<" cycle packet "<<"expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; }else{ - TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + //TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; } } } diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index a754a81e..5d460e91 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -117,7 +117,8 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd sendControlPacket(_handleshake_res, true); return; } - + _induction_ts = _now; + _start_timestamp = _now; _init_seq_number = pkt.initial_packet_sequence_number; _max_window_size = pkt.max_flow_window_size; _mtu = pkt.mtu; @@ -154,7 +155,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad HSExtMessage::Ptr req; HSExtStreamID::Ptr sid; uint32_t srt_flag = 0xbf; - uint16_t delay = 120; + uint16_t delay = DurationCountMicroseconds(_now - _induction_ts)*4/1000; for (auto ext : pkt.ext_list) { //TraceL << getIdentifier() << " ext " << ext->dump(); @@ -170,7 +171,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad } if(req){ srt_flag = req->srt_flag; - delay = req->recv_tsbpd_delay; + delay = delay <= req->recv_tsbpd_delay ? req->recv_tsbpd_delay : delay; } TraceL << getIdentifier() << " CONCLUSION Phase "; HandshakePacket::Ptr res = std::make_shared(); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index b9aeca5b..4f9c20cd 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -102,6 +102,9 @@ private: TimePoint _now; TimePoint _start_timestamp; + // for calculate rtt for delay + TimePoint _induction_ts; + uint32_t _mtu = 1500; uint32_t _max_window_size = 8192; uint32_t _init_seq_number = 0; From 9f357c24b8599939c3f12e3a3f8b3c16cc3379fc Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Mon, 6 Jun 2022 18:18:26 +0800 Subject: [PATCH 25/31] avoid seq cycle --- srt/SrtTransport.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 5d460e91..b127092d 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -537,7 +537,8 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ while(ptr < end && size >=payloadSize){ pkt = std::make_shared(); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number++; + pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; @@ -553,7 +554,8 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ if(size >0 && ptr (); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number++; + pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; From 83d75c9a720476ee7e760a79e6f09a14b362554f Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Mon, 6 Jun 2022 19:55:47 +0800 Subject: [PATCH 26/31] add srt config for lantency multiplier --- conf/config.ini | 3 +++ srt/SrtTransport.cpp | 6 +++--- srt/SrtTransport.hpp | 6 ++++-- srt/SrtTransportImp.cpp | 5 +++++ srt/SrtTransportImp.hpp | 1 + 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 7a199215..21931088 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -291,6 +291,9 @@ timeoutSec=5 #该端口是多线程的,同时支持客户端网络切换导致的连接迁移 port=9000 +#srt 协议中延迟缓存的估算参数,在握手阶段估算rtt ,然后lantencyMul*rtt 为最大缓存时长,此参数越大,表示等待重传的时长就越大 +lantencyMul=4 + [rtsp] #rtsp专有鉴权方式是采用base64还是md5方式 diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index b127092d..e7a84bf3 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -11,6 +11,8 @@ const std::string kTimeOutSec = SRT_FIELD"timeoutSec"; //srt 单端口udp服务器 const std::string kPort = SRT_FIELD"port"; +const std::string kLantencyMul = SRT_FIELD"lantencyMul"; + static std::atomic s_srt_socket_id_generate{125}; //////////// SrtTransport ////////////////////////// SrtTransport::SrtTransport(const EventPoller::Ptr &poller) @@ -155,7 +157,7 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad HSExtMessage::Ptr req; HSExtStreamID::Ptr sid; uint32_t srt_flag = 0xbf; - uint16_t delay = DurationCountMicroseconds(_now - _induction_ts)*4/1000; + uint16_t delay = DurationCountMicroseconds(_now - _induction_ts)*getLantencyMul()/1000; for (auto ext : pkt.ext_list) { //TraceL << getIdentifier() << " ext " << ext->dump(); @@ -210,8 +212,6 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad } _last_ack_pkt_seq_num = _init_seq_number; } -void SrtTransport::bufCheckInterval(){ -} void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ HandshakePacket pkt; assert(pkt.loadFromData(buf,len)); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 4f9c20cd..c055dd62 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -21,6 +21,7 @@ using namespace toolkit; extern const std::string kPort; extern const std::string kTimeOutSec; +extern const std::string kLantencyMul; class SrtTransport : public std::enable_shared_from_this { public: @@ -81,13 +82,14 @@ private: void sendShutDown(); void sendMsgDropReq(uint32_t first ,uint32_t last); - void bufCheckInterval(); - size_t getPayloadSize(); protected: void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); virtual void sendPacket(Buffer::Ptr pkt,bool flush = true); + virtual int getLantencyMul(){ + return 4; + }; private: //当前选中的udp链接 Session::Ptr _selected_session; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index b12e6e7c..9425e2e7 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -273,5 +273,10 @@ void SrtTransportImp::doCachedFunc() { _cached_func.clear(); } +int SrtTransportImp::getLantencyMul(){ + GET_CONFIG(int, lantencyMul, kLantencyMul); + return lantencyMul; +} + } // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 36a07e01..5e259632 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -38,6 +38,7 @@ protected: void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr) override; void onSRTData(DataPacket::Ptr pkt) override; void onShutdown(const SockException &ex) override; + int getLantencyMul() override; void sendPacket(Buffer::Ptr pkt,bool flush = true) override{ _total_bytes += pkt->size(); From c92fc8a4a8a2cb83d5452672f0deb4599ed16ad6 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Mon, 6 Jun 2022 20:40:04 +0800 Subject: [PATCH 27/31] format code and remove some useless code --- srt/Ack.cpp | 42 ++--- srt/Ack.hpp | 26 ++- srt/Common.hpp | 46 ++--- srt/HSExt.cpp | 124 +++++++------- srt/HSExt.hpp | 2 +- srt/Packet.cpp | 285 ++++++++++++++----------------- srt/Packet.hpp | 40 ++--- srt/PacketQueue.cpp | 157 ++++++++--------- srt/PacketQueue.hpp | 9 +- srt/PacketSendQueue.cpp | 2 +- srt/PacketSendQueue.hpp | 4 +- srt/SrtSession.cpp | 70 ++++---- srt/SrtSession.hpp | 3 +- srt/SrtTransport.cpp | 366 ++++++++++++++++++++-------------------- srt/SrtTransport.hpp | 51 +++--- srt/SrtTransportImp.cpp | 113 ++++++------- srt/SrtTransportImp.hpp | 39 ++--- srt/Statistic.cpp | 69 ++++---- srt/Statistic.hpp | 29 ++-- 19 files changed, 715 insertions(+), 762 deletions(-) diff --git a/srt/Ack.cpp b/srt/Ack.cpp index 7be5a08d..ba2e67c5 100644 --- a/srt/Ack.cpp +++ b/srt/Ack.cpp @@ -2,8 +2,8 @@ #include "Common.hpp" namespace SRT { -bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { - if(len < ACK_CIF_SIZE + ControlPacket::HEADER_SIZE){ +bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { + if (len < ACK_CIF_SIZE + ControlPacket::HEADER_SIZE) { return false; } @@ -11,7 +11,7 @@ bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { _data->assign((char *)(buf), len); ControlPacket::loadHeader(); ack_number = loadUint32(type_specific_info); - uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + ControlPacket::HEADER_SIZE; last_ack_pkt_seq_number = loadUint32(ptr); ptr += 4; @@ -32,52 +32,52 @@ bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { ptr += 4; recv_rate = loadUint32(ptr); - ptr += 4; + ptr += 4; return true; } -bool ACKPacket::storeToData() { +bool ACKPacket::storeToData() { _data = BufferRaw::create(); _data->setCapacity(HEADER_SIZE + ACK_CIF_SIZE); _data->setSize(HEADER_SIZE + ACK_CIF_SIZE); control_type = ControlPacket::ACK; sub_type = 0; - storeUint32(type_specific_info,ack_number); + storeUint32(type_specific_info, ack_number); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; - - storeUint32(ptr,last_ack_pkt_seq_number); + uint8_t *ptr = (uint8_t *)_data->data() + ControlPacket::HEADER_SIZE; + + storeUint32(ptr, last_ack_pkt_seq_number); ptr += 4; - storeUint32(ptr,rtt); + storeUint32(ptr, rtt); ptr += 4; - storeUint32(ptr,rtt_variance); + storeUint32(ptr, rtt_variance); ptr += 4; - storeUint32(ptr,pkt_recv_rate); + storeUint32(ptr, pkt_recv_rate); ptr += 4; - storeUint32(ptr,available_buf_size); + storeUint32(ptr, available_buf_size); ptr += 4; - storeUint32(ptr,estimated_link_capacity); + storeUint32(ptr, estimated_link_capacity); ptr += 4; - storeUint32(ptr,recv_rate); + storeUint32(ptr, recv_rate); ptr += 4; return true; } -std::string ACKPacket::dump(){ +std::string ACKPacket::dump() { _StrPrinter printer; - printer << "last_ack_pkt_seq_number="<; ACKPacket() = default; ~ACKPacket() = default; - enum{ - ACK_CIF_SIZE = 7*4 - }; + enum { ACK_CIF_SIZE = 7 * 4 }; std::string dump(); ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; @@ -59,15 +55,14 @@ public: uint32_t recv_rate; }; - -class ACKACKPacket : public ControlPacket{ +class ACKACKPacket : public ControlPacket { public: using Ptr = std::shared_ptr; ACKACKPacket() = default; ~ACKACKPacket() = default; ///////ControlPacket override/////// - bool loadFromData(uint8_t *buf, size_t len) override{ - if(len < ControlPacket::HEADER_SIZE){ + bool loadFromData(uint8_t *buf, size_t len) override { + if (len < ControlPacket::HEADER_SIZE) { return false; } _data = BufferRaw::create(); @@ -76,21 +71,20 @@ public: ack_number = loadUint32(type_specific_info); return true; } - bool storeToData() override{ + bool storeToData() override { _data = BufferRaw::create(); _data->setCapacity(HEADER_SIZE); - _data->setSize(HEADER_SIZE ); + _data->setSize(HEADER_SIZE); control_type = ControlPacket::ACKACK; sub_type = 0; - storeUint32(type_specific_info,ack_number); + storeUint32(type_specific_info, ack_number); storeToHeader(); return true; } uint32_t ack_number; - }; -} //namespace SRT +} // namespace SRT #endif // ZLMEDIAKIT_SRT_ACK_H \ No newline at end of file diff --git a/srt/Common.hpp b/srt/Common.hpp index d0ba6207..90ca20b0 100644 --- a/srt/Common.hpp +++ b/srt/Common.hpp @@ -1,16 +1,26 @@ #ifndef ZLMEDIAKIT_SRT_COMMON_H #define ZLMEDIAKIT_SRT_COMMON_H +#if defined(_WIN32) +#include +#include +#include +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Iphlpapi.lib") +#else +#include +#include +#endif // defined(_WIN32) + #include -namespace SRT -{ +namespace SRT { using SteadyClock = std::chrono::steady_clock; using TimePoint = std::chrono::time_point; using Microseconds = std::chrono::microseconds; using Milliseconds = std::chrono::milliseconds; -inline int64_t DurationCountMicroseconds( SteadyClock::duration dur){ +inline int64_t DurationCountMicroseconds(SteadyClock::duration dur) { return std::chrono::duration_cast(dur).count(); } @@ -37,48 +47,38 @@ inline void storeUint32LE(uint8_t *buf, uint32_t val) { buf[0] = val & 0xff; buf[1] = (val >> 8) & 0xff; buf[2] = (val >> 16) & 0xff; - buf[3] = (val >>24) & 0xff; + buf[3] = (val >> 24) & 0xff; } inline void storeUint16LE(uint8_t *buf, uint16_t val) { buf[0] = val & 0xff; - buf[1] = (val>>8) & 0xff; + buf[1] = (val >> 8) & 0xff; } -inline uint32_t srtVersion(int major, int minor, int patch) -{ - return patch + minor*0x100 + major*0x10000; +inline uint32_t srtVersion(int major, int minor, int patch) { + return patch + minor * 0x100 + major * 0x10000; } class UTicker { public: - UTicker() { - _created = _begin = SteadyClock::now(); - } + UTicker() { _created = _begin = SteadyClock::now(); } - ~UTicker() { - } + ~UTicker() {} /** * 获取创建时间,单位微妙 */ - int64_t elapsedTime(TimePoint now) const { - return DurationCountMicroseconds(now - _begin); - } + int64_t elapsedTime(TimePoint now) const { return DurationCountMicroseconds(now - _begin); } /** * 获取上次resetTime后至今的时间,单位毫秒 */ - int64_t createdTime(TimePoint now) const { - return DurationCountMicroseconds(now - _created); - } + int64_t createdTime(TimePoint now) const { return DurationCountMicroseconds(now - _created); } /** * 重置计时器 */ - void resetTime(TimePoint now) { - _begin = now; - } + void resetTime(TimePoint now) { _begin = now; } private: TimePoint _begin; @@ -87,4 +87,4 @@ private: } // namespace SRT -#endif //ZLMEDIAKIT_SRT_COMMON_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_COMMON_H \ No newline at end of file diff --git a/srt/HSExt.cpp b/srt/HSExt.cpp index ab4d4ff2..3a3a7809 100644 --- a/srt/HSExt.cpp +++ b/srt/HSExt.cpp @@ -2,19 +2,19 @@ namespace SRT { bool HSExtMessage::loadFromData(uint8_t *buf, size_t len) { - if(buf == NULL || len != HSEXT_MSG_SIZE){ + if (buf == NULL || len != HSEXT_MSG_SIZE) { return false; } _data = BufferRaw::create(); - _data->assign((char*)buf,len); + _data->assign((char *)buf, len); extension_length = 3; HSExt::loadHeader(); assert(extension_type == SRT_CMD_HSREQ || extension_type == SRT_CMD_HSRSP); - uint8_t* ptr = (uint8_t*)_data->data()+4; - srt_version = loadUint32(ptr); + uint8_t *ptr = (uint8_t *)_data->data() + 4; + srt_version = loadUint32(ptr); ptr += 4; srt_flag = loadUint32(ptr); @@ -27,105 +27,103 @@ bool HSExtMessage::loadFromData(uint8_t *buf, size_t len) { ptr += 2; return true; - - } - std::string HSExtMessage::dump(){ - _StrPrinter printer; - printer << "srt version : "<; + using Ptr = std::shared_ptr; HSExtStreamID() = default; ~HSExtStreamID() = default; bool loadFromData(uint8_t *buf, size_t len) override; diff --git a/srt/Packet.cpp b/srt/Packet.cpp index 18ad279c..7f2b6cc2 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -1,28 +1,11 @@ - -#if defined(_WIN32) -#include -#include -#include -#pragma comment (lib, "Ws2_32.lib") -#pragma comment(lib,"Iphlpapi.lib") -#else -#include -#include -#endif // defined(_WIN32) - - - -#include +#include "Util/MD5.h" #include "Util/logger.h" -#include "Util/MD5.h" +#include #include "Packet.hpp" - - namespace SRT { - const size_t DataPacket::HEADER_SIZE; const size_t ControlPacket::HEADER_SIZE; const size_t HandshakePacket::HS_CONTENT_MIN_SIZE; @@ -38,7 +21,7 @@ bool DataPacket::isDataPacket(uint8_t *buf, size_t len) { return false; } -uint32_t DataPacket::getSocketID(uint8_t *buf, size_t len){ +uint32_t DataPacket::getSocketID(uint8_t *buf, size_t len) { uint8_t *ptr = buf; ptr += 12; return loadUint32(ptr); @@ -51,7 +34,7 @@ bool DataPacket::loadFromData(uint8_t *buf, size_t len) { } uint8_t *ptr = buf; f = ptr[0] >> 7; - packet_seq_number = loadUint32(ptr)&0x7fffffff; + packet_seq_number = loadUint32(ptr) & 0x7fffffff; ptr += 4; PP = ptr[0] >> 6; @@ -71,7 +54,7 @@ bool DataPacket::loadFromData(uint8_t *buf, size_t len) { _data->assign((char *)(buf), len); return true; } -bool DataPacket::storeToHeader(){ +bool DataPacket::storeToHeader() { if (!_data || _data->size() < HEADER_SIZE) { WarnL << "data size less " << HEADER_SIZE; return false; @@ -158,8 +141,6 @@ size_t DataPacket::payloadSize() { return _data->size() - HEADER_SIZE; } - - bool ControlPacket::isControlPacket(uint8_t *buf, size_t len) { if (len < HEADER_SIZE) { WarnL << "data size" << len << " less " << HEADER_SIZE; @@ -234,11 +215,11 @@ size_t ControlPacket::size() const { } return _data->size(); } -uint32_t ControlPacket::getSocketID(uint8_t *buf, size_t len){ - return loadUint32(buf+12); +uint32_t ControlPacket::getSocketID(uint8_t *buf, size_t len) { + return loadUint32(buf + 12); } bool HandshakePacket::loadFromData(uint8_t *buf, size_t len) { - if(HEADER_SIZE+HS_CONTENT_MIN_SIZE > len){ + if (HEADER_SIZE + HS_CONTENT_MIN_SIZE > len) { ErrorL << "size too smalle " << encryption_field; return false; } @@ -282,79 +263,77 @@ bool HandshakePacket::loadFromData(uint8_t *buf, size_t len) { ErrorL << "not support encryption " << encryption_field; } - if(extension_field == 0){ + if (extension_field == 0) { return true; } - if(len == HEADER_SIZE+HS_CONTENT_MIN_SIZE){ - //ErrorL << "extension filed not exist " << extension_field; + if (len == HEADER_SIZE + HS_CONTENT_MIN_SIZE) { + // ErrorL << "extension filed not exist " << extension_field; return true; } - return loadExtMessage(ptr,len-HS_CONTENT_MIN_SIZE-HEADER_SIZE); + return loadExtMessage(ptr, len - HS_CONTENT_MIN_SIZE - HEADER_SIZE); } -bool HandshakePacket::loadExtMessage(uint8_t *buf,size_t len){ - uint8_t* ptr = buf; - ext_list.clear(); - uint16_t type; - uint16_t length; - HSExt::Ptr ext; - while(ptr(); break; case HSExt::SRT_CMD_SID: ext = std::make_shared(); break; default: - WarnL<<"not support ext "<loadFromData(ptr,length*4+4)){ - ext_list.push_back(std::move(ext)); - }else{ - WarnL<<"parse HS EXT failed type="<assign((char*)buf,len); - + _data->assign((char *)buf, len); + return loadHeader(); } -bool KeepLivePacket::storeToData(){ +bool KeepLivePacket::storeToData() { control_type = ControlPacket::KEEPALIVE; sub_type = 0; @@ -506,22 +480,21 @@ bool NAKPacket::loadFromData(uint8_t *buf, size_t len) { return false; } _data = BufferRaw::create(); - _data->assign((char*)buf,len); + _data->assign((char *)buf, len); loadHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; - uint8_t* end = (uint8_t*)_data->data()+_data->size(); + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; + uint8_t *end = (uint8_t *)_data->data() + _data->size(); LostPair lost; - while (ptrsetCapacity(HEADER_SIZE+cif_size); - _data->setSize(HEADER_SIZE+cif_size); + _data->setCapacity(HEADER_SIZE + cif_size); + _data->setSize(HEADER_SIZE + cif_size); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; - for(auto it : lost_list){ - if(it.first+1 ==it.second){ - storeUint32(ptr,it.first); - ptr[0] = ptr[0]&0x7f; - ptr += 4; - }else{ - storeUint32(ptr,it.first); - ptr[0] |= 0x80; + for (auto it : lost_list) { + if (it.first + 1 == it.second) { + storeUint32(ptr, it.first); + ptr[0] = ptr[0] & 0x7f; + ptr += 4; + } else { + storeUint32(ptr, it.first); + ptr[0] |= 0x80; - storeUint32(ptr+4,it.second-1); - //ptr[4] = ptr[4]&0x7f; + storeUint32(ptr + 4, it.second - 1); + // ptr[4] = ptr[4]&0x7f; - ptr += 8; + ptr += 8; } } return true; } -size_t NAKPacket::getCIFSize(){ +size_t NAKPacket::getCIFSize() { size_t size = 0; - for(auto it : lost_list){ - if(it.first+1 ==it.second){ + for (auto it : lost_list) { + if (it.first + 1 == it.second) { size += 4; - }else{ + } else { size += 8; } } return size; } -std::string NAKPacket::dump(){ +std::string NAKPacket::dump() { _StrPrinter printer; for (auto it : lost_list) { - printer<<"[ "<assign((char*)buf,len); + _data->assign((char *)buf, len); loadHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; first_pkt_seq_num = loadUint32(ptr); ptr += 4; @@ -602,17 +575,17 @@ bool MsgDropReqPacket::storeToData() { control_type = DROPREQ; sub_type = 0; _data = BufferRaw::create(); - _data->setCapacity(HEADER_SIZE+8); - _data->setSize(HEADER_SIZE+8); + _data->setCapacity(HEADER_SIZE + 8); + _data->setSize(HEADER_SIZE + 8); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; - storeUint32(ptr,first_pkt_seq_num); + storeUint32(ptr, first_pkt_seq_num); ptr += 4; - storeUint32(ptr,last_pkt_seq_num); + storeUint32(ptr, last_pkt_seq_num); ptr += 4; return true; } diff --git a/srt/Packet.hpp b/srt/Packet.hpp index bab6df0c..7ccfa643 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -62,8 +62,6 @@ public: uint32_t timestamp; uint32_t dst_socket_id; - TimePoint get_ts; // recv or send time - private: BufferRaw::Ptr _data; }; @@ -171,7 +169,7 @@ class HandshakePacket : public ControlPacket { public: using Ptr = std::shared_ptr; enum { NO_ENCRYPTION = 0, AES_128 = 1, AES_196 = 2, AES_256 = 3 }; - static const size_t HS_CONTENT_MIN_SIZE = 48; + static const size_t HS_CONTENT_MIN_SIZE = 48; enum { HS_TYPE_DONE = 0xFFFFFFFD, HS_TYPE_AGREEMENT = 0xFFFFFFFE, @@ -181,18 +179,17 @@ public: }; enum { HS_EXT_FILED_HSREQ = 0x00000001, HS_EXT_FILED_KMREQ = 0x00000002, HS_EXT_FILED_CONFIG = 0x00000004 }; - - - + HandshakePacket() = default; ~HandshakePacket() = default; static bool isHandshakePacket(uint8_t *buf, size_t len); static uint32_t getHandshakeType(uint8_t *buf, size_t len); static uint32_t getSynCookie(uint8_t *buf, size_t len); - static uint32_t generateSynCookie(struct sockaddr_storage* addr,TimePoint ts,uint32_t current_cookie = 0, int correction = 0); + static uint32_t + generateSynCookie(struct sockaddr_storage *addr, TimePoint ts, uint32_t current_cookie = 0, int correction = 0); - void assignPeerIP(struct sockaddr_storage* addr); + void assignPeerIP(struct sockaddr_storage *addr); ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; bool storeToData() override; @@ -209,8 +206,9 @@ public: uint8_t peer_ip_addr[16]; std::vector ext_list; + private: - bool loadExtMessage(uint8_t *buf,size_t len); + bool loadExtMessage(uint8_t *buf, size_t len); bool storeExtMessage(); size_t getExtSize(); }; @@ -229,13 +227,12 @@ private: Figure 12: Keep-Alive control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-keep-alive */ -class KeepLivePacket : public ControlPacket -{ +class KeepLivePacket : public ControlPacket { public: using Ptr = std::shared_ptr; KeepLivePacket() = default; ~KeepLivePacket() = default; - ///////ControlPacket override/////// + ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; bool storeToData() override; }; @@ -265,11 +262,10 @@ An SRT NAK packet is formatted as follows: Figure 14: NAK control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-nak-control-packet */ -class NAKPacket : public ControlPacket -{ +class NAKPacket : public ControlPacket { public: using Ptr = std::shared_ptr; - using LostPair = std::pair; + using LostPair = std::pair; NAKPacket() = default; ~NAKPacket() = default; std::string dump(); @@ -278,11 +274,11 @@ public: bool storeToData() override; std::list lost_list; + private: size_t getCIFSize(); }; - /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -302,9 +298,8 @@ private: Figure 18: Drop Request control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-message-drop-request */ -class MsgDropReqPacket : public ControlPacket -{ - public: +class MsgDropReqPacket : public ControlPacket { +public: using Ptr = std::shared_ptr; MsgDropReqPacket() = default; ~MsgDropReqPacket() = default; @@ -332,13 +327,12 @@ class MsgDropReqPacket : public ControlPacket https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-shutdown */ -class ShutDownPacket : public ControlPacket -{ +class ShutDownPacket : public ControlPacket { public: using Ptr = std::shared_ptr; ShutDownPacket() = default; ~ShutDownPacket() = default; - ///////ControlPacket override/////// + ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override { if (len < HEADER_SIZE) { WarnL << "data size" << len << " less " << HEADER_SIZE; @@ -360,4 +354,4 @@ public: }; } // namespace SRT -#endif //ZLMEDIAKIT_SRT_PACKET_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_PACKET_H \ No newline at end of file diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 7cfb4781..47edc73a 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -2,80 +2,82 @@ namespace SRT { -#define MAX_SEQ 0x7fffffff -#define MAX_TS 0xffffffff -inline uint32_t genExpectedSeq(uint32_t seq){ +#define MAX_SEQ 0x7fffffff +#define MAX_TS 0xffffffff +inline uint32_t genExpectedSeq(uint32_t seq) { return MAX_SEQ & seq; } -inline bool isSeqEdge(uint32_t seq,uint32_t cap){ - if(seq >(MAX_SEQ - cap)){ +inline bool isSeqEdge(uint32_t seq, uint32_t cap) { + if (seq > (MAX_SEQ - cap)) { return true; } return false; } -inline bool isTSCycle(uint32_t first,uint32_t second){ +inline bool isTSCycle(uint32_t first, uint32_t second) { uint32_t diff; - if(first>second){ + if (first > second) { diff = first - second; - }else{ + } else { diff = second - first; } - if(diff > (MAX_TS>>1)){ + if (diff > (MAX_TS >> 1)) { return true; - }else{ + } else { return false; } } PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency) : _pkt_expected_seq(init_seq) , _pkt_cap(max_size) - , _pkt_lantency(lantency) { -} -void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt){ + , _pkt_lantency(lantency) {} +void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt) { if (_pkt_expected_seq <= pkt->packet_seq_number) { auto diff = pkt->packet_seq_number - _pkt_expected_seq; - if(diff >= (MAX_SEQ>>1)){ - TraceL << "drop packet too later for cycle "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + if (diff >= (MAX_SEQ >> 1)) { + TraceL << "drop packet too later for cycle " + << "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; return; - }else{ + } else { _pkt_map.emplace(pkt->packet_seq_number, pkt); } } else { auto diff = _pkt_expected_seq - pkt->packet_seq_number; - if(diff >= (MAX_SEQ>>1)){ - _pkt_map.emplace(pkt->packet_seq_number, pkt); - TraceL<<" cycle packet "<<"expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; - }else{ - //TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + if (diff >= (MAX_SEQ >> 1)) { + _pkt_map.emplace(pkt->packet_seq_number, pkt); + TraceL << " cycle packet " + << "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + } else { + // TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << + // pkt->packet_seq_number; } } } -bool PacketQueue::inputPacket(DataPacket::Ptr pkt,std::list& out) { +bool PacketQueue::inputPacket(DataPacket::Ptr pkt, std::list &out) { tryInsertPkt(pkt); auto it = _pkt_map.find(_pkt_expected_seq); - while ( it != _pkt_map.end()) { + while (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); - _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq+1); + _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); it = _pkt_map.find(_pkt_expected_seq); } while (_pkt_map.size() > _pkt_cap) { // 防止回环 it = _pkt_map.find(_pkt_expected_seq); - if(it != _pkt_map.end()){ + if (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); } _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } - while (timeLantency() > _pkt_lantency) { + while (timeLantency() > _pkt_lantency) { it = _pkt_map.find(_pkt_expected_seq); - if(it != _pkt_map.end()){ + if (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); } @@ -85,16 +87,16 @@ bool PacketQueue::inputPacket(DataPacket::Ptr pkt,std::list& ou return true; } -bool PacketQueue::drop(uint32_t first, uint32_t last,std::list& out){ - uint32_t end = genExpectedSeq(last+1); +bool PacketQueue::drop(uint32_t first, uint32_t last, std::list &out) { + uint32_t end = genExpectedSeq(last + 1); decltype(_pkt_map.end()) it; - for(uint32_t i =_pkt_expected_seq;i< end;){ - it = _pkt_map.find(i); - if(it != _pkt_map.end()){ - out.push_back(it->second); - _pkt_map.erase(it); - } - i = genExpectedSeq(i+1); + for (uint32_t i = _pkt_expected_seq; i < end;) { + it = _pkt_map.find(i); + if (it != _pkt_map.end()) { + out.push_back(it->second); + _pkt_map.erase(it); + } + i = genExpectedSeq(i + 1); } _pkt_expected_seq = end; return true; @@ -108,15 +110,15 @@ uint32_t PacketQueue::timeLantency() { auto first = _pkt_map.begin()->second->timestamp; auto last = _pkt_map.rbegin()->second->timestamp; uint32_t dur; - if(last>first){ + if (last > first) { dur = last - first; - }else{ + } else { dur = first - last; } - if(dur > 0x80000000){ + if (dur > 0x80000000) { dur = MAX_TS - dur; - WarnL<<"cycle dur "< PacketQueue::getLostSeq() { std::list re; - if(_pkt_map.empty()){ + if (_pkt_map.empty()) { return re; } - - if(getExpectedSize() == getSize()){ + + if (getExpectedSize() == getSize()) { return re; } uint32_t end = 0; - uint32_t first,last; + uint32_t first, last; first = _pkt_map.begin()->second->packet_seq_number; last = _pkt_map.rbegin()->second->packet_seq_number; @@ -149,71 +151,74 @@ std::list PacketQueue::getLostSeq() { uint32_t i = _pkt_expected_seq; bool finish = true; - for(i = _pkt_expected_seq;i<=end;){ - if(_pkt_map.find(i) == _pkt_map.end()){ - if(finish){ + for (i = _pkt_expected_seq; i <= end;) { + if (_pkt_map.find(i) == _pkt_map.end()) { + if (finish) { finish = false; lost.first = i; - lost.second = i+1; - }else{ - lost.second = i+1; + lost.second = i + 1; + } else { + lost.second = i + 1; } - }else{ - if(!finish){ + } else { + if (!finish) { finish = true; re.push_back(lost); } } - i = genExpectedSeq(i+1); + i = genExpectedSeq(i + 1); } return re; } -size_t PacketQueue::getSize(){ +size_t PacketQueue::getSize() { return _pkt_map.size(); } size_t PacketQueue::getExpectedSize() { - if(_pkt_map.empty()){ + if (_pkt_map.empty()) { return 0; } uint32_t max = _pkt_map.rbegin()->first; uint32_t min = _pkt_map.begin()->first; - if((max-min)>=(MAX_SEQ>>1)){ - TraceL<<"cycle "<<"expected seq "<<_pkt_expected_seq<<" min "<= (MAX_SEQ >> 1)) { + TraceL << "cycle " + << "expected seq " << _pkt_expected_seq << " min " << min << " max " << max << " size " + << _pkt_map.size(); + return MAX_SEQ - _pkt_expected_seq + min + 1; + } else { + return max - _pkt_expected_seq + 1; } } -size_t PacketQueue::getAvailableBufferSize(){ - auto size = getExpectedSize(); - if(_pkt_cap > size){ +size_t PacketQueue::getAvailableBufferSize() { + auto size = getExpectedSize(); + if (_pkt_cap > size) { return _pkt_cap - size; } - if(_pkt_cap > _pkt_map.size()){ + if (_pkt_cap > _pkt_map.size()) { return _pkt_cap - _pkt_map.size(); } - WarnL<<" cap "<<_pkt_cap<<" expected size "<second->packet_seq_number; - printer<<" last:"<<_pkt_map.rbegin()->second->packet_seq_number; - printer<<" latency:"<second->packet_seq_number; + printer << " last:" << _pkt_map.rbegin()->second->packet_seq_number; + printer << " latency:" << timeLantency() / 1e3; + } + return std::move(printer); } } // namespace SRT \ No newline at end of file diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp index 66702d65..02903601 100644 --- a/srt/PacketQueue.hpp +++ b/srt/PacketQueue.hpp @@ -3,8 +3,8 @@ #include "Packet.hpp" #include #include -#include #include +#include #include #include @@ -18,7 +18,7 @@ public: PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency); ~PacketQueue() = default; - bool inputPacket(DataPacket::Ptr pkt,std::list& out); + bool inputPacket(DataPacket::Ptr pkt, std::list &out); uint32_t timeLantency(); std::list getLostSeq(); @@ -28,13 +28,14 @@ public: size_t getAvailableBufferSize(); uint32_t getExpectedSeq(); - bool drop(uint32_t first, uint32_t last,std::list& out); + bool drop(uint32_t first, uint32_t last, std::list &out); std::string dump(); + private: void tryInsertPkt(DataPacket::Ptr pkt); -private: +private: std::map _pkt_map; uint32_t _pkt_expected_seq = 0; diff --git a/srt/PacketSendQueue.cpp b/srt/PacketSendQueue.cpp index 9ea11aaf..61b46e7d 100644 --- a/srt/PacketSendQueue.cpp +++ b/srt/PacketSendQueue.cpp @@ -66,7 +66,7 @@ uint32_t PacketSendQueue::timeLantency() { } else { dur = first - last; } - if (dur > (0x01 << 31)) { + if (dur > ((uint32_t)0x01 << 31)) { TraceL << "cycle timeLantency " << dur; dur = 0xffffffff - dur; } diff --git a/srt/PacketSendQueue.hpp b/srt/PacketSendQueue.hpp index 86fa86f1..df9dc815 100644 --- a/srt/PacketSendQueue.hpp +++ b/srt/PacketSendQueue.hpp @@ -16,9 +16,11 @@ public: ~PacketSendQueue() = default; bool drop(uint32_t num); bool inputPacket(DataPacket::Ptr pkt); - std::list findPacketBySeq(uint32_t start,uint32_t end); + std::list findPacketBySeq(uint32_t start, uint32_t end); + private: uint32_t timeLantency(); + private: std::list _pkt_cache; uint32_t _pkt_cap; diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index fe8cfc13..c828fa13 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -10,10 +10,10 @@ using namespace mediakit; SrtSession::SrtSession(const Socket::Ptr &sock) : UdpSession(sock) { socklen_t addr_len = sizeof(_peer_addr); - memset(&_peer_addr,0,addr_len); - //TraceL<<"before addr len "<rawFD(), (struct sockaddr *)&_peer_addr, &addr_len); - //TraceL<<"after addr len "<data(); + uint8_t *data = (uint8_t *)buffer->data(); size_t size = buffer->size(); - if(DataPacket::isDataPacket(data,size)){ - uint32_t socket_id = DataPacket::getSocketID(data,size); + if (DataPacket::isDataPacket(data, size)) { + uint32_t socket_id = DataPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); return trans ? trans->getPoller() : nullptr; } - if(HandshakePacket::isHandshakePacket(data,size)){ - auto type = HandshakePacket::getHandshakeType(data,size); - if(type == HandshakePacket::HS_TYPE_INDUCTION){ + if (HandshakePacket::isHandshakePacket(data, size)) { + auto type = HandshakePacket::getHandshakeType(data, size); + if (type == HandshakePacket::HS_TYPE_INDUCTION) { // 握手第一阶段 return nullptr; - }else if(type == HandshakePacket::HS_TYPE_CONCLUSION){ + } else if (type == HandshakePacket::HS_TYPE_CONCLUSION) { // 握手第二阶段 - uint32_t sync_cookie = HandshakePacket::getSynCookie(data,size); + uint32_t sync_cookie = HandshakePacket::getSynCookie(data, size); auto trans = SrtTransportManager::Instance().getHandshakeItem(std::to_string(sync_cookie)); return trans ? trans->getPoller() : nullptr; - }else{ - WarnL<<" not reach there"; + } else { + WarnL << " not reach there"; } - }else{ - uint32_t socket_id = ControlPacket::getSocketID(data,size); + } else { + uint32_t socket_id = ControlPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); return trans ? trans->getPoller() : nullptr; } return nullptr; } -void SrtSession::attachServer(const toolkit::Server &server){ - SockUtil::setRecvBuf(getSock()->rawFD(),1024 * 1024); +void SrtSession::attachServer(const toolkit::Server &server) { + SockUtil::setRecvBuf(getSock()->rawFD(), 1024 * 1024); } void SrtSession::onRecv(const Buffer::Ptr &buffer) { - uint8_t* data = (uint8_t*)buffer->data(); + uint8_t *data = (uint8_t *)buffer->data(); size_t size = buffer->size(); if (_find_transport) { @@ -64,10 +64,10 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { if (DataPacket::isDataPacket(data, size)) { uint32_t socket_id = DataPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); - if(trans){ + if (trans) { _transport = std::move(trans); - }else{ - WarnL<<" data packet not find transport "; + } else { + WarnL << " data packet not find transport "; } } @@ -92,24 +92,24 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { } else { uint32_t socket_id = ControlPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); - if(trans){ + if (trans) { _transport = std::move(trans); - }else{ + } else { WarnL << " not find transport"; } } - if(_transport){ + if (_transport) { _transport->setSession(shared_from_this()); } InfoP(this); } _ticker.resetTime(); - if(_transport){ - _transport->inputSockData(data,size,&_peer_addr); - }else{ - //WarnL<< "ingore data"; + if (_transport) { + _transport->inputSockData(data, size, &_peer_addr); + } else { + // WarnL<< "ingore data"; } } @@ -122,18 +122,20 @@ void SrtSession::onError(const SockException &err) { if (!_transport) { return; } - + // 防止互相引用导致不释放 auto transport = std::move(_transport); - getPoller()->async([transport,err] { - //延时减引用,防止使用transport对象时,销毁对象 - transport->onShutdown(err); - }, false); + getPoller()->async( + [transport, err] { + //延时减引用,防止使用transport对象时,销毁对象 + transport->onShutdown(err); + }, + false); } void SrtSession::onManager() { GET_CONFIG(float, timeoutSec, kTimeOutSec); - if (_ticker.elapsedTime() > timeoutSec*1000) { + if (_ticker.elapsedTime() > timeoutSec * 1000) { shutdown(SockException(Err_timeout, "srt connection timeout")); return; } diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp index 401aae3c..342a4a91 100644 --- a/srt/SrtSession.hpp +++ b/srt/SrtSession.hpp @@ -24,8 +24,7 @@ private: Ticker _ticker; struct sockaddr_storage _peer_addr; SrtTransport::Ptr _transport; - }; } // namespace SRT -#endif //ZLMEDIAKIT_SRT_SESSION_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_SESSION_H \ No newline at end of file diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index e7a84bf3..0f9e1a7a 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -1,31 +1,31 @@ #include #include "Util/onceToken.h" -#include "SrtTransport.hpp" -#include "Packet.hpp" #include "Ack.hpp" +#include "Packet.hpp" +#include "SrtTransport.hpp" namespace SRT { #define SRT_FIELD "srt." -//srt 超时时间 -const std::string kTimeOutSec = SRT_FIELD"timeoutSec"; -//srt 单端口udp服务器 -const std::string kPort = SRT_FIELD"port"; +// srt 超时时间 +const std::string kTimeOutSec = SRT_FIELD "timeoutSec"; +// srt 单端口udp服务器 +const std::string kPort = SRT_FIELD "port"; -const std::string kLantencyMul = SRT_FIELD"lantencyMul"; +const std::string kLantencyMul = SRT_FIELD "lantencyMul"; -static std::atomic s_srt_socket_id_generate{125}; +static std::atomic s_srt_socket_id_generate { 125 }; //////////// SrtTransport ////////////////////////// SrtTransport::SrtTransport(const EventPoller::Ptr &poller) : _poller(poller) { - _start_timestamp = SteadyClock::now(); - _socket_id = s_srt_socket_id_generate.fetch_add(1);\ - _pkt_recv_rate_context = std::make_shared(_start_timestamp); - _recv_rate_context = std::make_shared(_start_timestamp); - _estimated_link_capacity_context = std::make_shared(_start_timestamp); - } + _start_timestamp = SteadyClock::now(); + _socket_id = s_srt_socket_id_generate.fetch_add(1); + _pkt_recv_rate_context = std::make_shared(_start_timestamp); + _recv_rate_context = std::make_shared(_start_timestamp); + _estimated_link_capacity_context = std::make_shared(_start_timestamp); +} -SrtTransport::~SrtTransport(){ - TraceL<<" "; +SrtTransport::~SrtTransport() { + TraceL << " "; } const EventPoller::Ptr &SrtTransport::getPoller() const { return _poller; @@ -44,20 +44,20 @@ const Session::Ptr &SrtTransport::getSession() const { return _selected_session; } -void SrtTransport::switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr){ +void SrtTransport::switchToOtherTransport(uint8_t *buf, int len, uint32_t socketid, struct sockaddr_storage *addr) { BufferRaw::Ptr tmp = BufferRaw::create(); struct sockaddr_storage tmp_addr = *addr; - tmp->assign((char*)buf,len); + tmp->assign((char *)buf, len); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socketid)); - if(trans){ - trans->getPoller()->async([tmp,tmp_addr,trans]{ - trans->inputSockData((uint8_t*)tmp->data(),tmp->size(),(struct sockaddr_storage*)&tmp_addr); + if (trans) { + trans->getPoller()->async([tmp, tmp_addr, trans] { + trans->inputSockData((uint8_t *)tmp->data(), tmp->size(), (struct sockaddr_storage *)&tmp_addr); }); } } void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr) { - using srt_control_handler = void (SrtTransport::*)(uint8_t* buf,int len,struct sockaddr_storage *addr); + using srt_control_handler = void (SrtTransport::*)(uint8_t * buf, int len, struct sockaddr_storage *addr); static std::unordered_map s_control_functions; static onceToken token([]() { s_control_functions.emplace(ControlPacket::HANDSHAKE, &SrtTransport::handleHandshake); @@ -74,23 +74,23 @@ void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage _now = SteadyClock::now(); // 处理srt数据 if (DataPacket::isDataPacket(buf, len)) { - uint32_t socketId = DataPacket::getSocketID(buf,len); - if(socketId == _socket_id){ + uint32_t socketId = DataPacket::getSocketID(buf, len); + if (socketId == _socket_id) { _pkt_recv_rate_context->inputPacket(_now); _estimated_link_capacity_context->inputPacket(_now); _recv_rate_context->inputPacket(_now, len); handleDataPacket(buf, len, addr); - }else{ - switchToOtherTransport(buf,len,socketId,addr); + } else { + switchToOtherTransport(buf, len, socketId, addr); } } else { if (ControlPacket::isControlPacket(buf, len)) { - uint32_t socketId = ControlPacket::getSocketID(buf,len); - uint16_t type = ControlPacket::getControlType(buf,len); - if(type != ControlPacket::HANDSHAKE && socketId != _socket_id && _socket_id != 0){ + uint32_t socketId = ControlPacket::getSocketID(buf, len); + uint16_t type = ControlPacket::getControlType(buf, len); + if (type != ControlPacket::HANDSHAKE && socketId != _socket_id && _socket_id != 0) { // socket id not same - switchToOtherTransport(buf,len,socketId,addr); + switchToOtherTransport(buf, len, socketId, addr); return; } _pkt_recv_rate_context->inputPacket(_now); @@ -99,10 +99,10 @@ void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage auto it = s_control_functions.find(type); if (it == s_control_functions.end()) { - WarnL<<" not support type ignore" << ControlPacket::getControlType(buf,len); + WarnL << " not support type ignore" << ControlPacket::getControlType(buf, len); return; - }else{ - (this->*(it->second))(buf,len,addr); + } else { + (this->*(it->second))(buf, len, addr); } } else { // not reach @@ -119,7 +119,7 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd sendControlPacket(_handleshake_res, true); return; } - _induction_ts = _now; + _induction_ts = _now; _start_timestamp = _now; _init_seq_number = pkt.initial_packet_sequence_number; _max_window_size = pkt.max_flow_window_size; @@ -147,8 +147,8 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd sendControlPacket(res, true); } void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockaddr_storage *addr) { - if(!_handleshake_res){ - ErrorL<<"must Induction Phase for handleshake "; + if (!_handleshake_res) { + ErrorL << "must Induction Phase for handleshake "; return; } @@ -157,21 +157,21 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad HSExtMessage::Ptr req; HSExtStreamID::Ptr sid; uint32_t srt_flag = 0xbf; - uint16_t delay = DurationCountMicroseconds(_now - _induction_ts)*getLantencyMul()/1000; + uint16_t delay = DurationCountMicroseconds(_now - _induction_ts) * getLantencyMul() / 1000; for (auto ext : pkt.ext_list) { - //TraceL << getIdentifier() << " ext " << ext->dump(); + // TraceL << getIdentifier() << " ext " << ext->dump(); if (!req) { req = std::dynamic_pointer_cast(ext); } - if(!sid){ + if (!sid) { sid = std::dynamic_pointer_cast(ext); } } - if(sid){ + if (sid) { _stream_id = sid->streamid; } - if(req){ + if (req) { srt_flag = req->srt_flag; delay = delay <= req->recv_tsbpd_delay ? req->recv_tsbpd_delay : delay; } @@ -200,167 +200,166 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad unregisterSelfHandshake(); registerSelf(); sendControlPacket(res, true); - TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<(res->max_flow_window_size,_init_seq_number, delay*1e3); - _send_buf = std::make_shared(res->max_flow_window_size, delay*1e3); + TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number + << " lantency=" << delay; + _recv_buf = std::make_shared(res->max_flow_window_size, _init_seq_number, delay * 1e3); + _send_buf = std::make_shared(res->max_flow_window_size, delay * 1e3); _send_packet_seq_number = _init_seq_number; _buf_delay = delay; - onHandShakeFinished(_stream_id,addr); + onHandShakeFinished(_stream_id, addr); } else { TraceL << getIdentifier() << " CONCLUSION handle repeate "; sendControlPacket(_handleshake_res, true); } _last_ack_pkt_seq_num = _init_seq_number; } -void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr) { HandshakePacket pkt; - assert(pkt.loadFromData(buf,len)); + assert(pkt.loadFromData(buf, len)); - if(pkt.handshake_type == HandshakePacket::HS_TYPE_INDUCTION){ - handleHandshakeInduction(pkt,addr); - }else if(pkt.handshake_type == HandshakePacket::HS_TYPE_CONCLUSION){ - handleHandshakeConclusion(pkt,addr); - }else{ - WarnL<<" not support handshake type = "<< pkt.handshake_type; + if (pkt.handshake_type == HandshakePacket::HS_TYPE_INDUCTION) { + handleHandshakeInduction(pkt, addr); + } else if (pkt.handshake_type == HandshakePacket::HS_TYPE_CONCLUSION) { + handleHandshakeConclusion(pkt, addr); + } else { + WarnL << " not support handshake type = " << pkt.handshake_type; } _ack_ticker.resetTime(_now); _nak_ticker.resetTime(_now); } -void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; +void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; sendKeepLivePacket(); } - void SrtTransport::sendKeepLivePacket(){ +void SrtTransport::sendKeepLivePacket() { KeepLivePacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->storeToData(); - sendControlPacket(pkt,true); - } -void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; + sendControlPacket(pkt, true); +} +void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; ACKPacket ack; - if(!ack.loadFromData(buf,len)){ + if (!ack.loadFromData(buf, len)) { return; } ACKACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = ack.ack_number; pkt->storeToData(); _send_buf->drop(ack.last_ack_pkt_seq_number); - sendControlPacket(pkt,true); - //TraceL<<"ack number "<(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->first_pkt_seq_num = first; pkt->last_pkt_seq_num = last; pkt->storeToData(); - sendControlPacket(pkt,true); + sendControlPacket(pkt, true); } -void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; +void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; NAKPacket pkt; - pkt.loadFromData(buf,len); + pkt.loadFromData(buf, len); bool empty = false; bool flush = false; - for(auto it : pkt.lost_list){ - if(pkt.lost_list.back() == it){ + for (auto it : pkt.lost_list) { + if (pkt.lost_list.back() == it) { flush = true; } empty = true; - auto re_list = _send_buf->findPacketBySeq(it.first,it.second-1); - for(auto pkt : re_list){ + auto re_list = _send_buf->findPacketBySeq(it.first, it.second - 1); + for (auto pkt : re_list) { pkt->R = 1; pkt->storeToHeader(); - sendPacket(pkt,flush); + sendPacket(pkt, flush); empty = false; } - if(empty){ - sendMsgDropReq(it.first,it.second-1); + if (empty) { + sendMsgDropReq(it.first, it.second - 1); } } } -void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } -void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; onShutdown(SockException(Err_shutdown, "peer close connection")); } -void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr) { MsgDropReqPacket pkt; - pkt.loadFromData(buf,len); + pkt.loadFromData(buf, len); std::list list; - //TraceL<<"drop "<drop(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num,list); - if(list.empty()){ + // TraceL<<"drop "<drop(pkt.first_pkt_seq_num, pkt.last_pkt_seq_num, list); + if (list.empty()) { return; } - for(auto data : list){ + for (auto data : list) { onSRTData(std::move(data)); } - auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval <= 20*1000){ - nak_interval = 20*1000; + auto nak_interval = (_rtt + _rtt_variance * 4) / 2; + if (nak_interval <= 20 * 1000) { + nak_interval = 20 * 1000; } - if(_nak_ticker.elapsedTime(_now)>nak_interval){ + if (_nak_ticker.elapsedTime(_now) > nak_interval) { auto lost = _recv_buf->getLostSeq(); - if(!lost.empty()){ - sendNAKPacket(lost); + if (!lost.empty()) { + sendNAKPacket(lost); } _nak_ticker.resetTime(_now); } - if(_ack_ticker.elapsedTime(_now)>10*1000){ + if (_ack_ticker.elapsedTime(_now) > 10 * 1000) { _light_ack_pkt_count = 0; _ack_ticker.resetTime(_now); - // send a ack per 10 ms for receiver + // send a ack per 10 ms for receiver sendACKPacket(); - }else{ - if(_light_ack_pkt_count >= 64){ + } else { + if (_light_ack_pkt_count >= 64) { // for high bitrate stream send light ack - // TODO + // TODO sendLightACKPacket(); - TraceL<<"send light ack"; + TraceL << "send light ack"; } _light_ack_pkt_count = 0; } _light_ack_pkt_count++; - } -void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } -void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; +void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; ACKACKPacket::Ptr pkt = std::make_shared(); - pkt->loadFromData(buf,len); + pkt->loadFromData(buf, len); uint32_t rtt = DurationCountMicroseconds(_now - _ack_send_timestamp[pkt->ack_number]); - _rtt_variance = (3*_rtt_variance+abs((long)_rtt - (long)rtt))/4; - _rtt = (7*rtt+_rtt)/8; + _rtt_variance = (3 * _rtt_variance + abs((long)_rtt - (long)rtt)) / 4; + _rtt = (7 * rtt + _rtt) / 8; - - //TraceL<<" rtt:"<<_rtt<<" rtt variance:"<<_rtt_variance; + // TraceL<<" rtt:"<<_rtt<<" rtt variance:"<<_rtt_variance; _ack_send_timestamp.erase(pkt->ack_number); } -void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } void SrtTransport::sendACKPacket() { - ACKPacket::Ptr pkt=std::make_shared(); + ACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = ++_ack_number_count; @@ -373,13 +372,13 @@ void SrtTransport::sendACKPacket() { pkt->recv_rate = _recv_rate_context->getRecvRate(); pkt->storeToData(); _ack_send_timestamp[pkt->ack_number] = _now; - _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; - sendControlPacket(pkt,true); - //TraceL<<"send ack "<dump(); + _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; + sendControlPacket(pkt, true); + // TraceL<<"send ack "<dump(); } void SrtTransport::sendLightACKPacket() { - ACKPacket::Ptr pkt=std::make_shared(); - + ACKPacket::Ptr pkt = std::make_shared(); + pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = 0; @@ -392,11 +391,11 @@ void SrtTransport::sendLightACKPacket() { pkt->recv_rate = 0; pkt->storeToData(); _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; - sendControlPacket(pkt,true); - TraceL<<"send ack "<dump(); + sendControlPacket(pkt, true); + TraceL << "send ack " << pkt->dump(); } -void SrtTransport::sendNAKPacket(std::list& lost_list){ +void SrtTransport::sendNAKPacket(std::list &lost_list) { NAKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; @@ -405,112 +404,111 @@ void SrtTransport::sendNAKPacket(std::list& lost_list){ pkt->storeToData(); - //TraceL<<"send NAK "<dump(); - sendControlPacket(pkt,true); + // TraceL<<"send NAK "<dump(); + sendControlPacket(pkt, true); } -void SrtTransport::sendShutDown(){ +void SrtTransport::sendShutDown() { ShutDownPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->storeToData(); - sendControlPacket(pkt,true); + sendControlPacket(pkt, true); } -void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr) { DataPacket::Ptr pkt = std::make_shared(); - pkt->loadFromData(buf,len); + pkt->loadFromData(buf, len); - pkt->get_ts = _now; std::list list; //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; - _recv_buf->inputPacket(pkt,list); - for(auto data : list){ + _recv_buf->inputPacket(pkt, list); + for (auto data : list) { onSRTData(std::move(data)); } - auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval <= 20*1000){ - nak_interval = 20*1000; + auto nak_interval = (_rtt + _rtt_variance * 4) / 2; + if (nak_interval <= 20 * 1000) { + nak_interval = 20 * 1000; } - if(list.empty()){ - //TraceL<<_recv_buf->dump()<<" nake interval:"<dump()<<" nake interval:"<nak_interval){ + if (_nak_ticker.elapsedTime(_now) > nak_interval) { auto lost = _recv_buf->getLostSeq(); - if(!lost.empty()){ - sendNAKPacket(lost); - //TraceL<<"send NAK"; - }else{ - //TraceL<<"lost is empty"; + if (!lost.empty()) { + sendNAKPacket(lost); + // TraceL<<"send NAK"; + } else { + // TraceL<<"lost is empty"; } _nak_ticker.resetTime(_now); } - if(_ack_ticker.elapsedTime(_now)>10*1000){ + if (_ack_ticker.elapsedTime(_now) > 10 * 1000) { _light_ack_pkt_count = 0; _ack_ticker.resetTime(_now); - // send a ack per 10 ms for receiver + // send a ack per 10 ms for receiver sendACKPacket(); - }else{ - if(_light_ack_pkt_count >= 64){ + } else { + if (_light_ack_pkt_count >= 64) { // for high bitrate stream send light ack - // TODO + // TODO sendLightACKPacket(); - TraceL<<"send light ack"; + TraceL << "send light ack"; } _light_ack_pkt_count = 0; } _light_ack_pkt_count++; - //bufCheckInterval(); + // bufCheckInterval(); } -void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { - pkt->storeToData((uint8_t*)buf,len); - sendPacket(pkt,flush); +void SrtTransport::sendDataPacket(DataPacket::Ptr pkt, char *buf, int len, bool flush) { + pkt->storeToData((uint8_t *)buf, len); + sendPacket(pkt, flush); _send_buf->inputPacket(pkt); } -void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { - sendPacket(pkt,flush); +void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { + sendPacket(pkt, flush); } -void SrtTransport::sendPacket(Buffer::Ptr pkt,bool flush){ - if(_selected_session){ - auto tmp = _packet_pool.obtain2(); - tmp->assign(pkt->data(),pkt->size()); - _selected_session->setSendFlushFlag(flush); - _selected_session->send(std::move(tmp)); - }else{ - WarnL<<"not reach this"; +void SrtTransport::sendPacket(Buffer::Ptr pkt, bool flush) { + if (_selected_session) { + auto tmp = _packet_pool.obtain2(); + tmp->assign(pkt->data(), pkt->size()); + _selected_session->setSendFlushFlag(flush); + _selected_session->send(std::move(tmp)); + } else { + WarnL << "not reach this"; } } -std::string SrtTransport::getIdentifier(){ +std::string SrtTransport::getIdentifier() { return _selected_session ? _selected_session->getIdentifier() : ""; } -void SrtTransport::registerSelfHandshake() { - SrtTransportManager::Instance().addHandshakeItem(std::to_string(_sync_cookie),shared_from_this()); +void SrtTransport::registerSelfHandshake() { + SrtTransportManager::Instance().addHandshakeItem(std::to_string(_sync_cookie), shared_from_this()); } -void SrtTransport::unregisterSelfHandshake() { - if(_sync_cookie == 0){ +void SrtTransport::unregisterSelfHandshake() { + if (_sync_cookie == 0) { return; } SrtTransportManager::Instance().removeHandshakeItem(std::to_string(_sync_cookie)); } void SrtTransport::registerSelf() { - if(_socket_id == 0){ + if (_socket_id == 0) { return; } - SrtTransportManager::Instance().addItem(std::to_string(_socket_id),shared_from_this()); - + SrtTransportManager::Instance().addItem(std::to_string(_socket_id), shared_from_this()); } -void SrtTransport::unregisterSelf() { +void SrtTransport::unregisterSelf() { SrtTransportManager::Instance().removeItem(std::to_string(_socket_id)); } -void SrtTransport::onShutdown(const SockException &ex){ +void SrtTransport::onShutdown(const SockException &ex) { sendShutDown(); WarnL << ex.what(); unregisterSelfHandshake(); @@ -522,23 +520,23 @@ void SrtTransport::onShutdown(const SockException &ex){ } } } -size_t SrtTransport::getPayloadSize(){ - size_t ret = (_mtu - 28 -16)/188*188; +size_t SrtTransport::getPayloadSize() { + size_t ret = (_mtu - 28 - 16) / 188 * 188; return ret; } -void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ - //TraceL; +void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush) { + // TraceL; DataPacket::Ptr pkt; size_t payloadSize = getPayloadSize(); - size_t size = buffer->size(); - char* ptr = buffer->data(); - char* end = buffer->data()+size; + size_t size = buffer->size(); + char *ptr = buffer->data(); + char *end = buffer->data() + size; - while(ptr < end && size >=payloadSize){ + while (ptr < end && size >= payloadSize) { pkt = std::make_shared(); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; - _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; + pkt->packet_seq_number = _send_packet_seq_number & 0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number + 1) & 0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; @@ -546,16 +544,16 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ pkt->msg_number = _send_msg_number++; pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); - sendDataPacket(pkt,ptr,(int)payloadSize,flush); + sendDataPacket(pkt, ptr, (int)payloadSize, flush); ptr += payloadSize; size -= payloadSize; } - if(size >0 && ptr 0 && ptr < end) { pkt = std::make_shared(); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; - _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; + pkt->packet_seq_number = _send_packet_seq_number & 0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number + 1) & 0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; @@ -563,9 +561,8 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ pkt->msg_number = _send_msg_number++; pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); - sendDataPacket(pkt,ptr,(int)size,flush); + sendDataPacket(pkt, ptr, (int)size, flush); } - } //////////// SrtTransportManager ////////////////////////// SrtTransportManager &SrtTransportManager::Instance() { @@ -600,7 +597,7 @@ void SrtTransportManager::addHandshakeItem(const std::string &key, const SrtTran _handshake_map[key] = ptr; } void SrtTransportManager::removeHandshakeItem(const std::string &key) { - std::lock_guard lck(_handshake_mtx); + std::lock_guard lck(_handshake_mtx); _handshake_map.erase(key); } SrtTransport::Ptr SrtTransportManager::getHandshakeItem(const std::string &key) { @@ -615,5 +612,4 @@ SrtTransport::Ptr SrtTransportManager::getHandshakeItem(const std::string &key) return it->second.lock(); } - } // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index c055dd62..64dc566d 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -1,10 +1,10 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_H #define ZLMEDIAKIT_SRT_TRANSPORT_H -#include +#include #include #include -#include +#include #include "Network/Session.h" #include "Poller/EventPoller.h" @@ -43,26 +43,25 @@ public: virtual void onSendTSData(const Buffer::Ptr &buffer, bool flush); std::string getIdentifier(); - + void unregisterSelfHandshake(); void unregisterSelf(); + protected: - virtual void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr){}; - virtual void onSRTData(DataPacket::Ptr pkt){}; + virtual void onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) {}; + virtual void onSRTData(DataPacket::Ptr pkt) {}; virtual void onShutdown(const SockException &ex); - virtual bool isPusher(){ - return true; - }; + virtual bool isPusher() { return true; }; private: void registerSelfHandshake(); void registerSelf(); - void switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr); + void switchToOtherTransport(uint8_t *buf, int len, uint32_t socketid, struct sockaddr_storage *addr); void handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr); - void handleHandshakeInduction(HandshakePacket& pkt,struct sockaddr_storage *addr); - void handleHandshakeConclusion(HandshakePacket& pkt,struct sockaddr_storage *addr); + void handleHandshakeInduction(HandshakePacket &pkt, struct sockaddr_storage *addr); + void handleHandshakeConclusion(HandshakePacket &pkt, struct sockaddr_storage *addr); void handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr); void handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr); @@ -74,27 +73,27 @@ private: void handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr); void handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr); void handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr); - - void sendNAKPacket(std::list& lost_list); + + void sendNAKPacket(std::list &lost_list); void sendACKPacket(); void sendLightACKPacket(); void sendKeepLivePacket(); void sendShutDown(); - void sendMsgDropReq(uint32_t first ,uint32_t last); + void sendMsgDropReq(uint32_t first, uint32_t last); size_t getPayloadSize(); + protected: - void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); - void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); - virtual void sendPacket(Buffer::Ptr pkt,bool flush = true); - virtual int getLantencyMul(){ - return 4; - }; + void sendDataPacket(DataPacket::Ptr pkt, char *buf, int len, bool flush = false); + void sendControlPacket(ControlPacket::Ptr pkt, bool flush = true); + virtual void sendPacket(Buffer::Ptr pkt, bool flush = true); + virtual int getLantencyMul() { return 4; }; + private: //当前选中的udp链接 Session::Ptr _selected_session; //链接迁移前后使用过的udp链接 - std::unordered_map > _history_sessions; + std::unordered_map> _history_sessions; EventPoller::Ptr _poller; @@ -109,7 +108,7 @@ private: uint32_t _mtu = 1500; uint32_t _max_window_size = 8192; - uint32_t _init_seq_number = 0; + uint32_t _init_seq_number = 0; std::string _stream_id; uint32_t _sync_cookie = 0; @@ -119,13 +118,13 @@ private: PacketSendQueue::Ptr _send_buf; uint32_t _buf_delay = 120; PacketQueue::Ptr _recv_buf; - uint32_t _rtt = 100*1000; - uint32_t _rtt_variance =50*1000; + uint32_t _rtt = 100 * 1000; + uint32_t _rtt_variance = 50 * 1000; uint32_t _light_ack_pkt_count = 0; uint32_t _ack_number_count = 0; uint32_t _last_ack_pkt_seq_num = 0; UTicker _ack_ticker; - std::map _ack_send_timestamp; + std::map _ack_send_timestamp; std::shared_ptr _pkt_recv_rate_context; std::shared_ptr _estimated_link_capacity_context; @@ -137,7 +136,6 @@ private: HandshakePacket::Ptr _handleshake_res; ResourcePool _packet_pool; - }; class SrtTransportManager { @@ -150,6 +148,7 @@ public: void addHandshakeItem(const std::string &key, const SrtTransport::Ptr &ptr); void removeHandshakeItem(const std::string &key); SrtTransport::Ptr getHandshakeItem(const std::string &key); + private: SrtTransportManager() = default; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 9425e2e7..09c37ef2 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -10,65 +10,64 @@ SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) SrtTransportImp::~SrtTransportImp() { InfoP(this); uint64_t duration = _alive_ticker.createdTime() / 1000; - WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") - << _media_info._vhost << "/" - << _media_info._app << "/" - << _media_info._streamid - << ")断开,耗时(s):" << duration; + WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info._vhost << "/" << _media_info._app << "/" + << _media_info._streamid << ")断开,耗时(s):" << duration; //流量统计事件广播 GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold); if (_total_bytes >= iFlowThreshold * 1024) { - NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport, _media_info, _total_bytes, duration, false, static_cast(*this)); + NoticeCenter::Instance().emitEvent( + Broadcast::kBroadcastFlowReport, _media_info, _total_bytes, duration, false, + static_cast(*this)); } } -void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_storage *addr) { - +void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) { + // TODO parse streamid like this zlmediakit.com/live/test?token=1213444&type=push - if(!_addr){ + if (!_addr) { _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); } - _is_pusher = false; - TraceL<<" stream id "<input(reinterpret_cast(pkt->payloadData()), pkt->payloadSize()); - }else{ - WarnP(this)<<" not reach this"; + } else { + WarnP(this) << " not reach this"; } } void SrtTransportImp::onShutdown(const SockException &ex) { SrtTransport::onShutdown(ex); } -bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force){ - if (!force && totalReaderCount(sender)) { +bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force) { + if (!force && totalReaderCount(sender)) { return false; } std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" - << sender.getApp() << "/" << sender.getId() << " " << force; + << sender.getApp() << "/" << sender.getId() << " " << force; weak_ptr weak_self = static_pointer_cast(shared_from_this()); getPoller()->async([weak_self, err]() { auto strong_self = weak_self.lock(); @@ -81,20 +80,20 @@ bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force){ return true; } // 播放总人数 -int SrtTransportImp::totalReaderCount(mediakit::MediaSource &sender){ +int SrtTransportImp::totalReaderCount(mediakit::MediaSource &sender) { return _muxer ? _muxer->totalReaderCount() : sender.readerCount(); } // 获取媒体源类型 -mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const{ +mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const { return MediaOriginType::srt_push; } // 获取媒体源url或者文件路径 -std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const{ +std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const { return _media_info._full_url; } // 获取媒体源客户端相关信息 -std::shared_ptr SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const{ - return static_pointer_cast(getSession()); +std::shared_ptr SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const { + return static_pointer_cast(getSession()); } void SrtTransportImp::emitOnPublish() { @@ -105,50 +104,51 @@ void SrtTransportImp::emitOnPublish() { return; } if (err.empty()) { - strong_self->_muxer = std::make_shared(strong_self->_media_info._vhost, - strong_self->_media_info._app, - strong_self->_media_info._streamid, 0.0f, - option); + strong_self->_muxer = std::make_shared( + strong_self->_media_info._vhost, strong_self->_media_info._app, strong_self->_media_info._streamid, + 0.0f, option); strong_self->_muxer->setMediaListener(strong_self); strong_self->doCachedFunc(); InfoP(strong_self) << "允许 srt 推流"; } else { WarnP(strong_self) << "禁止 srt 推流:" << err; - strong_self->onShutdown(SockException(Err_refused,err)); + strong_self->onShutdown(SockException(Err_refused, err)); } }; //触发推流鉴权事件 - auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::srt_push, _media_info, invoker, static_cast(*this)); + auto flag = NoticeCenter::Instance().emitEvent( + Broadcast::kBroadcastMediaPublish, MediaOriginType::srt_push, _media_info, invoker, + static_cast(*this)); if (!flag) { //该事件无人监听,默认不鉴权 invoker("", ProtocolOption()); } } - -void SrtTransportImp::emitOnPlay(){ +void SrtTransportImp::emitOnPlay() { std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); - Broadcast::AuthInvoker invoker = [weak_self](const string &err){ + Broadcast::AuthInvoker invoker = [weak_self](const string &err) { auto strong_self = weak_self.lock(); if (!strong_self) { return; } - strong_self->getPoller()->async([strong_self,err]{ - if(err != ""){ - strong_self->onShutdown(SockException(Err_refused,err)); - }else{ + strong_self->getPoller()->async([strong_self, err] { + if (err != "") { + strong_self->onShutdown(SockException(Err_refused, err)); + } else { strong_self->doPlay(); } }); }; - auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); - if(!flag){ + auto flag = NoticeCenter::Instance().emitEvent( + Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); + if (!flag) { doPlay(); } } -void SrtTransportImp::doPlay(){ +void SrtTransportImp::doPlay() { //异步查找直播流 std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); @@ -158,15 +158,15 @@ void SrtTransportImp::doPlay(){ auto strong_self = weak_self.lock(); if (!strong_self) { //本对象已经销毁 - TraceL<<"本对象已经销毁"; + TraceL << "本对象已经销毁"; return; } if (!src) { //未找到该流 - TraceL<<"未找到该流"; + TraceL << "未找到该流"; strong_self->onShutdown(SockException(Err_shutdown)); } else { - TraceL<<"找到该流"; + TraceL << "找到该流"; auto ts_src = dynamic_pointer_cast(src); assert(ts_src); ts_src->pause(false); @@ -215,7 +215,7 @@ std::string SrtTransportImp::get_local_ip() { } uint16_t SrtTransportImp::get_local_port() { - auto s = getSession(); + auto s = getSession(); if (s) { return s->get_local_port(); } @@ -236,9 +236,7 @@ bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) { } auto frame_cached = Frame::getCacheAbleFrame(frame); lock_guard lck(_func_mtx); - _cached_func.emplace_back([this, frame_cached]() { - _muxer->inputFrame(frame_cached); - }); + _cached_func.emplace_back([this, frame_cached]() { _muxer->inputFrame(frame_cached); }); return true; } @@ -248,9 +246,7 @@ bool SrtTransportImp::addTrack(const Track::Ptr &track) { } lock_guard lck(_func_mtx); - _cached_func.emplace_back([this, track]() { - _muxer->addTrack(track); - }); + _cached_func.emplace_back([this, track]() { _muxer->addTrack(track); }); return true; } @@ -259,9 +255,7 @@ void SrtTransportImp::addTrackCompleted() { _muxer->addTrackCompleted(); } else { lock_guard lck(_func_mtx); - _cached_func.emplace_back([this]() { - _muxer->addTrackCompleted(); - }); + _cached_func.emplace_back([this]() { _muxer->addTrackCompleted(); }); } } @@ -273,10 +267,9 @@ void SrtTransportImp::doCachedFunc() { _cached_func.clear(); } -int SrtTransportImp::getLantencyMul(){ +int SrtTransportImp::getLantencyMul() { GET_CONFIG(int, lantencyMul, kLantencyMul); return lantencyMul; } - } // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 5e259632..afa8ab7f 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -1,16 +1,15 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_IMP_H #define ZLMEDIAKIT_SRT_TRANSPORT_IMP_H -#include #include "Common/MultiMediaSourceMuxer.h" #include "Rtp/Decoder.h" -#include "TS/TSMediaSource.h" #include "SrtTransport.hpp" - +#include "TS/TSMediaSource.h" +#include namespace SRT { - using namespace toolkit; - using namespace mediakit; - using namespace std; +using namespace toolkit; +using namespace mediakit; +using namespace std; class SrtTransportImp : public SrtTransport , public toolkit::SockInfo @@ -19,13 +18,11 @@ class SrtTransportImp public: SrtTransportImp(const EventPoller::Ptr &poller); ~SrtTransportImp(); - void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr){ - SrtTransport::inputSockData(buf,len,addr); + void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr) { + SrtTransport::inputSockData(buf, len, addr); _total_bytes += len; } - void onSendTSData(const Buffer::Ptr &buffer, bool flush){ - SrtTransport::onSendTSData(buffer,flush); - } + void onSendTSData(const Buffer::Ptr &buffer, bool flush) { SrtTransport::onSendTSData(buffer, flush); } /// SockInfo override std::string get_local_ip() override; uint16_t get_local_port() override; @@ -35,19 +32,17 @@ public: protected: ///////SrtTransport override/////// - void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr) override; + void onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) override; void onSRTData(DataPacket::Ptr pkt) override; void onShutdown(const SockException &ex) override; int getLantencyMul() override; - void sendPacket(Buffer::Ptr pkt,bool flush = true) override{ + void sendPacket(Buffer::Ptr pkt, bool flush = true) override { _total_bytes += pkt->size(); - SrtTransport::sendPacket(pkt,flush); + SrtTransport::sendPacket(pkt, flush); }; - bool isPusher() override{ - return _is_pusher; - } + bool isPusher() override { return _is_pusher; } ///////MediaSourceEvent override/////// // 关闭 @@ -62,7 +57,7 @@ protected: std::shared_ptr getOriginSock(mediakit::MediaSource &sender) const override; bool inputFrame(const Frame::Ptr &frame) override; - bool addTrack(const Track::Ptr & track) override; + bool addTrack(const Track::Ptr &track) override; void addTrackCompleted() override; void resetTracks() override {}; @@ -76,16 +71,16 @@ private: private: bool _is_pusher = true; MediaInfo _media_info; - uint64_t _total_bytes = 0; + uint64_t _total_bytes = 0; Ticker _alive_ticker; std::unique_ptr _addr; - // for player + // for player TSMediaSource::RingType::RingReader::Ptr _ts_reader; - // for pusher + // for pusher MultiMediaSourceMuxer::Ptr _muxer; DecoderImp::Ptr _decoder; std::recursive_mutex _func_mtx; - std::deque > _cached_func; + std::deque> _cached_func; }; } // namespace SRT diff --git a/srt/Statistic.cpp b/srt/Statistic.cpp index 9fc13cd5..ad79cb8a 100644 --- a/srt/Statistic.cpp +++ b/srt/Statistic.cpp @@ -2,12 +2,12 @@ #include "Statistic.hpp" namespace SRT { -void PacketRecvRateContext::inputPacket(TimePoint& ts) { - if(_pkt_map.size()>100){ - _pkt_map.erase(_pkt_map.begin()); - } - auto tmp = DurationCountMicroseconds(ts - _start); - _pkt_map.emplace(tmp,tmp); +void PacketRecvRateContext::inputPacket(TimePoint &ts) { + if (_pkt_map.size() > 100) { + _pkt_map.erase(_pkt_map.begin()); + } + auto tmp = DurationCountMicroseconds(ts - _start); + _pkt_map.emplace(tmp, tmp); } uint32_t PacketRecvRateContext::getPacketRecvRate() { if (_pkt_map.size() < 2) { @@ -27,13 +27,13 @@ uint32_t PacketRecvRateContext::getPacketRecvRate() { } double rate = 1e6 / (double)dur; - if(rate <=1000){ + if (rate <= 1000) { return 50000; } return rate; } -void EstimatedLinkCapacityContext::inputPacket(TimePoint& ts) { +void EstimatedLinkCapacityContext::inputPacket(TimePoint &ts) { if (_pkt_map.size() > 16) { _pkt_map.erase(_pkt_map.begin()); } @@ -41,55 +41,54 @@ void EstimatedLinkCapacityContext::inputPacket(TimePoint& ts) { _pkt_map.emplace(tmp, tmp); } uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { - decltype(_pkt_map.begin()) next; - std::vector tmp; + decltype(_pkt_map.begin()) next; + std::vector tmp; - for(auto it = _pkt_map.begin();it != _pkt_map.end();++it){ - next = it; - ++next; - if(next != _pkt_map.end()){ - tmp.push_back(next->first -it->first); - }else{ - break; - } - } - std::sort(tmp.begin(),tmp.end()); - if(tmp.empty()){ - return 1000; - } + for (auto it = _pkt_map.begin(); it != _pkt_map.end(); ++it) { + next = it; + ++next; + if (next != _pkt_map.end()) { + tmp.push_back(next->first - it->first); + } else { + break; + } + } + std::sort(tmp.begin(), tmp.end()); + if (tmp.empty()) { + return 1000; + } - if(tmp.size()<16){ - return 1000; - } + if (tmp.size() < 16) { + return 1000; + } - double dur =tmp[0]/1e6; - - return (uint32_t)(1.0/dur); + double dur = tmp[0] / 1e6; + return (uint32_t)(1.0 / dur); } -void RecvRateContext::inputPacket(TimePoint& ts, size_t size ) { +void RecvRateContext::inputPacket(TimePoint &ts, size_t size) { if (_pkt_map.size() > 100) { _pkt_map.erase(_pkt_map.begin()); } - auto tmp = DurationCountMicroseconds(ts - _start); + auto tmp = DurationCountMicroseconds(ts - _start); _pkt_map.emplace(tmp, tmp); } uint32_t RecvRateContext::getRecvRate() { - if(_pkt_map.size()<2){ + if (_pkt_map.size() < 2) { return 0; } auto first = _pkt_map.begin(); auto last = _pkt_map.rbegin(); - double dur = (last->first - first->first)/1000000.0; + double dur = (last->first - first->first) / 1000000.0; size_t bytes = 0; - for(auto it : _pkt_map){ + for (auto it : _pkt_map) { bytes += it.second; } - double rate = (double)bytes/dur; + double rate = (double)bytes / dur; return (uint32_t)rate; } diff --git a/srt/Statistic.hpp b/srt/Statistic.hpp index 4524aebe..c47c9700 100644 --- a/srt/Statistic.hpp +++ b/srt/Statistic.hpp @@ -8,39 +8,42 @@ namespace SRT { class PacketRecvRateContext { public: - PacketRecvRateContext(TimePoint start):_start(start){}; + PacketRecvRateContext(TimePoint start) + : _start(start) {}; ~PacketRecvRateContext() = default; - void inputPacket(TimePoint& ts); + void inputPacket(TimePoint &ts); uint32_t getPacketRecvRate(); + private: - std::map _pkt_map; + std::map _pkt_map; TimePoint _start; - }; class EstimatedLinkCapacityContext { public: - EstimatedLinkCapacityContext(TimePoint start):_start(start){}; + EstimatedLinkCapacityContext(TimePoint start) + : _start(start) {}; ~EstimatedLinkCapacityContext() = default; - void inputPacket(TimePoint& ts); + void inputPacket(TimePoint &ts); uint32_t getEstimatedLinkCapacity(); + private: - std::map _pkt_map; + std::map _pkt_map; TimePoint _start; }; class RecvRateContext { public: - RecvRateContext(TimePoint start):_start(start){}; + RecvRateContext(TimePoint start) + : _start(start) {}; ~RecvRateContext() = default; - void inputPacket(TimePoint& ts,size_t size); + void inputPacket(TimePoint &ts, size_t size); uint32_t getRecvRate(); + private: - std::map _pkt_map; - TimePoint _start; + std::map _pkt_map; + TimePoint _start; }; - - } // namespace SRT #endif // ZLMEDIAKIT_SRT_STATISTIC_H \ No newline at end of file From 020b8b85ea44f030066a9d1c102db5807e29b957 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Mon, 6 Jun 2022 22:13:53 +0800 Subject: [PATCH 28/31] try fix for windows build --- srt/Common.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srt/Common.hpp b/srt/Common.hpp index 90ca20b0..cc49cff1 100644 --- a/srt/Common.hpp +++ b/srt/Common.hpp @@ -1,11 +1,11 @@ #ifndef ZLMEDIAKIT_SRT_COMMON_H #define ZLMEDIAKIT_SRT_COMMON_H #if defined(_WIN32) -#include #include #include -#pragma comment(lib, "Ws2_32.lib") -#pragma comment(lib, "Iphlpapi.lib") +#include +#pragma comment (lib, "Ws2_32.lib") +#pragma comment(lib,"Iphlpapi.lib") #else #include #include From e415230e472901daf73cc37caf341c004cc56836 Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Tue, 7 Jun 2022 09:52:20 +0800 Subject: [PATCH 29/31] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96srt=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 4 +- srt/Ack.cpp | 44 ++--- srt/Ack.hpp | 26 +-- srt/Common.hpp | 50 ++--- srt/HSExt.cpp | 125 ++++++------- srt/HSExt.hpp | 7 +- srt/Packet.cpp | 280 ++++++++++++++-------------- srt/Packet.hpp | 42 ++--- srt/PacketQueue.cpp | 171 +++++++++-------- srt/PacketQueue.hpp | 21 +-- srt/PacketSendQueue.cpp | 12 +- srt/PacketSendQueue.hpp | 18 +- srt/SrtSession.cpp | 72 ++++---- srt/SrtSession.hpp | 3 +- srt/SrtTransport.cpp | 395 +++++++++++++++++++++------------------- srt/SrtTransport.hpp | 58 +++--- srt/SrtTransportImp.cpp | 114 ++++++------ srt/SrtTransportImp.hpp | 55 +++--- srt/Statistic.cpp | 86 ++++----- srt/Statistic.hpp | 27 +-- 20 files changed, 821 insertions(+), 789 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 21931088..5a468bd7 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -291,8 +291,8 @@ timeoutSec=5 #该端口是多线程的,同时支持客户端网络切换导致的连接迁移 port=9000 -#srt 协议中延迟缓存的估算参数,在握手阶段估算rtt ,然后lantencyMul*rtt 为最大缓存时长,此参数越大,表示等待重传的时长就越大 -lantencyMul=4 +#srt 协议中延迟缓存的估算参数,在握手阶段估算rtt ,然后latencyMul*rtt 为最大缓存时长,此参数越大,表示等待重传的时长就越大 +latencyMul=4 [rtsp] diff --git a/srt/Ack.cpp b/srt/Ack.cpp index 7be5a08d..f0afc017 100644 --- a/srt/Ack.cpp +++ b/srt/Ack.cpp @@ -2,8 +2,9 @@ #include "Common.hpp" namespace SRT { -bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { - if(len < ACK_CIF_SIZE + ControlPacket::HEADER_SIZE){ + +bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { + if (len < ACK_CIF_SIZE + ControlPacket::HEADER_SIZE) { return false; } @@ -11,7 +12,7 @@ bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { _data->assign((char *)(buf), len); ControlPacket::loadHeader(); ack_number = loadUint32(type_specific_info); - uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + ControlPacket::HEADER_SIZE; last_ack_pkt_seq_number = loadUint32(ptr); ptr += 4; @@ -32,52 +33,53 @@ bool ACKPacket::loadFromData(uint8_t *buf, size_t len) { ptr += 4; recv_rate = loadUint32(ptr); - ptr += 4; + ptr += 4; return true; } -bool ACKPacket::storeToData() { + +bool ACKPacket::storeToData() { _data = BufferRaw::create(); _data->setCapacity(HEADER_SIZE + ACK_CIF_SIZE); _data->setSize(HEADER_SIZE + ACK_CIF_SIZE); control_type = ControlPacket::ACK; sub_type = 0; - storeUint32(type_specific_info,ack_number); + storeUint32(type_specific_info, ack_number); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+ControlPacket::HEADER_SIZE; - - storeUint32(ptr,last_ack_pkt_seq_number); + uint8_t *ptr = (uint8_t *)_data->data() + ControlPacket::HEADER_SIZE; + + storeUint32(ptr, last_ack_pkt_seq_number); ptr += 4; - storeUint32(ptr,rtt); + storeUint32(ptr, rtt); ptr += 4; - storeUint32(ptr,rtt_variance); + storeUint32(ptr, rtt_variance); ptr += 4; - storeUint32(ptr,pkt_recv_rate); + storeUint32(ptr, pkt_recv_rate); ptr += 4; - storeUint32(ptr,available_buf_size); + storeUint32(ptr, available_buf_size); ptr += 4; - storeUint32(ptr,estimated_link_capacity); + storeUint32(ptr, estimated_link_capacity); ptr += 4; - storeUint32(ptr,recv_rate); + storeUint32(ptr, recv_rate); ptr += 4; return true; } -std::string ACKPacket::dump(){ +std::string ACKPacket::dump() { _StrPrinter printer; - printer << "last_ack_pkt_seq_number="<; ACKPacket() = default; ~ACKPacket() = default; - enum{ - ACK_CIF_SIZE = 7*4 - }; + enum { ACK_CIF_SIZE = 7 * 4 }; std::string dump(); ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; @@ -59,15 +55,14 @@ public: uint32_t recv_rate; }; - -class ACKACKPacket : public ControlPacket{ +class ACKACKPacket : public ControlPacket { public: using Ptr = std::shared_ptr; ACKACKPacket() = default; ~ACKACKPacket() = default; ///////ControlPacket override/////// - bool loadFromData(uint8_t *buf, size_t len) override{ - if(len < ControlPacket::HEADER_SIZE){ + bool loadFromData(uint8_t *buf, size_t len) override { + if (len < ControlPacket::HEADER_SIZE) { return false; } _data = BufferRaw::create(); @@ -76,21 +71,20 @@ public: ack_number = loadUint32(type_specific_info); return true; } - bool storeToData() override{ + bool storeToData() override { _data = BufferRaw::create(); _data->setCapacity(HEADER_SIZE); - _data->setSize(HEADER_SIZE ); + _data->setSize(HEADER_SIZE); control_type = ControlPacket::ACKACK; sub_type = 0; - storeUint32(type_specific_info,ack_number); + storeUint32(type_specific_info, ack_number); storeToHeader(); return true; } uint32_t ack_number; - }; -} //namespace SRT +} // namespace SRT #endif // ZLMEDIAKIT_SRT_ACK_H \ No newline at end of file diff --git a/srt/Common.hpp b/srt/Common.hpp index d0ba6207..418a00a3 100644 --- a/srt/Common.hpp +++ b/srt/Common.hpp @@ -2,83 +2,73 @@ #define ZLMEDIAKIT_SRT_COMMON_H #include -namespace SRT -{ +namespace SRT { + using SteadyClock = std::chrono::steady_clock; using TimePoint = std::chrono::time_point; using Microseconds = std::chrono::microseconds; using Milliseconds = std::chrono::milliseconds; -inline int64_t DurationCountMicroseconds( SteadyClock::duration dur){ +static inline int64_t DurationCountMicroseconds(SteadyClock::duration dur) { return std::chrono::duration_cast(dur).count(); } -inline uint32_t loadUint32(uint8_t *ptr) { +static inline uint32_t loadUint32(uint8_t *ptr) { return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; } -inline uint16_t loadUint16(uint8_t *ptr) { + +static inline uint16_t loadUint16(uint8_t *ptr) { return ptr[0] << 8 | ptr[1]; } -inline void storeUint32(uint8_t *buf, uint32_t val) { +static inline void storeUint32(uint8_t *buf, uint32_t val) { buf[0] = val >> 24; buf[1] = (val >> 16) & 0xff; buf[2] = (val >> 8) & 0xff; buf[3] = val & 0xff; } -inline void storeUint16(uint8_t *buf, uint16_t val) { +static inline void storeUint16(uint8_t *buf, uint16_t val) { buf[0] = (val >> 8) & 0xff; buf[1] = val & 0xff; } -inline void storeUint32LE(uint8_t *buf, uint32_t val) { +static inline void storeUint32LE(uint8_t *buf, uint32_t val) { buf[0] = val & 0xff; buf[1] = (val >> 8) & 0xff; buf[2] = (val >> 16) & 0xff; - buf[3] = (val >>24) & 0xff; + buf[3] = (val >> 24) & 0xff; } -inline void storeUint16LE(uint8_t *buf, uint16_t val) { +static inline void storeUint16LE(uint8_t *buf, uint16_t val) { buf[0] = val & 0xff; - buf[1] = (val>>8) & 0xff; + buf[1] = (val >> 8) & 0xff; } -inline uint32_t srtVersion(int major, int minor, int patch) -{ - return patch + minor*0x100 + major*0x10000; +static inline uint32_t srtVersion(int major, int minor, int patch) { + return patch + minor * 0x100 + major * 0x10000; } class UTicker { public: - UTicker() { - _created = _begin = SteadyClock::now(); - } - - ~UTicker() { - } + UTicker() { _created = _begin = SteadyClock::now(); } + ~UTicker() = default; /** * 获取创建时间,单位微妙 */ - int64_t elapsedTime(TimePoint now) const { - return DurationCountMicroseconds(now - _begin); - } + int64_t elapsedTime(TimePoint now) const { return DurationCountMicroseconds(now - _begin); } /** * 获取上次resetTime后至今的时间,单位毫秒 */ - int64_t createdTime(TimePoint now) const { - return DurationCountMicroseconds(now - _created); - } + int64_t createdTime(TimePoint now) const { return DurationCountMicroseconds(now - _created); } /** * 重置计时器 */ - void resetTime(TimePoint now) { - _begin = now; - } + void resetTime(TimePoint now) { _begin = now; } private: TimePoint _begin; @@ -87,4 +77,4 @@ private: } // namespace SRT -#endif //ZLMEDIAKIT_SRT_COMMON_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_COMMON_H \ No newline at end of file diff --git a/srt/HSExt.cpp b/srt/HSExt.cpp index ab4d4ff2..d12b2b3c 100644 --- a/srt/HSExt.cpp +++ b/srt/HSExt.cpp @@ -1,20 +1,21 @@ #include "HSExt.hpp" namespace SRT { + bool HSExtMessage::loadFromData(uint8_t *buf, size_t len) { - if(buf == NULL || len != HSEXT_MSG_SIZE){ + if (buf == NULL || len != HSEXT_MSG_SIZE) { return false; } _data = BufferRaw::create(); - _data->assign((char*)buf,len); + _data->assign((char *)buf, len); extension_length = 3; HSExt::loadHeader(); assert(extension_type == SRT_CMD_HSREQ || extension_type == SRT_CMD_HSRSP); - uint8_t* ptr = (uint8_t*)_data->data()+4; - srt_version = loadUint32(ptr); + uint8_t *ptr = (uint8_t *)_data->data() + 4; + srt_version = loadUint32(ptr); ptr += 4; srt_flag = loadUint32(ptr); @@ -27,105 +28,107 @@ bool HSExtMessage::loadFromData(uint8_t *buf, size_t len) { ptr += 2; return true; +} - } - std::string HSExtMessage::dump(){ - _StrPrinter printer; - printer << "srt version : "<data(); } return nullptr; - }; + } size_t size() const override { if (_data) { return _data->size(); } return 0; - }; + } protected: void loadHeader() { @@ -116,7 +117,7 @@ public: */ class HSExtStreamID : public HSExt { public: - using Ptr = std::shared_ptr; + using Ptr = std::shared_ptr; HSExtStreamID() = default; ~HSExtStreamID() = default; bool loadFromData(uint8_t *buf, size_t len) override; diff --git a/srt/Packet.cpp b/srt/Packet.cpp index 18ad279c..51bc5ab0 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -10,19 +10,13 @@ #include #endif // defined(_WIN32) - - #include #include "Util/logger.h" #include "Util/MD5.h" - #include "Packet.hpp" - - namespace SRT { - const size_t DataPacket::HEADER_SIZE; const size_t ControlPacket::HEADER_SIZE; const size_t HandshakePacket::HS_CONTENT_MIN_SIZE; @@ -38,7 +32,7 @@ bool DataPacket::isDataPacket(uint8_t *buf, size_t len) { return false; } -uint32_t DataPacket::getSocketID(uint8_t *buf, size_t len){ +uint32_t DataPacket::getSocketID(uint8_t *buf, size_t len) { uint8_t *ptr = buf; ptr += 12; return loadUint32(ptr); @@ -51,7 +45,7 @@ bool DataPacket::loadFromData(uint8_t *buf, size_t len) { } uint8_t *ptr = buf; f = ptr[0] >> 7; - packet_seq_number = loadUint32(ptr)&0x7fffffff; + packet_seq_number = loadUint32(ptr) & 0x7fffffff; ptr += 4; PP = ptr[0] >> 6; @@ -71,7 +65,8 @@ bool DataPacket::loadFromData(uint8_t *buf, size_t len) { _data->assign((char *)(buf), len); return true; } -bool DataPacket::storeToHeader(){ + +bool DataPacket::storeToHeader() { if (!_data || _data->size() < HEADER_SIZE) { WarnL << "data size less " << HEADER_SIZE; return false; @@ -101,6 +96,7 @@ bool DataPacket::storeToHeader(){ ptr += 4; return true; } + bool DataPacket::storeToData(uint8_t *buf, size_t len) { _data = BufferRaw::create(); _data->setCapacity(len + HEADER_SIZE); @@ -139,6 +135,7 @@ char *DataPacket::data() const { return nullptr; return _data->data(); } + size_t DataPacket::size() const { if (!_data) { return 0; @@ -151,6 +148,7 @@ char *DataPacket::payloadData() { return nullptr; return _data->data() + HEADER_SIZE; } + size_t DataPacket::payloadSize() { if (!_data) { return 0; @@ -158,8 +156,6 @@ size_t DataPacket::payloadSize() { return _data->size() - HEADER_SIZE; } - - bool ControlPacket::isControlPacket(uint8_t *buf, size_t len) { if (len < HEADER_SIZE) { WarnL << "data size" << len << " less " << HEADER_SIZE; @@ -199,6 +195,7 @@ bool ControlPacket::loadHeader() { ptr += 4; return true; } + bool ControlPacket::storeToHeader() { uint8_t *ptr = (uint8_t *)_data->data(); ptr[0] = 0x80; @@ -228,17 +225,20 @@ char *ControlPacket::data() const { return nullptr; return _data->data(); } + size_t ControlPacket::size() const { if (!_data) { return 0; } return _data->size(); } -uint32_t ControlPacket::getSocketID(uint8_t *buf, size_t len){ - return loadUint32(buf+12); + +uint32_t ControlPacket::getSocketID(uint8_t *buf, size_t len) { + return loadUint32(buf + 12); } + bool HandshakePacket::loadFromData(uint8_t *buf, size_t len) { - if(HEADER_SIZE+HS_CONTENT_MIN_SIZE > len){ + if (HEADER_SIZE + HS_CONTENT_MIN_SIZE > len) { ErrorL << "size too smalle " << encryption_field; return false; } @@ -282,79 +282,75 @@ bool HandshakePacket::loadFromData(uint8_t *buf, size_t len) { ErrorL << "not support encryption " << encryption_field; } - if(extension_field == 0){ + if (extension_field == 0) { return true; } - if(len == HEADER_SIZE+HS_CONTENT_MIN_SIZE){ - //ErrorL << "extension filed not exist " << extension_field; + if (len == HEADER_SIZE + HS_CONTENT_MIN_SIZE) { + // ErrorL << "extension filed not exist " << extension_field; return true; } - return loadExtMessage(ptr,len-HS_CONTENT_MIN_SIZE-HEADER_SIZE); + return loadExtMessage(ptr, len - HS_CONTENT_MIN_SIZE - HEADER_SIZE); } -bool HandshakePacket::loadExtMessage(uint8_t *buf,size_t len){ - uint8_t* ptr = buf; - ext_list.clear(); - uint16_t type; - uint16_t length; - HSExt::Ptr ext; - while(ptr(); - break; - case HSExt::SRT_CMD_SID: - ext = std::make_shared(); - break; + +bool HandshakePacket::loadExtMessage(uint8_t *buf, size_t len) { + uint8_t *ptr = buf; + ext_list.clear(); + uint16_t type; + uint16_t length; + HSExt::Ptr ext; + while (ptr < buf + len) { + type = loadUint16(ptr); + length = loadUint16(ptr + 2); + switch (type) { + case HSExt::SRT_CMD_HSREQ: + case HSExt::SRT_CMD_HSRSP: ext = std::make_shared(); break; + case HSExt::SRT_CMD_SID: ext = std::make_shared(); break; default: - WarnL<<"not support ext "<loadFromData(ptr,length*4+4)){ - ext_list.push_back(std::move(ext)); - }else{ - WarnL<<"parse HS EXT failed type="<assign((char*)buf,len); - + _data->assign((char *)buf, len); + return loadHeader(); } -bool KeepLivePacket::storeToData(){ +bool KeepLivePacket::storeToData() { control_type = ControlPacket::KEEPALIVE; sub_type = 0; @@ -506,22 +503,21 @@ bool NAKPacket::loadFromData(uint8_t *buf, size_t len) { return false; } _data = BufferRaw::create(); - _data->assign((char*)buf,len); + _data->assign((char *)buf, len); loadHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; - uint8_t* end = (uint8_t*)_data->data()+_data->size(); + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; + uint8_t *end = (uint8_t *)_data->data() + _data->size(); LostPair lost; - while (ptrsetCapacity(HEADER_SIZE+cif_size); - _data->setSize(HEADER_SIZE+cif_size); + _data->setCapacity(HEADER_SIZE + cif_size); + _data->setSize(HEADER_SIZE + cif_size); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; - for(auto it : lost_list){ - if(it.first+1 ==it.second){ - storeUint32(ptr,it.first); - ptr[0] = ptr[0]&0x7f; - ptr += 4; - }else{ - storeUint32(ptr,it.first); - ptr[0] |= 0x80; + for (auto it : lost_list) { + if (it.first + 1 == it.second) { + storeUint32(ptr, it.first); + ptr[0] = ptr[0] & 0x7f; + ptr += 4; + } else { + storeUint32(ptr, it.first); + ptr[0] |= 0x80; - storeUint32(ptr+4,it.second-1); - //ptr[4] = ptr[4]&0x7f; + storeUint32(ptr + 4, it.second - 1); + // ptr[4] = ptr[4]&0x7f; - ptr += 8; + ptr += 8; } } return true; } -size_t NAKPacket::getCIFSize(){ +size_t NAKPacket::getCIFSize() { size_t size = 0; - for(auto it : lost_list){ - if(it.first+1 ==it.second){ + for (auto it : lost_list) { + if (it.first + 1 == it.second) { size += 4; - }else{ + } else { size += 8; } } return size; } -std::string NAKPacket::dump(){ +std::string NAKPacket::dump() { _StrPrinter printer; for (auto it : lost_list) { - printer<<"[ "<assign((char*)buf,len); + _data->assign((char *)buf, len); loadHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; first_pkt_seq_num = loadUint32(ptr); ptr += 4; @@ -602,17 +598,17 @@ bool MsgDropReqPacket::storeToData() { control_type = DROPREQ; sub_type = 0; _data = BufferRaw::create(); - _data->setCapacity(HEADER_SIZE+8); - _data->setSize(HEADER_SIZE+8); + _data->setCapacity(HEADER_SIZE + 8); + _data->setSize(HEADER_SIZE + 8); storeToHeader(); - uint8_t* ptr = (uint8_t*)_data->data()+HEADER_SIZE; + uint8_t *ptr = (uint8_t *)_data->data() + HEADER_SIZE; - storeUint32(ptr,first_pkt_seq_num); + storeUint32(ptr, first_pkt_seq_num); ptr += 4; - storeUint32(ptr,last_pkt_seq_num); + storeUint32(ptr, last_pkt_seq_num); ptr += 4; return true; } diff --git a/srt/Packet.hpp b/srt/Packet.hpp index bab6df0c..668885da 100644 --- a/srt/Packet.hpp +++ b/srt/Packet.hpp @@ -5,6 +5,7 @@ #include #include "Network/Buffer.h" +#include "Network/sockutil.h" #include "Util/logger.h" #include "Common.hpp" @@ -171,7 +172,7 @@ class HandshakePacket : public ControlPacket { public: using Ptr = std::shared_ptr; enum { NO_ENCRYPTION = 0, AES_128 = 1, AES_196 = 2, AES_256 = 3 }; - static const size_t HS_CONTENT_MIN_SIZE = 48; + static const size_t HS_CONTENT_MIN_SIZE = 48; enum { HS_TYPE_DONE = 0xFFFFFFFD, HS_TYPE_AGREEMENT = 0xFFFFFFFE, @@ -181,18 +182,16 @@ public: }; enum { HS_EXT_FILED_HSREQ = 0x00000001, HS_EXT_FILED_KMREQ = 0x00000002, HS_EXT_FILED_CONFIG = 0x00000004 }; - - - + HandshakePacket() = default; ~HandshakePacket() = default; static bool isHandshakePacket(uint8_t *buf, size_t len); static uint32_t getHandshakeType(uint8_t *buf, size_t len); static uint32_t getSynCookie(uint8_t *buf, size_t len); - static uint32_t generateSynCookie(struct sockaddr_storage* addr,TimePoint ts,uint32_t current_cookie = 0, int correction = 0); + static uint32_t generateSynCookie(struct sockaddr_storage *addr, TimePoint ts, uint32_t current_cookie = 0, int correction = 0); - void assignPeerIP(struct sockaddr_storage* addr); + void assignPeerIP(struct sockaddr_storage *addr); ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; bool storeToData() override; @@ -209,8 +208,9 @@ public: uint8_t peer_ip_addr[16]; std::vector ext_list; + private: - bool loadExtMessage(uint8_t *buf,size_t len); + bool loadExtMessage(uint8_t *buf, size_t len); bool storeExtMessage(); size_t getExtSize(); }; @@ -229,13 +229,12 @@ private: Figure 12: Keep-Alive control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-keep-alive */ -class KeepLivePacket : public ControlPacket -{ +class KeepLivePacket : public ControlPacket { public: using Ptr = std::shared_ptr; KeepLivePacket() = default; ~KeepLivePacket() = default; - ///////ControlPacket override/////// + ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override; bool storeToData() override; }; @@ -265,11 +264,10 @@ An SRT NAK packet is formatted as follows: Figure 14: NAK control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-nak-control-packet */ -class NAKPacket : public ControlPacket -{ +class NAKPacket : public ControlPacket { public: using Ptr = std::shared_ptr; - using LostPair = std::pair; + using LostPair = std::pair; NAKPacket() = default; ~NAKPacket() = default; std::string dump(); @@ -278,11 +276,11 @@ public: bool storeToData() override; std::list lost_list; + private: size_t getCIFSize(); }; - /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -302,9 +300,8 @@ private: Figure 18: Drop Request control packet https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-message-drop-request */ -class MsgDropReqPacket : public ControlPacket -{ - public: +class MsgDropReqPacket : public ControlPacket { +public: using Ptr = std::shared_ptr; MsgDropReqPacket() = default; ~MsgDropReqPacket() = default; @@ -332,13 +329,13 @@ class MsgDropReqPacket : public ControlPacket https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html#name-shutdown */ -class ShutDownPacket : public ControlPacket -{ +class ShutDownPacket : public ControlPacket { public: using Ptr = std::shared_ptr; ShutDownPacket() = default; ~ShutDownPacket() = default; - ///////ControlPacket override/////// + + ///////ControlPacket override/////// bool loadFromData(uint8_t *buf, size_t len) override { if (len < HEADER_SIZE) { WarnL << "data size" << len << " less " << HEADER_SIZE; @@ -348,7 +345,7 @@ public: _data->assign((char *)buf, len); return loadHeader(); - }; + } bool storeToData() override { control_type = ControlPacket::SHUTDOWN; sub_type = 0; @@ -356,8 +353,9 @@ public: _data->setCapacity(HEADER_SIZE); _data->setSize(HEADER_SIZE); return storeToHeader(); - }; + } }; + } // namespace SRT #endif //ZLMEDIAKIT_SRT_PACKET_H \ No newline at end of file diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 7cfb4781..001585d1 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -2,80 +2,86 @@ namespace SRT { -#define MAX_SEQ 0x7fffffff -#define MAX_TS 0xffffffff -inline uint32_t genExpectedSeq(uint32_t seq){ +#define MAX_SEQ 0x7fffffff +#define MAX_TS 0xffffffff + +static inline uint32_t genExpectedSeq(uint32_t seq) { return MAX_SEQ & seq; } -inline bool isSeqEdge(uint32_t seq,uint32_t cap){ - if(seq >(MAX_SEQ - cap)){ + +static inline bool isSeqEdge(uint32_t seq, uint32_t cap) { + if (seq > (MAX_SEQ - cap)) { return true; } return false; } -inline bool isTSCycle(uint32_t first,uint32_t second){ +static inline bool isTSCycle(uint32_t first, uint32_t second) { uint32_t diff; - if(first>second){ + if (first > second) { diff = first - second; - }else{ + } else { diff = second - first; } - if(diff > (MAX_TS>>1)){ + if (diff > (MAX_TS >> 1)) { return true; - }else{ + } else { return false; } } -PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency) - : _pkt_expected_seq(init_seq) - , _pkt_cap(max_size) - , _pkt_lantency(lantency) { -} -void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt){ +PacketQueue::PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency) + : _pkt_cap(max_size) + , _pkt_latency(latency) + , _pkt_expected_seq(init_seq) {} + +void PacketQueue::tryInsertPkt(DataPacket::Ptr pkt) { if (_pkt_expected_seq <= pkt->packet_seq_number) { auto diff = pkt->packet_seq_number - _pkt_expected_seq; - if(diff >= (MAX_SEQ>>1)){ - TraceL << "drop packet too later for cycle "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + if (diff >= (MAX_SEQ >> 1)) { + TraceL << "drop packet too later for cycle " + << "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; return; - }else{ + } else { _pkt_map.emplace(pkt->packet_seq_number, pkt); } } else { auto diff = _pkt_expected_seq - pkt->packet_seq_number; - if(diff >= (MAX_SEQ>>1)){ - _pkt_map.emplace(pkt->packet_seq_number, pkt); - TraceL<<" cycle packet "<<"expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; - }else{ - //TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + if (diff >= (MAX_SEQ >> 1)) { + _pkt_map.emplace(pkt->packet_seq_number, pkt); + TraceL << " cycle packet " + << "expected seq=" << _pkt_expected_seq << " pkt seq=" << pkt->packet_seq_number; + } else { + // TraceL << "drop packet too later "<< "expected seq=" << _pkt_expected_seq << " pkt seq=" << + // pkt->packet_seq_number; } } } -bool PacketQueue::inputPacket(DataPacket::Ptr pkt,std::list& out) { + +bool PacketQueue::inputPacket(DataPacket::Ptr pkt, std::list &out) { tryInsertPkt(pkt); auto it = _pkt_map.find(_pkt_expected_seq); - while ( it != _pkt_map.end()) { + while (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); - _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq+1); + _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); it = _pkt_map.find(_pkt_expected_seq); } while (_pkt_map.size() > _pkt_cap) { // 防止回环 it = _pkt_map.find(_pkt_expected_seq); - if(it != _pkt_map.end()){ + if (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); } _pkt_expected_seq = genExpectedSeq(_pkt_expected_seq + 1); } - while (timeLantency() > _pkt_lantency) { + while (timeLatency() > _pkt_latency) { it = _pkt_map.find(_pkt_expected_seq); - if(it != _pkt_map.end()){ + if (it != _pkt_map.end()) { out.push_back(it->second); _pkt_map.erase(it); } @@ -85,22 +91,22 @@ bool PacketQueue::inputPacket(DataPacket::Ptr pkt,std::list& ou return true; } -bool PacketQueue::drop(uint32_t first, uint32_t last,std::list& out){ - uint32_t end = genExpectedSeq(last+1); +bool PacketQueue::drop(uint32_t first, uint32_t last, std::list &out) { + uint32_t end = genExpectedSeq(last + 1); decltype(_pkt_map.end()) it; - for(uint32_t i =_pkt_expected_seq;i< end;){ - it = _pkt_map.find(i); - if(it != _pkt_map.end()){ - out.push_back(it->second); - _pkt_map.erase(it); - } - i = genExpectedSeq(i+1); + for (uint32_t i = _pkt_expected_seq; i < end;) { + it = _pkt_map.find(i); + if (it != _pkt_map.end()) { + out.push_back(it->second); + _pkt_map.erase(it); + } + i = genExpectedSeq(i + 1); } _pkt_expected_seq = end; return true; } -uint32_t PacketQueue::timeLantency() { +uint32_t PacketQueue::timeLatency() { if (_pkt_map.empty()) { return 0; } @@ -108,15 +114,15 @@ uint32_t PacketQueue::timeLantency() { auto first = _pkt_map.begin()->second->timestamp; auto last = _pkt_map.rbegin()->second->timestamp; uint32_t dur; - if(last>first){ + if (last > first) { dur = last - first; - }else{ + } else { dur = first - last; } - if(dur > 0x80000000){ + if (dur > 0x80000000) { dur = MAX_TS - dur; - WarnL<<"cycle dur "< PacketQueue::getLostSeq() { std::list re; - if(_pkt_map.empty()){ + if (_pkt_map.empty()) { return re; } - - if(getExpectedSize() == getSize()){ + + if (getExpectedSize() == getSize()) { return re; } uint32_t end = 0; - uint32_t first,last; + uint32_t first, last; first = _pkt_map.begin()->second->packet_seq_number; last = _pkt_map.rbegin()->second->packet_seq_number; @@ -149,71 +155,76 @@ std::list PacketQueue::getLostSeq() { uint32_t i = _pkt_expected_seq; bool finish = true; - for(i = _pkt_expected_seq;i<=end;){ - if(_pkt_map.find(i) == _pkt_map.end()){ - if(finish){ + for (i = _pkt_expected_seq; i <= end;) { + if (_pkt_map.find(i) == _pkt_map.end()) { + if (finish) { finish = false; lost.first = i; - lost.second = i+1; - }else{ - lost.second = i+1; + lost.second = i + 1; + } else { + lost.second = i + 1; } - }else{ - if(!finish){ + } else { + if (!finish) { finish = true; re.push_back(lost); } } - i = genExpectedSeq(i+1); + i = genExpectedSeq(i + 1); } return re; } -size_t PacketQueue::getSize(){ +size_t PacketQueue::getSize() { return _pkt_map.size(); } size_t PacketQueue::getExpectedSize() { - if(_pkt_map.empty()){ + if (_pkt_map.empty()) { return 0; } uint32_t max = _pkt_map.rbegin()->first; uint32_t min = _pkt_map.begin()->first; - if((max-min)>=(MAX_SEQ>>1)){ - TraceL<<"cycle "<<"expected seq "<<_pkt_expected_seq<<" min "<= (MAX_SEQ >> 1)) { + TraceL << "cycle " + << "expected seq " << _pkt_expected_seq << " min " << min << " max " << max << " size " + << _pkt_map.size(); + return MAX_SEQ - _pkt_expected_seq + min + 1; + } else { + return max - _pkt_expected_seq + 1; } } -size_t PacketQueue::getAvailableBufferSize(){ - auto size = getExpectedSize(); - if(_pkt_cap > size){ +size_t PacketQueue::getAvailableBufferSize() { + auto size = getExpectedSize(); + if (_pkt_cap > size) { return _pkt_cap - size; } - if(_pkt_cap > _pkt_map.size()){ + if (_pkt_cap > _pkt_map.size()) { return _pkt_cap - _pkt_map.size(); } - WarnL<<" cap "<<_pkt_cap<<" expected size "<second->packet_seq_number; - printer<<" last:"<<_pkt_map.rbegin()->second->packet_seq_number; - printer<<" latency:"<second->packet_seq_number; + printer << " last:" << _pkt_map.rbegin()->second->packet_seq_number; + printer << " latency:" << timeLatency() / 1e3; + } + return std::move(printer); } + } // namespace SRT \ No newline at end of file diff --git a/srt/PacketQueue.hpp b/srt/PacketQueue.hpp index 66702d65..58d5f18a 100644 --- a/srt/PacketQueue.hpp +++ b/srt/PacketQueue.hpp @@ -3,8 +3,8 @@ #include "Packet.hpp" #include #include -#include #include +#include #include #include @@ -16,11 +16,11 @@ public: using Ptr = std::shared_ptr; using LostPair = std::pair; - PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t lantency); + PacketQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency); ~PacketQueue() = default; - bool inputPacket(DataPacket::Ptr pkt,std::list& out); + bool inputPacket(DataPacket::Ptr pkt, std::list &out); - uint32_t timeLantency(); + uint32_t timeLatency(); std::list getLostSeq(); size_t getSize(); @@ -28,18 +28,17 @@ public: size_t getAvailableBufferSize(); uint32_t getExpectedSeq(); - bool drop(uint32_t first, uint32_t last,std::list& out); - std::string dump(); + bool drop(uint32_t first, uint32_t last, std::list &out); + private: void tryInsertPkt(DataPacket::Ptr pkt); + private: - - std::map _pkt_map; - - uint32_t _pkt_expected_seq = 0; uint32_t _pkt_cap; - uint32_t _pkt_lantency; + uint32_t _pkt_latency; + uint32_t _pkt_expected_seq = 0; + std::map _pkt_map; }; } // namespace SRT diff --git a/srt/PacketSendQueue.cpp b/srt/PacketSendQueue.cpp index 9ea11aaf..654b1194 100644 --- a/srt/PacketSendQueue.cpp +++ b/srt/PacketSendQueue.cpp @@ -2,9 +2,10 @@ namespace SRT { -PacketSendQueue::PacketSendQueue(uint32_t max_size, uint32_t lantency) +PacketSendQueue::PacketSendQueue(uint32_t max_size, uint32_t latency) : _pkt_cap(max_size) - , _pkt_lantency(lantency) {} + , _pkt_latency(latency) {} + bool PacketSendQueue::drop(uint32_t num) { decltype(_pkt_cache.begin()) it; for (it = _pkt_cache.begin(); it != _pkt_cache.end(); ++it) { @@ -17,12 +18,13 @@ bool PacketSendQueue::drop(uint32_t num) { } return true; } + bool PacketSendQueue::inputPacket(DataPacket::Ptr pkt) { _pkt_cache.push_back(pkt); while (_pkt_cache.size() > _pkt_cap) { _pkt_cache.pop_front(); } - while (timeLantency() > _pkt_lantency) { + while (timeLatency() > _pkt_latency) { _pkt_cache.pop_front(); } return true; @@ -53,7 +55,7 @@ std::list PacketSendQueue::findPacketBySeq(uint32_t start, uint return re; } -uint32_t PacketSendQueue::timeLantency() { +uint32_t PacketSendQueue::timeLatency() { if (_pkt_cache.empty()) { return 0; } @@ -67,7 +69,7 @@ uint32_t PacketSendQueue::timeLantency() { dur = first - last; } if (dur > (0x01 << 31)) { - TraceL << "cycle timeLantency " << dur; + TraceL << "cycle timeLatency " << dur; dur = 0xffffffff - dur; } diff --git a/srt/PacketSendQueue.hpp b/srt/PacketSendQueue.hpp index 86fa86f1..43227aca 100644 --- a/srt/PacketSendQueue.hpp +++ b/srt/PacketSendQueue.hpp @@ -1,5 +1,6 @@ #ifndef ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H #define ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H + #include "Packet.hpp" #include #include @@ -7,23 +8,30 @@ #include #include #include + namespace SRT { + class PacketSendQueue { public: using Ptr = std::shared_ptr; using LostPair = std::pair; - PacketSendQueue(uint32_t max_size, uint32_t lantency); + + PacketSendQueue(uint32_t max_size, uint32_t latency); ~PacketSendQueue() = default; + bool drop(uint32_t num); bool inputPacket(DataPacket::Ptr pkt); - std::list findPacketBySeq(uint32_t start,uint32_t end); + std::list findPacketBySeq(uint32_t start, uint32_t end); + private: - uint32_t timeLantency(); + uint32_t timeLatency(); + private: - std::list _pkt_cache; uint32_t _pkt_cap; - uint32_t _pkt_lantency; + uint32_t _pkt_latency; + std::list _pkt_cache; }; + } // namespace SRT #endif // ZLMEDIAKIT_SRT_PACKET_SEND_QUEUE_H \ No newline at end of file diff --git a/srt/SrtSession.cpp b/srt/SrtSession.cpp index fe8cfc13..d62cb7cd 100644 --- a/srt/SrtSession.cpp +++ b/srt/SrtSession.cpp @@ -10,10 +10,10 @@ using namespace mediakit; SrtSession::SrtSession(const Socket::Ptr &sock) : UdpSession(sock) { socklen_t addr_len = sizeof(_peer_addr); - memset(&_peer_addr,0,addr_len); - //TraceL<<"before addr len "<rawFD(), (struct sockaddr *)&_peer_addr, &addr_len); - //TraceL<<"after addr len "<data(); + uint8_t *data = (uint8_t *)buffer->data(); size_t size = buffer->size(); - if(DataPacket::isDataPacket(data,size)){ - uint32_t socket_id = DataPacket::getSocketID(data,size); + if (DataPacket::isDataPacket(data, size)) { + uint32_t socket_id = DataPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); return trans ? trans->getPoller() : nullptr; } - if(HandshakePacket::isHandshakePacket(data,size)){ - auto type = HandshakePacket::getHandshakeType(data,size); - if(type == HandshakePacket::HS_TYPE_INDUCTION){ + if (HandshakePacket::isHandshakePacket(data, size)) { + auto type = HandshakePacket::getHandshakeType(data, size); + if (type == HandshakePacket::HS_TYPE_INDUCTION) { // 握手第一阶段 return nullptr; - }else if(type == HandshakePacket::HS_TYPE_CONCLUSION){ + } else if (type == HandshakePacket::HS_TYPE_CONCLUSION) { // 握手第二阶段 - uint32_t sync_cookie = HandshakePacket::getSynCookie(data,size); + uint32_t sync_cookie = HandshakePacket::getSynCookie(data, size); auto trans = SrtTransportManager::Instance().getHandshakeItem(std::to_string(sync_cookie)); return trans ? trans->getPoller() : nullptr; - }else{ - WarnL<<" not reach there"; + } else { + WarnL << " not reach there"; } - }else{ - uint32_t socket_id = ControlPacket::getSocketID(data,size); + } else { + uint32_t socket_id = ControlPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); return trans ? trans->getPoller() : nullptr; } return nullptr; } -void SrtSession::attachServer(const toolkit::Server &server){ - SockUtil::setRecvBuf(getSock()->rawFD(),1024 * 1024); + +void SrtSession::attachServer(const toolkit::Server &server) { + SockUtil::setRecvBuf(getSock()->rawFD(), 1024 * 1024); } + void SrtSession::onRecv(const Buffer::Ptr &buffer) { - uint8_t* data = (uint8_t*)buffer->data(); + uint8_t *data = (uint8_t *)buffer->data(); size_t size = buffer->size(); if (_find_transport) { @@ -64,10 +66,10 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { if (DataPacket::isDataPacket(data, size)) { uint32_t socket_id = DataPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); - if(trans){ + if (trans) { _transport = std::move(trans); - }else{ - WarnL<<" data packet not find transport "; + } else { + WarnL << " data packet not find transport "; } } @@ -92,24 +94,24 @@ void SrtSession::onRecv(const Buffer::Ptr &buffer) { } else { uint32_t socket_id = ControlPacket::getSocketID(data, size); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socket_id)); - if(trans){ + if (trans) { _transport = std::move(trans); - }else{ + } else { WarnL << " not find transport"; } } - if(_transport){ + if (_transport) { _transport->setSession(shared_from_this()); } InfoP(this); } _ticker.resetTime(); - if(_transport){ - _transport->inputSockData(data,size,&_peer_addr); - }else{ - //WarnL<< "ingore data"; + if (_transport) { + _transport->inputSockData(data, size, &_peer_addr); + } else { + // WarnL<< "ingore data"; } } @@ -122,18 +124,20 @@ void SrtSession::onError(const SockException &err) { if (!_transport) { return; } - + // 防止互相引用导致不释放 auto transport = std::move(_transport); - getPoller()->async([transport,err] { - //延时减引用,防止使用transport对象时,销毁对象 - transport->onShutdown(err); - }, false); + getPoller()->async( + [transport, err] { + //延时减引用,防止使用transport对象时,销毁对象 + transport->onShutdown(err); + }, + false); } void SrtSession::onManager() { GET_CONFIG(float, timeoutSec, kTimeOutSec); - if (_ticker.elapsedTime() > timeoutSec*1000) { + if (_ticker.elapsedTime() > timeoutSec * 1000) { shutdown(SockException(Err_timeout, "srt connection timeout")); return; } diff --git a/srt/SrtSession.hpp b/srt/SrtSession.hpp index 401aae3c..342a4a91 100644 --- a/srt/SrtSession.hpp +++ b/srt/SrtSession.hpp @@ -24,8 +24,7 @@ private: Ticker _ticker; struct sockaddr_storage _peer_addr; SrtTransport::Ptr _transport; - }; } // namespace SRT -#endif //ZLMEDIAKIT_SRT_SESSION_H \ No newline at end of file +#endif // ZLMEDIAKIT_SRT_SESSION_H \ No newline at end of file diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index e7a84bf3..cce3e910 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -1,32 +1,33 @@ #include +#include "Ack.hpp" +#include "Packet.hpp" +#include "SrtTransport.hpp" #include "Util/onceToken.h" -#include "SrtTransport.hpp" -#include "Packet.hpp" -#include "Ack.hpp" namespace SRT { #define SRT_FIELD "srt." -//srt 超时时间 -const std::string kTimeOutSec = SRT_FIELD"timeoutSec"; -//srt 单端口udp服务器 -const std::string kPort = SRT_FIELD"port"; +// srt 超时时间 +const std::string kTimeOutSec = SRT_FIELD "timeoutSec"; +// srt 单端口udp服务器 +const std::string kPort = SRT_FIELD "port"; +const std::string kLatencyMul = SRT_FIELD "latencyMul"; -const std::string kLantencyMul = SRT_FIELD"lantencyMul"; +static std::atomic s_srt_socket_id_generate { 125 }; -static std::atomic s_srt_socket_id_generate{125}; //////////// SrtTransport ////////////////////////// SrtTransport::SrtTransport(const EventPoller::Ptr &poller) : _poller(poller) { - _start_timestamp = SteadyClock::now(); - _socket_id = s_srt_socket_id_generate.fetch_add(1);\ - _pkt_recv_rate_context = std::make_shared(_start_timestamp); - _recv_rate_context = std::make_shared(_start_timestamp); - _estimated_link_capacity_context = std::make_shared(_start_timestamp); - } - -SrtTransport::~SrtTransport(){ - TraceL<<" "; + _start_timestamp = SteadyClock::now(); + _socket_id = s_srt_socket_id_generate.fetch_add(1); + _pkt_recv_rate_context = std::make_shared(_start_timestamp); + _recv_rate_context = std::make_shared(_start_timestamp); + _estimated_link_capacity_context = std::make_shared(_start_timestamp); } + +SrtTransport::~SrtTransport() { + TraceL << " "; +} + const EventPoller::Ptr &SrtTransport::getPoller() const { return _poller; } @@ -40,24 +41,25 @@ void SrtTransport::setSession(Session::Ptr session) { } _selected_session = session; } + const Session::Ptr &SrtTransport::getSession() const { return _selected_session; } -void SrtTransport::switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr){ +void SrtTransport::switchToOtherTransport(uint8_t *buf, int len, uint32_t socketid, struct sockaddr_storage *addr) { BufferRaw::Ptr tmp = BufferRaw::create(); struct sockaddr_storage tmp_addr = *addr; - tmp->assign((char*)buf,len); + tmp->assign((char *)buf, len); auto trans = SrtTransportManager::Instance().getItem(std::to_string(socketid)); - if(trans){ - trans->getPoller()->async([tmp,tmp_addr,trans]{ - trans->inputSockData((uint8_t*)tmp->data(),tmp->size(),(struct sockaddr_storage*)&tmp_addr); + if (trans) { + trans->getPoller()->async([tmp, tmp_addr, trans] { + trans->inputSockData((uint8_t *)tmp->data(), tmp->size(), (struct sockaddr_storage *)&tmp_addr); }); } } void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr) { - using srt_control_handler = void (SrtTransport::*)(uint8_t* buf,int len,struct sockaddr_storage *addr); + using srt_control_handler = void (SrtTransport::*)(uint8_t * buf, int len, struct sockaddr_storage *addr); static std::unordered_map s_control_functions; static onceToken token([]() { s_control_functions.emplace(ControlPacket::HANDSHAKE, &SrtTransport::handleHandshake); @@ -74,23 +76,23 @@ void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage _now = SteadyClock::now(); // 处理srt数据 if (DataPacket::isDataPacket(buf, len)) { - uint32_t socketId = DataPacket::getSocketID(buf,len); - if(socketId == _socket_id){ + uint32_t socketId = DataPacket::getSocketID(buf, len); + if (socketId == _socket_id) { _pkt_recv_rate_context->inputPacket(_now); _estimated_link_capacity_context->inputPacket(_now); _recv_rate_context->inputPacket(_now, len); handleDataPacket(buf, len, addr); - }else{ - switchToOtherTransport(buf,len,socketId,addr); + } else { + switchToOtherTransport(buf, len, socketId, addr); } } else { if (ControlPacket::isControlPacket(buf, len)) { - uint32_t socketId = ControlPacket::getSocketID(buf,len); - uint16_t type = ControlPacket::getControlType(buf,len); - if(type != ControlPacket::HANDSHAKE && socketId != _socket_id && _socket_id != 0){ + uint32_t socketId = ControlPacket::getSocketID(buf, len); + uint16_t type = ControlPacket::getControlType(buf, len); + if (type != ControlPacket::HANDSHAKE && socketId != _socket_id && _socket_id != 0) { // socket id not same - switchToOtherTransport(buf,len,socketId,addr); + switchToOtherTransport(buf, len, socketId, addr); return; } _pkt_recv_rate_context->inputPacket(_now); @@ -99,10 +101,10 @@ void SrtTransport::inputSockData(uint8_t *buf, int len, struct sockaddr_storage auto it = s_control_functions.find(type); if (it == s_control_functions.end()) { - WarnL<<" not support type ignore" << ControlPacket::getControlType(buf,len); + WarnL << " not support type ignore" << ControlPacket::getControlType(buf, len); return; - }else{ - (this->*(it->second))(buf,len,addr); + } else { + (this->*(it->second))(buf, len, addr); } } else { // not reach @@ -119,7 +121,7 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd sendControlPacket(_handleshake_res, true); return; } - _induction_ts = _now; + _induction_ts = _now; _start_timestamp = _now; _init_seq_number = pkt.initial_packet_sequence_number; _max_window_size = pkt.max_flow_window_size; @@ -146,9 +148,10 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd registerSelfHandshake(); sendControlPacket(res, true); } + void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockaddr_storage *addr) { - if(!_handleshake_res){ - ErrorL<<"must Induction Phase for handleshake "; + if (!_handleshake_res) { + ErrorL << "must Induction Phase for handleshake "; return; } @@ -157,21 +160,21 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad HSExtMessage::Ptr req; HSExtStreamID::Ptr sid; uint32_t srt_flag = 0xbf; - uint16_t delay = DurationCountMicroseconds(_now - _induction_ts)*getLantencyMul()/1000; + uint16_t delay = DurationCountMicroseconds(_now - _induction_ts) * getLatencyMul() / 1000; for (auto ext : pkt.ext_list) { - //TraceL << getIdentifier() << " ext " << ext->dump(); + // TraceL << getIdentifier() << " ext " << ext->dump(); if (!req) { req = std::dynamic_pointer_cast(ext); } - if(!sid){ + if (!sid) { sid = std::dynamic_pointer_cast(ext); } } - if(sid){ + if (sid) { _stream_id = sid->streamid; } - if(req){ + if (req) { srt_flag = req->srt_flag; delay = delay <= req->recv_tsbpd_delay ? req->recv_tsbpd_delay : delay; } @@ -200,167 +203,174 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad unregisterSelfHandshake(); registerSelf(); sendControlPacket(res, true); - TraceL<<" buf size = "<max_flow_window_size<<" init seq ="<<_init_seq_number<<" lantency="<(res->max_flow_window_size,_init_seq_number, delay*1e3); - _send_buf = std::make_shared(res->max_flow_window_size, delay*1e3); + TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number << " latency=" << delay; + _recv_buf = std::make_shared(res->max_flow_window_size, _init_seq_number, delay * 1e3); + _send_buf = std::make_shared(res->max_flow_window_size, delay * 1e3); _send_packet_seq_number = _init_seq_number; _buf_delay = delay; - onHandShakeFinished(_stream_id,addr); + onHandShakeFinished(_stream_id, addr); } else { TraceL << getIdentifier() << " CONCLUSION handle repeate "; sendControlPacket(_handleshake_res, true); } _last_ack_pkt_seq_num = _init_seq_number; } -void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr){ - HandshakePacket pkt; - assert(pkt.loadFromData(buf,len)); - if(pkt.handshake_type == HandshakePacket::HS_TYPE_INDUCTION){ - handleHandshakeInduction(pkt,addr); - }else if(pkt.handshake_type == HandshakePacket::HS_TYPE_CONCLUSION){ - handleHandshakeConclusion(pkt,addr); - }else{ - WarnL<<" not support handshake type = "<< pkt.handshake_type; +void SrtTransport::handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr) { + HandshakePacket pkt; + assert(pkt.loadFromData(buf, len)); + + if (pkt.handshake_type == HandshakePacket::HS_TYPE_INDUCTION) { + handleHandshakeInduction(pkt, addr); + } else if (pkt.handshake_type == HandshakePacket::HS_TYPE_CONCLUSION) { + handleHandshakeConclusion(pkt, addr); + } else { + WarnL << " not support handshake type = " << pkt.handshake_type; } _ack_ticker.resetTime(_now); _nak_ticker.resetTime(_now); } -void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; + +void SrtTransport::handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; sendKeepLivePacket(); } - void SrtTransport::sendKeepLivePacket(){ +void SrtTransport::sendKeepLivePacket() { KeepLivePacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->storeToData(); - sendControlPacket(pkt,true); - } -void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; + sendControlPacket(pkt, true); +} + +void SrtTransport::handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; ACKPacket ack; - if(!ack.loadFromData(buf,len)){ + if (!ack.loadFromData(buf, len)) { return; } ACKACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = ack.ack_number; pkt->storeToData(); _send_buf->drop(ack.last_ack_pkt_seq_number); - sendControlPacket(pkt,true); - //TraceL<<"ack number "<(); pkt->dst_socket_id = _peer_socket_id; - pkt->timestamp = DurationCountMicroseconds(_now -_start_timestamp); + pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->first_pkt_seq_num = first; pkt->last_pkt_seq_num = last; pkt->storeToData(); - sendControlPacket(pkt,true); + sendControlPacket(pkt, true); } -void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; + +void SrtTransport::handleNAK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; NAKPacket pkt; - pkt.loadFromData(buf,len); + pkt.loadFromData(buf, len); bool empty = false; bool flush = false; - for(auto it : pkt.lost_list){ - if(pkt.lost_list.back() == it){ + for (auto it : pkt.lost_list) { + if (pkt.lost_list.back() == it) { flush = true; } empty = true; - auto re_list = _send_buf->findPacketBySeq(it.first,it.second-1); - for(auto pkt : re_list){ + auto re_list = _send_buf->findPacketBySeq(it.first, it.second - 1); + for (auto pkt : re_list) { pkt->R = 1; pkt->storeToHeader(); - sendPacket(pkt,flush); + sendPacket(pkt, flush); empty = false; } - if(empty){ - sendMsgDropReq(it.first,it.second-1); + if (empty) { + sendMsgDropReq(it.first, it.second - 1); } } } -void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr){ + +void SrtTransport::handleCongestionWarning(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } -void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr){ + +void SrtTransport::handleShutDown(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; onShutdown(SockException(Err_shutdown, "peer close connection")); } -void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr){ + +void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage *addr) { MsgDropReqPacket pkt; - pkt.loadFromData(buf,len); + pkt.loadFromData(buf, len); std::list list; - //TraceL<<"drop "<drop(pkt.first_pkt_seq_num,pkt.last_pkt_seq_num,list); - if(list.empty()){ + // TraceL<<"drop "<drop(pkt.first_pkt_seq_num, pkt.last_pkt_seq_num, list); + if (list.empty()) { return; } - for(auto data : list){ + for (auto data : list) { onSRTData(std::move(data)); } - auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval <= 20*1000){ - nak_interval = 20*1000; + auto nak_interval = (_rtt + _rtt_variance * 4) / 2; + if (nak_interval <= 20 * 1000) { + nak_interval = 20 * 1000; } - if(_nak_ticker.elapsedTime(_now)>nak_interval){ + if (_nak_ticker.elapsedTime(_now) > nak_interval) { auto lost = _recv_buf->getLostSeq(); - if(!lost.empty()){ - sendNAKPacket(lost); + if (!lost.empty()) { + sendNAKPacket(lost); } _nak_ticker.resetTime(_now); } - if(_ack_ticker.elapsedTime(_now)>10*1000){ + if (_ack_ticker.elapsedTime(_now) > 10 * 1000) { _light_ack_pkt_count = 0; _ack_ticker.resetTime(_now); - // send a ack per 10 ms for receiver + // send a ack per 10 ms for receiver sendACKPacket(); - }else{ - if(_light_ack_pkt_count >= 64){ + } else { + if (_light_ack_pkt_count >= 64) { // for high bitrate stream send light ack - // TODO + // TODO sendLightACKPacket(); - TraceL<<"send light ack"; + TraceL << "send light ack"; } _light_ack_pkt_count = 0; } _light_ack_pkt_count++; - } -void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr){ + +void SrtTransport::handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } -void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr){ - //TraceL; +void SrtTransport::handleACKACK(uint8_t *buf, int len, struct sockaddr_storage *addr) { + // TraceL; ACKACKPacket::Ptr pkt = std::make_shared(); - pkt->loadFromData(buf,len); + pkt->loadFromData(buf, len); uint32_t rtt = DurationCountMicroseconds(_now - _ack_send_timestamp[pkt->ack_number]); - _rtt_variance = (3*_rtt_variance+abs((long)_rtt - (long)rtt))/4; - _rtt = (7*rtt+_rtt)/8; + _rtt_variance = (3 * _rtt_variance + abs((long)_rtt - (long)rtt)) / 4; + _rtt = (7 * rtt + _rtt) / 8; - - //TraceL<<" rtt:"<<_rtt<<" rtt variance:"<<_rtt_variance; + // TraceL<<" rtt:"<<_rtt<<" rtt variance:"<<_rtt_variance; _ack_send_timestamp.erase(pkt->ack_number); } -void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr){ +void SrtTransport::handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr) { TraceL; } void SrtTransport::sendACKPacket() { - ACKPacket::Ptr pkt=std::make_shared(); + ACKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = ++_ack_number_count; @@ -373,13 +383,14 @@ void SrtTransport::sendACKPacket() { pkt->recv_rate = _recv_rate_context->getRecvRate(); pkt->storeToData(); _ack_send_timestamp[pkt->ack_number] = _now; - _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; - sendControlPacket(pkt,true); - //TraceL<<"send ack "<dump(); + _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; + sendControlPacket(pkt, true); + // TraceL<<"send ack "<dump(); } + void SrtTransport::sendLightACKPacket() { - ACKPacket::Ptr pkt=std::make_shared(); - + ACKPacket::Ptr pkt = std::make_shared(); + pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->ack_number = 0; @@ -392,11 +403,11 @@ void SrtTransport::sendLightACKPacket() { pkt->recv_rate = 0; pkt->storeToData(); _last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number; - sendControlPacket(pkt,true); - TraceL<<"send ack "<dump(); + sendControlPacket(pkt, true); + TraceL << "send ack " << pkt->dump(); } -void SrtTransport::sendNAKPacket(std::list& lost_list){ +void SrtTransport::sendNAKPacket(std::list &lost_list) { NAKPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; @@ -405,112 +416,118 @@ void SrtTransport::sendNAKPacket(std::list& lost_list){ pkt->storeToData(); - //TraceL<<"send NAK "<dump(); - sendControlPacket(pkt,true); + // TraceL<<"send NAK "<dump(); + sendControlPacket(pkt, true); } -void SrtTransport::sendShutDown(){ +void SrtTransport::sendShutDown() { ShutDownPacket::Ptr pkt = std::make_shared(); pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(_now - _start_timestamp); pkt->storeToData(); - sendControlPacket(pkt,true); + sendControlPacket(pkt, true); } -void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr){ + +void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr) { DataPacket::Ptr pkt = std::make_shared(); - pkt->loadFromData(buf,len); + pkt->loadFromData(buf, len); pkt->get_ts = _now; std::list list; //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; - _recv_buf->inputPacket(pkt,list); - for(auto data : list){ + _recv_buf->inputPacket(pkt, list); + for (auto data : list) { onSRTData(std::move(data)); } - auto nak_interval = (_rtt+_rtt_variance*4)/2; - if(nak_interval <= 20*1000){ - nak_interval = 20*1000; + auto nak_interval = (_rtt + _rtt_variance * 4) / 2; + if (nak_interval <= 20 * 1000) { + nak_interval = 20 * 1000; } - if(list.empty()){ - //TraceL<<_recv_buf->dump()<<" nake interval:"<dump()<<" nake interval:"<nak_interval){ + if (_nak_ticker.elapsedTime(_now) > nak_interval) { auto lost = _recv_buf->getLostSeq(); - if(!lost.empty()){ - sendNAKPacket(lost); - //TraceL<<"send NAK"; - }else{ - //TraceL<<"lost is empty"; + if (!lost.empty()) { + sendNAKPacket(lost); + // TraceL<<"send NAK"; + } else { + // TraceL<<"lost is empty"; } _nak_ticker.resetTime(_now); } - if(_ack_ticker.elapsedTime(_now)>10*1000){ + if (_ack_ticker.elapsedTime(_now) > 10 * 1000) { _light_ack_pkt_count = 0; _ack_ticker.resetTime(_now); - // send a ack per 10 ms for receiver + // send a ack per 10 ms for receiver sendACKPacket(); - }else{ - if(_light_ack_pkt_count >= 64){ + } else { + if (_light_ack_pkt_count >= 64) { // for high bitrate stream send light ack - // TODO + // TODO sendLightACKPacket(); - TraceL<<"send light ack"; + TraceL << "send light ack"; } _light_ack_pkt_count = 0; } _light_ack_pkt_count++; - //bufCheckInterval(); + // bufCheckInterval(); } -void SrtTransport::sendDataPacket(DataPacket::Ptr pkt,char* buf,int len, bool flush) { - pkt->storeToData((uint8_t*)buf,len); - sendPacket(pkt,flush); +void SrtTransport::sendDataPacket(DataPacket::Ptr pkt, char *buf, int len, bool flush) { + pkt->storeToData((uint8_t *)buf, len); + sendPacket(pkt, flush); _send_buf->inputPacket(pkt); } -void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { - sendPacket(pkt,flush); + +void SrtTransport::sendControlPacket(ControlPacket::Ptr pkt, bool flush) { + sendPacket(pkt, flush); } -void SrtTransport::sendPacket(Buffer::Ptr pkt,bool flush){ - if(_selected_session){ - auto tmp = _packet_pool.obtain2(); - tmp->assign(pkt->data(),pkt->size()); - _selected_session->setSendFlushFlag(flush); - _selected_session->send(std::move(tmp)); - }else{ - WarnL<<"not reach this"; + +void SrtTransport::sendPacket(Buffer::Ptr pkt, bool flush) { + if (_selected_session) { + auto tmp = _packet_pool.obtain2(); + tmp->assign(pkt->data(), pkt->size()); + _selected_session->setSendFlushFlag(flush); + _selected_session->send(std::move(tmp)); + } else { + WarnL << "not reach this"; } } -std::string SrtTransport::getIdentifier(){ + +std::string SrtTransport::getIdentifier() { return _selected_session ? _selected_session->getIdentifier() : ""; } -void SrtTransport::registerSelfHandshake() { - SrtTransportManager::Instance().addHandshakeItem(std::to_string(_sync_cookie),shared_from_this()); +void SrtTransport::registerSelfHandshake() { + SrtTransportManager::Instance().addHandshakeItem(std::to_string(_sync_cookie), shared_from_this()); } -void SrtTransport::unregisterSelfHandshake() { - if(_sync_cookie == 0){ + +void SrtTransport::unregisterSelfHandshake() { + if (_sync_cookie == 0) { return; } SrtTransportManager::Instance().removeHandshakeItem(std::to_string(_sync_cookie)); } void SrtTransport::registerSelf() { - if(_socket_id == 0){ + if (_socket_id == 0) { return; } - SrtTransportManager::Instance().addItem(std::to_string(_socket_id),shared_from_this()); - + SrtTransportManager::Instance().addItem(std::to_string(_socket_id), shared_from_this()); } -void SrtTransport::unregisterSelf() { + +void SrtTransport::unregisterSelf() { SrtTransportManager::Instance().removeItem(std::to_string(_socket_id)); } -void SrtTransport::onShutdown(const SockException &ex){ +void SrtTransport::onShutdown(const SockException &ex) { sendShutDown(); WarnL << ex.what(); unregisterSelfHandshake(); @@ -522,23 +539,25 @@ void SrtTransport::onShutdown(const SockException &ex){ } } } -size_t SrtTransport::getPayloadSize(){ - size_t ret = (_mtu - 28 -16)/188*188; + +size_t SrtTransport::getPayloadSize() { + size_t ret = (_mtu - 28 - 16) / 188 * 188; return ret; } -void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ - //TraceL; + +void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush) { + // TraceL; DataPacket::Ptr pkt; size_t payloadSize = getPayloadSize(); - size_t size = buffer->size(); - char* ptr = buffer->data(); - char* end = buffer->data()+size; + size_t size = buffer->size(); + char *ptr = buffer->data(); + char *end = buffer->data() + size; - while(ptr < end && size >=payloadSize){ + while (ptr < end && size >= payloadSize) { pkt = std::make_shared(); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; - _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; + pkt->packet_seq_number = _send_packet_seq_number & 0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number + 1) & 0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; @@ -546,16 +565,16 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ pkt->msg_number = _send_msg_number++; pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); - sendDataPacket(pkt,ptr,(int)payloadSize,flush); + sendDataPacket(pkt, ptr, (int)payloadSize, flush); ptr += payloadSize; size -= payloadSize; } - if(size >0 && ptr 0 && ptr < end) { pkt = std::make_shared(); pkt->f = 0; - pkt->packet_seq_number = _send_packet_seq_number&0x7fffffff; - _send_packet_seq_number = (_send_packet_seq_number+1)&0x7fffffff; + pkt->packet_seq_number = _send_packet_seq_number & 0x7fffffff; + _send_packet_seq_number = (_send_packet_seq_number + 1) & 0x7fffffff; pkt->PP = 3; pkt->O = 0; pkt->KK = 0; @@ -563,11 +582,12 @@ void SrtTransport::onSendTSData(const Buffer::Ptr &buffer, bool flush){ pkt->msg_number = _send_msg_number++; pkt->dst_socket_id = _peer_socket_id; pkt->timestamp = DurationCountMicroseconds(SteadyClock::now() - _start_timestamp); - sendDataPacket(pkt,ptr,(int)size,flush); + sendDataPacket(pkt, ptr, (int)size, flush); } - } + //////////// SrtTransportManager ////////////////////////// + SrtTransportManager &SrtTransportManager::Instance() { static SrtTransportManager s_instance; return s_instance; @@ -599,10 +619,12 @@ void SrtTransportManager::addHandshakeItem(const std::string &key, const SrtTran std::lock_guard lck(_handshake_mtx); _handshake_map[key] = ptr; } + void SrtTransportManager::removeHandshakeItem(const std::string &key) { - std::lock_guard lck(_handshake_mtx); + std::lock_guard lck(_handshake_mtx); _handshake_map.erase(key); } + SrtTransport::Ptr SrtTransportManager::getHandshakeItem(const std::string &key) { if (key.empty()) { return nullptr; @@ -615,5 +637,4 @@ SrtTransport::Ptr SrtTransportManager::getHandshakeItem(const std::string &key) return it->second.lock(); } - } // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index c055dd62..49d05677 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -1,10 +1,10 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_H #define ZLMEDIAKIT_SRT_TRANSPORT_H -#include +#include #include #include -#include +#include #include "Network/Session.h" #include "Poller/EventPoller.h" @@ -17,11 +17,12 @@ #include "Statistic.hpp" namespace SRT { + using namespace toolkit; extern const std::string kPort; extern const std::string kTimeOutSec; -extern const std::string kLantencyMul; +extern const std::string kLatencyMul; class SrtTransport : public std::enable_shared_from_this { public: @@ -33,6 +34,7 @@ public: const EventPoller::Ptr &getPoller() const; void setSession(Session::Ptr session); const Session::Ptr &getSession() const; + /** * socket收到udp数据 * @param buf 数据指针 @@ -43,26 +45,26 @@ public: virtual void onSendTSData(const Buffer::Ptr &buffer, bool flush); std::string getIdentifier(); - - void unregisterSelfHandshake(); void unregisterSelf(); + void unregisterSelfHandshake(); + protected: - virtual void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr){}; - virtual void onSRTData(DataPacket::Ptr pkt){}; + virtual bool isPusher() { return true; }; + virtual void onSRTData(DataPacket::Ptr pkt) {}; virtual void onShutdown(const SockException &ex); - virtual bool isPusher(){ - return true; - }; + virtual void onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) {}; + virtual void sendPacket(Buffer::Ptr pkt, bool flush = true); + virtual int getLatencyMul() { return 4; }; private: - void registerSelfHandshake(); void registerSelf(); + void registerSelfHandshake(); - void switchToOtherTransport(uint8_t *buf, int len,uint32_t socketid, struct sockaddr_storage *addr); + void switchToOtherTransport(uint8_t *buf, int len, uint32_t socketid, struct sockaddr_storage *addr); void handleHandshake(uint8_t *buf, int len, struct sockaddr_storage *addr); - void handleHandshakeInduction(HandshakePacket& pkt,struct sockaddr_storage *addr); - void handleHandshakeConclusion(HandshakePacket& pkt,struct sockaddr_storage *addr); + void handleHandshakeInduction(HandshakePacket &pkt, struct sockaddr_storage *addr); + void handleHandshakeConclusion(HandshakePacket &pkt, struct sockaddr_storage *addr); void handleKeeplive(uint8_t *buf, int len, struct sockaddr_storage *addr); void handleACK(uint8_t *buf, int len, struct sockaddr_storage *addr); @@ -74,27 +76,25 @@ private: void handleUserDefinedType(uint8_t *buf, int len, struct sockaddr_storage *addr); void handlePeerError(uint8_t *buf, int len, struct sockaddr_storage *addr); void handleDataPacket(uint8_t *buf, int len, struct sockaddr_storage *addr); - - void sendNAKPacket(std::list& lost_list); + + void sendNAKPacket(std::list &lost_list); void sendACKPacket(); void sendLightACKPacket(); void sendKeepLivePacket(); void sendShutDown(); - void sendMsgDropReq(uint32_t first ,uint32_t last); + void sendMsgDropReq(uint32_t first, uint32_t last); size_t getPayloadSize(); + protected: - void sendDataPacket(DataPacket::Ptr pkt,char* buf,int len,bool flush = false); - void sendControlPacket(ControlPacket::Ptr pkt,bool flush = true); - virtual void sendPacket(Buffer::Ptr pkt,bool flush = true); - virtual int getLantencyMul(){ - return 4; - }; + void sendDataPacket(DataPacket::Ptr pkt, char *buf, int len, bool flush = false); + void sendControlPacket(ControlPacket::Ptr pkt, bool flush = true); + private: //当前选中的udp链接 Session::Ptr _selected_session; //链接迁移前后使用过的udp链接 - std::unordered_map > _history_sessions; + std::unordered_map> _history_sessions; EventPoller::Ptr _poller; @@ -109,7 +109,7 @@ private: uint32_t _mtu = 1500; uint32_t _max_window_size = 8192; - uint32_t _init_seq_number = 0; + uint32_t _init_seq_number = 0; std::string _stream_id; uint32_t _sync_cookie = 0; @@ -119,13 +119,13 @@ private: PacketSendQueue::Ptr _send_buf; uint32_t _buf_delay = 120; PacketQueue::Ptr _recv_buf; - uint32_t _rtt = 100*1000; - uint32_t _rtt_variance =50*1000; + uint32_t _rtt = 100 * 1000; + uint32_t _rtt_variance = 50 * 1000; uint32_t _light_ack_pkt_count = 0; uint32_t _ack_number_count = 0; uint32_t _last_ack_pkt_seq_num = 0; UTicker _ack_ticker; - std::map _ack_send_timestamp; + std::map _ack_send_timestamp; std::shared_ptr _pkt_recv_rate_context; std::shared_ptr _estimated_link_capacity_context; @@ -137,7 +137,6 @@ private: HandshakePacket::Ptr _handleshake_res; ResourcePool _packet_pool; - }; class SrtTransportManager { @@ -150,6 +149,7 @@ public: void addHandshakeItem(const std::string &key, const SrtTransport::Ptr &ptr); void removeHandshakeItem(const std::string &key); SrtTransport::Ptr getHandshakeItem(const std::string &key); + private: SrtTransportManager() = default; diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 9425e2e7..a838a175 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -4,8 +4,7 @@ #include "SrtTransportImp.hpp" namespace SRT { -SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) - : SrtTransport(poller) {} +SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) : SrtTransport(poller) {} SrtTransportImp::~SrtTransportImp() { InfoP(this); @@ -23,52 +22,56 @@ SrtTransportImp::~SrtTransportImp() { } } -void SrtTransportImp::onHandShakeFinished(std::string &streamid,struct sockaddr_storage *addr) { - - // TODO parse streamid like this zlmediakit.com/live/test?token=1213444&type=push - if(!_addr){ +void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) { + // TODO parse stream id like this zlmediakit.com/live/test?token=1213444&type=push + if (!_addr) { _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr))); } - _is_pusher = false; - TraceL<<" stream id "<input(reinterpret_cast(pkt->payloadData()), pkt->payloadSize()); - }else{ - WarnP(this)<<" not reach this"; + } else { + WarnP(this) << " not reach this"; } } + void SrtTransportImp::onShutdown(const SockException &ex) { SrtTransport::onShutdown(ex); } -bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force){ - if (!force && totalReaderCount(sender)) { +bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force) { + if (!force && totalReaderCount(sender)) { return false; } - std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" - << sender.getApp() << "/" << sender.getId() << " " << force; + std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" + << sender.getVhost() << "/" + << sender.getApp() << "/" + << sender.getId() << " " << force; + weak_ptr weak_self = static_pointer_cast(shared_from_this()); getPoller()->async([weak_self, err]() { auto strong_self = weak_self.lock(); @@ -80,21 +83,25 @@ bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force){ }); return true; } + // 播放总人数 -int SrtTransportImp::totalReaderCount(mediakit::MediaSource &sender){ +int SrtTransportImp::totalReaderCount(mediakit::MediaSource &sender) { return _muxer ? _muxer->totalReaderCount() : sender.readerCount(); } + // 获取媒体源类型 -mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const{ +mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const { return MediaOriginType::srt_push; } + // 获取媒体源url或者文件路径 -std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const{ +std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const { return _media_info._full_url; } + // 获取媒体源客户端相关信息 -std::shared_ptr SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const{ - return static_pointer_cast(getSession()); +std::shared_ptr SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const { + return static_pointer_cast(getSession()); } void SrtTransportImp::emitOnPublish() { @@ -114,7 +121,7 @@ void SrtTransportImp::emitOnPublish() { InfoP(strong_self) << "允许 srt 推流"; } else { WarnP(strong_self) << "禁止 srt 推流:" << err; - strong_self->onShutdown(SockException(Err_refused,err)); + strong_self->onShutdown(SockException(Err_refused, err)); } }; @@ -126,47 +133,46 @@ void SrtTransportImp::emitOnPublish() { } } - -void SrtTransportImp::emitOnPlay(){ +void SrtTransportImp::emitOnPlay() { std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); - Broadcast::AuthInvoker invoker = [weak_self](const string &err){ + Broadcast::AuthInvoker invoker = [weak_self](const string &err) { auto strong_self = weak_self.lock(); if (!strong_self) { return; } - strong_self->getPoller()->async([strong_self,err]{ - if(err != ""){ - strong_self->onShutdown(SockException(Err_refused,err)); - }else{ + strong_self->getPoller()->async([strong_self, err] { + if (err != "") { + strong_self->onShutdown(SockException(Err_refused, err)); + } else { strong_self->doPlay(); } }); }; auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast(*this)); - if(!flag){ + if (!flag) { doPlay(); } } -void SrtTransportImp::doPlay(){ - //异步查找直播流 - std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); +void SrtTransportImp::doPlay() { + //异步查找直播流 MediaInfo info = _media_info; info._schema = TS_SCHEMA; + std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) { auto strong_self = weak_self.lock(); if (!strong_self) { //本对象已经销毁 - TraceL<<"本对象已经销毁"; + TraceL << "本对象已经销毁"; return; } if (!src) { //未找到该流 - TraceL<<"未找到该流"; + TraceL << "未找到该流"; strong_self->onShutdown(SockException(Err_shutdown)); } else { - TraceL<<"找到该流"; + TraceL << "找到该流"; auto ts_src = dynamic_pointer_cast(src); assert(ts_src); ts_src->pause(false); @@ -189,9 +195,10 @@ void SrtTransportImp::doPlay(){ auto size = ts_list->size(); ts_list->for_each([&](const TSPacket::Ptr &ts) { strong_self->onSendTSData(ts, ++i == size); }); }); - }; + } }); } + std::string SrtTransportImp::get_peer_ip() { if (!_addr) { return "::"; @@ -215,7 +222,7 @@ std::string SrtTransportImp::get_local_ip() { } uint16_t SrtTransportImp::get_local_port() { - auto s = getSession(); + auto s = getSession(); if (s) { return s->get_local_port(); } @@ -236,9 +243,7 @@ bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) { } auto frame_cached = Frame::getCacheAbleFrame(frame); lock_guard lck(_func_mtx); - _cached_func.emplace_back([this, frame_cached]() { - _muxer->inputFrame(frame_cached); - }); + _cached_func.emplace_back([this, frame_cached]() { _muxer->inputFrame(frame_cached); }); return true; } @@ -248,9 +253,7 @@ bool SrtTransportImp::addTrack(const Track::Ptr &track) { } lock_guard lck(_func_mtx); - _cached_func.emplace_back([this, track]() { - _muxer->addTrack(track); - }); + _cached_func.emplace_back([this, track]() { _muxer->addTrack(track); }); return true; } @@ -259,9 +262,7 @@ void SrtTransportImp::addTrackCompleted() { _muxer->addTrackCompleted(); } else { lock_guard lck(_func_mtx); - _cached_func.emplace_back([this]() { - _muxer->addTrackCompleted(); - }); + _cached_func.emplace_back([this]() { _muxer->addTrackCompleted(); }); } } @@ -273,10 +274,9 @@ void SrtTransportImp::doCachedFunc() { _cached_func.clear(); } -int SrtTransportImp::getLantencyMul(){ - GET_CONFIG(int, lantencyMul, kLantencyMul); - return lantencyMul; +int SrtTransportImp::getLatencyMul() { + GET_CONFIG(int, latencyMul, kLatencyMul); + return latencyMul; } - } // namespace SRT \ No newline at end of file diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 5e259632..5dc4b228 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -1,16 +1,18 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_IMP_H #define ZLMEDIAKIT_SRT_TRANSPORT_IMP_H -#include -#include "Common/MultiMediaSourceMuxer.h" -#include "Rtp/Decoder.h" -#include "TS/TSMediaSource.h" -#include "SrtTransport.hpp" +#include +#include "Rtp/Decoder.h" +#include "SrtTransport.hpp" +#include "TS/TSMediaSource.h" +#include "Common/MultiMediaSourceMuxer.h" namespace SRT { - using namespace toolkit; - using namespace mediakit; - using namespace std; + +using namespace std; +using namespace toolkit; +using namespace mediakit; + class SrtTransportImp : public SrtTransport , public toolkit::SockInfo @@ -19,13 +21,13 @@ class SrtTransportImp public: SrtTransportImp(const EventPoller::Ptr &poller); ~SrtTransportImp(); - void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr){ - SrtTransport::inputSockData(buf,len,addr); + + void inputSockData(uint8_t *buf, int len, struct sockaddr_storage *addr) override { + SrtTransport::inputSockData(buf, len, addr); _total_bytes += len; } - void onSendTSData(const Buffer::Ptr &buffer, bool flush){ - SrtTransport::onSendTSData(buffer,flush); - } + void onSendTSData(const Buffer::Ptr &buffer, bool flush) override { SrtTransport::onSendTSData(buffer, flush); } + /// SockInfo override std::string get_local_ip() override; uint16_t get_local_port() override; @@ -35,20 +37,18 @@ public: protected: ///////SrtTransport override/////// - void onHandShakeFinished(std::string& streamid,struct sockaddr_storage *addr) override; + int getLatencyMul() override; void onSRTData(DataPacket::Ptr pkt) override; void onShutdown(const SockException &ex) override; - int getLantencyMul() override; + void onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) override; - void sendPacket(Buffer::Ptr pkt,bool flush = true) override{ + void sendPacket(Buffer::Ptr pkt, bool flush = true) override { _total_bytes += pkt->size(); - SrtTransport::sendPacket(pkt,flush); - }; - - bool isPusher() override{ - return _is_pusher; + SrtTransport::sendPacket(pkt, flush); } + bool isPusher() override { return _is_pusher; } + ///////MediaSourceEvent override/////// // 关闭 bool close(mediakit::MediaSource &sender, bool force) override; @@ -61,10 +61,11 @@ protected: // 获取媒体源客户端相关信息 std::shared_ptr getOriginSock(mediakit::MediaSource &sender) const override; - bool inputFrame(const Frame::Ptr &frame) override; - bool addTrack(const Track::Ptr & track) override; - void addTrackCompleted() override; + ///////MediaSinkInterface override/////// void resetTracks() override {}; + void addTrackCompleted() override; + bool addTrack(const Track::Ptr &track) override; + bool inputFrame(const Frame::Ptr &frame) override; private: void emitOnPublish(); @@ -76,12 +77,12 @@ private: private: bool _is_pusher = true; MediaInfo _media_info; - uint64_t _total_bytes = 0; + uint64_t _total_bytes = 0; Ticker _alive_ticker; std::unique_ptr _addr; - // for player + // for player TSMediaSource::RingType::RingReader::Ptr _ts_reader; - // for pusher + // for pusher MultiMediaSourceMuxer::Ptr _muxer; DecoderImp::Ptr _decoder; std::recursive_mutex _func_mtx; diff --git a/srt/Statistic.cpp b/srt/Statistic.cpp index 9fc13cd5..446fc6fe 100644 --- a/srt/Statistic.cpp +++ b/srt/Statistic.cpp @@ -1,14 +1,17 @@ #include #include "Statistic.hpp" + namespace SRT { -void PacketRecvRateContext::inputPacket(TimePoint& ts) { - if(_pkt_map.size()>100){ - _pkt_map.erase(_pkt_map.begin()); - } - auto tmp = DurationCountMicroseconds(ts - _start); - _pkt_map.emplace(tmp,tmp); + +void PacketRecvRateContext::inputPacket(TimePoint &ts) { + if (_pkt_map.size() > 100) { + _pkt_map.erase(_pkt_map.begin()); + } + auto tmp = DurationCountMicroseconds(ts - _start); + _pkt_map.emplace(tmp, tmp); } + uint32_t PacketRecvRateContext::getPacketRecvRate() { if (_pkt_map.size() < 2) { return 50000; @@ -17,79 +20,78 @@ uint32_t PacketRecvRateContext::getPacketRecvRate() { for (auto it = _pkt_map.begin(); it != _pkt_map.end(); ++it) { auto next = it; ++next; - if (next != _pkt_map.end()) { - if ((next->first - it->first) < dur) { - dur = next->first - it->first; - } - } else { + if (next == _pkt_map.end()) { break; } + + if ((next->first - it->first) < dur) { + dur = next->first - it->first; + } } double rate = 1e6 / (double)dur; - if(rate <=1000){ + if (rate <= 1000) { return 50000; } return rate; } -void EstimatedLinkCapacityContext::inputPacket(TimePoint& ts) { +void EstimatedLinkCapacityContext::inputPacket(TimePoint &ts) { if (_pkt_map.size() > 16) { _pkt_map.erase(_pkt_map.begin()); } auto tmp = DurationCountMicroseconds(ts - _start); _pkt_map.emplace(tmp, tmp); } + uint32_t EstimatedLinkCapacityContext::getEstimatedLinkCapacity() { - decltype(_pkt_map.begin()) next; - std::vector tmp; + decltype(_pkt_map.begin()) next; + std::vector tmp; - for(auto it = _pkt_map.begin();it != _pkt_map.end();++it){ - next = it; - ++next; - if(next != _pkt_map.end()){ - tmp.push_back(next->first -it->first); - }else{ - break; - } - } - std::sort(tmp.begin(),tmp.end()); - if(tmp.empty()){ - return 1000; - } + for (auto it = _pkt_map.begin(); it != _pkt_map.end(); ++it) { + next = it; + ++next; + if (next != _pkt_map.end()) { + tmp.push_back(next->first - it->first); + } else { + break; + } + } + std::sort(tmp.begin(), tmp.end()); + if (tmp.empty()) { + return 1000; + } - if(tmp.size()<16){ - return 1000; - } - - double dur =tmp[0]/1e6; - - return (uint32_t)(1.0/dur); + if (tmp.size() < 16) { + return 1000; + } + double dur = tmp[0] / 1e6; + return (uint32_t)(1.0 / dur); } -void RecvRateContext::inputPacket(TimePoint& ts, size_t size ) { +void RecvRateContext::inputPacket(TimePoint &ts, size_t size) { if (_pkt_map.size() > 100) { _pkt_map.erase(_pkt_map.begin()); } - auto tmp = DurationCountMicroseconds(ts - _start); - + auto tmp = DurationCountMicroseconds(ts - _start); _pkt_map.emplace(tmp, tmp); } + uint32_t RecvRateContext::getRecvRate() { - if(_pkt_map.size()<2){ + if (_pkt_map.size() < 2) { return 0; } auto first = _pkt_map.begin(); auto last = _pkt_map.rbegin(); - double dur = (last->first - first->first)/1000000.0; + double dur = (last->first - first->first) / 1000000.0; size_t bytes = 0; - for(auto it : _pkt_map){ + for (auto it : _pkt_map) { bytes += it.second; } - double rate = (double)bytes/dur; + double rate = (double)bytes / dur; return (uint32_t)rate; } diff --git a/srt/Statistic.hpp b/srt/Statistic.hpp index 4524aebe..a2e9f68c 100644 --- a/srt/Statistic.hpp +++ b/srt/Statistic.hpp @@ -6,41 +6,42 @@ #include "Packet.hpp" namespace SRT { + class PacketRecvRateContext { public: - PacketRecvRateContext(TimePoint start):_start(start){}; + PacketRecvRateContext(TimePoint start): _start(start) {}; ~PacketRecvRateContext() = default; - void inputPacket(TimePoint& ts); + void inputPacket(TimePoint &ts); uint32_t getPacketRecvRate(); + private: - std::map _pkt_map; TimePoint _start; - + std::map _pkt_map; }; class EstimatedLinkCapacityContext { public: - EstimatedLinkCapacityContext(TimePoint start):_start(start){}; + EstimatedLinkCapacityContext(TimePoint start) : _start(start) {}; ~EstimatedLinkCapacityContext() = default; - void inputPacket(TimePoint& ts); + void inputPacket(TimePoint &ts); uint32_t getEstimatedLinkCapacity(); + private: - std::map _pkt_map; TimePoint _start; + std::map _pkt_map; }; class RecvRateContext { public: - RecvRateContext(TimePoint start):_start(start){}; + RecvRateContext(TimePoint start): _start(start) {}; ~RecvRateContext() = default; - void inputPacket(TimePoint& ts,size_t size); + void inputPacket(TimePoint &ts, size_t size); uint32_t getRecvRate(); + private: - std::map _pkt_map; - TimePoint _start; + TimePoint _start; + std::map _pkt_map; }; - - } // namespace SRT #endif // ZLMEDIAKIT_SRT_STATISTIC_H \ No newline at end of file From f58211fb08e409263c1e1af53e16805864b395f3 Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Thu, 9 Jun 2022 19:30:03 +0800 Subject: [PATCH 30/31] optimize send nack when check packet lost send nack immediately --- srt/Common.hpp | 11 +++-- srt/NackContext.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++ srt/NackContext.hpp | 30 ++++++++++++ srt/PacketQueue.cpp | 11 +---- srt/SrtTransport.cpp | 46 +++++++++++++----- srt/SrtTransport.hpp | 11 +++-- 6 files changed, 189 insertions(+), 28 deletions(-) create mode 100644 srt/NackContext.cpp create mode 100644 srt/NackContext.hpp diff --git a/srt/Common.hpp b/srt/Common.hpp index 8b5d57c3..81d98814 100644 --- a/srt/Common.hpp +++ b/srt/Common.hpp @@ -1,17 +1,19 @@ #ifndef ZLMEDIAKIT_SRT_COMMON_H #define ZLMEDIAKIT_SRT_COMMON_H #if defined(_WIN32) +#include #include #include -#include -#pragma comment (lib, "Ws2_32.lib") -#pragma comment(lib,"Iphlpapi.lib") +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Iphlpapi.lib") #else #include #include #endif // defined(_WIN32) #include +#define MAX_SEQ 0x7fffffff +#define MAX_TS 0xffffffff namespace SRT { using SteadyClock = std::chrono::steady_clock; @@ -59,6 +61,9 @@ static inline void storeUint16LE(uint8_t *buf, uint16_t val) { static inline uint32_t srtVersion(int major, int minor, int patch) { return patch + minor * 0x100 + major * 0x10000; } +static inline uint32_t genExpectedSeq(uint32_t seq) { + return MAX_SEQ & seq; +} class UTicker { public: diff --git a/srt/NackContext.cpp b/srt/NackContext.cpp new file mode 100644 index 00000000..9711531c --- /dev/null +++ b/srt/NackContext.cpp @@ -0,0 +1,108 @@ +#include "NackContext.hpp" + +namespace SRT { +void NackContext::update(TimePoint now, std::list &lostlist) { + for (auto item : lostlist) { + mergeItem(now, item); + } +} +void NackContext::getLostList( + TimePoint now, uint32_t rtt, uint32_t rtt_variance, std::list &lostlist) { + lostlist.clear(); + std::list tmp_list; + + for (auto it = _nack_map.begin(); it != _nack_map.end(); ++it) { + if (!it->second._is_nack) { + tmp_list.push_back(it->first); + it->second._ts = now; + it->second._is_nack = true; + } else { + if (DurationCountMicroseconds(now - it->second._ts) > rtt) { + tmp_list.push_back(it->first); + it->second._ts = now; + } + } + } + tmp_list.sort(); + + if (tmp_list.empty()) { + return; + } + + uint32_t min = *tmp_list.begin(); + uint32_t max = *tmp_list.rbegin(); + + if ((max - min) >= (MAX_SEQ >> 1)) { + while ((max - tmp_list.front()) > (MAX_SEQ >> 1)) { + tmp_list.push_back(tmp_list.front()); + tmp_list.pop_front(); + } + } + + PacketQueue::LostPair lost; + bool finish = true; + for (auto cur = tmp_list.begin(); cur != tmp_list.end(); ++cur) { + if (finish) { + lost.first = *cur; + lost.second = genExpectedSeq(*cur + 1); + finish = false; + } else { + if (lost.second == *cur) { + lost.second = genExpectedSeq(*cur + 1); + } else { + finish = true; + lostlist.push_back(lost); + } + } + } +} +void NackContext::drop(uint32_t seq) { + if (_nack_map.empty()) + return; + uint32_t min = _nack_map.begin()->first; + uint32_t max = _nack_map.rbegin()->first; + bool is_cycle = false; + if ((max - min) >= (MAX_SEQ >> 1)) { + is_cycle = true; + } + + for (auto it = _nack_map.begin(); it != _nack_map.end();) { + if (!is_cycle) { + // 不回环 + if (it->first <= seq) { + it = _nack_map.erase(it); + } else { + it++; + } + } else { + if (it->first <= seq) { + if ((seq - it->first) >= (MAX_SEQ >> 1)) { + WarnL << "cycle seq " << seq << " " << it->first; + it++; + } else { + it = _nack_map.erase(it); + } + } else { + if ((it->first - seq) >= (MAX_SEQ >> 1)) { + it = _nack_map.erase(it); + WarnL << "cycle seq " << seq << " " << it->first; + } else { + it++; + } + } + } + } +} + +void NackContext::mergeItem(TimePoint now, PacketQueue::LostPair &item) { + for (uint32_t i = item.first; i < item.second; ++i) { + auto it = _nack_map.find(i); + if (it != _nack_map.end()) { + } else { + NackItem tmp; + tmp._is_nack = false; + _nack_map.emplace(i, tmp); + } + } +} +} // namespace SRT \ No newline at end of file diff --git a/srt/NackContext.hpp b/srt/NackContext.hpp new file mode 100644 index 00000000..fe6a0ba6 --- /dev/null +++ b/srt/NackContext.hpp @@ -0,0 +1,30 @@ +#ifndef ZLMEDIAKIT_SRT_NACK_CONTEXT_H +#define ZLMEDIAKIT_SRT_NACK_CONTEXT_H +#include "Common.hpp" +#include "PacketQueue.hpp" +#include + +namespace SRT { +class NackContext { +public: + NackContext() = default; + ~NackContext() = default; + void update(TimePoint now, std::list &lostlist); + void getLostList(TimePoint now, uint32_t rtt, uint32_t rtt_variance, std::list &lostlist); + void drop(uint32_t seq); + +private: + void mergeItem(TimePoint now, PacketQueue::LostPair &item); + +private: + class NackItem { + public: + bool _is_nack = false; + TimePoint _ts; // send nak time + }; + + std::map _nack_map; +}; + +} // namespace SRT +#endif // ZLMEDIAKIT_SRT_NACK_CONTEXT_H \ No newline at end of file diff --git a/srt/PacketQueue.cpp b/srt/PacketQueue.cpp index 001585d1..cb43bd13 100644 --- a/srt/PacketQueue.cpp +++ b/srt/PacketQueue.cpp @@ -2,13 +2,6 @@ namespace SRT { -#define MAX_SEQ 0x7fffffff -#define MAX_TS 0xffffffff - -static inline uint32_t genExpectedSeq(uint32_t seq) { - return MAX_SEQ & seq; -} - static inline bool isSeqEdge(uint32_t seq, uint32_t cap) { if (seq > (MAX_SEQ - cap)) { return true; @@ -160,9 +153,9 @@ std::list PacketQueue::getLostSeq() { if (finish) { finish = false; lost.first = i; - lost.second = i + 1; + lost.second = genExpectedSeq(i + 1); } else { - lost.second = i + 1; + lost.second = genExpectedSeq(i + 1); } } else { if (!finish) { diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 11b637d7..570e09f8 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -1,5 +1,5 @@ -#include -#include "Util/onceToken.h" +#include "Util/onceToken.h" +#include #include "Ack.hpp" #include "Packet.hpp" @@ -203,7 +203,8 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad unregisterSelfHandshake(); registerSelf(); sendControlPacket(res, true); - TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number << " latency=" << delay; + TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number + << " latency=" << delay; _recv_buf = std::make_shared(res->max_flow_window_size, _init_seq_number, delay * 1e3); _send_buf = std::make_shared(res->max_flow_window_size, delay * 1e3); _send_packet_seq_number = _init_seq_number; @@ -314,10 +315,21 @@ void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage if (list.empty()) { return; } - + uint32_t max_seq = 0; for (auto data : list) { + max_seq = data->packet_seq_number; onSRTData(std::move(data)); } + _recv_nack.drop(max_seq); + + auto lost = _recv_buf->getLostSeq(); + _recv_nack.update(_now, lost); + lost.clear(); + _recv_nack.getLostList(_now, _rtt, _rtt_variance, lost); + if (!lost.empty()) { + sendNAKPacket(lost); + // TraceL << "check lost send nack"; + } auto nak_interval = (_rtt + _rtt_variance * 4) / 2; if (nak_interval <= 20 * 1000) { @@ -436,8 +448,24 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora //TraceL<<" seq="<< pkt->packet_seq_number<<" ts="<timestamp<<" size="<payloadSize()<<\ //" PP="<<(int)pkt->PP<<" O="<<(int)pkt->O<<" kK="<<(int)pkt->KK<<" R="<<(int)pkt->R; _recv_buf->inputPacket(pkt, list); - for (auto data : list) { - onSRTData(std::move(data)); + if (list.empty()) { + // when no data ok send nack to sender immediately + } else { + uint32_t last_seq; + for (auto data : list) { + last_seq = data->packet_seq_number; + onSRTData(std::move(data)); + } + _recv_nack.drop(last_seq); + } + + auto lost = _recv_buf->getLostSeq(); + _recv_nack.update(_now, lost); + lost.clear(); + _recv_nack.getLostList(_now, _rtt, _rtt_variance, lost); + if (!lost.empty()) { + // TraceL << "check lost send nack immediately"; + sendNAKPacket(lost); } auto nak_interval = (_rtt + _rtt_variance * 4) / 2; @@ -445,12 +473,8 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora nak_interval = 20 * 1000; } - if (list.empty()) { - // TraceL<<_recv_buf->dump()<<" nake interval:"< nak_interval) { + // Periodic NAK reports auto lost = _recv_buf->getLostSeq(); if (!lost.empty()) { sendNAKPacket(lost); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 3545dd95..43ae841f 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -11,11 +11,11 @@ #include "Poller/Timer.h" #include "Common.hpp" +#include "NackContext.hpp" #include "Packet.hpp" #include "PacketQueue.hpp" #include "PacketSendQueue.hpp" #include "Statistic.hpp" - namespace SRT { using namespace toolkit; @@ -45,7 +45,7 @@ public: virtual void onSendTSData(const Buffer::Ptr &buffer, bool flush); std::string getIdentifier(); -void unregisterSelf(); + void unregisterSelf(); void unregisterSelfHandshake(); protected: @@ -91,9 +91,9 @@ protected: void sendControlPacket(ControlPacket::Ptr pkt, bool flush = true); private: - //当前选中的udp链接 + // 当前选中的udp链接 Session::Ptr _selected_session; - //链接迁移前后使用过的udp链接 + // 链接迁移前后使用过的udp链接 std::unordered_map> _history_sessions; EventPoller::Ptr _poller; @@ -119,6 +119,7 @@ private: PacketSendQueue::Ptr _send_buf; uint32_t _buf_delay = 120; PacketQueue::Ptr _recv_buf; + NackContext _recv_nack; uint32_t _rtt = 100 * 1000; uint32_t _rtt_variance = 50 * 1000; uint32_t _light_ack_pkt_count = 0; @@ -133,7 +134,7 @@ private: UTicker _nak_ticker; - //保持发送的握手消息,防止丢失重发 + // 保持发送的握手消息,防止丢失重发 HandshakePacket::Ptr _handleshake_res; ResourcePool _packet_pool; From 49a0183df0061fa584242b7b5223c3b6a7ac7a3a Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Thu, 9 Jun 2022 22:54:24 +0800 Subject: [PATCH 31/31] fix clang format change include order result in windows build error --- srt/Common.hpp | 3 ++- srt/Packet.cpp | 10 +++++++--- srt/SrtTransport.cpp | 10 ++++++++++ srt/SrtTransport.hpp | 2 ++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/srt/Common.hpp b/srt/Common.hpp index 81d98814..de5d3aaa 100644 --- a/srt/Common.hpp +++ b/srt/Common.hpp @@ -1,9 +1,10 @@ #ifndef ZLMEDIAKIT_SRT_COMMON_H #define ZLMEDIAKIT_SRT_COMMON_H #if defined(_WIN32) -#include #include #include + +#include #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Iphlpapi.lib") #else diff --git a/srt/Packet.cpp b/srt/Packet.cpp index b4afbf4a..85de1cbf 100644 --- a/srt/Packet.cpp +++ b/srt/Packet.cpp @@ -294,8 +294,12 @@ bool HandshakePacket::loadExtMessage(uint8_t *buf, size_t len) { length = loadUint16(ptr + 2); switch (type) { case HSExt::SRT_CMD_HSREQ: - case HSExt::SRT_CMD_HSRSP: ext = std::make_shared(); break; - case HSExt::SRT_CMD_SID: ext = std::make_shared(); break; + case HSExt::SRT_CMD_HSRSP: + ext = std::make_shared(); + break; + case HSExt::SRT_CMD_SID: + ext = std::make_shared(); + break; default: WarnL << "not support ext " << type; break; @@ -410,7 +414,7 @@ void HandshakePacket::assignPeerIP(struct sockaddr_storage *addr) { memset(peer_ip_addr, 0, sizeof(peer_ip_addr) * sizeof(peer_ip_addr[0])); if (addr->ss_family == AF_INET) { struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr; - //抓包 奇怪好像是小头端??? + // 抓包 奇怪好像是小头端??? storeUint32LE(peer_ip_addr, ipv4->sin_addr.s_addr); } else if (addr->ss_family == AF_INET6) { if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) { diff --git a/srt/SrtTransport.cpp b/srt/SrtTransport.cpp index 570e09f8..4714bc64 100644 --- a/srt/SrtTransport.cpp +++ b/srt/SrtTransport.cpp @@ -127,6 +127,8 @@ void SrtTransport::handleHandshakeInduction(HandshakePacket &pkt, struct sockadd _max_window_size = pkt.max_flow_window_size; _mtu = pkt.mtu; + _last_pkt_seq = _init_seq_number - 1; + _peer_socket_id = pkt.srt_socket_id; HandshakePacket::Ptr res = std::make_shared(); res->dst_socket_id = _peer_socket_id; @@ -318,6 +320,10 @@ void SrtTransport::handleDropReq(uint8_t *buf, int len, struct sockaddr_storage uint32_t max_seq = 0; for (auto data : list) { max_seq = data->packet_seq_number; + if (_last_pkt_seq + 1 != data->packet_seq_number) { + TraceL << "pkt lost " << _last_pkt_seq + 1 << "->" << data->packet_seq_number; + } + _last_pkt_seq = data->packet_seq_number; onSRTData(std::move(data)); } _recv_nack.drop(max_seq); @@ -454,6 +460,10 @@ void SrtTransport::handleDataPacket(uint8_t *buf, int len, struct sockaddr_stora uint32_t last_seq; for (auto data : list) { last_seq = data->packet_seq_number; + if (_last_pkt_seq + 1 != data->packet_seq_number) { + TraceL << "pkt lost " << _last_pkt_seq + 1 << "->" << data->packet_seq_number; + } + _last_pkt_seq = data->packet_seq_number; onSRTData(std::move(data)); } _recv_nack.drop(last_seq); diff --git a/srt/SrtTransport.hpp b/srt/SrtTransport.hpp index 43ae841f..27281063 100644 --- a/srt/SrtTransport.hpp +++ b/srt/SrtTransport.hpp @@ -125,6 +125,8 @@ private: uint32_t _light_ack_pkt_count = 0; uint32_t _ack_number_count = 0; uint32_t _last_ack_pkt_seq_num = 0; + + uint32_t _last_pkt_seq = 0; UTicker _ack_ticker; std::map _ack_send_timestamp;