From 471cf611c69b2569750c37ad84103f7d2a51dc86 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 27 Feb 2021 11:23:50 +0800 Subject: [PATCH] Perf: Refine object cache, avoid dynamic cast --- trunk/src/app/srs_app_rtc_conn.cpp | 6 +-- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/app/srs_app_rtc_source.cpp | 20 ++++--- trunk/src/app/srs_app_rtc_source.hpp | 4 +- trunk/src/kernel/srs_kernel_rtc_rtp.cpp | 70 ++++++++++++++----------- trunk/src/kernel/srs_kernel_rtc_rtp.hpp | 23 ++++++-- 6 files changed, 76 insertions(+), 49 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 2ac360d5d..894d5c65f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1268,7 +1268,7 @@ srs_error_t SrsRtcPublishStream::check_send_nacks() return err; } -void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1280,9 +1280,9 @@ void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer SrsRtcVideoRecvTrack* video_track = get_video_track(ssrc); if (audio_track) { - audio_track->on_before_decode_payload(pkt, buf, ppayload); + audio_track->on_before_decode_payload(pkt, buf, ppayload, ppt); } else if (video_track) { - video_track->on_before_decode_payload(pkt, buf, ppayload); + video_track->on_before_decode_payload(pkt, buf, ppayload, ppt); } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 644c718f9..437857833 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -361,7 +361,7 @@ private: public: srs_error_t check_send_nacks(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); private: srs_error_t send_periodic_twcc(); public: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 87ef3fb24..54d7e2a1e 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -826,7 +826,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack audio_timestamp += 960; SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeRaw); raw->payload = pkt->wrap(data, size); raw->nn_payload = size; @@ -961,7 +961,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); - pkt->payload = stap; + pkt->set_payload(stap, SrsRtpPacketPayloadTypeSTAP); uint8_t header = sps[0]; stap->nri = (SrsAvcNaluType)header; @@ -1041,7 +1041,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const pkt->nalu_type = (SrsAvcNaluType)first_nalu_type; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeNALU); pkt->wrap(msg); } else { // We must free it, should never use RTP packets to free it, @@ -1082,7 +1082,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); - pkt->payload = fua; + pkt->set_payload(fua, SrsRtpPacketPayloadTypeFUA); pkt->wrap(msg); nb_left -= packet_size; @@ -1108,7 +1108,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpRawPayload* raw = _srs_rtp_raw_cache->allocate(); - pkt->payload = raw; + pkt->set_payload(raw, SrsRtpPacketPayloadTypeRaw); raw->payload = sample->bytes; raw->nn_payload = sample->size; @@ -1142,7 +1142,7 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam pkt->header.set_timestamp(msg->timestamp * 90); SrsRtpFUAPayload2* fua = _srs_rtp_fua_cache->allocate(); - pkt->payload = fua; + pkt->set_payload(fua, SrsRtpPacketPayloadTypeFUA2); fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; @@ -1854,7 +1854,7 @@ SrsRtcAudioRecvTrack::~SrsRtcAudioRecvTrack() { } -void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1862,6 +1862,7 @@ void SrsRtcAudioRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe } *ppayload = _srs_rtp_raw_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeRaw; } srs_error_t SrsRtcAudioRecvTrack::on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled) @@ -1910,7 +1911,7 @@ SrsRtcVideoRecvTrack::~SrsRtcVideoRecvTrack() { } -void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) +void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) { // No payload, ignore. if (buf->empty()) { @@ -1920,10 +1921,13 @@ void SrsRtcVideoRecvTrack::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffe uint8_t v = (uint8_t)pkt->nalu_type; if (v == kStapA) { *ppayload = new SrsRtpSTAPPayload(); + *ppt = SrsRtpPacketPayloadTypeUnknown; } else if (v == kFuA) { *ppayload = _srs_rtp_fua_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeFUA2; } else { *ppayload = _srs_rtp_raw_cache->allocate(); + *ppt = SrsRtpPacketPayloadTypeRaw; } } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 5d8f03f99..d5155c263 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -549,7 +549,7 @@ public: SrsRtcAudioRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc); virtual ~SrsRtcAudioRecvTrack(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); virtual srs_error_t check_send_nacks(); @@ -561,7 +561,7 @@ public: SrsRtcVideoRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* stream_descs); virtual ~SrsRtcVideoRecvTrack(); public: - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt, bool nack_enabled); virtual srs_error_t check_send_nacks(); diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp index 5b6bcab7f..e60be64d6 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp @@ -811,7 +811,7 @@ ISrsRtpPacketDecodeHandler::~ISrsRtpPacketDecodeHandler() SrsRtpPacket2::SrsRtpPacket2() { - payload = NULL; + payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; shared_msg = NULL; reset(); @@ -821,31 +821,31 @@ SrsRtpPacket2::SrsRtpPacket2() SrsRtpPacket2::~SrsRtpPacket2() { - reuse(); + reuse_payload(); + reuse_shared_msg(); } -void SrsRtpPacket2::reuse() +void SrsRtpPacket2::reuse_payload() { - if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { - // Only recycle some common payloads. - SrsRtpRawPayload* raw_payload; - SrsRtpFUAPayload2* fua_payload; - - if ((raw_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_raw_cache->recycle(raw_payload); - payload = NULL; - } else if ((fua_payload = dynamic_cast(payload)) != NULL) { - _srs_rtp_fua_cache->recycle(fua_payload); - payload = NULL; - } else { - srs_freep(payload); - } - } else { - srs_freep(payload); + if (!payload_) { + return; } - // Recycle the real owner of message, clear the reference. - reuse_shared_msg(); + if (_srs_rtp_raw_cache->enabled() || _srs_rtp_fua_cache->enabled()) { + // Only recycle some common payloads. + if (payload_type_ == SrsRtpPacketPayloadTypeRaw) { + _srs_rtp_raw_cache->recycle((SrsRtpRawPayload*)payload_); + } else if (payload_type_ == SrsRtpPacketPayloadTypeFUA2) { + _srs_rtp_fua_cache->recycle((SrsRtpFUAPayload2*)payload_); + } else { + srs_freep(payload_); + } + } else { + srs_freep(payload_); + } + + // Reset the payload and its type. + payload_ = NULL; payload_type_ = SrsRtpPacketPayloadTypeUnknown; } void SrsRtpPacket2::reuse_shared_msg() @@ -854,6 +854,7 @@ void SrsRtpPacket2::reuse_shared_msg() return; } + // Recycle the real owner of message, clear the reference. if (_srs_rtp_msg_cache_buffers->enabled() || _srs_rtp_msg_cache_objs->enabled()) { // We only recycle the RTC UDP packet messages. if (shared_msg->payload && shared_msg->size == kRtpPacketSize && shared_msg->count() == 0) { @@ -877,9 +878,8 @@ bool SrsRtpPacket2::reset() decode_handler = NULL; header.reset(); - - // Reset and reuse the payload and shared message. - reuse(); + reuse_payload(); + reuse_shared_msg(); return true; } @@ -967,11 +967,16 @@ SrsRtpPacket2* SrsRtpPacket2::copy() { SrsRtpPacket2* cp = _srs_rtp_cache->allocate(); + // We got packet from cache, so we must recycle it. + cp->reuse_payload(); + cp->reuse_shared_msg(); + cp->header = header; - cp->payload = payload? payload->copy():NULL; + cp->payload_ = payload_? payload_->copy():NULL; + cp->payload_type_ = payload_type_; cp->nalu_type = nalu_type; - cp->wrap(shared_msg); // Wrap the shared message and buffer. + cp->shared_msg = shared_msg->copy(); cp->frame_type = frame_type; cp->cached_payload_size = cached_payload_size; @@ -988,7 +993,7 @@ void SrsRtpPacket2::set_extension_types(const SrsRtpExtensionTypes* v) uint64_t SrsRtpPacket2::nb_bytes() { if (!cached_payload_size) { - int nn_payload = (payload? payload->nb_bytes():0); + int nn_payload = (payload_? payload_->nb_bytes():0); cached_payload_size = header.nb_bytes() + nn_payload + header.get_padding(); } return cached_payload_size; @@ -1002,7 +1007,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) return srs_error_wrap(err, "rtp header"); } - if (payload && (err = payload->encode(buf)) != srs_success) { + if (payload_ && (err = payload_->encode(buf)) != srs_success) { return srs_error_wrap(err, "rtp payload"); } @@ -1040,15 +1045,16 @@ srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf) // If user set the decode handler, call it to set the payload. if (decode_handler) { - decode_handler->on_before_decode_payload(this, buf, &payload); + decode_handler->on_before_decode_payload(this, buf, &payload_, &payload_type_); } // By default, we always use the RAW payload. - if (!payload) { - payload = _srs_rtp_raw_cache->allocate(); + if (!payload_) { + payload_ = _srs_rtp_raw_cache->allocate(); + payload_type_ = SrsRtpPacketPayloadTypeRaw; } - if ((err = payload->decode(buf)) != srs_success) { + if ((err = payload_->decode(buf)) != srs_success) { return srs_error_wrap(err, "rtp payload"); } diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 652128c88..7d3fd5f44 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -258,6 +258,7 @@ public: srs_error_t set_twcc_sequence_number(uint8_t id, uint16_t sn); }; +// The common payload interface for RTP packet. class ISrsRtpPayloader : public ISrsCodec { public: @@ -267,6 +268,17 @@ public: virtual ISrsRtpPayloader* copy() = 0; }; +// The payload type, for performance to avoid dynamic cast. +enum SrsRtpPacketPayloadType +{ + SrsRtpPacketPayloadTypeRaw, + SrsRtpPacketPayloadTypeFUA2, + SrsRtpPacketPayloadTypeFUA, + SrsRtpPacketPayloadTypeNALU, + SrsRtpPacketPayloadTypeSTAP, + SrsRtpPacketPayloadTypeUnknown, +}; + class ISrsRtpPacketDecodeHandler { public: @@ -274,7 +286,7 @@ public: virtual ~ISrsRtpPacketDecodeHandler(); public: // We don't know the actual payload, so we depends on external handler. - virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) = 0; + virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload, SrsRtpPacketPayloadType* ppt) = 0; }; // The RTP packet with cached shared message. @@ -283,7 +295,9 @@ class SrsRtpPacket2 // RTP packet fields. public: SrsRtpHeader header; - ISrsRtpPayloader* payload; +private: + ISrsRtpPayloader* payload_; + SrsRtpPacketPayloadType payload_type_; private: // The original shared message, all RTP packets can refer to its data. SrsSharedPtrMessage* shared_msg; @@ -303,7 +317,7 @@ public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); private: - void reuse(); + void reuse_payload(); void reuse_shared_msg(); public: // Reset the object to reuse it. @@ -314,6 +328,9 @@ public: // Wrap the shared message, we copy it. char* wrap(SrsSharedPtrMessage* msg); public: + // Get and set the payload of packet. + void set_payload(ISrsRtpPayloader* p, SrsRtpPacketPayloadType pt) { payload_ = p; payload_type_ = pt; } + ISrsRtpPayloader* payload() { return payload_; } // Set the padding of RTP packet. void set_padding(int size); // Increase the padding of RTP packet.