From 1a7c98b5fce09d1f36f78cc98749ca0daa84502c Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 9 Apr 2020 15:20:32 +0800 Subject: [PATCH 001/131] Refine README --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 507fab89a..728152999 100755 --- a/README.md +++ b/README.md @@ -149,7 +149,6 @@ For previous versions, please read: - [ ] Support publishing stream by WebRTC, [#307][bug #307]. - [ ] Support change user to run SRS, [#1111][bug #1111]. - [ ] Support HLS variant, [#463][bug #463]. -- [ ] Support playing stream by WebRTC. > Remark: About the milestone and product plan, please read ([CN][v1_CN_Product], [EN][v1_EN_Product]) wiki. From c54d5be93c401fc68042f4c466ad652f83807a64 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 9 Apr 2020 19:38:50 +0800 Subject: [PATCH 002/131] For #307, refine RTP packet cache. --- trunk/src/app/srs_app_rtc_conn.cpp | 154 ++++++++++++++++------------- trunk/src/app/srs_app_rtc_conn.hpp | 13 ++- 2 files changed, 98 insertions(+), 69 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 9c6c3cf8f..e8bf756ed 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -574,59 +574,61 @@ void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* ukt) void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* udp_mux_skt) { - srs_error_t err = srs_success; + if (!rtc_session->dtls_session) { + return; + } - vector mhdrs; for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; + bool is_video = msg->is_video(); + bool is_audio = msg->is_audio(); - for (int i = 0; i < (int)msg->rtp_packets.size(); ++i) { - if (!rtc_session->dtls_session) { - continue; - } - - SrsRtpSharedPacket* pkt = msg->rtp_packets[i]; - - if (msg->is_video()) { - pkt->modify_rtp_header_payload_type(video_payload_type); - pkt->modify_rtp_header_ssrc(video_ssrc); - srs_verbose("send video, ssrc=%u, seq=%u, timestamp=%u", video_ssrc, pkt->rtp_header.get_sequence(), pkt->rtp_header.get_timestamp()); - } - - if (msg->is_audio()) { - pkt->modify_rtp_header_payload_type(audio_payload_type); - pkt->modify_rtp_header_ssrc(audio_ssrc); - } - - int length = pkt->size; - char* buf = new char[kRtpPacketSize]; - if (rtc_session->encrypt) { - if ((err = rtc_session->dtls_session->protect_rtp(buf, pkt->payload, length)) != srs_success) { - srs_warn("srtp err %s", srs_error_desc(err).c_str()); srs_freep(err); srs_freepa(buf); - continue; - } - } else { - memcpy(buf, pkt->payload, length); - } - - mmsghdr mhdr; - memset(&mhdr, 0, sizeof(mmsghdr)); - mhdr.msg_hdr.msg_name = (sockaddr_in*)udp_mux_skt->peer_addr(); - mhdr.msg_hdr.msg_namelen = udp_mux_skt->peer_addrlen(); - mhdr.msg_hdr.msg_iovlen = 1; - mhdr.msg_hdr.msg_iov = new iovec(); - mhdr.msg_hdr.msg_iov->iov_base = buf; - mhdr.msg_hdr.msg_iov->iov_len = length; - mhdrs.push_back(mhdr); + for (vector::iterator it = msg->rtp_packets.begin(); it != msg->rtp_packets.end(); ++it) { + SrsRtpSharedPacket* pkt = *it; + send_and_free_message(msg, is_video, is_audio, pkt, udp_mux_skt); } srs_freep(msg); } +} - if ((err = rtc_session->rtc_server->send_and_free_messages(udp_mux_skt->stfd(), mhdrs)) != srs_success) { - srs_warn("sendmsg %d msgs, err %s", mhdrs.size(), srs_error_summary(err).c_str()); - srs_freep(err); +void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* udp_mux_skt) +{ + srs_error_t err = srs_success; + + if (is_video) { + pkt->modify_rtp_header_payload_type(video_payload_type); + pkt->modify_rtp_header_ssrc(video_ssrc); + srs_verbose("send video, ssrc=%u, seq=%u, timestamp=%u", video_ssrc, pkt->rtp_header.get_sequence(), pkt->rtp_header.get_timestamp()); + } else if (is_audio) { + pkt->modify_rtp_header_payload_type(audio_payload_type); + pkt->modify_rtp_header_ssrc(audio_ssrc); } + + int length = pkt->size; + // Fetch a cached message from queue. + // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. + mmsghdr* mhdr = rtc_session->rtc_server->fetch(); + char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; + + if (rtc_session->encrypt) { + if ((err = rtc_session->dtls_session->protect_rtp(buf, pkt->payload, length)) != srs_success) { + srs_warn("srtp err %s", srs_error_desc(err).c_str()); srs_freep(err); srs_freepa(buf); + return; + } + } else { + memcpy(buf, pkt->payload, length); + } + + sockaddr_in* addr = (sockaddr_in*)udp_mux_skt->peer_addr(); + socklen_t addrlen = (socklen_t)udp_mux_skt->peer_addrlen(); + + mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; + mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; + mhdr->msg_hdr.msg_iov->iov_len = length; + mhdr->msg_len = 0; + + rtc_session->rtc_server->sendmmsg(udp_mux_skt->stfd(), mhdr); } SrsRtcSession::SrsRtcSession(SrsRtcServer* rtc_svr, const SrsRequest& req, const std::string& un, int context_id) @@ -728,7 +730,7 @@ srs_error_t SrsRtcSession::on_binding_request(SrsUdpMuxSocket* udp_mux_skt, SrsS } SrsStunPacket stun_binding_response; - char buf[1460]; + char buf[kRtpPacketSize]; SrsBuffer* stream = new SrsBuffer(buf, sizeof(buf)); SrsAutoFree(SrsBuffer, stream); @@ -1023,7 +1025,7 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* udp_mux_skt) return srs_error_new(ERROR_RTC_RTCP, "recv unexpect rtp packet before dtls done"); } - char unprotected_buf[1460]; + char unprotected_buf[kRtpPacketSize]; int nb_unprotected_buf = udp_mux_skt->size(); if ((err = dtls_session->unprotect_rtcp(unprotected_buf, udp_mux_skt->data(), nb_unprotected_buf)) != srs_success) { return srs_error_wrap(err, "rtcp unprotect failed"); @@ -1094,6 +1096,8 @@ SrsRtcServer::SrsRtcServer() waiting_msgs = false; cond = srs_cond_new(); trd = new SrsDummyCoroutine(); + + cache_pos = 0; } SrsRtcServer::~SrsRtcServer() @@ -1104,8 +1108,11 @@ SrsRtcServer::~SrsRtcServer() srs_freep(trd); srs_cond_destroy(cond); - free_messages(mmhdrs); - mmhdrs.clear(); + free_mhdrs(hotspot); + hotspot.clear(); + + free_mhdrs(cache); + cache.clear(); } srs_error_t SrsRtcServer::initialize() @@ -1344,27 +1351,42 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic return srs_success; } -srs_error_t SrsRtcServer::send_and_free_messages(srs_netfd_t stfd, const vector& msgs) +mmsghdr* SrsRtcServer::fetch() { - srs_error_t err = srs_success; + // TODO: FIXME: Maybe need to shrink? + if (cache_pos >= (int)cache.size()) { + mmsghdr mhdr; + memset(&mhdr, 0, sizeof(mmsghdr)); + mhdr.msg_hdr.msg_iovlen = 1; + mhdr.msg_hdr.msg_iov = new iovec(); + mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; + mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; + mhdr.msg_len = 0; + + cache.push_back(mhdr); + } + + return &cache[cache_pos++]; +} + +void SrsRtcServer::sendmmsg(srs_netfd_t stfd, mmsghdr* /*hdr*/) +{ mmstfd = stfd; - mmhdrs.insert(mmhdrs.end(), msgs.begin(), msgs.end()); if (waiting_msgs) { waiting_msgs = false; srs_cond_signal(cond); } - - return err; } -void SrsRtcServer::free_messages(vector& hdrs) +void SrsRtcServer::free_mhdrs(std::vector& mhdrs) { - for (int i = 0; i < (int)hdrs.size(); i++) { - msghdr* hdr = &hdrs[i].msg_hdr; - for (int j = (int)hdr->msg_iovlen - 1; j >= 0 ; j--) { - iovec* iov = hdr->msg_iov + j; + for (int i = 0; i < (int)mhdrs.size(); i++) { + mmsghdr* hdr = &mhdrs[i]; + + for (int j = (int)hdr->msg_hdr.msg_iovlen - 1; j >= 0 ; j--) { + iovec* iov = hdr->msg_hdr.msg_iov + j; char* data = (char*)iov->iov_base; srs_freep(data); srs_freep(iov); @@ -1389,17 +1411,19 @@ srs_error_t SrsRtcServer::cycle() return err; } - // TODO: FIXME: Use cond trigger. - if (mmhdrs.empty()) { + int pos = cache_pos; + if (pos <= 0) { waiting_msgs = true; srs_cond_wait(cond); + continue; } - vector mhdrs; - mmhdrs.swap(mhdrs); + // We are working on hotspot now. + cache.swap(hotspot); + cache_pos = 0; - mmsghdr* p = &mhdrs[0]; - for (mmsghdr* end = p + mhdrs.size(); p < end; p += max_sendmmsg) { + mmsghdr* p = &hotspot[0]; + for (mmsghdr* end = p + pos; p < end; p += max_sendmmsg) { int vlen = (int)(end - p); vlen = srs_min(max_sendmmsg, vlen); @@ -1415,10 +1439,8 @@ srs_error_t SrsRtcServer::cycle() if ((cnt++ % 100) == 0) { // TODO: FIXME: Support reload. max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - srs_trace("-> RTC SEND %d msgs, by sendmmsg %d", mhdrs.size(), max_sendmmsg); + srs_trace("-> RTC SEND %d msgs, by sendmmsg %d", pos, max_sendmmsg); } - - free_messages(mhdrs); } return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index e1bb21fff..9ccc297dc 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -144,6 +144,7 @@ public: void update_sendonly_socket(SrsUdpMuxSocket* ukt); private: void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* udp_mux_skt); + void send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* udp_mux_skt); }; class SrsRtcSession @@ -224,7 +225,12 @@ private: bool waiting_msgs; // TODO: FIXME: Support multiple stfd. srs_netfd_t mmstfd; - std::vector mmhdrs; + // Hotspot msgs, we are working on it. + // @remark We will wait util all messages are ready. + std::vector hotspot; + // Cache msgs, for other coroutines to fill it. + std::vector cache; + int cache_pos; private: std::map map_username_session; // key: username(local_ufrag + ":" + remote_ufrag) std::map map_id_session; // key: peerip(ip + ":" + port) @@ -255,8 +261,9 @@ public: virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); // Internal only. public: - srs_error_t send_and_free_messages(srs_netfd_t stfd, const std::vector& msgs); - void free_messages(std::vector& hdrs); + mmsghdr* fetch(); + void sendmmsg(srs_netfd_t stfd, mmsghdr* hdr); + void free_mhdrs(std::vector& mhdrs); virtual srs_error_t cycle(); }; From 9b2f429571542278a262a926ef94b4586d22e219 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 9 Apr 2020 20:43:51 +0800 Subject: [PATCH 003/131] Allows empty body metadata. --- trunk/src/protocol/srs_rtmp_stack.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 8d3a2378e..6c0889d3f 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -4539,6 +4539,11 @@ srs_error_t SrsOnMetaDataPacket::decode(SrsBuffer* stream) return srs_error_wrap(err, "name"); } } + + // Allows empty body metadata. + if (stream->empty()) { + return err; + } // the metadata maybe object or ecma array SrsAmf0Any* any = NULL; From 40eb5c0ef56bd823ef3ed4d3d8967f926c5fce55 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Apr 2020 08:55:04 +0800 Subject: [PATCH 004/131] For #307, disable vappi for FFmpeg-fit --- trunk/auto/depends.sh | 9 +++++---- trunk/configure | 12 +++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 1d72c02ab..457b371a5 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -639,10 +639,11 @@ if [[ $SRS_EXPORT_LIBRTMP_PROJECT == NO && $SRS_RTC == YES ]]; then --disable-programs --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages \ --disable-avdevice --disable-avformat --disable-swscale --disable-postproc --disable-avfilter --disable-network \ --disable-dct --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils \ - --disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-appkit --disable-coreimage \ - --disable-avfoundation --disable-securetransport --disable-iconv --disable-lzma --disable-sdl2 --disable-everything \ - --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-decoder=libopus --enable-encoder=aac \ - --enable-encoder=opus --enable-encoder=libopus --enable-libopus && + --disable-hwaccels --disable-devices --disable-audiotoolbox --disable-videotoolbox --disable-cuda-llvm --disable-cuvid \ + --disable-d3d11va --disable-dxva2 --disable-ffnvcodec --disable-nvdec --disable-nvenc --disable-v4l2-m2m --disable-vaapi \ + --disable-vdpau --disable-appkit --disable-coreimage --disable-avfoundation --disable-securetransport --disable-iconv \ + --disable-lzma --disable-sdl2 --disable-everything --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm \ + --enable-decoder=libopus --enable-encoder=aac --enable-encoder=opus --enable-encoder=libopus --enable-libopus && make ${SRS_JOBS} && make install && cd .. && rm -rf ffmpeg && ln -sf ffmpeg-4.2-fit/${SRS_PLATFORM}/_release ffmpeg ) diff --git a/trunk/configure b/trunk/configure index 3c8e71976..ed76da4d5 100755 --- a/trunk/configure +++ b/trunk/configure @@ -444,7 +444,7 @@ mv ${SRS_WORKDIR}/${SRS_MAKEFILE} ${SRS_WORKDIR}/${SRS_MAKEFILE}.bk # generate phony header cat << END > ${SRS_WORKDIR}/${SRS_MAKEFILE} .PHONY: default _default install install-api help clean destroy server srs_ingest_hls librtmp utest _prepare_dir $__mphonys -.PHONY: clean_srs clean_modules clean_openssl clean_nginx clean_cherrypy clean_srtp2 clean_opus +.PHONY: clean_srs clean_modules clean_openssl clean_nginx clean_cherrypy clean_srtp2 clean_opus clean_ffmpeg clean_st .PHONY: st ffmpeg # install prefix. @@ -481,6 +481,8 @@ help: @echo " clean_openssl Remove the openssl cache." @echo " clean_srtp2 Remove the libsrtp2 cache." @echo " clean_opus Remove the opus cache." + @echo " clean_ffmpeg Remove the FFmpeg cache." + @echo " clean_st Remove the ST cache." @echo "For example:" @echo " make" @echo " make help" @@ -519,6 +521,14 @@ clean_opus: (cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf opus-1.3.1) @echo "Please rebuild opus by: ./configure" +clean_ffmpeg: + (cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf ffmpeg-4.2-fit) + @echo "Please rebuild FFmpeg by: ./configure" + +clean_st: + (cd ${SRS_OBJS_DIR}/${SRS_PLATFORM} && rm -rf st-srs) + @echo "Please rebuild ST by: ./configure" + clean_nginx: (cd ${SRS_OBJS_DIR} && rm -rf nginx) From 94afe6c56e3a417561dbbc5b83191e9122292c33 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Apr 2020 15:44:46 +0800 Subject: [PATCH 005/131] Refactor the print message --- trunk/src/app/srs_app_rtc_conn.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e8bf756ed..386ebab65 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -970,7 +970,7 @@ block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ srs_error_t SrsRtcSession::on_connection_established(SrsUdpMuxSocket* udp_mux_skt) { - srs_trace("rtc session=%s, timeout=%dms connection established", id().c_str(), srsu2msi(sessionStunTimeout)); + srs_trace("rtc session=%s, to=%dms connection established", id().c_str(), srsu2msi(sessionStunTimeout)); return start_play(udp_mux_skt); } @@ -1400,6 +1400,7 @@ srs_error_t SrsRtcServer::cycle() // TODO: FIXME: Use pithy print. uint32_t cnt = 1; + uint64_t nn_msgs = 0; SrsStatistic* stat = SrsStatistic::instance(); @@ -1435,11 +1436,14 @@ srs_error_t SrsRtcServer::cycle() stat->perf_mw_on_packets(vlen); } + // Increase total messages. + nn_msgs += pos; + // TODO: FIXME: Use pithy print. if ((cnt++ % 100) == 0) { // TODO: FIXME: Support reload. max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - srs_trace("-> RTC SEND %d msgs, by sendmmsg %d", pos, max_sendmmsg); + srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 " msgs", pos, max_sendmmsg, nn_msgs); } } From 928d863e504ba8c7dfa8cfcb9242ca6f4a4097ab Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Apr 2020 17:42:54 +0800 Subject: [PATCH 006/131] Refactor code, use pithy print for RTC send. --- trunk/src/app/srs_app_pithy_print.cpp | 7 +++++++ trunk/src/app/srs_app_pithy_print.hpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index cef07f1de..09ae09cf6 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -112,6 +112,8 @@ SrsPithyPrint::SrsPithyPrint(int _stage_id) #define SRS_CONSTS_STAGE_EXEC 11 // for the rtc play #define SRS_CONSTS_STAGE_RTC_PLAY 12 +// for the rtc send +#define SRS_CONSTS_STAGE_RTC_SEND 13 SrsPithyPrint* SrsPithyPrint::create_rtmp_play() { @@ -173,6 +175,11 @@ SrsPithyPrint* SrsPithyPrint::create_rtc_play() return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_PLAY); } +SrsPithyPrint* SrsPithyPrint::create_rtc_send() +{ + return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_SEND); +} + SrsPithyPrint::~SrsPithyPrint() { leave_stage(); diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index c3b9f1219..77993b047 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -88,6 +88,7 @@ public: static SrsPithyPrint* create_http_stream(); static SrsPithyPrint* create_http_stream_cache(); static SrsPithyPrint* create_rtc_play(); + static SrsPithyPrint* create_rtc_send(); virtual ~SrsPithyPrint(); private: // Enter the specified stage, return the client id. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 386ebab65..ec4a5c501 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1398,12 +1398,12 @@ srs_error_t SrsRtcServer::cycle() { srs_error_t err = srs_success; - // TODO: FIXME: Use pithy print. - uint32_t cnt = 1; uint64_t nn_msgs = 0; - SrsStatistic* stat = SrsStatistic::instance(); + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); + SrsAutoFree(SrsPithyPrint, pprint); + // TODO: FIXME: Support reload. int max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); @@ -1439,8 +1439,8 @@ srs_error_t SrsRtcServer::cycle() // Increase total messages. nn_msgs += pos; - // TODO: FIXME: Use pithy print. - if ((cnt++ % 100) == 0) { + pprint->elapse(); + if (pprint->can_print()) { // TODO: FIXME: Support reload. max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 " msgs", pos, max_sendmmsg, nn_msgs); From d6a5651a3095a0b1a6d9791f381608ae7c12fd9b Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Apr 2020 18:14:33 +0800 Subject: [PATCH 007/131] For #307, support reload rtc_server section --- trunk/src/app/srs_app_config.cpp | 39 ++++++++++++++++++++++++++++++ trunk/src/app/srs_app_config.hpp | 2 ++ trunk/src/app/srs_app_reload.cpp | 5 ++++ trunk/src/app/srs_app_reload.hpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 23 ++++++++++++++---- trunk/src/app/srs_app_rtc_conn.hpp | 9 ++++++- 6 files changed, 73 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f63c3a07c..30e987ec7 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1540,6 +1540,11 @@ srs_error_t SrsConfig::reload_conf(SrsConfig* conf) if ((err = reload_http_stream(old_root)) != srs_success) { return srs_error_wrap(err, "http steram");; } + + // Merge config: rtc_server + if ((err = reload_rtc_server(old_root)) != srs_success) { + return srs_error_wrap(err, "http steram");; + } // TODO: FIXME: support reload stream_caster. @@ -1697,6 +1702,40 @@ srs_error_t SrsConfig::reload_http_stream(SrsConfDirective* old_root) return err; } +srs_error_t SrsConfig::reload_rtc_server(SrsConfDirective* old_root) +{ + srs_error_t err = srs_success; + + // merge config. + std::vector::iterator it; + + // state graph + // old_rtc_server new_rtc_server + // ENABLED => ENABLED (modified) + + SrsConfDirective* new_rtc_server = root->get("rtc_server"); + SrsConfDirective* old_rtc_server = old_root->get("rtc_server"); + + // TODO: FIXME: Support disable or enable reloading. + + // ENABLED => ENABLED (modified) + if (get_rtc_server_enabled(old_rtc_server) && get_rtc_server_enabled(new_rtc_server) + && !srs_directive_equals(old_rtc_server, new_rtc_server) + ) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((err = subscribe->on_reload_rtc_server()) != srs_success) { + return srs_error_wrap(err, "rtc server enabled"); + } + } + srs_trace("reload rtc server success."); + return err; + } + + srs_trace("reload rtc server success, nothing changed."); + return err; +} + srs_error_t SrsConfig::reload_transcode(SrsConfDirective* new_vhost, SrsConfDirective* old_vhost) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index f7f449b08..c17e26033 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -333,6 +333,8 @@ private: // Reload the http_stream section of config. // TODO: FIXME: rename to http_server. virtual srs_error_t reload_http_stream(SrsConfDirective* old_root); + // Reload the rtc_server section of config. + virtual srs_error_t reload_rtc_server(SrsConfDirective* old_root); // Reload the transcode section of vhost of config. virtual srs_error_t reload_transcode(SrsConfDirective* new_vhost, SrsConfDirective* old_vhost); // Reload the ingest section of vhost of config. diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index 175cbfc14..3546f44de 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -115,6 +115,11 @@ srs_error_t ISrsReloadHandler::on_reload_http_stream_crossdomain() return srs_success; } +srs_error_t ISrsReloadHandler::on_reload_rtc_server() +{ + return srs_success; +} + srs_error_t ISrsReloadHandler::on_reload_vhost_http_updated() { return srs_success; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 442f44ebd..a7af5e790 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -55,6 +55,7 @@ public: virtual srs_error_t on_reload_http_stream_disabled(); virtual srs_error_t on_reload_http_stream_updated(); virtual srs_error_t on_reload_http_stream_crossdomain(); + virtual srs_error_t on_reload_rtc_server(); public: // TODO: FIXME: should rename to http_static virtual srs_error_t on_reload_vhost_http_updated(); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ec4a5c501..bdcc8c705 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1098,10 +1098,14 @@ SrsRtcServer::SrsRtcServer() trd = new SrsDummyCoroutine(); cache_pos = 0; + + _srs_config->subscribe(this); } SrsRtcServer::~SrsRtcServer() { + _srs_config->unsubscribe(this); + srs_freep(listener); srs_freep(timer); @@ -1133,6 +1137,9 @@ srs_error_t SrsRtcServer::initialize() return srs_error_wrap(err, "start coroutine"); } + max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); + srs_trace("RTC server init ok, max_sendmmsg=%d", max_sendmmsg); + return err; } @@ -1351,6 +1358,17 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic return srs_success; } +srs_error_t SrsRtcServer::on_reload_rtc_server() +{ + int v = _srs_config->get_rtc_server_sendmmsg(); + if (max_sendmmsg != v) { + max_sendmmsg = v; + srs_trace("Reload max_sendmmsg=%d", max_sendmmsg); + } + + return srs_success; +} + mmsghdr* SrsRtcServer::fetch() { // TODO: FIXME: Maybe need to shrink? @@ -1404,9 +1422,6 @@ srs_error_t SrsRtcServer::cycle() SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); SrsAutoFree(SrsPithyPrint, pprint); - // TODO: FIXME: Support reload. - int max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - while (true) { if ((err = trd->pull()) != srs_success) { return err; @@ -1441,8 +1456,6 @@ srs_error_t SrsRtcServer::cycle() pprint->elapse(); if (pprint->can_print()) { - // TODO: FIXME: Support reload. - max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 " msgs", pos, max_sendmmsg, nn_msgs); } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 9ccc297dc..f7cb9137d 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -214,7 +215,8 @@ private: srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt); }; -class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, virtual public ISrsCoroutineHandler +class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, + virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler { private: SrsUdpMuxListener* listener; @@ -231,6 +233,8 @@ private: // Cache msgs, for other coroutines to fill it. std::vector cache; int cache_pos; + // The max number of messages for sendmmsg. If 1, we use sendmsg to send. + int max_sendmmsg; private: std::map map_username_session; // key: username(local_ufrag + ":" + remote_ufrag) std::map map_id_session; // key: peerip(ip + ":" + port) @@ -259,6 +263,9 @@ private: // interface ISrsHourGlass public: virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); +// interface ISrsReloadHandler +public: + virtual srs_error_t on_reload_rtc_server(); // Internal only. public: mmsghdr* fetch(); From 162055f6d0102c758a9003344d315a6a73354236 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 10 Apr 2020 19:21:47 +0800 Subject: [PATCH 008/131] Refactor variable name --- trunk/src/app/srs_app_listener.cpp | 6 +- trunk/src/app/srs_app_listener.hpp | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 151 +++++++++++++++-------------- trunk/src/app/srs_app_rtc_conn.hpp | 40 ++++---- 4 files changed, 102 insertions(+), 97 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index a88bf1af3..9f93b2cf8 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -428,9 +428,9 @@ srs_error_t SrsUdpMuxListener::cycle() return srs_error_wrap(err, "udp listener"); } - SrsUdpMuxSocket udp_mux_skt(lfd); + SrsUdpMuxSocket skt(lfd); - int nread = udp_mux_skt.recvfrom(SRS_UTIME_NO_TIMEOUT); + int nread = skt.recvfrom(SRS_UTIME_NO_TIMEOUT); if (nread <= 0) { if (nread < 0) { srs_warn("udp recv error"); @@ -439,7 +439,7 @@ srs_error_t SrsUdpMuxListener::cycle() continue; } - if ((err = handler->on_udp_packet(&udp_mux_skt)) != srs_success) { + if ((err = handler->on_udp_packet(&skt)) != srs_success) { // remux udp never return srs_warn("udp packet handler error:%s", srs_error_desc(err).c_str()); continue; diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 0222413c1..78db998bd 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -69,7 +69,7 @@ public: virtual ~ISrsUdpMuxHandler(); public: virtual srs_error_t on_stfd_change(srs_netfd_t fd); - virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* udp_mux_skt) = 0; + virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* skt) = 0; }; // The tcp connection handler. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index bdcc8c705..da3a4fc2f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -174,7 +174,7 @@ srs_error_t SrsDtlsSession::initialize(const SrsRequest& req) return err; } -srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -186,7 +186,7 @@ srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* udp_mux_skt) int ssl_err = SSL_get_error(dtls, ret); switch(ssl_err) { case SSL_ERROR_NONE: { - if ((err = on_dtls_handshake_done(udp_mux_skt)) != srs_success) { + if ((err = on_dtls_handshake_done(skt)) != srs_success) { return srs_error_wrap(err, "dtls handshake done handle"); } break; @@ -206,7 +206,7 @@ srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* udp_mux_skt) } if (out_bio_len) { - if ((err = udp_mux_skt->sendto(out_bio_data, out_bio_len, 0)) != srs_success) { + if ((err = skt->sendto(out_bio_data, out_bio_len, 0)) != srs_success) { return srs_error_wrap(err, "send dtls packet"); } } @@ -214,7 +214,7 @@ srs_error_t SrsDtlsSession::handshake(SrsUdpMuxSocket* udp_mux_skt) return err; } -srs_error_t SrsDtlsSession::on_dtls(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsDtlsSession::on_dtls(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; if (BIO_reset(bio_in) != 1) { @@ -224,13 +224,13 @@ srs_error_t SrsDtlsSession::on_dtls(SrsUdpMuxSocket* udp_mux_skt) return srs_error_new(ERROR_OpenSslBIOReset, "BIO_reset"); } - if (BIO_write(bio_in, udp_mux_skt->data(), udp_mux_skt->size()) <= 0) { + if (BIO_write(bio_in, skt->data(), skt->size()) <= 0) { // TODO: 0 or -1 maybe block, use BIO_should_retry to check. return srs_error_new(ERROR_OpenSslBIOWrite, "BIO_write"); } if (! handshake_done) { - err = handshake(udp_mux_skt); + err = handshake(skt); } else { while (BIO_ctrl_pending(bio_in) > 0) { char dtls_read_buf[8092]; @@ -247,7 +247,7 @@ srs_error_t SrsDtlsSession::on_dtls(SrsUdpMuxSocket* udp_mux_skt) return err; } -srs_error_t SrsDtlsSession::on_dtls_handshake_done(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsDtlsSession::on_dtls_handshake_done(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; srs_trace("dtls handshake done"); @@ -257,7 +257,7 @@ srs_error_t SrsDtlsSession::on_dtls_handshake_done(SrsUdpMuxSocket* udp_mux_skt) return srs_error_wrap(err, "srtp init failed"); } - return rtc_session->on_connection_established(udp_mux_skt); + return rtc_session->on_connection_established(skt); } srs_error_t SrsDtlsSession::on_dtls_application_data(const char* buf, const int nb_buf) @@ -529,13 +529,6 @@ srs_error_t SrsRtcSenderThread::cycle() return srs_error_wrap(err, "rtc sender thread"); } - pprint->elapse(); - - if (pprint->can_print()) { - // TODO: FIXME: - // Print stat like frame/s, packet/s, loss_packets. - } - #ifdef SRS_PERF_QUEUE_COND_WAIT if (realtime) { // for realtime, min required msgs is 0, send when got one+ msgs. @@ -559,20 +552,28 @@ srs_error_t SrsRtcSenderThread::cycle() continue; } - send_and_free_messages(msgs.msgs, msg_count, sendonly_ukt); + int nn = 0; + int nn_rtp_pkts = 0; + send_and_free_messages(msgs.msgs, msg_count, sendonly_ukt, &nn, &nn_rtp_pkts); + + pprint->elapse(); + if (pprint->can_print()) { + // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. + srs_trace("-> RTC PLAY %d msgs, %d packets, %d bytes", msg_count, nn_rtp_pkts, nn); + } } } -void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* ukt) +void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) { srs_trace("session %s address changed, update %s -> %s", - rtc_session->id().c_str(), sendonly_ukt->get_peer_id().c_str(), ukt->get_peer_id().c_str()); + rtc_session->id().c_str(), sendonly_ukt->get_peer_id().c_str(), skt->get_peer_id().c_str()); srs_freep(sendonly_ukt); - sendonly_ukt = ukt->copy_sendonly(); + sendonly_ukt = skt->copy_sendonly(); } -void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* udp_mux_skt) +void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts) { if (!rtc_session->dtls_session) { return; @@ -583,16 +584,20 @@ void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int bool is_video = msg->is_video(); bool is_audio = msg->is_audio(); - for (vector::iterator it = msg->rtp_packets.begin(); it != msg->rtp_packets.end(); ++it) { - SrsRtpSharedPacket* pkt = *it; - send_and_free_message(msg, is_video, is_audio, pkt, udp_mux_skt); + int nn_rtp_pkts = (int)msg->rtp_packets.size(); + for (int j = 0; j < nn_rtp_pkts; j++) { + SrsRtpSharedPacket* pkt = msg->rtp_packets[j]; + send_and_free_message(msg, is_video, is_audio, pkt, skt); } + *pnn += msg->size; + *pnn_rtp_pkts += nn_rtp_pkts; + srs_freep(msg); } } -void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* udp_mux_skt) +void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -620,15 +625,15 @@ void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is memcpy(buf, pkt->payload, length); } - sockaddr_in* addr = (sockaddr_in*)udp_mux_skt->peer_addr(); - socklen_t addrlen = (socklen_t)udp_mux_skt->peer_addrlen(); + sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); + socklen_t addrlen = (socklen_t)skt->peer_addrlen(); mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; mhdr->msg_hdr.msg_iov->iov_len = length; mhdr->msg_len = 0; - rtc_session->rtc_server->sendmmsg(udp_mux_skt->stfd(), mhdr); + rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); } SrsRtcSession::SrsRtcSession(SrsRtcServer* rtc_svr, const SrsRequest& req, const std::string& un, int context_id) @@ -673,12 +678,12 @@ void SrsRtcSession::switch_to_context() _srs_context->set_id(cid); } -srs_error_t SrsRtcSession::on_stun(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req) +srs_error_t SrsRtcSession::on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req) { srs_error_t err = srs_success; if (stun_req->is_binding_request()) { - if ((err = on_binding_request(udp_mux_skt, stun_req)) != srs_success) { + if ((err = on_binding_request(skt, stun_req)) != srs_success) { return srs_error_wrap(err, "stun binding request failed"); } @@ -687,8 +692,8 @@ srs_error_t SrsRtcSession::on_stun(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* if (strd && strd->sendonly_ukt) { // We are running in the ice-lite(server) mode. If client have multi network interface, // we only choose one candidate pair which is determined by client. - if (stun_req->get_use_candidate() && strd->sendonly_ukt->get_peer_id() != udp_mux_skt->get_peer_id()) { - strd->update_sendonly_socket(udp_mux_skt); + if (stun_req->get_use_candidate() && strd->sendonly_ukt->get_peer_id() != skt->get_peer_id()) { + strd->update_sendonly_socket(skt); } } } @@ -718,7 +723,7 @@ srs_error_t SrsRtcSession::check_source() #define be32toh ntohl #endif -srs_error_t SrsRtcSession::on_binding_request(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req) +srs_error_t SrsRtcSession::on_binding_request(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req) { srs_error_t err = srs_success; @@ -739,28 +744,28 @@ srs_error_t SrsRtcSession::on_binding_request(SrsUdpMuxSocket* udp_mux_skt, SrsS stun_binding_response.set_remote_ufrag(stun_req->get_local_ufrag()); stun_binding_response.set_transcation_id(stun_req->get_transcation_id()); // FIXME: inet_addr is deprecated, IPV6 support - stun_binding_response.set_mapped_address(be32toh(inet_addr(udp_mux_skt->get_peer_ip().c_str()))); - stun_binding_response.set_mapped_port(udp_mux_skt->get_peer_port()); + stun_binding_response.set_mapped_address(be32toh(inet_addr(skt->get_peer_ip().c_str()))); + stun_binding_response.set_mapped_port(skt->get_peer_port()); if ((err = stun_binding_response.encode(get_local_sdp()->get_ice_pwd(), stream)) != srs_success) { return srs_error_wrap(err, "stun binding response encode failed"); } - if ((err = udp_mux_skt->sendto(stream->data(), stream->pos(), 0)) != srs_success) { + if ((err = skt->sendto(stream->data(), stream->pos(), 0)) != srs_success) { return srs_error_wrap(err, "stun binding response send failed"); } if (get_session_state() == WAITING_STUN) { set_session_state(DOING_DTLS_HANDSHAKE); - peer_id = udp_mux_skt->get_peer_id(); + peer_id = skt->get_peer_id(); rtc_server->insert_into_id_sessions(peer_id, this); } return err; } -srs_error_t SrsRtcSession::on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -845,14 +850,14 @@ srs_error_t SrsRtcSession::on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSock srs_verbose("resend pkt sequence=%u", resend_pkts[i]->rtp_header.get_sequence()); dtls_session->protect_rtp(protected_buf, resend_pkts[i]->payload, nb_protected_buf); - udp_mux_skt->sendto(protected_buf, nb_protected_buf, 0); + skt->sendto(protected_buf, nb_protected_buf, 0); } } return err; } -srs_error_t SrsRtcSession::on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -899,7 +904,7 @@ srs_error_t SrsRtcSession::on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxS return err; } -srs_error_t SrsRtcSession::on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -968,18 +973,18 @@ block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ return err; } -srs_error_t SrsRtcSession::on_connection_established(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_connection_established(SrsUdpMuxSocket* skt) { srs_trace("rtc session=%s, to=%dms connection established", id().c_str(), srsu2msi(sessionStunTimeout)); - return start_play(udp_mux_skt); + return start_play(skt); } -srs_error_t SrsRtcSession::start_play(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::start_play(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; srs_freep(strd); - strd = new SrsRtcSenderThread(this, udp_mux_skt, _srs_context->get_id()); + strd = new SrsRtcSenderThread(this, skt, _srs_context->get_id()); uint32_t video_ssrc = 0; uint32_t audio_ssrc = 0; @@ -1012,12 +1017,12 @@ bool SrsRtcSession::is_stun_timeout() return last_stun_time + sessionStunTimeout < srs_get_system_time(); } -srs_error_t SrsRtcSession::on_dtls(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_dtls(SrsUdpMuxSocket* skt) { - return dtls_session->on_dtls(udp_mux_skt); + return dtls_session->on_dtls(skt); } -srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -1026,8 +1031,8 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* udp_mux_skt) } char unprotected_buf[kRtpPacketSize]; - int nb_unprotected_buf = udp_mux_skt->size(); - if ((err = dtls_session->unprotect_rtcp(unprotected_buf, udp_mux_skt->data(), nb_unprotected_buf)) != srs_success) { + int nb_unprotected_buf = skt->size(); + if ((err = dtls_session->unprotect_rtcp(unprotected_buf, skt->data(), nb_unprotected_buf)) != srs_success) { return srs_error_wrap(err, "rtcp unprotect failed"); } @@ -1050,7 +1055,7 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* udp_mux_skt) break; } case kRR: { - err = on_rtcp_receiver_report(ph, length, udp_mux_skt); + err = on_rtcp_receiver_report(ph, length, skt); break; } case kSDES: { @@ -1063,11 +1068,11 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* udp_mux_skt) break; } case kRtpFb: { - err = on_rtcp_feedback(ph, length, udp_mux_skt); + err = on_rtcp_feedback(ph, length, skt); break; } case kPsFb: { - err = on_rtcp_ps_feedback(ph, length, udp_mux_skt); + err = on_rtcp_ps_feedback(ph, length, skt); break; } default:{ @@ -1170,14 +1175,14 @@ srs_error_t SrsRtcServer::listen_udp() return err; } -srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcServer::on_udp_packet(SrsUdpMuxSocket* skt) { - if (is_stun(reinterpret_cast(udp_mux_skt->data()), udp_mux_skt->size())) { - return on_stun(udp_mux_skt); - } else if (is_dtls(reinterpret_cast(udp_mux_skt->data()), udp_mux_skt->size())) { - return on_dtls(udp_mux_skt); - } else if (is_rtp_or_rtcp(reinterpret_cast(udp_mux_skt->data()), udp_mux_skt->size())) { - return on_rtp_or_rtcp(udp_mux_skt); + if (is_stun(reinterpret_cast(skt->data()), skt->size())) { + return on_stun(skt); + } else if (is_dtls(reinterpret_cast(skt->data()), skt->size())) { + return on_dtls(skt); + } else if (is_rtp_or_rtcp(reinterpret_cast(skt->data()), skt->size())) { + return on_rtp_or_rtcp(skt); } return srs_error_new(ERROR_RTC_UDP, "unknown udp packet type"); @@ -1246,17 +1251,17 @@ SrsRtcSession* SrsRtcServer::find_rtc_session_by_peer_id(const string& peer_id) return iter->second; } -srs_error_t SrsRtcServer::on_stun(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcServer::on_stun(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; SrsStunPacket stun_req; - if ((err = stun_req.decode(udp_mux_skt->data(), udp_mux_skt->size())) != srs_success) { + if ((err = stun_req.decode(skt->data(), skt->size())) != srs_success) { return srs_error_wrap(err, "decode stun packet failed"); } srs_verbose("recv stun packet from %s, use-candidate=%d, ice-controlled=%d, ice-controlling=%d", - udp_mux_skt->get_peer_id().c_str(), stun_req.get_use_candidate(), stun_req.get_ice_controlled(), stun_req.get_ice_controlling()); + skt->get_peer_id().c_str(), stun_req.get_use_candidate(), stun_req.get_ice_controlled(), stun_req.get_ice_controlling()); std::string username = stun_req.get_username(); SrsRtcSession* rtc_session = find_rtc_session_by_username(username); @@ -1268,44 +1273,44 @@ srs_error_t SrsRtcServer::on_stun(SrsUdpMuxSocket* udp_mux_skt) // to make all logs write to the "correct" pid+cid. rtc_session->switch_to_context(); - return rtc_session->on_stun(udp_mux_skt, &stun_req); + return rtc_session->on_stun(skt, &stun_req); } -srs_error_t SrsRtcServer::on_dtls(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcServer::on_dtls(SrsUdpMuxSocket* skt) { - SrsRtcSession* rtc_session = find_rtc_session_by_peer_id(udp_mux_skt->get_peer_id()); + SrsRtcSession* rtc_session = find_rtc_session_by_peer_id(skt->get_peer_id()); if (rtc_session == NULL) { - return srs_error_new(ERROR_RTC_DTLS, "can not find rtc session by peer_id=%s", udp_mux_skt->get_peer_id().c_str()); + return srs_error_new(ERROR_RTC_DTLS, "can not find rtc session by peer_id=%s", skt->get_peer_id().c_str()); } // Now, we got the RTC session to handle the packet, switch to its context // to make all logs write to the "correct" pid+cid. rtc_session->switch_to_context(); - return rtc_session->on_dtls(udp_mux_skt); + return rtc_session->on_dtls(skt); } -srs_error_t SrsRtcServer::on_rtp_or_rtcp(SrsUdpMuxSocket* udp_mux_skt) +srs_error_t SrsRtcServer::on_rtp_or_rtcp(SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; - SrsRtcSession* rtc_session = find_rtc_session_by_peer_id(udp_mux_skt->get_peer_id()); + SrsRtcSession* rtc_session = find_rtc_session_by_peer_id(skt->get_peer_id()); if (rtc_session == NULL) { - return srs_error_new(ERROR_RTC_RTP, "can not find rtc session by peer_id=%s", udp_mux_skt->get_peer_id().c_str()); + return srs_error_new(ERROR_RTC_RTP, "can not find rtc session by peer_id=%s", skt->get_peer_id().c_str()); } // Now, we got the RTC session to handle the packet, switch to its context // to make all logs write to the "correct" pid+cid. rtc_session->switch_to_context(); - if (is_rtcp(reinterpret_cast(udp_mux_skt->data()), udp_mux_skt->size())) { - err = rtc_session->on_rtcp(udp_mux_skt); + if (is_rtcp(reinterpret_cast(skt->data()), skt->size())) { + err = rtc_session->on_rtcp(skt); } else { // We disable it because no RTP for player. // see https://github.com/ossrs/srs/blob/018577e685a07d9de7a47354e7a9c5f77f5f4202/trunk/src/app/srs_app_rtc_conn.cpp#L1081 - // err = rtc_session->on_rtp(udp_mux_skt); + // err = rtc_session->on_rtp(skt); } return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index f7cb9137d..f448778b9 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -99,8 +99,8 @@ public: srs_error_t initialize(const SrsRequest& req); - srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_dtls_handshake_done(SrsUdpMuxSocket* udp_mux_skt); + srs_error_t on_dtls(SrsUdpMuxSocket* skt); + srs_error_t on_dtls_handshake_done(SrsUdpMuxSocket* skt); srs_error_t on_dtls_application_data(const char* data, const int len); public: srs_error_t protect_rtp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); @@ -108,7 +108,7 @@ public: srs_error_t protect_rtcp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); srs_error_t unprotect_rtcp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); private: - srs_error_t handshake(SrsUdpMuxSocket* udp_mux_skt); + srs_error_t handshake(SrsUdpMuxSocket* skt); private: srs_error_t srtp_initialize(); srs_error_t srtp_send_init(); @@ -142,10 +142,10 @@ public: public: virtual srs_error_t cycle(); public: - void update_sendonly_socket(SrsUdpMuxSocket* ukt); + void update_sendonly_socket(SrsUdpMuxSocket* skt); private: - void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* udp_mux_skt); - void send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* udp_mux_skt); + void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); + void send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); }; class SrsRtcSession @@ -196,23 +196,23 @@ public: void switch_to_context(); public: - srs_error_t on_stun(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req); - srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_rtcp(SrsUdpMuxSocket* udp_mux_skt); + srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req); + srs_error_t on_dtls(SrsUdpMuxSocket* skt); + srs_error_t on_rtcp(SrsUdpMuxSocket* skt); public: - srs_error_t send_client_hello(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_connection_established(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t start_play(SrsUdpMuxSocket* udp_mux_skt); + srs_error_t send_client_hello(SrsUdpMuxSocket* skt); + srs_error_t on_connection_established(SrsUdpMuxSocket* skt); + srs_error_t start_play(SrsUdpMuxSocket* skt); public: bool is_stun_timeout(); private: srs_error_t check_source(); private: - srs_error_t on_binding_request(SrsUdpMuxSocket* udp_mux_skt, SrsStunPacket* stun_req); + srs_error_t on_binding_request(SrsUdpMuxSocket* skt, SrsStunPacket* stun_req); private: - srs_error_t on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* udp_mux_skt); + srs_error_t on_rtcp_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt); + srs_error_t on_rtcp_ps_feedback(char* buf, int nb_buf, SrsUdpMuxSocket* skt); + srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* skt); }; class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, @@ -247,16 +247,16 @@ public: // TODO: FIXME: Support gracefully quit. // TODO: FIXME: Support reload. virtual srs_error_t listen_udp(); - virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* udp_mux_skt); + virtual srs_error_t on_udp_packet(SrsUdpMuxSocket* skt); public: virtual srs_error_t listen_api(); SrsRtcSession* create_rtc_session(const SrsRequest& req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip); bool insert_into_id_sessions(const std::string& peer_id, SrsRtcSession* rtc_session); void check_and_clean_timeout_session(); private: - srs_error_t on_stun(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_dtls(SrsUdpMuxSocket* udp_mux_skt); - srs_error_t on_rtp_or_rtcp(SrsUdpMuxSocket* udp_mux_skt); + srs_error_t on_stun(SrsUdpMuxSocket* skt); + srs_error_t on_dtls(SrsUdpMuxSocket* skt); + srs_error_t on_rtp_or_rtcp(SrsUdpMuxSocket* skt); private: SrsRtcSession* find_rtc_session_by_username(const std::string& ufrag); SrsRtcSession* find_rtc_session_by_peer_id(const std::string& peer_id); From fca81f02f5554022d10e4f0246b8e5402929cb12 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 09:00:50 +0800 Subject: [PATCH 009/131] Refactor code, add comment when string.assign(xx, 0) --- trunk/src/app/srs_app_rtc.cpp | 2 ++ trunk/src/main/srs_main_server.cpp | 2 +- trunk/src/utest/srs_utest_kernel.cpp | 51 +++++++++++++++++----------- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 8424216ce..64c654fc7 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -105,8 +105,10 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, srs_error_t err = srs_success; if (format->is_avc_sequence_header()) { + // It is ok when size is 0, @see http://www.cplusplus.com/reference/string/string/assign/ sps.assign(format->vcodec->sequenceParameterSetNALUnit.data(), format->vcodec->sequenceParameterSetNALUnit.size()); pps.assign(format->vcodec->pictureParameterSetNALUnit.data(), format->vcodec->pictureParameterSetNALUnit.size()); + // only collect SPS/PPS. return err; } diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index e4641285c..8195d0020 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -209,7 +209,7 @@ srs_error_t do_main(int argc, char** argv) int main(int argc, char** argv) { srs_error_t err = do_main(argc, argv); - + if (err != srs_success) { srs_error("Failed, %s", srs_error_desc(err).c_str()); } diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 29638dceb..72395fc61 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4869,20 +4869,20 @@ VOID TEST(KernelMP4Test, CoverMP4CodecSingleFrame) // Sequence header. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); // Frame group #0 HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); } @@ -4984,20 +4984,20 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleVideos) // Sequence header. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); // Frames order by dts asc. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(40, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(40, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); } } @@ -5082,24 +5082,24 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleCTTs) // Sequence header. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); // Frames order by dts asc. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(40, (int)dts); EXPECT_EQ(80, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(40, (int)dts); EXPECT_EQ(80, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(80, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(80, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); } } @@ -5194,28 +5194,28 @@ VOID TEST(KernelMP4Test, CoverMP4MultipleAVs) // Sequence header. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(41, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(2, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_EQ(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); // Frames order by dts asc. HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(0, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(20, (int)dts); EXPECT_EQ(87, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(20, (int)dts); EXPECT_EQ(87, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeSOUN, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); HELPER_EXPECT_SUCCESS(dec.read_sample(&ht, &ft, &ct, &dts, &pts, &sample, &nb_sample)); - EXPECT_EQ(40, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); + EXPECT_EQ(40, (int)dts); EXPECT_EQ(40, (int)pts); EXPECT_EQ(127, (int)nb_sample); EXPECT_EQ(SrsMp4HandlerTypeVIDE, ht); EXPECT_NE(SrsAudioAacFrameTraitSequenceHeader, ct); srs_freepa(sample); } } @@ -5338,3 +5338,16 @@ VOID TEST(KernelMP4Test, CoverMP4M2tsSegmentEncoder) HELPER_EXPECT_SUCCESS(enc.flush(dts)); } +VOID TEST(KernelUtilityTest, CoverStringAssign) +{ + string sps = "SRS"; + ASSERT_STREQ("SRS", sps.c_str()); + + sps.assign("Hello", 5); + ASSERT_STREQ("Hello", sps.c_str()); + + sps.assign("World", 0); + ASSERT_EQ(0, (int)sps.length()); + ASSERT_STREQ("", sps.c_str()); +} + From 1ecd8bee40ee0354a285242d9f46eeb6352f0b86 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 09:11:34 +0800 Subject: [PATCH 010/131] Refactor bframe discard strategy --- trunk/src/app/srs_app_rtc.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 64c654fc7..90cb8dd46 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -121,8 +121,9 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, uint8_t header = sample.bytes[0]; uint8_t nal_type = header & kNalTypeMask; - // TODO: Use config to determine should check avc stream. - if (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR) { + // Because RTC does not support B-frame, so we will drop them. + // TODO: Drop B-frame in better way, which not cause picture corruption. + if (discard_bframe && (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR)) { SrsBuffer* stream = new SrsBuffer(sample.bytes, sample.size); SrsAutoFree(SrsBuffer, stream); @@ -142,9 +143,7 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, srs_verbose("nal_type=%d, slice type=%d", nal_type, slice_type); if (slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1) { - if (discard_bframe) { - continue; - } + continue; } } From a1371fe93c013cce785a5be7d04f71dbe7dce9a1 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 09:11:46 +0800 Subject: [PATCH 011/131] Fix utest warnings --- trunk/src/utest/srs_utest_config.cpp | 116 ++++++++++++------------- trunk/src/utest/srs_utest_protocol.cpp | 28 +++--- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index 1d03cefda..ec6bef58f 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -2010,7 +2010,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost) if (true) { HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF)); - EXPECT_EQ(0, conf.get_hls_dispose("")); + EXPECT_EQ(0, (int)conf.get_hls_dispose("")); EXPECT_EQ(10 * SRS_UTIME_SECONDS, conf.get_hls_fragment("")); EXPECT_EQ(60 * SRS_UTIME_SECONDS, conf.get_hls_window("")); @@ -2033,7 +2033,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost) if (true) { HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF)); EXPECT_EQ(30 * SRS_UTIME_SECONDS, conf.get_queue_length("")); - EXPECT_EQ(0, conf.get_send_min_interval("")); + EXPECT_EQ(0, (int)conf.get_send_min_interval("")); HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost v{play{queue_length 100;send_min_interval 10;}}")); EXPECT_EQ(100 * SRS_UTIME_SECONDS, conf.get_queue_length("v")); @@ -2042,7 +2042,7 @@ VOID TEST(ConfigUnitTest, CheckDefaultValuesVhost) if (true) { HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF)); - EXPECT_EQ(0, conf.get_vhost_http_remux_fast_cache("")); + EXPECT_EQ(0, (int)conf.get_vhost_http_remux_fast_cache("")); HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost v{http_remux{fast_cache 10;}}")); EXPECT_EQ(10 * SRS_UTIME_SECONDS, conf.get_vhost_http_remux_fast_cache("v")); @@ -2768,19 +2768,19 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF)); - EXPECT_EQ(0, conf.get_stream_casters().size()); + EXPECT_EQ(0, (int)conf.get_stream_casters().size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); - EXPECT_EQ(1, conf.get_stream_casters().size()); + EXPECT_EQ(1, (int)conf.get_stream_casters().size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster; stream_caster;")); - EXPECT_EQ(2, conf.get_stream_casters().size()); + EXPECT_EQ(2, (int)conf.get_stream_casters().size()); } if (true) { @@ -2788,7 +2788,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_FALSE(conf.get_stream_caster_enabled(arr.at(0))); } @@ -2798,7 +2798,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {enabled off;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_FALSE(conf.get_stream_caster_enabled(arr.at(0))); } @@ -2808,7 +2808,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {enabled on;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_TRUE(conf.get_stream_caster_enabled(arr.at(0))); } @@ -2818,7 +2818,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_TRUE(conf.get_stream_caster_output(arr.at(0)).empty()); } @@ -2828,7 +2828,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {output xxx;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("xxx", conf.get_stream_caster_output(arr.at(0)).c_str()); } @@ -2838,9 +2838,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); - EXPECT_EQ(0, conf.get_stream_caster_listen(arr.at(0))); + EXPECT_EQ(0, (int)conf.get_stream_caster_listen(arr.at(0))); } if (true) { @@ -2848,7 +2848,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {listen 8080;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(8080, conf.get_stream_caster_listen(arr.at(0))); } @@ -2858,9 +2858,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); - EXPECT_EQ(0, conf.get_stream_caster_rtp_port_min(arr.at(0))); + EXPECT_EQ(0, (int)conf.get_stream_caster_rtp_port_min(arr.at(0))); } if (true) { @@ -2868,7 +2868,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {rtp_port_min 8080;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(8080, conf.get_stream_caster_rtp_port_min(arr.at(0))); } @@ -2878,9 +2878,9 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster;")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); - EXPECT_EQ(0, conf.get_stream_caster_rtp_port_max(arr.at(0))); + EXPECT_EQ(0, (int)conf.get_stream_caster_rtp_port_max(arr.at(0))); } if (true) { @@ -2888,7 +2888,7 @@ VOID TEST(ConfigMainTest, CheckStreamCaster) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stream_caster {rtp_port_max 8080;}")); vector arr = conf.get_stream_casters(); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(8080, conf.get_stream_caster_rtp_port_max(arr.at(0))); } @@ -2912,14 +2912,14 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2) EXPECT_TRUE(conf.get_debug_srs_upnode("ossrs.net")); EXPECT_FALSE(conf.get_atc("ossrs.net")); EXPECT_FALSE(conf.get_atc_auto("ossrs.net")); - EXPECT_EQ(1, conf.get_time_jitter("ossrs.net")); + EXPECT_EQ(1, (int)conf.get_time_jitter("ossrs.net")); EXPECT_FALSE(conf.get_mix_correct("ossrs.net")); EXPECT_EQ(30 * SRS_UTIME_SECONDS, conf.get_queue_length("ossrs.net")); EXPECT_FALSE(conf.get_refer_enabled("ossrs.net")); EXPECT_TRUE(conf.get_refer_all("ossrs.net") == NULL); EXPECT_TRUE(conf.get_refer_play("ossrs.net") == NULL); EXPECT_TRUE(conf.get_refer_publish("ossrs.net") == NULL); - EXPECT_EQ(0, conf.get_in_ack_size("ossrs.net")); + EXPECT_EQ(0, (int)conf.get_in_ack_size("ossrs.net")); EXPECT_EQ(2500000, conf.get_out_ack_size("ossrs.net")); EXPECT_EQ(60000, conf.get_chunk_size("ossrs.net")); EXPECT_TRUE(conf.get_parse_sps("ossrs.net")); @@ -2928,7 +2928,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2) EXPECT_EQ(350 * SRS_UTIME_MILLISECONDS, conf.get_mw_sleep("ossrs.net")); EXPECT_FALSE(conf.get_realtime_enabled("ossrs.net")); EXPECT_FALSE(conf.get_tcp_nodelay("ossrs.net")); - EXPECT_EQ(0, conf.get_send_min_interval("ossrs.net")); + EXPECT_EQ(0, (int)conf.get_send_min_interval("ossrs.net")); EXPECT_FALSE(conf.get_reduce_sequence_header("ossrs.net")); EXPECT_EQ(20000000, conf.get_publish_1stpkt_timeout("ossrs.net")); EXPECT_EQ(5000000, conf.get_publish_normal_timeout("ossrs.net")); @@ -3065,7 +3065,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig2) if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{play{time_jitter zero;}}")); - EXPECT_EQ(2, conf.get_time_jitter("ossrs.net")); + EXPECT_EQ(2, (int)conf.get_time_jitter("ossrs.net")); } if (true) { @@ -3132,7 +3132,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig3) EXPECT_FALSE(conf.get_vhost_edge_token_traverse("ossrs.net")); EXPECT_STREQ("[vhost]", conf.get_vhost_edge_transform_vhost("ossrs.net").c_str()); EXPECT_FALSE(conf.get_vhost_origin_cluster("ossrs.net")); - EXPECT_EQ(0, conf.get_vhost_coworkers("ossrs.net").size()); + EXPECT_EQ(0, (int)conf.get_vhost_coworkers("ossrs.net").size()); EXPECT_FALSE(conf.get_security_enabled("ossrs.net")); EXPECT_TRUE(conf.get_security_rules("ossrs.net") == NULL); } @@ -3152,7 +3152,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig3) if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{cluster{coworkers xxx;}}")); - EXPECT_EQ(1, conf.get_vhost_coworkers("ossrs.net").size()); + EXPECT_EQ(1, (int)conf.get_vhost_coworkers("ossrs.net").size()); } if (true) { @@ -3286,14 +3286,14 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) EXPECT_TRUE(conf.get_transcode("ossrs.net", "") == NULL); EXPECT_FALSE(conf.get_transcode_enabled(conf.get_transcode("ossrs.net", ""))); EXPECT_TRUE(conf.get_transcode_ffmpeg(conf.get_transcode("ossrs.net", "")).empty()); - EXPECT_EQ(0, conf.get_transcode_engines(conf.get_transcode("ossrs.net", "")).size()); + EXPECT_EQ(0, (int)conf.get_transcode_engines(conf.get_transcode("ossrs.net", "")).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{output xxx;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("xxx", conf.get_engine_output(arr.at(0)).c_str()); } @@ -3301,7 +3301,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{oformat flv;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("flv", conf.get_engine_oformat(arr.at(0)).c_str()); } @@ -3309,15 +3309,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{aparams {i;}}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); - EXPECT_EQ(1, conf.get_engine_aparams(arr.at(0)).size()); + ASSERT_EQ(1, (int)arr.size()); + EXPECT_EQ(1, (int)conf.get_engine_aparams(arr.at(0)).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{achannels 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_achannels(arr.at(0))); } @@ -3325,7 +3325,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{asample_rate 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_asample_rate(arr.at(0))); } @@ -3333,7 +3333,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{abitrate 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_abitrate(arr.at(0))); } @@ -3341,7 +3341,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{acodec aac;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("aac", conf.get_engine_acodec(arr.at(0)).c_str()); } @@ -3349,15 +3349,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vparams {t;}}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); - EXPECT_EQ(1, conf.get_engine_vparams(arr.at(0)).size()); + ASSERT_EQ(1, (int)arr.size()); + EXPECT_EQ(1, (int)conf.get_engine_vparams(arr.at(0)).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vpreset main;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("main", conf.get_engine_vpreset(arr.at(0)).c_str()); } @@ -3365,7 +3365,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vprofile main;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("main", conf.get_engine_vprofile(arr.at(0)).c_str()); } @@ -3373,7 +3373,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vthreads 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_vthreads(arr.at(0))); } @@ -3381,7 +3381,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vheight 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_vheight(arr.at(0))); } @@ -3389,7 +3389,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vwidth 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_vwidth(arr.at(0))); } @@ -3397,7 +3397,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfps 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_vfps(arr.at(0))); } @@ -3405,7 +3405,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vbitrate 1000;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_EQ(1000, conf.get_engine_vbitrate(arr.at(0))); } @@ -3413,7 +3413,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vcodec x264;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("x264", conf.get_engine_vcodec(arr.at(0)).c_str()); } @@ -3421,23 +3421,23 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfilter {i;}}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); - EXPECT_EQ(1, conf.get_engine_vfilter(arr.at(0)).size()); + ASSERT_EQ(1, (int)arr.size()); + EXPECT_EQ(1, (int)conf.get_engine_vfilter(arr.at(0)).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{vfilter {i logo.png;}}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); - EXPECT_EQ(2, conf.get_engine_vfilter(arr.at(0)).size()); + ASSERT_EQ(1, (int)arr.size()); + EXPECT_EQ(2, (int)conf.get_engine_vfilter(arr.at(0)).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{iformat mp4;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_STREQ("mp4", conf.get_engine_iformat(arr.at(0)).c_str()); } @@ -3445,15 +3445,15 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{perfile {re;}}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); - EXPECT_EQ(1, conf.get_engine_perfile(arr.at(0)).size()); + ASSERT_EQ(1, (int)arr.size()); + EXPECT_EQ(1, (int)conf.get_engine_perfile(arr.at(0)).size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine{enabled on;}}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); EXPECT_TRUE(conf.get_engine_enabled(arr.at(0))); } @@ -3461,7 +3461,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{transcode xxx{engine;}}")); vector arr = conf.get_transcode_engines(conf.get_transcode("ossrs.net", "xxx")); - ASSERT_EQ(1, arr.size()); + ASSERT_EQ(1, (int)arr.size()); } if (true) { @@ -3492,13 +3492,13 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5) HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{exec{enabled on;publish xxx;}}")); EXPECT_TRUE(conf.get_exec("ossrs.net") != NULL); EXPECT_TRUE(conf.get_exec_enabled("ossrs.net")); - EXPECT_EQ(1, conf.get_exec_publishs("ossrs.net").size()); + EXPECT_EQ(1, (int)conf.get_exec_publishs("ossrs.net").size()); } if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{ingest xxx{enabled on;ffmpeg xxx2;input{type xxx3;url xxx4;}}}")); - EXPECT_EQ(1, conf.get_ingesters("ossrs.net").size()); + EXPECT_EQ(1, (int)conf.get_ingesters("ossrs.net").size()); ASSERT_TRUE(conf.get_ingest_by_id("ossrs.net", "xxx") != NULL); EXPECT_TRUE(conf.get_ingest_enabled(conf.get_ingest_by_id("ossrs.net", "xxx"))); EXPECT_STREQ("xxx2", conf.get_ingest_ffmpeg(conf.get_ingest_by_id("ossrs.net", "xxx")).c_str()); @@ -3584,7 +3584,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5) EXPECT_STREQ("xxx2", conf.get_dvr_plan("ossrs.net").c_str()); EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dvr_duration("ossrs.net")); EXPECT_TRUE(conf.get_dvr_wait_keyframe("ossrs.net")); - EXPECT_EQ(1, conf.get_dvr_time_jitter("ossrs.net")); + EXPECT_EQ(1, (int)conf.get_dvr_time_jitter("ossrs.net")); } if (true) { @@ -3637,7 +3637,7 @@ VOID TEST(ConfigMainTest, CheckVhostConfig5) if (true) { MockSrsConfig conf; HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stats{network 0;disk xxx;}")); - EXPECT_EQ(0, conf.get_stats_network()); + EXPECT_EQ(0, (int)conf.get_stats_network()); EXPECT_TRUE(conf.get_stats_disk_device() != NULL); } } diff --git a/trunk/src/utest/srs_utest_protocol.cpp b/trunk/src/utest/srs_utest_protocol.cpp index 2b13b2835..ebd260aa1 100644 --- a/trunk/src/utest/srs_utest_protocol.cpp +++ b/trunk/src/utest/srs_utest_protocol.cpp @@ -5855,7 +5855,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) HELPER_EXPECT_SUCCESS(parser.parse("HelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld")); EXPECT_EQ(80, (int)parser.parsed); EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(0, parser.parser->content_length); + EXPECT_EQ(0, (int)parser.parser->content_length); } if (true) { @@ -5864,7 +5864,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHel")); EXPECT_EQ(73, (int)parser.parsed); EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(2, parser.parser->content_length); + EXPECT_EQ(2, (int)parser.parser->content_length); } if (true) { @@ -5881,7 +5881,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 34, nparsed = 34, nread = 34 HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHo")); EXPECT_EQ(34, (int)parser.parsed); - EXPECT_EQ(34, parser.parser->nread); + EXPECT_EQ(34, (int)parser.parser->nread); // size = 41, nparsed = 41, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("st: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); @@ -5894,7 +5894,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 41, nparsed = 41, nread = 41 HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: oss")); EXPECT_EQ(41, (int)parser.parsed); - EXPECT_EQ(41, parser.parser->nread); + EXPECT_EQ(41, (int)parser.parser->nread); // size = 34, nparsed = 34, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("rs.net\r\nContent-Length: 5\r\n\r\nHello")); @@ -5907,7 +5907,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 48, nparsed = 48, nread = 48 HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r")); EXPECT_EQ(48, (int)parser.parsed); - EXPECT_EQ(48, parser.parser->nread); + EXPECT_EQ(48, (int)parser.parser->nread); // size = 27, nparsed = 27, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello")); @@ -5920,7 +5920,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 68, nparsed = 68, nread = 68 HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n")); EXPECT_EQ(68, (int)parser.parsed); - EXPECT_EQ(68, parser.parser->nread); + EXPECT_EQ(68, (int)parser.parser->nread); // size = 7, nparsed = 7, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello")); @@ -5933,7 +5933,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 69, nparsed = 69, nread = 69 HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r")); EXPECT_EQ(69, (int)parser.parsed); - EXPECT_EQ(69, parser.parser->nread); + EXPECT_EQ(69, (int)parser.parser->nread); // size = 6, nparsed = 6, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\nHello")); @@ -5954,12 +5954,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // nparsed = 2, size = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, parser.parser->nread); + EXPECT_EQ(2, (int)parser.parser->nread); // size = 0, nparsed = 1, nread=2 HELPER_EXPECT_FAILED(parser.parse("")); EXPECT_EQ(1, (int)parser.parsed); - EXPECT_EQ(2, parser.parser->nread); + EXPECT_EQ(2, (int)parser.parser->nread); } if (true) { @@ -5967,12 +5967,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 2, nparsed = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, parser.parser->nread); + EXPECT_EQ(2, (int)parser.parser->nread); // size = 1, nparsed = 0, nread = 3 HELPER_EXPECT_FAILED(parser.parse("X")); EXPECT_EQ(0, (int)parser.parsed); - EXPECT_EQ(3, parser.parser->nread); + EXPECT_EQ(3, (int)parser.parser->nread); } if (true) { @@ -5980,12 +5980,12 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 2, nparsed = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, parser.parser->nread); + EXPECT_EQ(2, (int)parser.parser->nread); // size = 1, nparsed = 1, nread = 3 HELPER_EXPECT_SUCCESS(parser.parse("T")); EXPECT_EQ(1, (int)parser.parsed); - EXPECT_EQ(3, parser.parser->nread); + EXPECT_EQ(3, (int)parser.parser->nread); } if (true) { @@ -5993,7 +5993,7 @@ VOID TEST(ProtocolHTTPTest, HTTPParser) // size = 3, nparsed = 3, nread = 3 HELPER_EXPECT_SUCCESS(parser.parse("GET")); EXPECT_EQ(3, (int)parser.parsed); - EXPECT_EQ(3, parser.parser->nread); + EXPECT_EQ(3, (int)parser.parser->nread); } } From a695afb368ef93d219ed44dafae3d52345c2fc13 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 09:56:58 +0800 Subject: [PATCH 012/131] Refactor code to rename rtp_shared_pkt to packet --- trunk/src/app/srs_app_rtc.cpp | 57 +++++++++++++++++------------------ trunk/src/app/srs_app_rtc.hpp | 8 ++--- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 90cb8dd46..e734e1e5e 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -113,7 +113,7 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, return err; } - vector rtp_packet_vec; + vector rtp_packets; for (int i = 0; i < format->video->nb_samples; ++i) { SrsSample sample = format->video->samples[i]; @@ -148,30 +148,30 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, } if (sample.size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(shared_frame, format, &sample, rtp_packet_vec)) != srs_success) { + if ((err = packet_single_nalu(shared_frame, format, &sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } } else { - if ((err = packet_fu_a(shared_frame, format, &sample, rtp_packet_vec)) != srs_success) { + if ((err = packet_fu_a(shared_frame, format, &sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } } } - if (! rtp_packet_vec.empty()) { + if (!rtp_packets.empty()) { // At the end of the frame, set marker bit. // One frame may have multi nals. Set the marker bit in the last nal end, no the end of the nal. - if ((err = rtp_packet_vec.back()->modify_rtp_header_marker(true)) != srs_success) { + if ((err = rtp_packets.back()->modify_rtp_header_marker(true)) != srs_success) { return srs_error_wrap(err, "set marker"); } } - shared_frame->set_rtp_packets(rtp_packet_vec); + shared_frame->set_rtp_packets(rtp_packets); return err; } -srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packet_vec) +srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) { srs_error_t err = srs_success; @@ -181,7 +181,7 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF uint8_t nal_type = header & kNalTypeMask; if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packet_vec)) != srs_success) { + if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet stap-a"); } } @@ -212,44 +212,43 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF srs_verbose("rtp fu-a nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); - SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket(); - if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { return srs_error_wrap(err, "rtp packet encode"); } - rtp_packet_vec.push_back(rtp_shared_pkt); + rtp_packets.push_back(packet); } return err; } -srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packet_vec) +srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) { srs_error_t err = srs_success; uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packet_vec)) != srs_success) { + if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet stap-a"); } } srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); - SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket(); - if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) { + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) { return srs_error_wrap(err, "rtp packet encode"); } - rtp_packet_vec.push_back(rtp_shared_pkt); + rtp_packets.push_back(packet); return err; } -srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsSharedPtrMessage* shared_frame, vector& rtp_packet_vec) +srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsSharedPtrMessage* shared_frame, vector& rtp_packets) { srs_error_t err = srs_success; @@ -277,12 +276,12 @@ srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", (sps.size() + pps.size()), sequence, (shared_frame->timestamp * 90)); - SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket(); - if ((err = rtp_shared_pkt->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { return srs_error_wrap(err, "rtp packet encode"); } - rtp_packet_vec.push_back(rtp_shared_pkt); + rtp_packets.push_back(packet); return err; } @@ -319,7 +318,7 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, { srs_error_t err = srs_success; - vector rtp_packet_vec; + vector rtp_packets; char* data_ptr[kArrayLength]; static char data_array[kArrayLength][kArrayBuffer]; @@ -342,28 +341,28 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsSample sample; sample.size = elen[i]; sample.bytes = data_ptr[i]; - packet_opus(shared_audio, &sample, rtp_packet_vec); + packet_opus(shared_audio, &sample, rtp_packets); } - shared_audio->set_rtp_packets(rtp_packet_vec); + shared_audio->set_rtp_packets(rtp_packets); return err; } -srs_error_t SrsRtpOpusMuxer::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packet_vec) +srs_error_t SrsRtpOpusMuxer::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets) { srs_error_t err = srs_success; - SrsRtpSharedPacket* rtp_shared_pkt = new SrsRtpSharedPacket(); - rtp_shared_pkt->rtp_header.set_marker(true); - if ((err = rtp_shared_pkt->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + packet->rtp_header.set_marker(true); + if ((err = packet->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { return srs_error_wrap(err, "rtp packet encode"); } // TODO: FIXME: Why 960? Need Refactoring? timestamp += 960; - rtp_packet_vec.push_back(rtp_shared_pkt); + rtp_packets.push_back(packet); return err; } diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index cf3e36a31..45d78c8a2 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -83,9 +83,9 @@ public: public: srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_video, SrsFormat* format); private: - srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packet_vec); - srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packet_vec); - srs_error_t packet_stap_a(const std::string &sps, const std::string& pps, SrsSharedPtrMessage* shared_frame, std::vector& rtp_packet_vec); + srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packets); + srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packets); + srs_error_t packet_stap_a(const std::string &sps, const std::string& pps, SrsSharedPtrMessage* shared_frame, std::vector& rtp_packets); }; // TODO: FIXME: It's not a muxer, but a transcoder. @@ -103,7 +103,7 @@ public: public: srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer* stream); private: - srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packet_vec); + srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); }; class SrsRtc From 719c0ae85b26cef60c6109a975d103f0346a0725 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 13:10:27 +0800 Subject: [PATCH 013/131] For #307, refactor SPS/PPS only before IDR, not each FUA --- trunk/src/app/srs_app_rtc.cpp | 34 ++++++++++++--------------- trunk/src/app/srs_app_sdp.cpp | 8 +++++++ trunk/src/kernel/srs_kernel_codec.cpp | 7 ++++++ trunk/src/kernel/srs_kernel_codec.hpp | 2 ++ 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index e734e1e5e..c44d203df 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -115,16 +115,23 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, vector rtp_packets; - for (int i = 0; i < format->video->nb_samples; ++i) { - SrsSample sample = format->video->samples[i]; + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (format->video && format->video->has_idr) { + if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + } - uint8_t header = sample.bytes[0]; + for (int i = 0; i < format->video->nb_samples; ++i) { + SrsSample* sample = &format->video->samples[i]; + + uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; // Because RTC does not support B-frame, so we will drop them. // TODO: Drop B-frame in better way, which not cause picture corruption. if (discard_bframe && (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR)) { - SrsBuffer* stream = new SrsBuffer(sample.bytes, sample.size); + SrsBuffer* stream = new SrsBuffer(sample->bytes, sample->size); SrsAutoFree(SrsBuffer, stream); // Skip nalu header. @@ -147,12 +154,12 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, } } - if (sample.size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(shared_frame, format, &sample, rtp_packets)) != srs_success) { + if (sample->size <= kRtpMaxPayloadSize) { + if ((err = packet_single_nalu(shared_frame, format, sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } } else { - if ((err = packet_fu_a(shared_frame, format, &sample, rtp_packets)) != srs_success) { + if ((err = packet_fu_a(shared_frame, format, sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } } @@ -180,12 +187,6 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - } - int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize; for (int i = 0; i < num_of_packet; ++i) { char buf[kRtpPacketSize]; @@ -223,6 +224,7 @@ srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsF return err; } +// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) { srs_error_t err = srs_success; @@ -230,12 +232,6 @@ srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_fram uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - if (nal_type == SrsAvcNaluTypeIDR) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - } - srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); diff --git a/trunk/src/app/srs_app_sdp.cpp b/trunk/src/app/srs_app_sdp.cpp index f5f4ee47f..c67dbd9a4 100644 --- a/trunk/src/app/srs_app_sdp.cpp +++ b/trunk/src/app/srs_app_sdp.cpp @@ -78,6 +78,14 @@ srs_error_t parse_h264_fmtp(const std::string& fmtp, H264SpecificParam& h264_par if (kv[0] == "profile-level-id") { h264_param.profile_level_id = kv[1]; } else if (kv[0] == "packetization-mode") { + // 6.3. Non-Interleaved Mode + // This mode is in use when the value of the OPTIONAL packetization-mode + // media type parameter is equal to 1. This mode SHOULD be supported. + // It is primarily intended for low-delay applications. Only single NAL + // unit packets, STAP-As, and FU-As MAY be used in this mode. STAP-Bs, + // MTAPs, and FU-Bs MUST NOT be used. The transmission order of NAL + // units MUST comply with the NAL unit decoding order. + // @see https://tools.ietf.org/html/rfc6184#section-6.3 h264_param.packetization_mode = kv[1]; } else if (kv[0] == "level-asymmetry-allowed") { h264_param.level_asymmerty_allow = kv[1]; diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 2f6c14bff..8b4b8c41e 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -488,6 +488,13 @@ SrsVideoFrame::~SrsVideoFrame() { } +srs_error_t SrsVideoFrame::initialize(SrsCodecConfig* c) +{ + first_nalu_type = SrsAvcNaluTypeForbidden; + has_idr = has_sps_pps = has_aud = false; + return SrsFrame::initialize(c); +} + srs_error_t SrsVideoFrame::add_sample(char* bytes, int size) { srs_error_t err = srs_success; diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index c820cbeef..bffeee505 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -703,6 +703,8 @@ public: SrsVideoFrame(); virtual ~SrsVideoFrame(); public: + // Initialize the frame, to parse sampels. + virtual srs_error_t initialize(SrsCodecConfig* c); // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data. virtual srs_error_t add_sample(char* bytes, int size); public: From 5b9cb7dc3f2f1cc36a6aadb12f140d18a14ee5fd Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 15:11:42 +0800 Subject: [PATCH 014/131] For #307, refactor code, parse B-frame by sample. --- trunk/src/app/srs_app_rtc.cpp | 26 +++-------------- trunk/src/kernel/srs_kernel_codec.cpp | 42 +++++++++++++++++++++++++++ trunk/src/kernel/srs_kernel_codec.hpp | 5 ++++ 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index c44d203df..ff3633b20 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -125,31 +125,13 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, for (int i = 0; i < format->video->nb_samples; ++i) { SrsSample* sample = &format->video->samples[i]; - uint8_t header = sample->bytes[0]; - uint8_t nal_type = header & kNalTypeMask; - // Because RTC does not support B-frame, so we will drop them. // TODO: Drop B-frame in better way, which not cause picture corruption. - if (discard_bframe && (nal_type == SrsAvcNaluTypeNonIDR || nal_type == SrsAvcNaluTypeDataPartitionA || nal_type == SrsAvcNaluTypeIDR)) { - SrsBuffer* stream = new SrsBuffer(sample->bytes, sample->size); - SrsAutoFree(SrsBuffer, stream); - - // Skip nalu header. - stream->skip(1); - - SrsBitBuffer bitstream(stream); - int32_t first_mb_in_slice = 0; - if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) { - return srs_error_wrap(err, "nalu read uev"); + if (discard_bframe) { + if ((err = sample->parse_bframe()) != srs_success) { + return srs_error_wrap(err, "parse bframe"); } - - int32_t slice_type = 0; - if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type)) != srs_success) { - return srs_error_wrap(err, "nalu read uev"); - } - - srs_verbose("nal_type=%d, slice type=%d", nal_type, slice_type); - if (slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1) { + if (sample->bframe) { continue; } } diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 8b4b8c41e..41034e6f4 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -364,12 +364,53 @@ SrsSample::SrsSample() { size = 0; bytes = NULL; + bframe = false; } SrsSample::~SrsSample() { } +srs_error_t SrsSample::parse_bframe() +{ + srs_error_t err = srs_success; + + // H.264 nalu header type mask. + static uint8_t kNalTypeMask = 0x1F; + + uint8_t header = bytes[0]; + SrsAvcNaluType nal_type = (SrsAvcNaluType)(header & kNalTypeMask); + + if (nal_type != SrsAvcNaluTypeNonIDR && nal_type != SrsAvcNaluTypeDataPartitionA && nal_type != SrsAvcNaluTypeIDR) { + return err; + } + + SrsBuffer* stream = new SrsBuffer(bytes, size); + SrsAutoFree(SrsBuffer, stream); + + // Skip nalu header. + stream->skip(1); + + SrsBitBuffer bitstream(stream); + int32_t first_mb_in_slice = 0; + if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) { + return srs_error_wrap(err, "nalu read uev"); + } + + int32_t slice_type_v = 0; + if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type_v)) != srs_success) { + return srs_error_wrap(err, "nalu read uev"); + } + SrsAvcSliceType slice_type = (SrsAvcSliceType)slice_type_v; + + if (slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1) { + bframe = true; + srs_verbose("nal_type=%d, slice type=%d", nal_type, slice_type); + } + + return err; +} + SrsCodecConfig::SrsCodecConfig() { } @@ -458,6 +499,7 @@ srs_error_t SrsFrame::add_sample(char* bytes, int size) SrsSample* sample = &samples[nb_samples++]; sample->bytes = bytes; sample->size = size; + sample->bframe = false; return err; } diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index bffeee505..b265ccb2d 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -534,9 +534,14 @@ public: int size; // The ptr of unit, user must manage it. char* bytes; + // Whether is B frame. + bool bframe; public: SrsSample(); virtual ~SrsSample(); +public: + // If we need to know whether sample is bframe, we have to parse the NALU payload. + virtual srs_error_t parse_bframe(); }; /** From 7ffe4aacb8408ff712702c53cf8e8d2d00f027d0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 15:26:20 +0800 Subject: [PATCH 015/131] For #307, refactor shared msg, add samples and extra payload --- trunk/src/kernel/srs_kernel_flv.cpp | 13 ++++++++++++- trunk/src/kernel/srs_kernel_flv.hpp | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index f24dc2047..411b42596 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -194,8 +194,11 @@ srs_error_t SrsCommonMessage::create(SrsMessageHeader* pheader, char* body, int return srs_success; } -SrsSharedMessageHeader::SrsSharedMessageHeader() : payload_length(0), message_type(0), perfer_cid(0) +SrsSharedMessageHeader::SrsSharedMessageHeader() { + payload_length = 0; + message_type = 0; + perfer_cid = 0; } SrsSharedMessageHeader::~SrsSharedMessageHeader() @@ -207,6 +210,12 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload() payload = NULL; size = 0; shared_count = 0; + + samples = NULL; + nb_samples = 0; + + extra_payload = NULL; + extra_size = 0; } SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() @@ -215,6 +224,8 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() srs_memory_unwatch(payload); #endif srs_freepa(payload); + srs_freepa(samples); + srs_freepa(extra_payload); } SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL) diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 23fa0baf0..397439b7c 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -40,6 +40,7 @@ class ISrsReader; class SrsFileReader; class SrsPacket; class SrsRtpSharedPacket; +class SrsSample; #define SRS_FLV_TAG_HEADER_SIZE 11 #define SRS_FLV_PREVIOUS_TAG_SIZE 4 @@ -287,7 +288,6 @@ public: // @remark, not all message payload can be decoded to packet. for example, // video/audio packet use raw bytes, no video/audio packet. char* payload; - #ifdef SRS_AUTO_RTC std::vector rtp_packets; #endif @@ -305,6 +305,15 @@ private: int size; // The reference count int shared_count; + public: + // For RTC video, we need to know the NALU structures, + // because the RTP STAP-A or FU-A based on NALU. + SrsSample* samples; + int nb_samples; + // For RTC audio, we may need to transcode AAC to opus, + // so there must be an extra payload, which is transformed from payload. + char* extra_payload; + int extra_size; public: SrsSharedPtrPayload(); virtual ~SrsSharedPtrPayload(); From 6ed2a4b6cb3a0147725cbf160670b2d883b9980f Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 16:33:47 +0800 Subject: [PATCH 016/131] For #307, refine audio transcode buffer --- trunk/src/app/srs_app_audio_recode.cpp | 15 +++---- trunk/src/app/srs_app_rtc.cpp | 55 ++++++++++++-------------- trunk/src/app/srs_app_rtc.hpp | 2 +- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/trunk/src/app/srs_app_audio_recode.cpp b/trunk/src/app/srs_app_audio_recode.cpp index 77a2a440d..6e60c2e96 100644 --- a/trunk/src/app/srs_app_audio_recode.cpp +++ b/trunk/src/app/srs_app_audio_recode.cpp @@ -388,16 +388,13 @@ srs_error_t SrsAudioRecode::initialize() srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int &n) { srs_error_t err = srs_success; - - static char decode_buffer[kPacketBufMax]; - static char resample_buffer[kFrameBufMax]; - static char encode_buffer[kPacketBufMax]; if (!dec_) { return srs_error_new(ERROR_RTC_RTP_MUXER, "dec_ nullptr"); } int decode_len = kPacketBufMax; + static char decode_buffer[kPacketBufMax]; if ((err = dec_->decode(pkt, decode_buffer, decode_len)) != srs_success) { return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error"); } @@ -412,15 +409,18 @@ srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int if (!resample_) { return srs_error_new(ERROR_RTC_RTP_MUXER, "SrsAudioResample failed"); } - resample_->initialize(); + if ((err = resample_->initialize()) != srs_success) { + return srs_error_wrap(err, "init resample"); + } } SrsSample pcm; pcm.bytes = decode_buffer; pcm.size = decode_len; int resample_len = kFrameBufMax; + static char resample_buffer[kFrameBufMax]; if ((err = resample_->resample(&pcm, resample_buffer, resample_len)) != srs_success) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error"); + return srs_error_new(ERROR_RTC_RTP_MUXER, "resample error"); } n = 0; @@ -445,8 +445,9 @@ srs_error_t SrsAudioRecode::recode(SrsSample *pkt, char **buf, int *buf_len, int int encode_len; pcm.bytes = (char *)data_; pcm.size = size_; + static char encode_buffer[kPacketBufMax]; if ((err = enc_->encode(&pcm, encode_buffer, encode_len)) != srs_success) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "decode error"); + return srs_error_new(ERROR_RTC_RTP_MUXER, "encode error"); } memcpy(buf[n], encode_buffer, encode_len); diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index ff3633b20..80b28ddf5 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -54,7 +54,7 @@ using namespace std; #include // TODO: Add this function into SrsRtpMux class. -srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer** stream_ptr) +srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char** pbuf, int* pnn_buf) { srs_error_t err = srs_success; @@ -62,30 +62,27 @@ srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFor return err; } - if (stream_ptr == NULL) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "adts"); - } - if (format->audio->nb_samples != 1) { return srs_error_new(ERROR_RTC_RTP_MUXER, "adts"); } int nb_buf = format->audio->samples[0].size + 7; char* buf = new char[nb_buf]; - SrsBuffer* stream = new SrsBuffer(buf, nb_buf); + SrsBuffer stream(buf, nb_buf); // TODO: Add comment. - stream->write_1bytes(0xFF); - stream->write_1bytes(0xF9); - stream->write_1bytes(((format->acodec->aac_object - 1) << 6) | ((format->acodec->aac_sample_rate & 0x0F) << 2) | ((format->acodec->aac_channels & 0x04) >> 2)); - stream->write_1bytes(((format->acodec->aac_channels & 0x03) << 6) | ((nb_buf >> 11) & 0x03)); - stream->write_1bytes((nb_buf >> 3) & 0xFF); - stream->write_1bytes(((nb_buf & 0x07) << 5) | 0x1F); - stream->write_1bytes(0xFC); + stream.write_1bytes(0xFF); + stream.write_1bytes(0xF9); + stream.write_1bytes(((format->acodec->aac_object - 1) << 6) | ((format->acodec->aac_sample_rate & 0x0F) << 2) | ((format->acodec->aac_channels & 0x04) >> 2)); + stream.write_1bytes(((format->acodec->aac_channels & 0x03) << 6) | ((nb_buf >> 11) & 0x03)); + stream.write_1bytes((nb_buf >> 3) & 0xFF); + stream.write_1bytes(((nb_buf & 0x07) << 5) | 0x1F); + stream.write_1bytes(0xFC); - stream->write_bytes(format->audio->samples[0].bytes, format->audio->samples[0].size); + stream.write_bytes(format->audio->samples[0].bytes, format->audio->samples[0].size); - *stream_ptr = stream; + *pbuf = buf; + *pnn_buf = nb_buf; return err; } @@ -212,8 +209,6 @@ srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_fram srs_error_t err = srs_success; uint8_t header = sample->bytes[0]; - uint8_t nal_type = header & kNalTypeMask; - srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); @@ -292,7 +287,7 @@ srs_error_t SrsRtpOpusMuxer::initialize() return err; } -srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer* stream) +srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio) { srs_error_t err = srs_success; @@ -308,9 +303,8 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, } SrsSample pkt; - pkt.bytes = stream->data(); - pkt.size = stream->pos(); - + pkt.bytes = adts_audio; + pkt.size = nn_adts_audio; if ((err = transcode->recode(&pkt, data_ptr, elen, number)) != srs_success) { return srs_error_wrap(err, "recode error"); } @@ -319,7 +313,9 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsSample sample; sample.size = elen[i]; sample.bytes = data_ptr[i]; - packet_opus(shared_audio, &sample, rtp_packets); + if ((err = packet_opus(shared_audio, &sample, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet as opus"); + } } shared_audio->set_rtp_packets(rtp_packets); @@ -463,17 +459,16 @@ srs_error_t SrsRtc::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma // ignore sequence header srs_assert(format->audio); - SrsBuffer* stream = NULL; - SrsAutoFree(SrsBuffer, stream); - if ((err = aac_raw_append_adts_header(shared_audio, format, &stream)) != srs_success) { + char* adts_audio = NULL; + int nn_adts_audio = 0; + // TODO: FIXME: Reserve 7 bytes header when create shared message. + if ((err = aac_raw_append_adts_header(shared_audio, format, &adts_audio, &nn_adts_audio)) != srs_success) { return srs_error_wrap(err, "aac append header"); } - if (stream) { - char* stream_data = stream->data(); - SrsAutoFreeA(char, stream_data); - - return rtp_opus_muxer->frame_to_packet(shared_audio, format, stream); + if (adts_audio) { + err = rtp_opus_muxer->frame_to_packet(shared_audio, format, adts_audio, nn_adts_audio); + srs_freep(adts_audio); } return err; diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index 45d78c8a2..2ba18c43e 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -101,7 +101,7 @@ public: virtual ~SrsRtpOpusMuxer(); virtual srs_error_t initialize(); public: - srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, SrsBuffer* stream); + srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio); private: srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); }; From 1f2db4d746677a4ccefd5d2cbc732cd04ca31eb0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 17:09:55 +0800 Subject: [PATCH 017/131] For #307, refactor aac to opus code --- trunk/src/app/srs_app_rtc.cpp | 44 ++++++++++++++++++--------- trunk/src/app/srs_app_rtc.hpp | 2 -- trunk/src/kernel/srs_kernel_codec.hpp | 2 +- trunk/src/kernel/srs_kernel_flv.cpp | 11 +++++-- trunk/src/kernel/srs_kernel_flv.hpp | 6 ++-- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 80b28ddf5..ca525637e 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -208,7 +208,6 @@ srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_fram { srs_error_t err = srs_success; - uint8_t header = sample->bytes[0]; srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); @@ -287,32 +286,47 @@ srs_error_t SrsRtpOpusMuxer::initialize() return err; } +// An AAC packet may be transcoded to many OPUS packets. +const int kMaxOpusPackets = 8; +// The max size for each OPUS packet. +const int kMaxOpusPacketSize = 4096; + srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio) { srs_error_t err = srs_success; - vector rtp_packets; + // Opus packet cache. + static char* opus_payloads[kMaxOpusPackets]; - char* data_ptr[kArrayLength]; - static char data_array[kArrayLength][kArrayBuffer]; - int elen[kArrayLength], number = 0; + static bool initialized = false; + if (!initialized) { + initialized = true; - data_ptr[0] = &data_array[0][0]; - for (int i = 1; i < kArrayLength; i++) { - data_ptr[i] = data_array[i]; + static char opus_packets_cache[kMaxOpusPackets][kMaxOpusPacketSize]; + opus_payloads[0] = &opus_packets_cache[0][0]; + for (int i = 1; i < kMaxOpusPackets; i++) { + opus_payloads[i] = opus_packets_cache[i]; + } } - SrsSample pkt; - pkt.bytes = adts_audio; - pkt.size = nn_adts_audio; - if ((err = transcode->recode(&pkt, data_ptr, elen, number)) != srs_success) { + // Transcode aac packet to opus packets. + SrsSample aac; + aac.bytes = adts_audio; + aac.size = nn_adts_audio; + + int nn_opus_packets = 0; + int opus_sizes[kMaxOpusPackets]; + if ((err = transcode->recode(&aac, opus_payloads, opus_sizes, nn_opus_packets)) != srs_success) { return srs_error_wrap(err, "recode error"); } - for (int i = 0; i < number; i++) { + // Package opus packets to RTP packets. + vector rtp_packets; + + for (int i = 0; i < nn_opus_packets; i++) { SrsSample sample; - sample.size = elen[i]; - sample.bytes = data_ptr[i]; + sample.size = opus_sizes[i]; + sample.bytes = opus_payloads[i]; if ((err = packet_opus(shared_audio, &sample, rtp_packets)) != srs_success) { return srs_error_wrap(err, "packet as opus"); } diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index 2ba18c43e..f409e2624 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -61,8 +61,6 @@ const uint8_t kEnd = 0x40; // Fu-header end bit const int kChannel = 2; const int kSamplerate = 48000; -const int kArrayLength = 8; -const int kArrayBuffer = 4096; // SSRC will rewrite in srs_app_rtc_conn.cpp when send to client. const uint32_t kAudioSSRC = 1; diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index b265ccb2d..14e486835 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -532,7 +532,7 @@ class SrsSample public: // The size of unit. int size; - // The ptr of unit, user must manage it. + // The ptr of unit, user must free it. char* bytes; // Whether is B frame. bool bframe; diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 411b42596..f74df7968 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -214,8 +214,8 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload() samples = NULL; nb_samples = 0; - extra_payload = NULL; - extra_size = 0; + extra_payloads = NULL; + nn_extra_payloads = 0; } SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() @@ -225,7 +225,12 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() #endif srs_freepa(payload); srs_freepa(samples); - srs_freepa(extra_payload); + + for (int i = 0; i < nn_extra_payloads; i++) { + SrsSample* p = extra_payloads + i; + srs_freep(p->bytes); + } + srs_freep(extra_payloads); } SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL) diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 397439b7c..b948d2596 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -311,9 +311,9 @@ private: SrsSample* samples; int nb_samples; // For RTC audio, we may need to transcode AAC to opus, - // so there must be an extra payload, which is transformed from payload. - char* extra_payload; - int extra_size; + // so there must be an extra payloads, which is transformed from payload. + SrsSample* extra_payloads; + int nn_extra_payloads; public: SrsSharedPtrPayload(); virtual ~SrsSharedPtrPayload(); From 3cccef327c38e6b40567b7040bd7ff8f93a36e50 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 17:52:14 +0800 Subject: [PATCH 018/131] For #307, package opus when send it. --- trunk/src/app/srs_app_rtc.cpp | 46 ++++++--------------- trunk/src/app/srs_app_rtc.hpp | 5 --- trunk/src/app/srs_app_rtc_conn.cpp | 58 +++++++++++++++++++++++---- trunk/src/app/srs_app_rtc_conn.hpp | 6 +++ trunk/src/kernel/srs_kernel_codec.hpp | 4 +- trunk/src/kernel/srs_kernel_flv.cpp | 14 ++++++- trunk/src/kernel/srs_kernel_flv.hpp | 6 +++ 7 files changed, 90 insertions(+), 49 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index ca525637e..7b74ba3fe 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -260,17 +260,12 @@ srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsRtpOpusMuxer::SrsRtpOpusMuxer() { - sequence = 0; - timestamp = 0; transcode = NULL; } SrsRtpOpusMuxer::~SrsRtpOpusMuxer() { - if (transcode) { - delete transcode; - transcode = NULL; - } + srs_freep(transcode); } srs_error_t SrsRtpOpusMuxer::initialize() @@ -309,7 +304,7 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, } } - // Transcode aac packet to opus packets. + // Transcode an aac packet to many opus packets. SrsSample aac; aac.bytes = adts_audio; aac.size = nn_adts_audio; @@ -320,37 +315,20 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, return srs_error_wrap(err, "recode error"); } - // Package opus packets to RTP packets. - vector rtp_packets; + // Save OPUS packets in shared message. + if (nn_opus_packets <= 0) { + return err; + } + SrsSample samples[nn_opus_packets]; for (int i = 0; i < nn_opus_packets; i++) { - SrsSample sample; - sample.size = opus_sizes[i]; - sample.bytes = opus_payloads[i]; - if ((err = packet_opus(shared_audio, &sample, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet as opus"); - } + SrsSample* p = samples + i; + p->size = opus_sizes[i]; + p->bytes = new char[p->size]; + memcpy(p->bytes, opus_payloads[i], p->size); } - shared_audio->set_rtp_packets(rtp_packets); - - return err; -} - -srs_error_t SrsRtpOpusMuxer::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets) -{ - srs_error_t err = srs_success; - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - packet->rtp_header.set_marker(true); - if ((err = packet->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - // TODO: FIXME: Why 960? Need Refactoring? - timestamp += 960; - - rtp_packets.push_back(packet); + shared_audio->set_extra_payloads(samples, nn_opus_packets); return err; } diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index f409e2624..855c2e62b 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -90,9 +90,6 @@ private: class SrsRtpOpusMuxer { private: - // TODO: FIXME: How to handle timestamp overflow? - uint32_t timestamp; - uint16_t sequence; SrsAudioRecode* transcode; public: SrsRtpOpusMuxer(); @@ -100,8 +97,6 @@ public: virtual srs_error_t initialize(); public: srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio); -private: - srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); }; class SrsRtc diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index da3a4fc2f..4492d9122 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -442,6 +442,9 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int rtc_session = s; sendonly_ukt = u->copy_sendonly(); + + timestamp = 0; + sequence = 0; } SrsRtcSenderThread::~SrsRtcSenderThread() @@ -575,6 +578,8 @@ void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts) { + srs_error_t err = srs_success; + if (!rtc_session->dtls_session) { return; } @@ -584,14 +589,35 @@ void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int bool is_video = msg->is_video(); bool is_audio = msg->is_audio(); - int nn_rtp_pkts = (int)msg->rtp_packets.size(); - for (int j = 0; j < nn_rtp_pkts; j++) { - SrsRtpSharedPacket* pkt = msg->rtp_packets[j]; - send_and_free_message(msg, is_video, is_audio, pkt, skt); - } + if (is_audio) { + // Package opus packets to RTP packets. + vector rtp_packets; - *pnn += msg->size; - *pnn_rtp_pkts += nn_rtp_pkts; + for (int i = 0; i < msg->nn_extra_payloads(); i++) { + SrsSample* sample = msg->extra_payloads() + i; + if ((err = packet_opus(msg, sample, rtp_packets)) != srs_success) { + srs_warn("packet opus err %s", srs_error_summary(err).c_str()); srs_error_reset(err); + } + } + + int nn_rtp_pkts = (int)rtp_packets.size(); + for (int j = 0; j < nn_rtp_pkts; j++) { + SrsRtpSharedPacket* pkt = rtp_packets[j]; + send_and_free_message(msg, is_video, is_audio, pkt, skt); + } + + *pnn += msg->size; + *pnn_rtp_pkts += nn_rtp_pkts; + } else { + int nn_rtp_pkts = (int)msg->rtp_packets.size(); + for (int j = 0; j < nn_rtp_pkts; j++) { + SrsRtpSharedPacket* pkt = msg->rtp_packets[j]; + send_and_free_message(msg, is_video, is_audio, pkt, skt); + } + + *pnn += msg->size; + *pnn_rtp_pkts += nn_rtp_pkts; + } srs_freep(msg); } @@ -636,6 +662,24 @@ void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); } +srs_error_t SrsRtcSenderThread::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets) +{ + srs_error_t err = srs_success; + + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + packet->rtp_header.set_marker(true); + if ((err = packet->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { + return srs_error_wrap(err, "rtp packet encode"); + } + + // TODO: FIXME: Why 960? Need Refactoring? + timestamp += 960; + + rtp_packets.push_back(packet); + + return err; +} + SrsRtcSession::SrsRtcSession(SrsRtcServer* rtc_svr, const SrsRequest& req, const std::string& un, int context_id) { rtc_server = rtc_svr; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index f448778b9..7e8019f54 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -126,6 +126,10 @@ private: uint32_t audio_ssrc; uint16_t video_payload_type; uint16_t audio_payload_type; +private: + // TODO: FIXME: How to handle timestamp overflow? + uint32_t timestamp; + uint16_t sequence; public: SrsUdpMuxSocket* sendonly_ukt; public: @@ -146,6 +150,8 @@ public: private: void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); void send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); +private: + srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); }; class SrsRtcSession diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 14e486835..49447b5de 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -538,10 +538,10 @@ public: bool bframe; public: SrsSample(); - virtual ~SrsSample(); + ~SrsSample(); public: // If we need to know whether sample is bframe, we have to parse the NALU payload. - virtual srs_error_t parse_bframe(); + srs_error_t parse_bframe(); }; /** diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index f74df7968..b0ced2f92 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -230,7 +230,8 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() SrsSample* p = extra_payloads + i; srs_freep(p->bytes); } - srs_freep(extra_payloads); + srs_freepa(extra_payloads); + nn_extra_payloads = 0; } SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL) @@ -385,6 +386,17 @@ void SrsSharedPtrMessage::set_rtp_packets(const std::vector { rtp_packets = pkts; } + +void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payloads) +{ + srs_assert(nn_payloads); + srs_assert(!ptr->extra_payloads); + + ptr->nn_extra_payloads = nn_payloads; + + ptr->extra_payloads = new SrsSample[nn_payloads]; + memcpy(ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample)); +} #endif SrsFlvTransmuxer::SrsFlvTransmuxer() diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index b948d2596..ca5f24f09 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -358,6 +358,12 @@ public: public: #ifdef SRS_AUTO_RTC virtual void set_rtp_packets(const std::vector& pkts); + // Set extra samples, for example, when we transcode an AAC audio packet to OPUS, + // we may get more than one OPUS packets, we set these OPUS packets in extra payloads. + void set_extra_payloads(SrsSample* payloads, int nn_payloads); + // Get the extra payloads and the number of it. + int nn_extra_payloads() { return ptr->nn_extra_payloads; } + SrsSample* extra_payloads() { return ptr->extra_payloads; } #endif }; From c6fb5e6fdd3596b5545dcd038badf3955579cff5 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 18:01:38 +0800 Subject: [PATCH 019/131] Refactor code, rename variable --- trunk/src/app/srs_app_rtc.cpp | 19 +++++++++++-------- trunk/src/app/srs_app_rtc.hpp | 4 ++-- trunk/src/utest/srs_utest_avc.cpp | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 7b74ba3fe..c99db24ce 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -260,23 +260,26 @@ srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsRtpOpusMuxer::SrsRtpOpusMuxer() { - transcode = NULL; + codec = NULL; } SrsRtpOpusMuxer::~SrsRtpOpusMuxer() { - srs_freep(transcode); + srs_freep(codec); } srs_error_t SrsRtpOpusMuxer::initialize() { srs_error_t err = srs_success; - transcode = new SrsAudioRecode(kChannel, kSamplerate); - if (!transcode) { + codec = new SrsAudioRecode(kChannel, kSamplerate); + if (!codec) { return srs_error_new(ERROR_RTC_RTP_MUXER, "SrsAacOpus init failed"); } - transcode->initialize(); + + if ((err = codec->initialize()) != srs_success) { + return srs_error_wrap(err, "init codec"); + } return err; } @@ -286,7 +289,7 @@ const int kMaxOpusPackets = 8; // The max size for each OPUS packet. const int kMaxOpusPacketSize = 4096; -srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio) +srs_error_t SrsRtpOpusMuxer::transcode(SrsSharedPtrMessage* shared_audio, char* adts_audio, int nn_adts_audio) { srs_error_t err = srs_success; @@ -311,7 +314,7 @@ srs_error_t SrsRtpOpusMuxer::frame_to_packet(SrsSharedPtrMessage* shared_audio, int nn_opus_packets = 0; int opus_sizes[kMaxOpusPackets]; - if ((err = transcode->recode(&aac, opus_payloads, opus_sizes, nn_opus_packets)) != srs_success) { + if ((err = codec->recode(&aac, opus_payloads, opus_sizes, nn_opus_packets)) != srs_success) { return srs_error_wrap(err, "recode error"); } @@ -459,7 +462,7 @@ srs_error_t SrsRtc::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma } if (adts_audio) { - err = rtp_opus_muxer->frame_to_packet(shared_audio, format, adts_audio, nn_adts_audio); + err = rtp_opus_muxer->transcode(shared_audio, adts_audio, nn_adts_audio); srs_freep(adts_audio); } diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index 855c2e62b..320a9e277 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -90,13 +90,13 @@ private: class SrsRtpOpusMuxer { private: - SrsAudioRecode* transcode; + SrsAudioRecode* codec; public: SrsRtpOpusMuxer(); virtual ~SrsRtpOpusMuxer(); virtual srs_error_t initialize(); public: - srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_audio, SrsFormat* format, char* adts_audio, int nn_adts_audio); + srs_error_t transcode(SrsSharedPtrMessage* shared_audio, char* adts_audio, int nn_adts_audio); }; class SrsRtc diff --git a/trunk/src/utest/srs_utest_avc.cpp b/trunk/src/utest/srs_utest_avc.cpp index 4aa8f037f..60b4bb29d 100644 --- a/trunk/src/utest/srs_utest_avc.cpp +++ b/trunk/src/utest/srs_utest_avc.cpp @@ -462,7 +462,7 @@ VOID TEST(SrsAVCTest, AACMuxSequenceHeader) codec.sound_rate = SrsAudioSampleRate44100; codec.sampling_frequency_index = 4; HELPER_ASSERT_SUCCESS(h.mux_sequence_header(&codec, sh)); - EXPECT_EQ(2, sh.length()); + EXPECT_EQ(2, (int)sh.length()); EXPECT_EQ(0x0a, (uint8_t)sh.at(0)); EXPECT_EQ(0x08, (uint8_t)sh.at(1)); } @@ -475,7 +475,7 @@ VOID TEST(SrsAVCTest, AACMuxSequenceHeader) codec.sound_rate = SrsAudioSampleRate22050; codec.sampling_frequency_index = 4; HELPER_ASSERT_SUCCESS(h.mux_sequence_header(&codec, sh)); - EXPECT_EQ(2, sh.length()); + EXPECT_EQ(2, (int)sh.length()); EXPECT_EQ(0x0a, (uint8_t)sh.at(0)); EXPECT_EQ(0x08, (uint8_t)sh.at(1)); } From 8121f9ab4e76ce23d033a02f32e8b211923b3e40 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 18:39:46 +0800 Subject: [PATCH 020/131] Refactor variable name --- trunk/src/app/srs_app_rtc_conn.cpp | 8 ++++---- trunk/src/app/srs_app_rtc_conn.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 4492d9122..941210a7e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -443,8 +443,8 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int rtc_session = s; sendonly_ukt = u->copy_sendonly(); - timestamp = 0; - sequence = 0; + audio_timestamp = 0; + audio_sequence = 0; } SrsRtcSenderThread::~SrsRtcSenderThread() @@ -668,12 +668,12 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSharedPtrMessage* shared_frame, S SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); packet->rtp_header.set_marker(true); - if ((err = packet->create(timestamp, sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { + if ((err = packet->create(audio_timestamp, audio_sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { return srs_error_wrap(err, "rtp packet encode"); } // TODO: FIXME: Why 960? Need Refactoring? - timestamp += 960; + audio_timestamp += 960; rtp_packets.push_back(packet); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 7e8019f54..5063dea49 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -128,8 +128,8 @@ private: uint16_t audio_payload_type; private: // TODO: FIXME: How to handle timestamp overflow? - uint32_t timestamp; - uint16_t sequence; + uint32_t audio_timestamp; + uint16_t audio_sequence; public: SrsUdpMuxSocket* sendonly_ukt; public: From a2fdf0d3c7556c5ef8531ca5cd41ea05a9e3e9e2 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 21:03:37 +0800 Subject: [PATCH 021/131] For #307, package video rtp packets when send message --- trunk/src/app/srs_app_rtc.cpp | 144 ++----------------- trunk/src/app/srs_app_rtc.hpp | 10 +- trunk/src/app/srs_app_rtc_conn.cpp | 208 ++++++++++++++++++++++++---- trunk/src/app/srs_app_rtc_conn.hpp | 10 +- trunk/src/app/srs_app_source.cpp | 8 +- trunk/src/app/srs_app_source.hpp | 3 + trunk/src/kernel/srs_kernel_flv.cpp | 35 +++-- trunk/src/kernel/srs_kernel_flv.hpp | 18 ++- 8 files changed, 236 insertions(+), 200 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index c99db24ce..7d2d44e82 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -89,7 +89,6 @@ srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage* shared_audio, SrsFor SrsRtpH264Muxer::SrsRtpH264Muxer() { - sequence = 0; discard_bframe = false; } @@ -97,28 +96,16 @@ SrsRtpH264Muxer::~SrsRtpH264Muxer() { } -srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsFormat* format) +srs_error_t SrsRtpH264Muxer::filter(SrsSharedPtrMessage* shared_frame, SrsFormat* format) { srs_error_t err = srs_success; - if (format->is_avc_sequence_header()) { - // It is ok when size is 0, @see http://www.cplusplus.com/reference/string/string/assign/ - sps.assign(format->vcodec->sequenceParameterSetNALUnit.data(), format->vcodec->sequenceParameterSetNALUnit.size()); - pps.assign(format->vcodec->pictureParameterSetNALUnit.data(), format->vcodec->pictureParameterSetNALUnit.size()); - - // only collect SPS/PPS. - return err; - } - - vector rtp_packets; - - // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + // If IDR, we will insert SPS/PPS before IDR frame. if (format->video && format->video->has_idr) { - if ((err = packet_stap_a(sps, pps, shared_frame, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } + shared_frame->set_has_idr(true); } + // Update samples to shared frame. for (int i = 0; i < format->video->nb_samples; ++i) { SrsSample* sample = &format->video->samples[i]; @@ -132,128 +119,13 @@ srs_error_t SrsRtpH264Muxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, continue; } } - - if (sample->size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(shared_frame, format, sample, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet single nalu"); - } - } else { - if ((err = packet_fu_a(shared_frame, format, sample, rtp_packets)) != srs_success) { - return srs_error_wrap(err, "packet fu-a"); - } - } } - if (!rtp_packets.empty()) { - // At the end of the frame, set marker bit. - // One frame may have multi nals. Set the marker bit in the last nal end, no the end of the nal. - if ((err = rtp_packets.back()->modify_rtp_header_marker(true)) != srs_success) { - return srs_error_wrap(err, "set marker"); - } + if (format->video->nb_samples <= 0) { + return err; } - shared_frame->set_rtp_packets(rtp_packets); - - return err; -} - -srs_error_t SrsRtpH264Muxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) -{ - srs_error_t err = srs_success; - - char* p = sample->bytes + 1; - int nb_left = sample->size - 1; - uint8_t header = sample->bytes[0]; - uint8_t nal_type = header & kNalTypeMask; - - int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize; - for (int i = 0; i < num_of_packet; ++i) { - char buf[kRtpPacketSize]; - SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); - SrsAutoFree(SrsBuffer, stream); - - int packet_size = min(nb_left, kRtpMaxPayloadSize); - - // fu-indicate - uint8_t fu_indicate = kFuA; - fu_indicate |= (header & (~kNalTypeMask)); - stream->write_1bytes(fu_indicate); - - uint8_t fu_header = nal_type; - if (i == 0) - fu_header |= kStart; - if (i == num_of_packet - 1) - fu_header |= kEnd; - stream->write_1bytes(fu_header); - - stream->write_bytes(p, packet_size); - p += packet_size; - nb_left -= packet_size; - - srs_verbose("rtp fu-a nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - rtp_packets.push_back(packet); - } - - return err; -} - -// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 -srs_error_t SrsRtpH264Muxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector& rtp_packets) -{ - srs_error_t err = srs_success; - - srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, sequence, (shared_frame->timestamp * 90)); - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - rtp_packets.push_back(packet); - - return err; -} - -srs_error_t SrsRtpH264Muxer::packet_stap_a(const string &sps, const string& pps, SrsSharedPtrMessage* shared_frame, vector& rtp_packets) -{ - srs_error_t err = srs_success; - - if (sps.empty() || pps.empty()) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); - } - - uint8_t header = sps[0]; - uint8_t nal_type = header & kNalTypeMask; - - char buf[kRtpPacketSize]; - SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); - SrsAutoFree(SrsBuffer, stream); - - // stap-a header - uint8_t stap_a_header = kStapA; - stap_a_header |= (nal_type & (~kNalTypeMask)); - stream->write_1bytes(stap_a_header); - - stream->write_2bytes(sps.size()); - stream->write_bytes((char*)sps.data(), sps.size()); - - stream->write_2bytes(pps.size()); - stream->write_bytes((char*)pps.data(), pps.size()); - - srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", (sps.size() + pps.size()), sequence, (shared_frame->timestamp * 90)); - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - rtp_packets.push_back(packet); + shared_frame->set_samples(format->video->samples, format->video->nb_samples); return err; } @@ -490,5 +362,5 @@ srs_error_t SrsRtc::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* forma // ignore info frame, // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909 srs_assert(format->video); - return rtp_h264_muxer->frame_to_packet(shared_video, format); + return rtp_h264_muxer->filter(shared_video, format); } diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index 320a9e277..c75eae7ce 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -69,21 +69,13 @@ const uint32_t kVideoSSRC = 2; // TODO: Define interface class like ISrsRtpMuxer class SrsRtpH264Muxer { -private: - uint16_t sequence; - std::string sps; - std::string pps; public: bool discard_bframe; public: SrsRtpH264Muxer(); virtual ~SrsRtpH264Muxer(); public: - srs_error_t frame_to_packet(SrsSharedPtrMessage* shared_video, SrsFormat* format); -private: - srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packets); - srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, std::vector& rtp_packets); - srs_error_t packet_stap_a(const std::string &sps, const std::string& pps, SrsSharedPtrMessage* shared_frame, std::vector& rtp_packets); + srs_error_t filter(SrsSharedPtrMessage* shared_video, SrsFormat* format); }; // TODO: FIXME: It's not a muxer, but a transcoder. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 941210a7e..b7038da79 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -445,6 +445,8 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int audio_timestamp = 0; audio_sequence = 0; + + video_sequence = 0; } SrsRtcSenderThread::~SrsRtcSenderThread() @@ -557,7 +559,14 @@ srs_error_t SrsRtcSenderThread::cycle() int nn = 0; int nn_rtp_pkts = 0; - send_and_free_messages(msgs.msgs, msg_count, sendonly_ukt, &nn, &nn_rtp_pkts); + if ((err = send_messages(source, msgs.msgs, msg_count, sendonly_ukt, &nn, &nn_rtp_pkts)) != srs_success) { + srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); + } + + for (int i = 0; i < msg_count; i++) { + SrsSharedPtrMessage* msg = msgs.msgs[i]; + srs_freep(msg); + } pprint->elapse(); if (pprint->can_print()) { @@ -576,12 +585,14 @@ void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) sendonly_ukt = skt->copy_sendonly(); } -void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts) -{ +srs_error_t SrsRtcSenderThread::send_messages( + SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, + SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts +) { srs_error_t err = srs_success; if (!rtc_session->dtls_session) { - return; + return err; } for (int i = 0; i < nb_msgs; i++) { @@ -589,41 +600,69 @@ void SrsRtcSenderThread::send_and_free_messages(SrsSharedPtrMessage** msgs, int bool is_video = msg->is_video(); bool is_audio = msg->is_audio(); - if (is_audio) { - // Package opus packets to RTP packets. - vector rtp_packets; + // Package opus packets to RTP packets. + vector rtp_packets; + if (is_audio) { for (int i = 0; i < msg->nn_extra_payloads(); i++) { SrsSample* sample = msg->extra_payloads() + i; if ((err = packet_opus(msg, sample, rtp_packets)) != srs_success) { - srs_warn("packet opus err %s", srs_error_summary(err).c_str()); srs_error_reset(err); + return srs_error_wrap(err, "opus package"); + } + } + } else { + for (int i = 0; i < msg->nn_samples(); i++) { + SrsSample* sample = msg->samples() + i; + + // We always ignore bframe here, if config to discard bframe, + // the bframe flag will not be set. + if (sample->bframe) { + continue; + } + + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (msg->has_idr()) { + if ((err = packet_stap_a(source, msg, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + } + + if (sample->size <= kRtpMaxPayloadSize) { + if ((err = packet_single_nalu(msg, sample, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet single nalu"); + } + } else { + if ((err = packet_fu_a(msg, sample, rtp_packets)) != srs_success) { + return srs_error_wrap(err, "packet fu-a"); + } } } - int nn_rtp_pkts = (int)rtp_packets.size(); - for (int j = 0; j < nn_rtp_pkts; j++) { - SrsRtpSharedPacket* pkt = rtp_packets[j]; - send_and_free_message(msg, is_video, is_audio, pkt, skt); + if (!rtp_packets.empty()) { + // At the end of the frame, set marker bit. + // One frame may have multi nals. Set the marker bit in the last nal end, no the end of the nal. + if ((err = rtp_packets.back()->modify_rtp_header_marker(true)) != srs_success) { + return srs_error_wrap(err, "set marker"); + } } - - *pnn += msg->size; - *pnn_rtp_pkts += nn_rtp_pkts; - } else { - int nn_rtp_pkts = (int)msg->rtp_packets.size(); - for (int j = 0; j < nn_rtp_pkts; j++) { - SrsRtpSharedPacket* pkt = msg->rtp_packets[j]; - send_and_free_message(msg, is_video, is_audio, pkt, skt); - } - - *pnn += msg->size; - *pnn_rtp_pkts += nn_rtp_pkts; } - srs_freep(msg); + int nn_rtp_pkts = (int)rtp_packets.size(); + for (int j = 0; j < nn_rtp_pkts; j++) { + SrsRtpSharedPacket* pkt = rtp_packets[j]; + if ((err = send_message(msg, is_video, is_audio, pkt, skt)) != srs_success) { + return srs_error_wrap(err, "send message"); + } + } + + *pnn += msg->size; + *pnn_rtp_pkts += nn_rtp_pkts; } + + return err; } -void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt) +srs_error_t SrsRtcSenderThread::send_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -644,8 +683,7 @@ void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is if (rtc_session->encrypt) { if ((err = rtc_session->dtls_session->protect_rtp(buf, pkt->payload, length)) != srs_success) { - srs_warn("srtp err %s", srs_error_desc(err).c_str()); srs_freep(err); srs_freepa(buf); - return; + return srs_error_wrap(err, "srtp protect"); } } else { memcpy(buf, pkt->payload, length); @@ -660,6 +698,7 @@ void SrsRtcSenderThread::send_and_free_message(SrsSharedPtrMessage* msg, bool is mhdr->msg_len = 0; rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); + return err; } srs_error_t SrsRtcSenderThread::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets) @@ -680,6 +719,119 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSharedPtrMessage* shared_frame, S return err; } +srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, vector& rtp_packets) +{ + srs_error_t err = srs_success; + + char* p = sample->bytes + 1; + int nb_left = sample->size - 1; + uint8_t header = sample->bytes[0]; + uint8_t nal_type = header & kNalTypeMask; + + int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize; + for (int i = 0; i < num_of_packet; ++i) { + char buf[kRtpPacketSize]; + SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); + SrsAutoFree(SrsBuffer, stream); + + int packet_size = min(nb_left, kRtpMaxPayloadSize); + + // fu-indicate + uint8_t fu_indicate = kFuA; + fu_indicate |= (header & (~kNalTypeMask)); + stream->write_1bytes(fu_indicate); + + uint8_t fu_header = nal_type; + if (i == 0) + fu_header |= kStart; + if (i == num_of_packet - 1) + fu_header |= kEnd; + stream->write_1bytes(fu_header); + + stream->write_bytes(p, packet_size); + p += packet_size; + nb_left -= packet_size; + + srs_verbose("rtp fu-a nalu, size=%u, seq=%u, timestamp=%lu", sample->size, video_sequence, (shared_frame->timestamp * 90)); + + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { + return srs_error_wrap(err, "rtp packet encode"); + } + + rtp_packets.push_back(packet); + } + + return err; +} + +// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 +srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, vector& rtp_packets) +{ + srs_error_t err = srs_success; + + srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, video_sequence, (shared_frame->timestamp * 90)); + + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) { + return srs_error_wrap(err, "rtp packet encode"); + } + + rtp_packets.push_back(packet); + + return err; +} + +srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, vector& rtp_packets) +{ + srs_error_t err = srs_success; + + SrsMetaCache* meta = source->cached_meta(); + if (!meta) { + return err; + } + + SrsFormat* format = meta->vsh_format(); + if (!format || !format->vcodec) { + return err; + } + + const vector& sps = format->vcodec->sequenceParameterSetNALUnit; + const vector& pps = format->vcodec->pictureParameterSetNALUnit; + if (sps.empty() || pps.empty()) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); + } + + uint8_t header = sps[0]; + uint8_t nal_type = header & kNalTypeMask; + + char buf[kRtpPacketSize]; + SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); + SrsAutoFree(SrsBuffer, stream); + + // stap-a header + uint8_t stap_a_header = kStapA; + stap_a_header |= (nal_type & (~kNalTypeMask)); + stream->write_1bytes(stap_a_header); + + stream->write_2bytes(sps.size()); + stream->write_bytes((char*)sps.data(), sps.size()); + + stream->write_2bytes(pps.size()); + stream->write_bytes((char*)pps.data(), pps.size()); + + srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", (sps.size() + pps.size()), video_sequence, (shared_frame->timestamp * 90)); + + SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); + if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { + return srs_error_wrap(err, "rtp packet encode"); + } + + rtp_packets.push_back(packet); + + return err; +} + SrsRtcSession::SrsRtcSession(SrsRtcServer* rtc_svr, const SrsRequest& req, const std::string& un, int context_id) { rtc_server = rtc_svr; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 5063dea49..d9fd03cfe 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -130,6 +130,8 @@ private: // TODO: FIXME: How to handle timestamp overflow? uint32_t audio_timestamp; uint16_t audio_sequence; +private: + uint16_t video_sequence; public: SrsUdpMuxSocket* sendonly_ukt; public: @@ -148,10 +150,14 @@ public: public: void update_sendonly_socket(SrsUdpMuxSocket* skt); private: - void send_and_free_messages(SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); - void send_and_free_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); + srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); + srs_error_t send_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); private: srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); +private: + srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); + srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); + srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, std::vector& rtp_packets); }; class SrsRtcSession diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index cb7d1b505..fcf3b071e 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1143,7 +1143,8 @@ srs_error_t SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_se // TODO: FIXME: Refactor to move to rtp? // Save the RTP packets for find_rtp_packet() to rtx or restore it. - source->rtp_queue->push(msg->rtp_packets); + // TODO: FIXME: Remove dead code. + //source->rtp_queue->push(msg->rtp_packets); #endif if ((err = hls->on_video(msg, format)) != srs_success) { @@ -2718,4 +2719,9 @@ SrsRtpSharedPacket* SrsSource::find_rtp_packet(const uint16_t& seq) { return rtp_queue->find(seq); } + +SrsMetaCache* SrsSource::cached_meta() +{ + return meta; +} #endif diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index ac04f5a05..6e64e9b21 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -327,6 +327,7 @@ public: #ifdef SRS_AUTO_RTC // To find the RTP packet for RTX or restore. +// TODO: FIXME: Should queue RTP packets in connection level. class SrsRtpPacketQueue { private: @@ -634,6 +635,8 @@ public: #ifdef SRS_AUTO_RTC // Find rtp packet by sequence SrsRtpSharedPacket* find_rtp_packet(const uint16_t& seq); + // Get the cached meta, as such the sps/pps. + SrsMetaCache* cached_meta(); #endif }; diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index b0ced2f92..00e289feb 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -211,11 +211,14 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload() size = 0; shared_count = 0; +#ifdef SRS_AUTO_RTC samples = NULL; - nb_samples = 0; + nn_samples = 0; + has_idr = false; extra_payloads = NULL; nn_extra_payloads = 0; +#endif } SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() @@ -226,12 +229,14 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() srs_freepa(payload); srs_freepa(samples); +#ifdef SRS_AUTO_RTC for (int i = 0; i < nn_extra_payloads; i++) { SrsSample* p = extra_payloads + i; srs_freep(p->bytes); } srs_freepa(extra_payloads); nn_extra_payloads = 0; +#endif } SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), size(0), payload(NULL) @@ -248,12 +253,6 @@ SrsSharedPtrMessage::~SrsSharedPtrMessage() ptr->shared_count--; } } - -#ifdef SRS_AUTO_RTC - for (int i = 0; i < (int)rtp_packets.size(); ++i) { - srs_freep(rtp_packets[i]); - } -#endif } srs_error_t SrsSharedPtrMessage::create(SrsCommonMessage* msg) @@ -372,21 +371,10 @@ SrsSharedPtrMessage* SrsSharedPtrMessage::copy() copy->payload = ptr->payload; copy->size = ptr->size; -#ifdef SRS_AUTO_RTC - for (int i = 0; i < (int)rtp_packets.size(); ++i) { - copy->rtp_packets.push_back(rtp_packets[i]->copy()); - } -#endif - return copy; } #ifdef SRS_AUTO_RTC -void SrsSharedPtrMessage::set_rtp_packets(const std::vector& pkts) -{ - rtp_packets = pkts; -} - void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payloads) { srs_assert(nn_payloads); @@ -397,6 +385,17 @@ void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payload ptr->extra_payloads = new SrsSample[nn_payloads]; memcpy(ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample)); } + +void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples) +{ + srs_assert(nn_samples); + srs_assert(!ptr->samples); + + ptr->nn_samples = nn_samples; + + ptr->samples = new SrsSample[nn_samples]; + memcpy(ptr->samples, samples, nn_samples * sizeof(SrsSample)); +} #endif SrsFlvTransmuxer::SrsFlvTransmuxer() diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index ca5f24f09..84d7d34d9 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -288,9 +288,6 @@ public: // @remark, not all message payload can be decoded to packet. for example, // video/audio packet use raw bytes, no video/audio packet. char* payload; -#ifdef SRS_AUTO_RTC - std::vector rtp_packets; -#endif private: class SrsSharedPtrPayload @@ -305,15 +302,19 @@ private: int size; // The reference count int shared_count; +#ifdef SRS_AUTO_RTC public: // For RTC video, we need to know the NALU structures, // because the RTP STAP-A or FU-A based on NALU. SrsSample* samples; - int nb_samples; + int nn_samples; + // For RTC video, whether NALUs has IDR. + bool has_idr; // For RTC audio, we may need to transcode AAC to opus, // so there must be an extra payloads, which is transformed from payload. SrsSample* extra_payloads; int nn_extra_payloads; +#endif public: SrsSharedPtrPayload(); virtual ~SrsSharedPtrPayload(); @@ -357,13 +358,18 @@ public: virtual SrsSharedPtrMessage* copy(); public: #ifdef SRS_AUTO_RTC - virtual void set_rtp_packets(const std::vector& pkts); // Set extra samples, for example, when we transcode an AAC audio packet to OPUS, // we may get more than one OPUS packets, we set these OPUS packets in extra payloads. void set_extra_payloads(SrsSample* payloads, int nn_payloads); - // Get the extra payloads and the number of it. int nn_extra_payloads() { return ptr->nn_extra_payloads; } SrsSample* extra_payloads() { return ptr->extra_payloads; } + // Whether samples has idr. + bool has_idr() { return ptr->has_idr; } + void set_has_idr(bool v) { ptr->has_idr = v; } + // Set samples, each sample points to the address of payload. + void set_samples(SrsSample* samples, int nn_samples); + int nn_samples() { return ptr->nn_samples; } + SrsSample* samples() { return ptr->samples; } #endif }; From bf6224490804699dbb295053a34f88d30d1da322 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 21:46:34 +0800 Subject: [PATCH 022/131] Free RTP packet for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b7038da79..d00ca49ab 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -653,6 +653,7 @@ srs_error_t SrsRtcSenderThread::send_messages( if ((err = send_message(msg, is_video, is_audio, pkt, skt)) != srs_success) { return srs_error_wrap(err, "send message"); } + srs_freep(pkt); } *pnn += msg->size; From 4b2404c203fc20559855c3a2487f975610cb6648 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 22:54:44 +0800 Subject: [PATCH 023/131] For #307, zero copy for RTP audio packet --- trunk/src/app/srs_app_rtc_conn.cpp | 109 +++++++++++++++++++++++----- trunk/src/app/srs_app_rtc_conn.hpp | 5 +- trunk/src/kernel/srs_kernel_rtp.cpp | 49 +++++++++++-- trunk/src/kernel/srs_kernel_rtp.hpp | 14 ++++ 4 files changed, 148 insertions(+), 29 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d00ca49ab..20a1e02f3 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -386,6 +386,28 @@ srs_error_t SrsDtlsSession::protect_rtp(char* out_buf, const char* in_buf, int& return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); } +srs_error_t SrsDtlsSession::protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* pkt) +{ + srs_error_t err = srs_success; + + if (!srtp_send) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); + } + + SrsBuffer stream(buf, *pnn_buf); + if ((err = pkt->encode(&stream)) != srs_success) { + return srs_error_wrap(err, "encode packet"); + } + + *pnn_buf = stream.pos(); + + if (srtp_protect(srtp_send, buf, pnn_buf) != 0) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); + } + + return err; +} + srs_error_t SrsDtlsSession::unprotect_rtp(char* out_buf, const char* in_buf, int& nb_out_buf) { srs_error_t err = srs_success; @@ -599,18 +621,28 @@ srs_error_t SrsRtcSenderThread::send_messages( SrsSharedPtrMessage* msg = msgs[i]; bool is_video = msg->is_video(); bool is_audio = msg->is_audio(); - - // Package opus packets to RTP packets. - vector rtp_packets; + *pnn += msg->size; if (is_audio) { for (int i = 0; i < msg->nn_extra_payloads(); i++) { SrsSample* sample = msg->extra_payloads() + i; - if ((err = packet_opus(msg, sample, rtp_packets)) != srs_success) { + + SrsRtpPacket2* packet = NULL; + if ((err = packet_opus(sample, &packet)) != srs_success) { return srs_error_wrap(err, "opus package"); } + + err = send_message2(msg, is_video, is_audio, packet, skt); + srs_freep(packet); + if (err != srs_success) { + return srs_error_wrap(err, "send message"); + } + + *pnn_rtp_pkts += 1; } } else { + vector rtp_packets; + for (int i = 0; i < msg->nn_samples(); i++) { SrsSample* sample = msg->samples() + i; @@ -645,19 +677,18 @@ srs_error_t SrsRtcSenderThread::send_messages( return srs_error_wrap(err, "set marker"); } } - } - int nn_rtp_pkts = (int)rtp_packets.size(); - for (int j = 0; j < nn_rtp_pkts; j++) { - SrsRtpSharedPacket* pkt = rtp_packets[j]; - if ((err = send_message(msg, is_video, is_audio, pkt, skt)) != srs_success) { - return srs_error_wrap(err, "send message"); + int nn_rtp_pkts = (int)rtp_packets.size(); + for (int j = 0; j < nn_rtp_pkts; j++) { + SrsRtpSharedPacket* pkt = rtp_packets[j]; + if ((err = send_message(msg, is_video, is_audio, pkt, skt)) != srs_success) { + return srs_error_wrap(err, "send message"); + } + srs_freep(pkt); } - srs_freep(pkt); - } - *pnn += msg->size; - *pnn_rtp_pkts += nn_rtp_pkts; + *pnn_rtp_pkts += nn_rtp_pkts; + } } return err; @@ -702,20 +733,58 @@ srs_error_t SrsRtcSenderThread::send_message(SrsSharedPtrMessage* msg, bool is_v return err; } -srs_error_t SrsRtcSenderThread::packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets) +srs_error_t SrsRtcSenderThread::send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - packet->rtp_header.set_marker(true); - if ((err = packet->create(audio_timestamp, audio_sequence++, kAudioSSRC, kOpusPayloadType, sample->bytes, sample->size)) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); + int length = kRtpPacketSize; + // Fetch a cached message from queue. + // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. + mmsghdr* mhdr = rtc_session->rtc_server->fetch(); + char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; + + if (rtc_session->encrypt) { + if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length, pkt)) != srs_success) { + return srs_error_wrap(err, "srtp protect"); + } + } else { + SrsBuffer stream(buf, length); + if ((err = pkt->encode(&stream)) != srs_success) { + return srs_error_wrap(err, "encode packet"); + } + length = stream.pos(); } + sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); + socklen_t addrlen = (socklen_t)skt->peer_addrlen(); + + mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; + mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; + mhdr->msg_hdr.msg_iov->iov_len = length; + mhdr->msg_len = 0; + + rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); + return err; +} + +srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket) +{ + srs_error_t err = srs_success; + + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packet->rtp_header.set_marker(true); + packet->rtp_header.set_timestamp(audio_timestamp); + packet->rtp_header.set_sequence(audio_sequence++); + packet->rtp_header.set_ssrc(audio_ssrc); + packet->rtp_header.set_payload_type(audio_payload_type); + + packet->payload = sample->bytes; + packet->nn_payload = sample->size; + // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; - rtp_packets.push_back(packet); + *ppacket = packet; return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index d9fd03cfe..b2729e843 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -49,6 +49,7 @@ class SrsRtcServer; class SrsRtcSession; class SrsSharedPtrMessage; class SrsSource; +class SrsRtpPacket2; const uint8_t kSR = 200; const uint8_t kRR = 201; @@ -104,6 +105,7 @@ public: srs_error_t on_dtls_application_data(const char* data, const int len); public: srs_error_t protect_rtp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); + srs_error_t protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* pkt); srs_error_t unprotect_rtp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); srs_error_t protect_rtcp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); srs_error_t unprotect_rtcp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); @@ -152,8 +154,9 @@ public: private: srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); srs_error_t send_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); + srs_error_t send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); private: - srs_error_t packet_opus(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); + srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 59ad7ca93..5cef33e9c 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -77,7 +77,7 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* stream) { srs_error_t err = srs_success; - // TODO: + // TODO: FIXME: Implements it. return err; } @@ -86,19 +86,21 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream) { srs_error_t err = srs_success; - uint8_t first = 0x80 | cc; + uint8_t v = 0x80 | cc; if (padding) { - first |= 0x40; + v |= 0x40; } if (extension) { - first |= 0x10; + v |= 0x10; } - stream->write_1bytes(first); - uint8_t second = payload_type; + stream->write_1bytes(v); + + v = payload_type; if (marker) { - payload_type |= kRtpMarker; + v |= kRtpMarker; } - stream->write_1bytes(second); + stream->write_1bytes(v); + stream->write_2bytes(sequence); stream->write_4bytes(timestamp); stream->write_4bytes(ssrc); @@ -143,6 +145,37 @@ void SrsRtpHeader::set_ssrc(uint32_t ssrc) this->ssrc = ssrc; } +SrsRtpPacket2::SrsRtpPacket2() +{ + payload = NULL; + nn_payload = 0; +} + +SrsRtpPacket2::~SrsRtpPacket2() +{ +} + +srs_error_t SrsRtpPacket2::encode(SrsBuffer* stream) +{ + srs_error_t err = srs_success; + + if ((err = rtp_header.encode(stream)) != srs_success) { + return srs_error_wrap(err, "rtp header"); + } + + if (nn_payload <= 0) { + return 0; + } + + if (!stream->require(nn_payload)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", nn_payload); + } + + stream->write_bytes(payload, nn_payload); + + return err; +} + SrsRtpSharedPacket::SrsRtpSharedPacketPayload::SrsRtpSharedPacketPayload() { payload = NULL; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 396cb2687..368dc5b0f 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -70,6 +70,20 @@ public: uint32_t get_ssrc() const { return ssrc; } }; +class SrsRtpPacket2 +{ +public: + SrsRtpHeader rtp_header; + // @remark We only refer to the memory, user must free it. + char* payload; + int nn_payload; +public: + SrsRtpPacket2(); + virtual ~SrsRtpPacket2(); +public: + virtual srs_error_t encode(SrsBuffer* stream); +}; + class SrsRtpSharedPacket { private: From aa81b47c9a50158c770a711db105340cc2fee810 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 11 Apr 2020 23:57:04 +0800 Subject: [PATCH 024/131] For #307, zero copy for RTP STAP packet --- trunk/src/app/srs_app_rtc.hpp | 4 -- trunk/src/app/srs_app_rtc_conn.cpp | 61 ++++++++++------- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- trunk/src/kernel/srs_kernel_buffer.cpp | 8 +++ trunk/src/kernel/srs_kernel_buffer.hpp | 30 ++++++--- trunk/src/kernel/srs_kernel_codec.cpp | 4 +- trunk/src/kernel/srs_kernel_rtp.cpp | 92 +++++++++++++++++++++++--- trunk/src/kernel/srs_kernel_rtp.hpp | 45 +++++++++++-- 8 files changed, 191 insertions(+), 55 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index c75eae7ce..c695718ec 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -48,11 +48,7 @@ const int kRtpPacketSize = 1500; const uint8_t kOpusPayloadType = 111; const uint8_t kH264PayloadType = 102; -// H.264 nalu header type mask. -const uint8_t kNalTypeMask = 0x1F; - // @see: https://tools.ietf.org/html/rfc6184#section-5.2 -const uint8_t kStapA = 24; const uint8_t kFuA = 28; // @see: https://tools.ietf.org/html/rfc6184#section-5.8 diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 20a1e02f3..0e3e02aec 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -398,7 +398,7 @@ srs_error_t SrsDtlsSession::protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* if ((err = pkt->encode(&stream)) != srs_success) { return srs_error_wrap(err, "encode packet"); } - + *pnn_buf = stream.pos(); if (srtp_protect(srtp_send, buf, pnn_buf) != 0) { @@ -654,9 +654,18 @@ srs_error_t SrsRtcSenderThread::send_messages( // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. if (msg->has_idr()) { - if ((err = packet_stap_a(source, msg, rtp_packets)) != srs_success) { + SrsRtpPacket2* packet = NULL; + if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { return srs_error_wrap(err, "packet stap-a"); } + + err = send_message2(msg, is_video, is_audio, packet, skt); + srs_freep(packet); + if (err != srs_success) { + return srs_error_wrap(err, "send message"); + } + + *pnn_rtp_pkts += 1; } if (sample->size <= kRtpMaxPayloadSize) { @@ -778,8 +787,10 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** p packet->rtp_header.set_ssrc(audio_ssrc); packet->rtp_header.set_payload_type(audio_payload_type); - packet->payload = sample->bytes; - packet->nn_payload = sample->size; + SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + raw->payload = sample->bytes; + raw->nn_payload = sample->size; + packet->payload = raw; // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; @@ -852,7 +863,7 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* shared_f return err; } -srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, vector& rtp_packets) +srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, SrsRtpPacket2** ppacket) { srs_error_t err = srs_success; @@ -872,32 +883,34 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); } + srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", + (sps.size() + pps.size()), video_sequence, (shared_frame->timestamp * 90)); + + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packet->rtp_header.set_marker(false); + packet->rtp_header.set_timestamp(shared_frame->timestamp * 90); + packet->rtp_header.set_sequence(video_sequence++); + packet->rtp_header.set_ssrc(video_ssrc); + packet->rtp_header.set_payload_type(video_payload_type); + + SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); + uint8_t header = sps[0]; uint8_t nal_type = header & kNalTypeMask; - char buf[kRtpPacketSize]; - SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); - SrsAutoFree(SrsBuffer, stream); + stap->nri = (SrsAvcNaluType)nal_type; + stap->nn_nalus = 2; + stap->nalus = new SrsSample[stap->nn_nalus]; - // stap-a header - uint8_t stap_a_header = kStapA; - stap_a_header |= (nal_type & (~kNalTypeMask)); - stream->write_1bytes(stap_a_header); + stap->nalus[0].bytes = (char*)&sps[0]; + stap->nalus[0].size = (int)sps.size(); - stream->write_2bytes(sps.size()); - stream->write_bytes((char*)sps.data(), sps.size()); + stap->nalus[1].bytes = (char*)&pps[0]; + stap->nalus[1].size = (int)pps.size(); - stream->write_2bytes(pps.size()); - stream->write_bytes((char*)pps.data(), pps.size()); + packet->payload = stap; - srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", (sps.size() + pps.size()), video_sequence, (shared_frame->timestamp * 90)); - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - rtp_packets.push_back(packet); + *ppacket = packet; return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index b2729e843..fb5095b81 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -160,7 +160,7 @@ private: private: srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); - srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, std::vector& rtp_packets); + srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, SrsRtpPacket2** ppacket); }; class SrsRtcSession diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index e6fcfe1fa..73c6cafe1 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -29,6 +29,14 @@ using namespace std; #include #include +ISrsEncoder::ISrsEncoder() +{ +} + +ISrsEncoder::~ISrsEncoder() +{ +} + ISrsCodec::ISrsCodec() { } diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index 3fdb7e74b..870da9ef8 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -31,6 +31,24 @@ class SrsBuffer; +// Encoder. +class ISrsEncoder +{ +public: + ISrsEncoder(); + virtual ~ISrsEncoder(); +public: + /** + * get the number of bytes to code to. + */ + // TODO: FIXME: change to uint64_t. + virtual int nb_bytes() = 0; + /** + * encode object to bytes in SrsBuffer. + */ + virtual srs_error_t encode(SrsBuffer* buf) = 0; +}; + /** * the srs codec, to code and decode object with bytes: * code: to encode/serialize object to bytes in buffer, @@ -56,21 +74,11 @@ class SrsBuffer; * @remark protocol or amf0 or json should implements this interface. */ // TODO: FIXME: protocol, amf0, json should implements it. -class ISrsCodec +class ISrsCodec : public ISrsEncoder { public: ISrsCodec(); virtual ~ISrsCodec(); -public: - /** - * get the number of bytes to code to. - */ - // TODO: FIXME: change to uint64_t. - virtual int nb_bytes() = 0; - /** - * encode object to bytes in SrsBuffer. - */ - virtual srs_error_t encode(SrsBuffer* buf) = 0; public: /** * decode object from bytes in SrsBuffer. diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 41034e6f4..a351dcc52 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -32,6 +32,7 @@ using namespace std; #include #include #include +#include string srs_video_codec_id2str(SrsVideoCodecId codec) { @@ -375,9 +376,6 @@ srs_error_t SrsSample::parse_bframe() { srs_error_t err = srs_success; - // H.264 nalu header type mask. - static uint8_t kNalTypeMask = 0x1F; - uint8_t header = bytes[0]; SrsAvcNaluType nal_type = (SrsAvcNaluType)(header & kNalTypeMask); diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 5cef33e9c..733b67315 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -32,6 +32,8 @@ using namespace std; #include #include +// @see: https://tools.ietf.org/html/rfc6184#section-5.2 +const uint8_t kStapA = 24; SrsRtpHeader::SrsRtpHeader() { @@ -148,32 +150,106 @@ void SrsRtpHeader::set_ssrc(uint32_t ssrc) SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; - nn_payload = 0; } SrsRtpPacket2::~SrsRtpPacket2() { + srs_freep(payload); } -srs_error_t SrsRtpPacket2::encode(SrsBuffer* stream) +srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) { srs_error_t err = srs_success; - if ((err = rtp_header.encode(stream)) != srs_success) { + if ((err = rtp_header.encode(buf)) != srs_success) { return srs_error_wrap(err, "rtp header"); } - if (nn_payload <= 0) { - return 0; + if (payload && (err = payload->encode(buf)) != srs_success) { + return srs_error_wrap(err, "encode payload"); } - if (!stream->require(nn_payload)) { + return err; +} + +SrsRtpRawPayload::SrsRtpRawPayload() +{ + payload = NULL; + nn_payload = 0; +} + +SrsRtpRawPayload::~SrsRtpRawPayload() +{ +} + +int SrsRtpRawPayload::nb_bytes() +{ + return nn_payload; +} + +srs_error_t SrsRtpRawPayload::encode(SrsBuffer* buf) +{ + if (nn_payload <= 0) { + return srs_success; + } + + if (!buf->require(nn_payload)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", nn_payload); } - stream->write_bytes(payload, nn_payload); + buf->write_bytes(payload, nn_payload); - return err; + return srs_success; +} + +SrsRtpSTAPPayload::SrsRtpSTAPPayload() +{ + nri = (SrsAvcNaluType)0; + nalus = NULL; + nn_nalus = 0; +} + +SrsRtpSTAPPayload::~SrsRtpSTAPPayload() +{ + srs_freepa(nalus); +} + +int SrsRtpSTAPPayload::nb_bytes() +{ + int size = 1; + + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus + i; + size += 2 + p->size; + } + + return size; +} + +srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf) +{ + if (!buf->require(1)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // STAP header, RTP payload format for aggregation packets + // @see https://tools.ietf.org/html/rfc6184#section-5.7 + uint8_t v = kStapA; + v |= (nri & (~kNalTypeMask)); + buf->write_1bytes(v); + + // NALUs. + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus + i; + if (!buf->require(2 + p->size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); + } + + buf->write_2bytes(p->size); + buf->write_bytes(p->bytes, p->size); + } + + return srs_success; } SrsRtpSharedPacket::SrsRtpSharedPacketPayload::SrsRtpSharedPacketPayload() diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 368dc5b0f..c5379b9fb 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -26,11 +26,17 @@ #include +#include +#include + #include const int kRtpHeaderFixedSize = 12; const uint8_t kRtpMarker = 0x80; +// H.264 nalu header type mask. +const uint8_t kNalTypeMask = 0x1F; + class SrsBuffer; class SrsRtpHeader @@ -74,14 +80,45 @@ class SrsRtpPacket2 { public: SrsRtpHeader rtp_header; - // @remark We only refer to the memory, user must free it. - char* payload; - int nn_payload; + ISrsEncoder* payload; public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); public: - virtual srs_error_t encode(SrsBuffer* stream); + virtual srs_error_t encode(SrsBuffer* buf); +}; + +class SrsRtpRawPayload : public ISrsEncoder +{ +public: + // @remark We only refer to the memory, user must free it. + char* payload; + int nn_payload; +public: + SrsRtpRawPayload(); + virtual ~SrsRtpRawPayload(); +// interface ISrsEncoder +public: + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer* buf); +}; + +class SrsRtpSTAPPayload : public ISrsEncoder +{ +public: + // The NRI in NALU type. + SrsAvcNaluType nri; + // The NALU samples. + // @remark We only refer to the memory, user must free its bytes. + SrsSample* nalus; + int nn_nalus; +public: + SrsRtpSTAPPayload(); + virtual ~SrsRtpSTAPPayload(); +// interface ISrsEncoder +public: + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer* buf); }; class SrsRtpSharedPacket From ca027ca5cb60c553ac7cb56f5ed49e32fdbc04f9 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 01:01:39 +0800 Subject: [PATCH 025/131] For #307, zero copy for RTP FUA packet --- trunk/src/app/srs_app_rtc.hpp | 7 -- trunk/src/app/srs_app_rtc_conn.cpp | 151 ++++++++++------------------ trunk/src/app/srs_app_rtc_conn.hpp | 7 +- trunk/src/kernel/srs_kernel_rtp.cpp | 70 +++++++++++++ trunk/src/kernel/srs_kernel_rtp.hpp | 21 ++++ 5 files changed, 147 insertions(+), 109 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index c695718ec..9bd794b62 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -48,13 +48,6 @@ const int kRtpPacketSize = 1500; const uint8_t kOpusPayloadType = 111; const uint8_t kH264PayloadType = 102; -// @see: https://tools.ietf.org/html/rfc6184#section-5.2 -const uint8_t kFuA = 28; - -// @see: https://tools.ietf.org/html/rfc6184#section-5.8 -const uint8_t kStart = 0x80; // Fu-header start bit -const uint8_t kEnd = 0x40; // Fu-header end bit - const int kChannel = 2; const int kSamplerate = 48000; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 0e3e02aec..14f105ca8 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -641,8 +641,6 @@ srs_error_t SrsRtcSenderThread::send_messages( *pnn_rtp_pkts += 1; } } else { - vector rtp_packets; - for (int i = 0; i < msg->nn_samples(); i++) { SrsSample* sample = msg->samples() + i; @@ -668,90 +666,51 @@ srs_error_t SrsRtcSenderThread::send_messages( *pnn_rtp_pkts += 1; } + vector packets; if (sample->size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(msg, sample, rtp_packets)) != srs_success) { + SrsRtpPacket2* packet = NULL; + if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } + packets.push_back(packet); } else { - if ((err = packet_fu_a(msg, sample, rtp_packets)) != srs_success) { + if ((err = packet_fu_a(msg, sample, packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } } - } - if (!rtp_packets.empty()) { - // At the end of the frame, set marker bit. - // One frame may have multi nals. Set the marker bit in the last nal end, no the end of the nal. - if ((err = rtp_packets.back()->modify_rtp_header_marker(true)) != srs_success) { - return srs_error_wrap(err, "set marker"); + if (i == msg->nn_samples() - 1) { + packets.back()->rtp_header.set_marker(true); } - } - int nn_rtp_pkts = (int)rtp_packets.size(); - for (int j = 0; j < nn_rtp_pkts; j++) { - SrsRtpSharedPacket* pkt = rtp_packets[j]; - if ((err = send_message(msg, is_video, is_audio, pkt, skt)) != srs_success) { - return srs_error_wrap(err, "send message"); + for (int j = 0; j < (int)packets.size(); j++) { + SrsRtpPacket2* packet = packets[j]; + err = send_message2(msg, is_video, is_audio, packet, skt); + srs_freep(packet); + if (err != srs_success) { + return srs_error_wrap(err, "send message"); + } } - srs_freep(pkt); + *pnn_rtp_pkts += (int)packets.size(); } - - *pnn_rtp_pkts += nn_rtp_pkts; } } return err; } -srs_error_t SrsRtcSenderThread::send_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt) -{ - srs_error_t err = srs_success; - - if (is_video) { - pkt->modify_rtp_header_payload_type(video_payload_type); - pkt->modify_rtp_header_ssrc(video_ssrc); - srs_verbose("send video, ssrc=%u, seq=%u, timestamp=%u", video_ssrc, pkt->rtp_header.get_sequence(), pkt->rtp_header.get_timestamp()); - } else if (is_audio) { - pkt->modify_rtp_header_payload_type(audio_payload_type); - pkt->modify_rtp_header_ssrc(audio_ssrc); - } - - int length = pkt->size; - // Fetch a cached message from queue. - // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. - mmsghdr* mhdr = rtc_session->rtc_server->fetch(); - char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; - - if (rtc_session->encrypt) { - if ((err = rtc_session->dtls_session->protect_rtp(buf, pkt->payload, length)) != srs_success) { - return srs_error_wrap(err, "srtp protect"); - } - } else { - memcpy(buf, pkt->payload, length); - } - - sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); - socklen_t addrlen = (socklen_t)skt->peer_addrlen(); - - mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; - mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; - mhdr->msg_hdr.msg_iov->iov_len = length; - mhdr->msg_len = 0; - - rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); - return err; -} - srs_error_t SrsRtcSenderThread::send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; - int length = kRtpPacketSize; // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. mmsghdr* mhdr = rtc_session->rtc_server->fetch(); char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; + // Length of iov, default size. + int length = kRtpPacketSize; + if (rtc_session->encrypt) { if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length, pkt)) != srs_success) { return srs_error_wrap(err, "srtp protect"); @@ -800,7 +759,7 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** p return err; } -srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, vector& rtp_packets) +srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, vector& packets) { srs_error_t err = srs_success; @@ -809,61 +768,60 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* shared_frame, S uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - int num_of_packet = (sample->size - 1 + kRtpMaxPayloadSize) / kRtpMaxPayloadSize; + int num_of_packet = 1 + (sample->size - 1) / kRtpMaxPayloadSize; for (int i = 0; i < num_of_packet; ++i) { - char buf[kRtpPacketSize]; - SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize); - SrsAutoFree(SrsBuffer, stream); + int packet_size = srs_min(nb_left, kRtpMaxPayloadSize); - int packet_size = min(nb_left, kRtpMaxPayloadSize); + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packets.push_back(packet); - // fu-indicate - uint8_t fu_indicate = kFuA; - fu_indicate |= (header & (~kNalTypeMask)); - stream->write_1bytes(fu_indicate); + packet->rtp_header.set_timestamp(msg->timestamp * 90); + packet->rtp_header.set_sequence(video_sequence++); + packet->rtp_header.set_ssrc(video_ssrc); + packet->rtp_header.set_payload_type(video_payload_type); - uint8_t fu_header = nal_type; - if (i == 0) - fu_header |= kStart; - if (i == num_of_packet - 1) - fu_header |= kEnd; - stream->write_1bytes(fu_header); + SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); + packet->payload = fua; + + fua->nri = (SrsAvcNaluType)header; + fua->nalu_type = (SrsAvcNaluType)nal_type; + fua->start = bool(i == 0); + fua->end = bool(i == num_of_packet - 1); + + SrsSample* sample = new SrsSample(); + sample->bytes = p; + sample->size = packet_size; + fua->nalus.push_back(sample); - stream->write_bytes(p, packet_size); p += packet_size; nb_left -= packet_size; - - srs_verbose("rtp fu-a nalu, size=%u, seq=%u, timestamp=%lu", sample->size, video_sequence, (shared_frame->timestamp * 90)); - - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, stream->data(), stream->pos())) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } - - rtp_packets.push_back(packet); } return err; } // Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 -srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, vector& rtp_packets) +srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket) { srs_error_t err = srs_success; - srs_verbose("rtp single nalu, size=%u, seq=%u, timestamp=%lu", sample->size, video_sequence, (shared_frame->timestamp * 90)); + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packet->rtp_header.set_timestamp(msg->timestamp * 90); + packet->rtp_header.set_sequence(video_sequence++); + packet->rtp_header.set_ssrc(video_ssrc); + packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpSharedPacket* packet = new SrsRtpSharedPacket(); - if ((err = packet->create((shared_frame->timestamp * 90), video_sequence++, kVideoSSRC, kH264PayloadType, sample->bytes, sample->size)) != srs_success) { - return srs_error_wrap(err, "rtp packet encode"); - } + SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + raw->payload = sample->bytes; + raw->nn_payload = sample->size; + packet->payload = raw; - rtp_packets.push_back(packet); + *ppacket = packet; return err; } -srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, SrsRtpPacket2** ppacket) +srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket) { srs_error_t err = srs_success; @@ -883,12 +841,9 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); } - srs_verbose("rtp stap-a nalu, size=%u, seq=%u, timestamp=%lu", - (sps.size() + pps.size()), video_sequence, (shared_frame->timestamp * 90)); - SrsRtpPacket2* packet = new SrsRtpPacket2(); packet->rtp_header.set_marker(false); - packet->rtp_header.set_timestamp(shared_frame->timestamp * 90); + packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); @@ -898,7 +853,7 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes uint8_t header = sps[0]; uint8_t nal_type = header & kNalTypeMask; - stap->nri = (SrsAvcNaluType)nal_type; + stap->nri = (SrsAvcNaluType)header; stap->nn_nalus = 2; stap->nalus = new SrsSample[stap->nn_nalus]; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index fb5095b81..16cba0d9f 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -153,14 +153,13 @@ public: void update_sendonly_socket(SrsUdpMuxSocket* skt); private: srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); - srs_error_t send_message(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpSharedPacket* pkt, SrsUdpMuxSocket* skt); srs_error_t send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: - srs_error_t packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); - srs_error_t packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsSample* sample, std::vector& rtp_packets); - srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* shared_frame, SrsRtpPacket2** ppacket); + srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, std::vector& packets); + srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket); + srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket); }; class SrsRtcSession diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 733b67315..7a719abcc 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -35,6 +35,13 @@ using namespace std; // @see: https://tools.ietf.org/html/rfc6184#section-5.2 const uint8_t kStapA = 24; +// @see: https://tools.ietf.org/html/rfc6184#section-5.2 +const uint8_t kFuA = 28; + +// @see: https://tools.ietf.org/html/rfc6184#section-5.8 +const uint8_t kStart = 0x80; // Fu-header start bit +const uint8_t kEnd = 0x40; // Fu-header end bit + SrsRtpHeader::SrsRtpHeader() { padding = false; @@ -252,6 +259,69 @@ srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf) return srs_success; } +SrsRtpFUAPayload::SrsRtpFUAPayload() +{ + start = end = false; + nri = nalu_type = (SrsAvcNaluType)0; +} + +SrsRtpFUAPayload::~SrsRtpFUAPayload() +{ + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + srs_freep(p); + } +} + +int SrsRtpFUAPayload::nb_bytes() +{ + int size = 2; + + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + size += p->size; + } + + return size; +} + +srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf) +{ + if (!buf->require(2)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_indicate = kFuA; + fu_indicate |= (nri & (~kNalTypeMask)); + buf->write_1bytes(fu_indicate); + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_header = nalu_type; + if (start) { + fu_header |= kStart; + } + if (end) { + fu_header |= kEnd; + } + buf->write_1bytes(fu_header); + + // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + if (!buf->require(p->size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); + } + + buf->write_bytes(p->bytes, p->size); + } + + return srs_success; +} + SrsRtpSharedPacket::SrsRtpSharedPacketPayload::SrsRtpSharedPacketPayload() { payload = NULL; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index c5379b9fb..be22567b8 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -121,6 +121,27 @@ public: virtual srs_error_t encode(SrsBuffer* buf); }; +class SrsRtpFUAPayload : public ISrsEncoder +{ +public: + // The NRI in NALU type. + SrsAvcNaluType nri; + // The FUA header. + bool start; + bool end; + SrsAvcNaluType nalu_type; + // The NALU samples. + // @remark We only refer to the memory, user must free its bytes. + std::vector nalus; +public: + SrsRtpFUAPayload(); + virtual ~SrsRtpFUAPayload(); +// interface ISrsEncoder +public: + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer* buf); +}; + class SrsRtpSharedPacket { private: From acbbdf51d6bc87a6af12e4d54483da89fa441e37 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 01:05:11 +0800 Subject: [PATCH 026/131] Refacor STAP RTP packet --- trunk/src/kernel/srs_kernel_rtp.cpp | 20 +++++++++++++------- trunk/src/kernel/srs_kernel_rtp.hpp | 3 +-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 7a719abcc..9f8a3b671 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -212,21 +212,25 @@ srs_error_t SrsRtpRawPayload::encode(SrsBuffer* buf) SrsRtpSTAPPayload::SrsRtpSTAPPayload() { nri = (SrsAvcNaluType)0; - nalus = NULL; - nn_nalus = 0; } SrsRtpSTAPPayload::~SrsRtpSTAPPayload() { - srs_freepa(nalus); + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + srs_freep(p); + } + nalus.clear(); } int SrsRtpSTAPPayload::nb_bytes() { int size = 1; - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus + i; + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; size += 2 + p->size; } @@ -246,8 +250,9 @@ srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf) buf->write_1bytes(v); // NALUs. - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = nalus + i; + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; if (!buf->require(2 + p->size)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); } @@ -272,6 +277,7 @@ SrsRtpFUAPayload::~SrsRtpFUAPayload() SrsSample* p = *it; srs_freep(p); } + nalus.clear(); } int SrsRtpFUAPayload::nb_bytes() diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index be22567b8..6fe5f32ef 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -110,8 +110,7 @@ public: SrsAvcNaluType nri; // The NALU samples. // @remark We only refer to the memory, user must free its bytes. - SrsSample* nalus; - int nn_nalus; + std::vector nalus; public: SrsRtpSTAPPayload(); virtual ~SrsRtpSTAPPayload(); From 32efc71ba9aec840486de96d0ebb44c738936308 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 01:05:32 +0800 Subject: [PATCH 027/131] Fix the STAP NRI flag --- trunk/src/app/srs_app_rtc_conn.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 14f105ca8..3eb093c70 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -851,7 +851,6 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); uint8_t header = sps[0]; - uint8_t nal_type = header & kNalTypeMask; stap->nri = (SrsAvcNaluType)header; stap->nn_nalus = 2; From 79d46fa2e183f22f702b5fb5127b468b5e20ff74 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 01:08:21 +0800 Subject: [PATCH 028/131] Fix build failed bug --- trunk/src/app/srs_app_rtc_conn.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3eb093c70..7a7b84463 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -812,9 +812,10 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, Srs packet->rtp_header.set_payload_type(video_payload_type); SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + packet->payload = raw; + raw->payload = sample->bytes; raw->nn_payload = sample->size; - packet->payload = raw; *ppacket = packet; @@ -849,20 +850,24 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes packet->rtp_header.set_payload_type(video_payload_type); SrsRtpSTAPPayload* stap = new SrsRtpSTAPPayload(); + packet->payload = stap; uint8_t header = sps[0]; - stap->nri = (SrsAvcNaluType)header; - stap->nn_nalus = 2; - stap->nalus = new SrsSample[stap->nn_nalus]; - stap->nalus[0].bytes = (char*)&sps[0]; - stap->nalus[0].size = (int)sps.size(); + if (true) { + SrsSample* sample = new SrsSample(); + sample->bytes = (char*)&sps[0]; + sample->size = (int)sps.size(); + stap->nalus.push_back(sample); + } - stap->nalus[1].bytes = (char*)&pps[0]; - stap->nalus[1].size = (int)pps.size(); - - packet->payload = stap; + if (true) { + SrsSample* sample = new SrsSample(); + sample->bytes = (char*)&pps[0]; + sample->size = (int)pps.size(); + stap->nalus.push_back(sample); + } *ppacket = packet; From 5e66a0d342868cbbeb0453bdb4f970d639a85c19 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 01:13:31 +0800 Subject: [PATCH 029/131] Send SPS/PPS before IDR --- trunk/src/app/srs_app_rtc_conn.cpp | 62 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 7a7b84463..c4fec589d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -641,6 +641,23 @@ srs_error_t SrsRtcSenderThread::send_messages( *pnn_rtp_pkts += 1; } } else { + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (msg->has_idr()) { + SrsRtpPacket2* packet = NULL; + if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + + err = send_message2(msg, is_video, is_audio, packet, skt); + srs_freep(packet); + if (err != srs_success) { + return srs_error_wrap(err, "send message"); + } + + *pnn_rtp_pkts += 1; + } + + vector packets; for (int i = 0; i < msg->nn_samples(); i++) { SrsSample* sample = msg->samples() + i; @@ -650,23 +667,6 @@ srs_error_t SrsRtcSenderThread::send_messages( continue; } - // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. - if (msg->has_idr()) { - SrsRtpPacket2* packet = NULL; - if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - - err = send_message2(msg, is_video, is_audio, packet, skt); - srs_freep(packet); - if (err != srs_success) { - return srs_error_wrap(err, "send message"); - } - - *pnn_rtp_pkts += 1; - } - - vector packets; if (sample->size <= kRtpMaxPayloadSize) { SrsRtpPacket2* packet = NULL; if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { @@ -678,21 +678,21 @@ srs_error_t SrsRtcSenderThread::send_messages( return srs_error_wrap(err, "packet fu-a"); } } - - if (i == msg->nn_samples() - 1) { - packets.back()->rtp_header.set_marker(true); - } - - for (int j = 0; j < (int)packets.size(); j++) { - SrsRtpPacket2* packet = packets[j]; - err = send_message2(msg, is_video, is_audio, packet, skt); - srs_freep(packet); - if (err != srs_success) { - return srs_error_wrap(err, "send message"); - } - } - *pnn_rtp_pkts += (int)packets.size(); } + + if (!packets.empty()) { + packets.back()->rtp_header.set_marker(true); + } + + for (int j = 0; j < (int)packets.size(); j++) { + SrsRtpPacket2* packet = packets[j]; + err = send_message2(msg, is_video, is_audio, packet, skt); + srs_freep(packet); + if (err != srs_success) { + return srs_error_wrap(err, "send message"); + } + } + *pnn_rtp_pkts += (int)packets.size(); } } From edad6ac93d4fdc6337b373764b4a0b006941a7a0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 08:25:57 +0800 Subject: [PATCH 030/131] Fix memory leak. Refine RTC SEND pithy print message --- trunk/src/app/srs_app_listener.cpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 9f93b2cf8..b9d571d83 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -442,6 +442,7 @@ srs_error_t SrsUdpMuxListener::cycle() if ((err = handler->on_udp_packet(&skt)) != srs_success) { // remux udp never return srs_warn("udp packet handler error:%s", srs_error_desc(err).c_str()); + srs_error_reset(err); continue; } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c4fec589d..d391cfe8f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1660,6 +1660,8 @@ srs_error_t SrsRtcServer::cycle() srs_error_t err = srs_success; uint64_t nn_msgs = 0; + uint64_t nn_msgs_last = 0; + srs_utime_t time_last = srs_get_system_time(); SrsStatistic* stat = SrsStatistic::instance(); SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); @@ -1699,7 +1701,17 @@ srs_error_t SrsRtcServer::cycle() pprint->elapse(); if (pprint->can_print()) { - srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 " msgs", pos, max_sendmmsg, nn_msgs); + int pps_average = 0; int pps_last = 0; + if (true) { + if (srs_get_system_time() > srs_get_system_startup_time()) { + pps_average = (int)(nn_msgs * SRS_UTIME_SECONDS / (srs_get_system_time() - srs_get_system_startup_time())); + } + if (srs_get_system_time() > time_last) { + pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); + } + } + srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 ", pps %d/%d", pos, max_sendmmsg, nn_msgs, pps_average, pps_last); + nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); } } From a7f2bde8e270bb6bd87c98fc605d14c70829781c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 08:42:12 +0800 Subject: [PATCH 031/131] Refine UDP socketopt logs --- trunk/src/app/srs_app_listener.cpp | 47 +++++++++++++++++------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index b9d571d83..15c4ab773 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -390,33 +390,40 @@ srs_error_t SrsUdpMuxListener::listen() void SrsUdpMuxListener::set_socket_buffer() { - int sndbuf_size = 0; - socklen_t opt_len = sizeof(sndbuf_size); - getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, &opt_len); - srs_trace("default udp remux socket sndbuf=%d", sndbuf_size); + int default_sndbuf = 0; + int expect_sndbuf = 1024*1024*10; // 10M + int actual_sndbuf = expect_sndbuf; + int r0_sndbuf = 0; + if (true) { + socklen_t opt_len = sizeof(default_sndbuf); + getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&default_sndbuf, &opt_len); - sndbuf_size = 1024*1024*10; // 10M - if (setsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, sizeof(sndbuf_size)) < 0) { - srs_warn("set sock opt SO_SNDBUFFORCE failed"); + if ((r0_sndbuf = setsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&actual_sndbuf, sizeof(actual_sndbuf))) < 0) { + srs_warn("set SO_SNDBUF failed, expect=%d, r0=%d", expect_sndbuf, r0_sndbuf); + } + + opt_len = sizeof(actual_sndbuf); + getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&actual_sndbuf, &opt_len); } - opt_len = sizeof(sndbuf_size); - getsockopt(fd(), SOL_SOCKET, SO_SNDBUF, (void*)&sndbuf_size, &opt_len); - srs_trace("udp remux socket sndbuf=%d", sndbuf_size); + int default_rcvbuf = 0; + int expect_rcvbuf = 1024*1024*10; // 10M + int actual_rcvbuf = expect_rcvbuf; + int r0_rcvbuf = 0; + if (true) { + socklen_t opt_len = sizeof(default_rcvbuf); + getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&default_rcvbuf, &opt_len); - int rcvbuf_size = 0; - opt_len = sizeof(rcvbuf_size); - getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, &opt_len); - srs_trace("default udp remux socket rcvbuf=%d", rcvbuf_size); + if ((r0_rcvbuf = setsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&actual_rcvbuf, sizeof(actual_rcvbuf))) < 0) { + srs_warn("set SO_RCVBUF failed, expect=%d, r0=%d", expect_rcvbuf, r0_rcvbuf); + } - rcvbuf_size = 1024*1024*10; // 10M - if (setsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, sizeof(rcvbuf_size)) < 0) { - srs_warn("set sock opt SO_RCVBUFFORCE failed"); + opt_len = sizeof(actual_rcvbuf); + getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&actual_rcvbuf, &opt_len); } - opt_len = sizeof(rcvbuf_size); - getsockopt(fd(), SOL_SOCKET, SO_RCVBUF, (void*)&rcvbuf_size, &opt_len); - srs_trace("udp remux socket rcvbuf=%d", rcvbuf_size); + srs_trace("UDP #%d LISTEN at %s:%d, SO_SNDBUF(default=%d, expect=%d, actual=%d, r0=%d), SO_RCVBUF(default=%d, expect=%d, actual=%d, r0=%d)", + srs_netfd_fileno(lfd), ip.c_str(), port, default_sndbuf, expect_sndbuf, actual_sndbuf, r0_sndbuf, default_rcvbuf, expect_rcvbuf, actual_rcvbuf, r0_rcvbuf); } srs_error_t SrsUdpMuxListener::cycle() From 78aad11eeb590a53e77631bad900ea08d53b6f4e Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 08:55:43 +0800 Subject: [PATCH 032/131] For #307, enable REUSEPORT to increase UDP buffer --- trunk/conf/full.conf | 5 +++++ trunk/src/app/srs_app_config.cpp | 29 ++++++++++++++++++++++++++++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_listener.cpp | 2 ++ trunk/src/app/srs_app_rtc_conn.cpp | 25 +++++++++++++++++-------- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 513a55b87..ff17617d9 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -430,6 +430,11 @@ rtc_server { # @remark Should always turn it on, or Chrome will fail. # default: on encrypt on; + # We listen multiple times at the same port, by REUSEPORT, to increase the UDP queue. + # Note that you can set to 1 and increase the system UDP buffer size by net.core.rmem_max + # or just increase this to get larger UDP recv and send buffer. + # default: 4 + reuseport 4; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 30e987ec7..d3e790426 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3614,7 +3614,7 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" - && n != "sendmmsg" && n != "encrypt") { + && n != "sendmmsg" && n != "encrypt" && n != "reuseport") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4745,6 +4745,33 @@ int SrsConfig::get_rtc_server_sendmmsg() #endif } +int SrsConfig::get_rtc_server_reuseport() +{ +#if defined(SO_REUSEPORT) + static int DEFAULT = 4; +#else + static int DEFAULT = 1; +#endif + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("reuseport"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + int reuseport = ::atoi(conf->arg0().c_str()); +#if !defined(SO_REUSEPORT) + srs_warn("REUSEPORT not supported, reset %d to %d", reuseport, DEFAULT); + reuseport = DEFAULT +#endif + + return reuseport; +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index c17e26033..ba46984e3 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -527,6 +527,7 @@ public: virtual bool get_rtc_server_ecdsa(); virtual int get_rtc_server_sendmmsg(); virtual bool get_rtc_server_encrypt(); + virtual int get_rtc_server_reuseport(); SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 15c4ab773..eee324613 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -391,6 +391,7 @@ srs_error_t SrsUdpMuxListener::listen() void SrsUdpMuxListener::set_socket_buffer() { int default_sndbuf = 0; + // TODO: FIXME: Config it. int expect_sndbuf = 1024*1024*10; // 10M int actual_sndbuf = expect_sndbuf; int r0_sndbuf = 0; @@ -407,6 +408,7 @@ void SrsUdpMuxListener::set_socket_buffer() } int default_rcvbuf = 0; + // TODO: FIXME: Config it. int expect_rcvbuf = 1024*1024*10; // 10M int actual_rcvbuf = expect_rcvbuf; int r0_rcvbuf = 0; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d391cfe8f..3c96e69c4 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1332,7 +1332,6 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* skt) SrsRtcServer::SrsRtcServer() { - listener = NULL; timer = new SrsHourGlass(this, 1 * SRS_UTIME_SECONDS); mmstfd = NULL; @@ -1349,7 +1348,12 @@ SrsRtcServer::~SrsRtcServer() { _srs_config->unsubscribe(this); - srs_freep(listener); + vector::iterator it; + for (it = listeners.begin(); it != listeners.end(); ++it) { + SrsUdpMuxListener* listener = *it; + srs_freep(listener); + } + srs_freep(timer); srs_freep(trd); @@ -1400,16 +1404,21 @@ srs_error_t SrsRtcServer::listen_udp() } string ip = srs_any_address_for_listener(); + srs_assert(listeners.empty()); - srs_freep(listener); - listener = new SrsUdpMuxListener(this, ip, port); + int nn_listeners = _srs_config->get_rtc_server_reuseport(); + for (int i = 0; i < nn_listeners; i++) { + SrsUdpMuxListener* listener = new SrsUdpMuxListener(this, ip, port); - if ((err = listener->listen()) != srs_success) { - return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port); + if ((err = listener->listen()) != srs_success) { + srs_freep(listener); + return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port); + } + + srs_trace("rtc listen at udp://%s:%d, fd=%d", ip.c_str(), port, listener->fd()); + listeners.push_back(listener); } - srs_trace("rtc listen at udp://%s:%d, fd=%d", ip.c_str(), port, listener->fd()); - return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 16cba0d9f..e63f2109b 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -233,7 +233,7 @@ class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGl virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler { private: - SrsUdpMuxListener* listener; + std::vector listeners; SrsHourGlass* timer; private: SrsCoroutine* trd; From 2b132d6d6480c87b832ebb9ef0683f7ce7c9dedf Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 09:17:52 +0800 Subject: [PATCH 033/131] Refine RTC server log --- trunk/conf/full.conf | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index ff17617d9..7304edd06 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -432,7 +432,7 @@ rtc_server { encrypt on; # We listen multiple times at the same port, by REUSEPORT, to increase the UDP queue. # Note that you can set to 1 and increase the system UDP buffer size by net.core.rmem_max - # or just increase this to get larger UDP recv and send buffer. + # and net.core.rmem_default or just increase this to get larger UDP recv and send buffer. # default: 4 reuseport 4; } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3c96e69c4..bdaa197f0 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1719,7 +1719,8 @@ srs_error_t SrsRtcServer::cycle() pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); } } - srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 ", pps %d/%d", pos, max_sendmmsg, nn_msgs, pps_average, pps_last); + srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 ", pps %d/%d, sessions %d/%d", + pos, max_sendmmsg, nn_msgs, pps_average, pps_last, (int)map_username_session.size(), (int)map_id_session.size()); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); } } From d5b3cf9af75f6b7b900f2bd03c355e43033c21f4 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 16:10:08 +0800 Subject: [PATCH 034/131] Refactor pithy print logs --- trunk/src/app/srs_app_listener.cpp | 18 +++++++++++++++--- trunk/src/app/srs_app_pithy_print.cpp | 7 +++++++ trunk/src/app/srs_app_pithy_print.hpp | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 19 +++++++++++++++---- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index eee324613..2ae221b14 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -431,11 +431,18 @@ void SrsUdpMuxListener::set_socket_buffer() srs_error_t SrsUdpMuxListener::cycle() { srs_error_t err = srs_success; + + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_recv(); + SrsAutoFree(SrsPithyPrint, pprint); + + uint64_t nn_loop = 0; while (true) { if ((err = trd->pull()) != srs_success) { return srs_error_wrap(err, "udp listener"); - } + } + + nn_loop++; SrsUdpMuxSocket skt(lfd); @@ -452,8 +459,13 @@ srs_error_t SrsUdpMuxListener::cycle() // remux udp never return srs_warn("udp packet handler error:%s", srs_error_desc(err).c_str()); srs_error_reset(err); - continue; - } + } + + pprint->elapse(); + if (pprint->can_print()) { + srs_trace("-> RTC #%d RECV schedule %" PRId64, srs_netfd_fileno(lfd), nn_loop); + nn_loop = 0; + } if (SrsUdpPacketRecvCycleInterval > 0) { srs_usleep(SrsUdpPacketRecvCycleInterval); diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index 09ae09cf6..84c3c854d 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -114,6 +114,8 @@ SrsPithyPrint::SrsPithyPrint(int _stage_id) #define SRS_CONSTS_STAGE_RTC_PLAY 12 // for the rtc send #define SRS_CONSTS_STAGE_RTC_SEND 13 +// for the rtc recv +#define SRS_CONSTS_STAGE_RTC_RECV 14 SrsPithyPrint* SrsPithyPrint::create_rtmp_play() { @@ -180,6 +182,11 @@ SrsPithyPrint* SrsPithyPrint::create_rtc_send() return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_SEND); } +SrsPithyPrint* SrsPithyPrint::create_rtc_recv() +{ + return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_RECV); +} + SrsPithyPrint::~SrsPithyPrint() { leave_stage(); diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index 77993b047..4518b7a7c 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -89,6 +89,7 @@ public: static SrsPithyPrint* create_http_stream_cache(); static SrsPithyPrint* create_rtc_play(); static SrsPithyPrint* create_rtc_send(); + static SrsPithyPrint* create_rtc_recv(); virtual ~SrsPithyPrint(); private: // Enter the specified stage, return the client id. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index bdaa197f0..20af21ed2 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1670,6 +1670,9 @@ srs_error_t SrsRtcServer::cycle() uint64_t nn_msgs = 0; uint64_t nn_msgs_last = 0; + uint64_t nn_msgs_max = 0; + uint64_t nn_loop = 0; + uint64_t nn_wait = 0; srs_utime_t time_last = srs_get_system_time(); SrsStatistic* stat = SrsStatistic::instance(); @@ -1681,9 +1684,12 @@ srs_error_t SrsRtcServer::cycle() return err; } + nn_loop++; + int pos = cache_pos; if (pos <= 0) { waiting_msgs = true; + nn_wait++; srs_cond_wait(cond); continue; } @@ -1693,11 +1699,13 @@ srs_error_t SrsRtcServer::cycle() cache_pos = 0; mmsghdr* p = &hotspot[0]; - for (mmsghdr* end = p + pos; p < end; p += max_sendmmsg) { + mmsghdr* end = p + pos; + srs_netfd_t stfd = mmstfd; + for (; p < end; p += max_sendmmsg) { int vlen = (int)(end - p); vlen = srs_min(max_sendmmsg, vlen); - int r0 = srs_sendmmsg(mmstfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); + int r0 = srs_sendmmsg(stfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); if (r0 != vlen) { srs_warn("sendmsg %d msgs, %d done", vlen, r0); } @@ -1707,6 +1715,7 @@ srs_error_t SrsRtcServer::cycle() // Increase total messages. nn_msgs += pos; + nn_msgs_max = srs_max(pos, nn_msgs_max); pprint->elapse(); if (pprint->can_print()) { @@ -1719,9 +1728,11 @@ srs_error_t SrsRtcServer::cycle() pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); } } - srs_trace("-> RTC SEND %d by sendmmsg %d, total %" PRId64 ", pps %d/%d, sessions %d/%d", - pos, max_sendmmsg, nn_msgs, pps_average, pps_last, (int)map_username_session.size(), (int)map_id_session.size()); + + srs_trace("-> RTC #%d SEND %d by sendmmsg %d, pps %d/%d, sessions %d, schedule %" PRId64 "/%" PRId64 "/%"PRId64, + srs_netfd_fileno(stfd), pos, max_sendmmsg, pps_average, pps_last, (int)map_username_session.size(), nn_loop, nn_wait, nn_msgs_max); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); + nn_loop = nn_wait = nn_msgs_max = 0; } } From 37e2f8896c0789197042097c28a660e02ada8553 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 16:31:32 +0800 Subject: [PATCH 035/131] Refactor pithy print logs --- trunk/src/app/srs_app_listener.cpp | 33 +++++++++++++++++++++++++++--- trunk/src/app/srs_app_rtc_conn.cpp | 11 ++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 2ae221b14..37ff176bb 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -40,6 +40,7 @@ using namespace std; #include #include #include +#include // set the max packet size. #define SRS_UDP_MAX_PACKET_SIZE 65535 @@ -435,7 +436,11 @@ srs_error_t SrsUdpMuxListener::cycle() SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_recv(); SrsAutoFree(SrsPithyPrint, pprint); + uint64_t nn_msgs = 0; + uint64_t nn_msgs_stage = 0; + uint64_t nn_msgs_last = 0; uint64_t nn_loop = 0; + srs_utime_t time_last = srs_get_system_time(); while (true) { if ((err = trd->pull()) != srs_success) { @@ -453,7 +458,10 @@ srs_error_t SrsUdpMuxListener::cycle() } // remux udp never return continue; - } + } + + nn_msgs++; + nn_msgs_stage++; if ((err = handler->on_udp_packet(&skt)) != srs_success) { // remux udp never return @@ -463,8 +471,27 @@ srs_error_t SrsUdpMuxListener::cycle() pprint->elapse(); if (pprint->can_print()) { - srs_trace("-> RTC #%d RECV schedule %" PRId64, srs_netfd_fileno(lfd), nn_loop); - nn_loop = 0; + int pps_average = 0; int pps_last = 0; + if (true) { + if (srs_get_system_time() > srs_get_system_startup_time()) { + pps_average = (int)(nn_msgs * SRS_UTIME_SECONDS / (srs_get_system_time() - srs_get_system_startup_time())); + } + if (srs_get_system_time() > time_last) { + pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); + } + } + + string pps_unit = ""; + if (pps_last > 10000 || pps_average > 10000) { + pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000; + } else if (pps_last > 1000 || pps_average > 1000) { + pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; + } + + srs_trace("-> RTC #%d RECV %" PRId64 ", pps %d/%d%s, schedule %" PRId64, + srs_netfd_fileno(lfd), nn_msgs_stage, pps_average, pps_last, pps_unit.c_str(), nn_loop); + nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); + nn_loop = 0; nn_msgs_stage = 0; } if (SrsUdpPacketRecvCycleInterval > 0) { diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 20af21ed2..3e8f686f8 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1729,8 +1729,15 @@ srs_error_t SrsRtcServer::cycle() } } - srs_trace("-> RTC #%d SEND %d by sendmmsg %d, pps %d/%d, sessions %d, schedule %" PRId64 "/%" PRId64 "/%"PRId64, - srs_netfd_fileno(stfd), pos, max_sendmmsg, pps_average, pps_last, (int)map_username_session.size(), nn_loop, nn_wait, nn_msgs_max); + string pps_unit = ""; + if (pps_last > 10000 || pps_average > 10000) { + pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000; + } else if (pps_last > 1000 || pps_average > 1000) { + pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; + } + + srs_trace("-> RTC #%d SEND %d, pps %d/%d%s, schedule %" PRId64 "/%" PRId64 "/%" PRId64 ", sessions %d by sendmmsg %d", + srs_netfd_fileno(stfd), pos, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, nn_msgs_max, (int)map_username_session.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; } From 82579e4b0c07c12b3c0a72b3ba24cb34921f4461 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 17:19:49 +0800 Subject: [PATCH 036/131] For #370, use round-trip to send on all fds --- trunk/src/app/srs_app_rtc_conn.cpp | 24 ++++++++++++++---------- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3e8f686f8..0cf4e9bd4 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1334,7 +1334,6 @@ SrsRtcServer::SrsRtcServer() { timer = new SrsHourGlass(this, 1 * SRS_UTIME_SECONDS); - mmstfd = NULL; waiting_msgs = false; cond = srs_cond_new(); trd = new SrsDummyCoroutine(); @@ -1415,6 +1414,9 @@ srs_error_t SrsRtcServer::listen_udp() return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port); } + // We will use all FDs to sendmmsg. + stfds.push_back(listener->stfd()); + srs_trace("rtc listen at udp://%s:%d, fd=%d", ip.c_str(), port, listener->fd()); listeners.push_back(listener); } @@ -1642,8 +1644,6 @@ mmsghdr* SrsRtcServer::fetch() void SrsRtcServer::sendmmsg(srs_netfd_t stfd, mmsghdr* /*hdr*/) { - mmstfd = stfd; - if (waiting_msgs) { waiting_msgs = false; srs_cond_signal(cond); @@ -1670,12 +1670,15 @@ srs_error_t SrsRtcServer::cycle() uint64_t nn_msgs = 0; uint64_t nn_msgs_last = 0; - uint64_t nn_msgs_max = 0; - uint64_t nn_loop = 0; - uint64_t nn_wait = 0; + int nn_msgs_max = 0; + int nn_loop = 0; + int nn_wait = 0; srs_utime_t time_last = srs_get_system_time(); SrsStatistic* stat = SrsStatistic::instance(); + // We use FDs to send out messages, by round-trip algorithm. + uint32_t fd_index = 0; + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); SrsAutoFree(SrsPithyPrint, pprint); @@ -1698,12 +1701,12 @@ srs_error_t SrsRtcServer::cycle() cache.swap(hotspot); cache_pos = 0; - mmsghdr* p = &hotspot[0]; - mmsghdr* end = p + pos; - srs_netfd_t stfd = mmstfd; + srs_netfd_t stfd = NULL; + mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (; p < end; p += max_sendmmsg) { int vlen = (int)(end - p); vlen = srs_min(max_sendmmsg, vlen); + stfd = stfds.at((fd_index++) % stfds.size()); int r0 = srs_sendmmsg(stfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); if (r0 != vlen) { @@ -1719,6 +1722,7 @@ srs_error_t SrsRtcServer::cycle() pprint->elapse(); if (pprint->can_print()) { + // TODO: FIXME: Extract a PPS calculator. int pps_average = 0; int pps_last = 0; if (true) { if (srs_get_system_time() > srs_get_system_startup_time()) { @@ -1736,7 +1740,7 @@ srs_error_t SrsRtcServer::cycle() pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; } - srs_trace("-> RTC #%d SEND %d, pps %d/%d%s, schedule %" PRId64 "/%" PRId64 "/%" PRId64 ", sessions %d by sendmmsg %d", + srs_trace("-> RTC #%d SEND %d, pps %d/%d%s, schedule %d/%d/%d, sessions %d by sendmmsg %d", srs_netfd_fileno(stfd), pos, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, nn_msgs_max, (int)map_username_session.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index e63f2109b..9eb518018 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -240,7 +240,7 @@ private: srs_cond_t cond; bool waiting_msgs; // TODO: FIXME: Support multiple stfd. - srs_netfd_t mmstfd; + std::vector stfds; // Hotspot msgs, we are working on it. // @remark We will wait util all messages are ready. std::vector hotspot; From 73a915568668e3f5ce44ee75a39765f03e226be0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 18:34:42 +0800 Subject: [PATCH 037/131] Refine logs --- trunk/src/app/srs_app_listener.cpp | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 37ff176bb..2508ae511 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -488,7 +488,7 @@ srs_error_t SrsUdpMuxListener::cycle() pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; } - srs_trace("-> RTC #%d RECV %" PRId64 ", pps %d/%d%s, schedule %" PRId64, + srs_trace("<- RTC #%d RECV %" PRId64 ", pps %d/%d%s, schedule %" PRId64, srs_netfd_fileno(lfd), nn_msgs_stage, pps_average, pps_last, pps_unit.c_str(), nn_loop); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = 0; nn_msgs_stage = 0; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 0cf4e9bd4..c6a5e9a2e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1737,7 +1737,7 @@ srs_error_t SrsRtcServer::cycle() if (pps_last > 10000 || pps_average > 10000) { pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000; } else if (pps_last > 1000 || pps_average > 1000) { - pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; + pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } srs_trace("-> RTC #%d SEND %d, pps %d/%d%s, schedule %d/%d/%d, sessions %d by sendmmsg %d", From 59dc771dd50c4dc414508c728ff6efef4b238d7f Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 23:05:07 +0800 Subject: [PATCH 038/131] Refactor pithy print for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c6a5e9a2e..5cc98f1ef 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1740,8 +1740,8 @@ srs_error_t SrsRtcServer::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC #%d SEND %d, pps %d/%d%s, schedule %d/%d/%d, sessions %d by sendmmsg %d", - srs_netfd_fileno(stfd), pos, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, nn_msgs_max, (int)map_username_session.size(), max_sendmmsg); + srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d by sendmmsg %d", + srs_netfd_fileno(stfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, (int)map_username_session.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; } From 863d6b4f15e770a05f9edbc10bfd75b95f463ae6 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 12 Apr 2020 23:11:53 +0800 Subject: [PATCH 039/131] Refactor pithy print for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 5cc98f1ef..3754ae927 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1740,8 +1740,9 @@ srs_error_t SrsRtcServer::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d by sendmmsg %d", - srs_netfd_fileno(stfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, (int)map_username_session.size(), max_sendmmsg); + srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d by sendmmsg %d", + srs_netfd_fileno(stfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, + (int)map_username_session.size(), (int)cache.size(), (int)hotspot.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; } From 087559813fcdf1af1e9ad017466ea4270cc5832f Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 09:13:12 +0800 Subject: [PATCH 040/131] For #307, use UDP sender binding to FD for RTC --- trunk/src/app/srs_app_listener.cpp | 21 +- trunk/src/app/srs_app_listener.hpp | 19 +- trunk/src/app/srs_app_rtc_conn.cpp | 364 ++++++++++++++++------------- trunk/src/app/srs_app_rtc_conn.hpp | 43 ++-- 4 files changed, 261 insertions(+), 186 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 2508ae511..3187a3569 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -236,12 +236,21 @@ srs_error_t SrsTcpListener::cycle() return err; } -SrsUdpMuxSocket::SrsUdpMuxSocket(srs_netfd_t fd) +ISrsUdpSender::ISrsUdpSender() +{ +} + +ISrsUdpSender::~ISrsUdpSender() +{ +} + +SrsUdpMuxSocket::SrsUdpMuxSocket(ISrsUdpSender* h, srs_netfd_t fd) { nb_buf = SRS_UDP_MAX_PACKET_SIZE; buf = new char[nb_buf]; nread = 0; + handler = h; lfd = fd; fromlen = 0; @@ -254,7 +263,7 @@ SrsUdpMuxSocket::~SrsUdpMuxSocket() SrsUdpMuxSocket* SrsUdpMuxSocket::copy_sendonly() { - SrsUdpMuxSocket* sendonly = new SrsUdpMuxSocket(lfd); + SrsUdpMuxSocket* sendonly = new SrsUdpMuxSocket(handler, lfd); // Don't copy buffer srs_freepa(sendonly->buf); @@ -340,16 +349,18 @@ std::string SrsUdpMuxSocket::get_peer_id() return string(id_buf, len); } -SrsUdpMuxListener::SrsUdpMuxListener(ISrsUdpMuxHandler* h, std::string i, int p) +SrsUdpMuxListener::SrsUdpMuxListener(ISrsUdpMuxHandler* h, ISrsUdpSender* s, std::string i, int p) { handler = h; + sender = s; + ip = i; port = p; lfd = NULL; nb_buf = SRS_UDP_MAX_PACKET_SIZE; buf = new char[nb_buf]; - + trd = new SrsDummyCoroutine(); } @@ -449,7 +460,7 @@ srs_error_t SrsUdpMuxListener::cycle() nn_loop++; - SrsUdpMuxSocket skt(lfd); + SrsUdpMuxSocket skt(sender, lfd); int nread = skt.recvfrom(SRS_UTIME_NO_TIMEOUT); if (nread <= 0) { diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 78db998bd..8ef384dd9 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -131,9 +131,22 @@ public: virtual srs_error_t cycle(); }; +class ISrsUdpSender +{ +public: + ISrsUdpSender(); + virtual ~ISrsUdpSender(); +public: + // Fetch a mmsghdr from sender's cache. + virtual srs_error_t fetch(mmsghdr** pphdr) = 0; + // Notify the sender to send out the msg. + virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0; +}; + class SrsUdpMuxSocket { private: + ISrsUdpSender* handler; char* buf; int nb_buf; int nread; @@ -143,7 +156,7 @@ private: std::string peer_ip; int peer_port; public: - SrsUdpMuxSocket(srs_netfd_t fd); + SrsUdpMuxSocket(ISrsUdpSender* h, srs_netfd_t fd); virtual ~SrsUdpMuxSocket(); int recvfrom(srs_utime_t timeout); @@ -160,6 +173,7 @@ public: std::string get_peer_id(); public: SrsUdpMuxSocket* copy_sendonly(); + ISrsUdpSender* sender() { return handler; }; private: // Don't allow copy, user copy_sendonly instead SrsUdpMuxSocket(const SrsUdpMuxSocket& rhs); @@ -170,6 +184,7 @@ class SrsUdpMuxListener : public ISrsCoroutineHandler { protected: srs_netfd_t lfd; + ISrsUdpSender* sender; SrsCoroutine* trd; protected: char* buf; @@ -179,7 +194,7 @@ protected: std::string ip; int port; public: - SrsUdpMuxListener(ISrsUdpMuxHandler* h, std::string i, int p); + SrsUdpMuxListener(ISrsUdpMuxHandler* h, ISrsUdpSender* s, std::string i, int p); virtual ~SrsUdpMuxListener(); public: virtual int fd(); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3754ae927..c7c03cfd8 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -703,9 +703,14 @@ srs_error_t SrsRtcSenderThread::send_message2(SrsSharedPtrMessage* msg, bool is_ { srs_error_t err = srs_success; + ISrsUdpSender* sender = skt->sender(); + // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. - mmsghdr* mhdr = rtc_session->rtc_server->fetch(); + mmsghdr* mhdr = NULL; + if ((err = sender->fetch(&mhdr)) != srs_success) { + return srs_error_wrap(err, "fetch msghdr"); + } char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; // Length of iov, default size. @@ -731,7 +736,9 @@ srs_error_t SrsRtcSenderThread::send_message2(SrsSharedPtrMessage* msg, bool is_ mhdr->msg_hdr.msg_iov->iov_len = length; mhdr->msg_len = 0; - rtc_session->rtc_server->sendmmsg(skt->stfd(), mhdr); + if ((err = sender->sendmmsg(mhdr)) != srs_success) { + return srs_error_wrap(err, "send msghdr"); + } return err; } @@ -1330,9 +1337,10 @@ srs_error_t SrsRtcSession::on_rtcp(SrsUdpMuxSocket* skt) return err; } -SrsRtcServer::SrsRtcServer() +SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) { - timer = new SrsHourGlass(this, 1 * SRS_UTIME_SECONDS); + lfd = NULL; + server = s; waiting_msgs = false; cond = srs_cond_new(); @@ -1343,18 +1351,10 @@ SrsRtcServer::SrsRtcServer() _srs_config->subscribe(this); } -SrsRtcServer::~SrsRtcServer() +SrsUdpMuxSender::~SrsUdpMuxSender() { _srs_config->unsubscribe(this); - vector::iterator it; - for (it = listeners.begin(); it != listeners.end(); ++it) { - SrsUdpMuxListener* listener = *it; - srs_freep(listener); - } - - srs_freep(timer); - srs_freep(trd); srs_cond_destroy(cond); @@ -1365,6 +1365,187 @@ SrsRtcServer::~SrsRtcServer() cache.clear(); } +srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) +{ + srs_error_t err = srs_success; + + lfd = fd; + + srs_freep(trd); + trd = new SrsSTCoroutine("udp", this); + if ((err = trd->start()) != srs_success) { + return srs_error_wrap(err, "start coroutine"); + } + + max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); + srs_trace("UDP sender #%d init ok, max_sendmmsg=%d", srs_netfd_fileno(fd), max_sendmmsg); + + return err; +} + +void SrsUdpMuxSender::free_mhdrs(std::vector& mhdrs) +{ + for (int i = 0; i < (int)mhdrs.size(); i++) { + mmsghdr* hdr = &mhdrs[i]; + + for (int j = (int)hdr->msg_hdr.msg_iovlen - 1; j >= 0 ; j--) { + iovec* iov = hdr->msg_hdr.msg_iov + j; + char* data = (char*)iov->iov_base; + srs_freep(data); + srs_freep(iov); + } + } +} + +srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) +{ + // TODO: FIXME: Maybe need to shrink? + if (cache_pos >= (int)cache.size()) { + mmsghdr mhdr; + memset(&mhdr, 0, sizeof(mmsghdr)); + + mhdr.msg_hdr.msg_iovlen = 1; + mhdr.msg_hdr.msg_iov = new iovec(); + mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; + mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; + mhdr.msg_len = 0; + + cache.push_back(mhdr); + } + + *pphdr = &cache[cache_pos++]; + return srs_success; +} + +srs_error_t SrsUdpMuxSender::sendmmsg(mmsghdr* hdr) +{ + if (waiting_msgs) { + waiting_msgs = false; + srs_cond_signal(cond); + } + + return srs_success; +} + +srs_error_t SrsUdpMuxSender::cycle() +{ + srs_error_t err = srs_success; + + uint64_t nn_msgs = 0; + uint64_t nn_msgs_last = 0; + int nn_msgs_max = 0; + int nn_loop = 0; + int nn_wait = 0; + srs_utime_t time_last = srs_get_system_time(); + SrsStatistic* stat = SrsStatistic::instance(); + + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); + SrsAutoFree(SrsPithyPrint, pprint); + + while (true) { + if ((err = trd->pull()) != srs_success) { + return err; + } + + nn_loop++; + + int pos = cache_pos; + if (pos <= 0) { + waiting_msgs = true; + nn_wait++; + srs_cond_wait(cond); + continue; + } + + // We are working on hotspot now. + cache.swap(hotspot); + cache_pos = 0; + + mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; + for (; p < end; p += max_sendmmsg) { + int vlen = (int)(end - p); + vlen = srs_min(max_sendmmsg, vlen); + + int r0 = srs_sendmmsg(lfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); + if (r0 != vlen) { + srs_warn("sendmsg %d msgs, %d done", vlen, r0); + } + + stat->perf_mw_on_packets(vlen); + } + + // Increase total messages. + nn_msgs += pos; + nn_msgs_max = srs_max(pos, nn_msgs_max); + + pprint->elapse(); + if (pprint->can_print()) { + // TODO: FIXME: Extract a PPS calculator. + int pps_average = 0; int pps_last = 0; + if (true) { + if (srs_get_system_time() > srs_get_system_startup_time()) { + pps_average = (int)(nn_msgs * SRS_UTIME_SECONDS / (srs_get_system_time() - srs_get_system_startup_time())); + } + if (srs_get_system_time() > time_last) { + pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); + } + } + + string pps_unit = ""; + if (pps_last > 10000 || pps_average > 10000) { + pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000; + } else if (pps_last > 1000 || pps_average > 1000) { + pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; + } + + srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d by sendmmsg %d", + srs_netfd_fileno(lfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, + (int)server->nn_sessions(), (int)cache.size(), (int)hotspot.size(), max_sendmmsg); + nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); + nn_loop = nn_wait = nn_msgs_max = 0; + } + } + + return err; +} + +srs_error_t SrsUdpMuxSender::on_reload_rtc_server() +{ + int v = _srs_config->get_rtc_server_sendmmsg(); + if (max_sendmmsg != v) { + max_sendmmsg = v; + srs_trace("Reload max_sendmmsg=%d", max_sendmmsg); + } + + return srs_success; +} + +SrsRtcServer::SrsRtcServer() +{ + timer = new SrsHourGlass(this, 1 * SRS_UTIME_SECONDS); +} + +SrsRtcServer::~SrsRtcServer() +{ + srs_freep(timer); + + if (true) { + vector::iterator it; + for (it = listeners.begin(); it != listeners.end(); ++it) { + SrsUdpMuxListener* listener = *it; + srs_freep(listener); + } + } + + if (true) { + vector::iterator it; + for (it = senders.begin(); it != senders.end(); ++it) { + SrsUdpMuxSender* sender = *it; + srs_freep(sender); + } + } +} + srs_error_t SrsRtcServer::initialize() { srs_error_t err = srs_success; @@ -1377,14 +1558,7 @@ srs_error_t SrsRtcServer::initialize() return srs_error_wrap(err, "start timer"); } - srs_freep(trd); - trd = new SrsSTCoroutine("udp", this); - if ((err = trd->start()) != srs_success) { - return srs_error_wrap(err, "start coroutine"); - } - - max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - srs_trace("RTC server init ok, max_sendmmsg=%d", max_sendmmsg); + srs_trace("RTC server init ok"); return err; } @@ -1407,18 +1581,21 @@ srs_error_t SrsRtcServer::listen_udp() int nn_listeners = _srs_config->get_rtc_server_reuseport(); for (int i = 0; i < nn_listeners; i++) { - SrsUdpMuxListener* listener = new SrsUdpMuxListener(this, ip, port); + SrsUdpMuxSender* sender = new SrsUdpMuxSender(this); + SrsUdpMuxListener* listener = new SrsUdpMuxListener(this, sender, ip, port); if ((err = listener->listen()) != srs_success) { srs_freep(listener); return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port); } - // We will use all FDs to sendmmsg. - stfds.push_back(listener->stfd()); + if ((err = sender->initialize(listener->stfd())) != srs_success) { + return srs_error_wrap(err, "init sender"); + } srs_trace("rtc listen at udp://%s:%d, fd=%d", ip.c_str(), port, listener->fd()); listeners.push_back(listener); + senders.push_back(sender); } return err; @@ -1612,145 +1789,6 @@ srs_error_t SrsRtcServer::notify(int type, srs_utime_t interval, srs_utime_t tic return srs_success; } -srs_error_t SrsRtcServer::on_reload_rtc_server() -{ - int v = _srs_config->get_rtc_server_sendmmsg(); - if (max_sendmmsg != v) { - max_sendmmsg = v; - srs_trace("Reload max_sendmmsg=%d", max_sendmmsg); - } - - return srs_success; -} - -mmsghdr* SrsRtcServer::fetch() -{ - // TODO: FIXME: Maybe need to shrink? - if (cache_pos >= (int)cache.size()) { - mmsghdr mhdr; - memset(&mhdr, 0, sizeof(mmsghdr)); - - mhdr.msg_hdr.msg_iovlen = 1; - mhdr.msg_hdr.msg_iov = new iovec(); - mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; - mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; - mhdr.msg_len = 0; - - cache.push_back(mhdr); - } - - return &cache[cache_pos++]; -} - -void SrsRtcServer::sendmmsg(srs_netfd_t stfd, mmsghdr* /*hdr*/) -{ - if (waiting_msgs) { - waiting_msgs = false; - srs_cond_signal(cond); - } -} - -void SrsRtcServer::free_mhdrs(std::vector& mhdrs) -{ - for (int i = 0; i < (int)mhdrs.size(); i++) { - mmsghdr* hdr = &mhdrs[i]; - - for (int j = (int)hdr->msg_hdr.msg_iovlen - 1; j >= 0 ; j--) { - iovec* iov = hdr->msg_hdr.msg_iov + j; - char* data = (char*)iov->iov_base; - srs_freep(data); - srs_freep(iov); - } - } -} - -srs_error_t SrsRtcServer::cycle() -{ - srs_error_t err = srs_success; - - uint64_t nn_msgs = 0; - uint64_t nn_msgs_last = 0; - int nn_msgs_max = 0; - int nn_loop = 0; - int nn_wait = 0; - srs_utime_t time_last = srs_get_system_time(); - SrsStatistic* stat = SrsStatistic::instance(); - - // We use FDs to send out messages, by round-trip algorithm. - uint32_t fd_index = 0; - - SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); - SrsAutoFree(SrsPithyPrint, pprint); - - while (true) { - if ((err = trd->pull()) != srs_success) { - return err; - } - - nn_loop++; - - int pos = cache_pos; - if (pos <= 0) { - waiting_msgs = true; - nn_wait++; - srs_cond_wait(cond); - continue; - } - - // We are working on hotspot now. - cache.swap(hotspot); - cache_pos = 0; - - srs_netfd_t stfd = NULL; - mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; - for (; p < end; p += max_sendmmsg) { - int vlen = (int)(end - p); - vlen = srs_min(max_sendmmsg, vlen); - stfd = stfds.at((fd_index++) % stfds.size()); - - int r0 = srs_sendmmsg(stfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); - if (r0 != vlen) { - srs_warn("sendmsg %d msgs, %d done", vlen, r0); - } - - stat->perf_mw_on_packets(vlen); - } - - // Increase total messages. - nn_msgs += pos; - nn_msgs_max = srs_max(pos, nn_msgs_max); - - pprint->elapse(); - if (pprint->can_print()) { - // TODO: FIXME: Extract a PPS calculator. - int pps_average = 0; int pps_last = 0; - if (true) { - if (srs_get_system_time() > srs_get_system_startup_time()) { - pps_average = (int)(nn_msgs * SRS_UTIME_SECONDS / (srs_get_system_time() - srs_get_system_startup_time())); - } - if (srs_get_system_time() > time_last) { - pps_last = (int)((nn_msgs - nn_msgs_last) * SRS_UTIME_SECONDS / (srs_get_system_time() - time_last)); - } - } - - string pps_unit = ""; - if (pps_last > 10000 || pps_average > 10000) { - pps_unit = "(w)"; pps_last /= 10000; pps_average /= 10000; - } else if (pps_last > 1000 || pps_average > 1000) { - pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; - } - - srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d by sendmmsg %d", - srs_netfd_fileno(stfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, - (int)map_username_session.size(), (int)cache.size(), (int)hotspot.size(), max_sendmmsg); - nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); - nn_loop = nn_wait = nn_msgs_max = 0; - } - } - - return err; -} - RtcServerAdapter::RtcServerAdapter() { rtc = new SrsRtcServer(); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 9eb518018..1ecfd5998 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -229,18 +229,15 @@ private: srs_error_t on_rtcp_receiver_report(char* buf, int nb_buf, SrsUdpMuxSocket* skt); }; -class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass, - virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler +class SrsUdpMuxSender : virtual public ISrsUdpSender, virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler { private: - std::vector listeners; - SrsHourGlass* timer; -private: + srs_netfd_t lfd; + SrsRtcServer* server; SrsCoroutine* trd; +private: srs_cond_t cond; bool waiting_msgs; - // TODO: FIXME: Support multiple stfd. - std::vector stfds; // Hotspot msgs, we are working on it. // @remark We will wait util all messages are ready. std::vector hotspot; @@ -249,6 +246,28 @@ private: int cache_pos; // The max number of messages for sendmmsg. If 1, we use sendmsg to send. int max_sendmmsg; +public: + SrsUdpMuxSender(SrsRtcServer* s); + virtual ~SrsUdpMuxSender(); +public: + virtual srs_error_t initialize(srs_netfd_t fd); +private: + void free_mhdrs(std::vector& mhdrs); +public: + virtual srs_error_t fetch(mmsghdr** pphdr); + virtual srs_error_t sendmmsg(mmsghdr* hdr); + virtual srs_error_t cycle(); +// interface ISrsReloadHandler +public: + virtual srs_error_t on_reload_rtc_server(); +}; + +class SrsRtcServer : virtual public ISrsUdpMuxHandler, virtual public ISrsHourGlass +{ +private: + SrsHourGlass* timer; + std::vector listeners; + std::vector senders; private: std::map map_username_session; // key: username(local_ufrag + ":" + remote_ufrag) std::map map_id_session; // key: peerip(ip + ":" + port) @@ -267,6 +286,7 @@ public: SrsRtcSession* create_rtc_session(const SrsRequest& req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip); bool insert_into_id_sessions(const std::string& peer_id, SrsRtcSession* rtc_session); void check_and_clean_timeout_session(); + int nn_sessions() { return (int)map_username_session.size(); } private: srs_error_t on_stun(SrsUdpMuxSocket* skt); srs_error_t on_dtls(SrsUdpMuxSocket* skt); @@ -277,15 +297,6 @@ private: // interface ISrsHourGlass public: virtual srs_error_t notify(int type, srs_utime_t interval, srs_utime_t tick); -// interface ISrsReloadHandler -public: - virtual srs_error_t on_reload_rtc_server(); -// Internal only. -public: - mmsghdr* fetch(); - void sendmmsg(srs_netfd_t stfd, mmsghdr* hdr); - void free_mhdrs(std::vector& mhdrs); - virtual srs_error_t cycle(); }; // The RTC server adapter. From 216b3bf41476d03e50b67b09716faa0cc45da979 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 09:32:48 +0800 Subject: [PATCH 041/131] Create isolate pithy printer for each RTC FD --- trunk/src/app/srs_app_listener.cpp | 2 +- trunk/src/app/srs_app_pithy_print.cpp | 8 ++++---- trunk/src/app/srs_app_pithy_print.hpp | 5 +++-- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 3187a3569..2117983be 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -444,7 +444,7 @@ srs_error_t SrsUdpMuxListener::cycle() { srs_error_t err = srs_success; - SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_recv(); + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_recv(srs_netfd_fileno(lfd)); SrsAutoFree(SrsPithyPrint, pprint); uint64_t nn_msgs = 0; diff --git a/trunk/src/app/srs_app_pithy_print.cpp b/trunk/src/app/srs_app_pithy_print.cpp index 84c3c854d..58f8bca4a 100644 --- a/trunk/src/app/srs_app_pithy_print.cpp +++ b/trunk/src/app/srs_app_pithy_print.cpp @@ -177,14 +177,14 @@ SrsPithyPrint* SrsPithyPrint::create_rtc_play() return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_PLAY); } -SrsPithyPrint* SrsPithyPrint::create_rtc_send() +SrsPithyPrint* SrsPithyPrint::create_rtc_send(int fd) { - return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_SEND); + return new SrsPithyPrint(fd<<16 | SRS_CONSTS_STAGE_RTC_SEND); } -SrsPithyPrint* SrsPithyPrint::create_rtc_recv() +SrsPithyPrint* SrsPithyPrint::create_rtc_recv(int fd) { - return new SrsPithyPrint(SRS_CONSTS_STAGE_RTC_RECV); + return new SrsPithyPrint(fd<<16 | SRS_CONSTS_STAGE_RTC_RECV); } SrsPithyPrint::~SrsPithyPrint() diff --git a/trunk/src/app/srs_app_pithy_print.hpp b/trunk/src/app/srs_app_pithy_print.hpp index 4518b7a7c..ab289e0e7 100644 --- a/trunk/src/app/srs_app_pithy_print.hpp +++ b/trunk/src/app/srs_app_pithy_print.hpp @@ -88,8 +88,9 @@ public: static SrsPithyPrint* create_http_stream(); static SrsPithyPrint* create_http_stream_cache(); static SrsPithyPrint* create_rtc_play(); - static SrsPithyPrint* create_rtc_send(); - static SrsPithyPrint* create_rtc_recv(); + // For RTC sender and receiver, we create printer for each fd. + static SrsPithyPrint* create_rtc_send(int fd); + static SrsPithyPrint* create_rtc_recv(int fd); virtual ~SrsPithyPrint(); private: // Enter the specified stage, return the client id. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c7c03cfd8..757d6b8a7 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1439,7 +1439,7 @@ srs_error_t SrsUdpMuxSender::cycle() srs_utime_t time_last = srs_get_system_time(); SrsStatistic* stat = SrsStatistic::instance(); - SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(); + SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(srs_netfd_fileno(lfd)); SrsAutoFree(SrsPithyPrint, pprint); while (true) { From 0bb61f7d98bfb4c89a86c8ef20de4aec15dde7b0 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 13:44:55 +0800 Subject: [PATCH 042/131] For #307, RTC RTP support padding --- trunk/src/kernel/srs_kernel_rtp.cpp | 20 ++++++++++++++++++++ trunk/src/kernel/srs_kernel_rtp.hpp | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 9f8a3b671..d00140005 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -157,6 +157,7 @@ void SrsRtpHeader::set_ssrc(uint32_t ssrc) SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; + padding = 0; } SrsRtpPacket2::~SrsRtpPacket2() @@ -164,6 +165,17 @@ SrsRtpPacket2::~SrsRtpPacket2() srs_freep(payload); } +void SrsRtpPacket2::set_padding(int size) +{ + rtp_header.set_padding(size > 0); + padding = size; +} + +int SrsRtpPacket2::nb_bytes() +{ + return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; +} + srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) { srs_error_t err = srs_success; @@ -176,6 +188,14 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) return srs_error_wrap(err, "encode payload"); } + if (padding) { + if (!buf->require(padding)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", padding); + } + memset(buf->data(), padding, padding); + buf->skip(padding); + } + return err; } diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 6fe5f32ef..975b2b463 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -74,6 +74,7 @@ public: int64_t get_timestamp() const { return timestamp; } void set_ssrc(uint32_t ssrc); uint32_t get_ssrc() const { return ssrc; } + void set_padding(bool v) { padding = v; } }; class SrsRtpPacket2 @@ -81,10 +82,16 @@ class SrsRtpPacket2 public: SrsRtpHeader rtp_header; ISrsEncoder* payload; + int padding; public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); public: + // Append size of bytes as padding. + virtual void set_padding(int size); +// interface ISrsEncoder +public: + virtual int nb_bytes(); virtual srs_error_t encode(SrsBuffer* buf); }; From fa21df7bb891b77d6d094a732760a84480297e3b Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 13:58:34 +0800 Subject: [PATCH 043/131] Refactor RTC package RTP packets. --- trunk/src/app/srs_app_rtc.hpp | 4 +- trunk/src/app/srs_app_rtc_conn.cpp | 145 +++++++++++++---------------- trunk/src/app/srs_app_rtc_conn.hpp | 8 +- 3 files changed, 72 insertions(+), 85 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.hpp b/trunk/src/app/srs_app_rtc.hpp index 9bd794b62..d232ca31f 100644 --- a/trunk/src/app/srs_app_rtc.hpp +++ b/trunk/src/app/srs_app_rtc.hpp @@ -39,9 +39,7 @@ class SrsOriginHub; class SrsAudioRecode; class SrsBuffer; -// Rtp packet max payload size, not include rtp header. -// Must left some bytes to payload header, rtp header, udp header, ip header. -const int kRtpMaxPayloadSize = 1200; +// The RTP packet max size, should never exceed this size. const int kRtpPacketSize = 1500; // Payload type will rewrite in srs_app_rtc_conn.cpp when send to client. diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 757d6b8a7..cd0e8b0b3 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -519,6 +519,14 @@ void SrsRtcSenderThread::stop_loop() trd->interrupt(); } +void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) +{ + srs_trace("session %s address changed, update %s -> %s", + rtc_session->id().c_str(), sendonly_ukt->get_peer_id().c_str(), skt->get_peer_id().c_str()); + + srs_freep(sendonly_ukt); + sendonly_ukt = skt->copy_sendonly(); +} srs_error_t SrsRtcSenderThread::cycle() { @@ -598,15 +606,6 @@ srs_error_t SrsRtcSenderThread::cycle() } } -void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) -{ - srs_trace("session %s address changed, update %s -> %s", - rtc_session->id().c_str(), sendonly_ukt->get_peer_id().c_str(), skt->get_peer_id().c_str()); - - srs_freep(sendonly_ukt); - sendonly_ukt = skt->copy_sendonly(); -} - srs_error_t SrsRtcSenderThread::send_messages( SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts @@ -617,89 +616,79 @@ srs_error_t SrsRtcSenderThread::send_messages( return err; } + // Covert kernel messages to RTP packets. + vector packets; + for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; - bool is_video = msg->is_video(); - bool is_audio = msg->is_audio(); *pnn += msg->size; - if (is_audio) { + SrsRtpPacket2* packet = NULL; + if (msg->is_audio()) { for (int i = 0; i < msg->nn_extra_payloads(); i++) { SrsSample* sample = msg->extra_payloads() + i; - - SrsRtpPacket2* packet = NULL; if ((err = packet_opus(sample, &packet)) != srs_success) { return srs_error_wrap(err, "opus package"); } - - err = send_message2(msg, is_video, is_audio, packet, skt); - srs_freep(packet); - if (err != srs_success) { - return srs_error_wrap(err, "send message"); - } - - *pnn_rtp_pkts += 1; - } - } else { - // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. - if (msg->has_idr()) { - SrsRtpPacket2* packet = NULL; - if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { - return srs_error_wrap(err, "packet stap-a"); - } - - err = send_message2(msg, is_video, is_audio, packet, skt); - srs_freep(packet); - if (err != srs_success) { - return srs_error_wrap(err, "send message"); - } - - *pnn_rtp_pkts += 1; + packets.push_back(packet); } - vector packets; - for (int i = 0; i < msg->nn_samples(); i++) { - SrsSample* sample = msg->samples() + i; - - // We always ignore bframe here, if config to discard bframe, - // the bframe flag will not be set. - if (sample->bframe) { - continue; - } - - if (sample->size <= kRtpMaxPayloadSize) { - SrsRtpPacket2* packet = NULL; - if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { - return srs_error_wrap(err, "packet single nalu"); - } - packets.push_back(packet); - } else { - if ((err = packet_fu_a(msg, sample, packets)) != srs_success) { - return srs_error_wrap(err, "packet fu-a"); - } - } - } - - if (!packets.empty()) { - packets.back()->rtp_header.set_marker(true); - } - - for (int j = 0; j < (int)packets.size(); j++) { - SrsRtpPacket2* packet = packets[j]; - err = send_message2(msg, is_video, is_audio, packet, skt); - srs_freep(packet); - if (err != srs_success) { - return srs_error_wrap(err, "send message"); - } - } - *pnn_rtp_pkts += (int)packets.size(); + continue; } + + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (msg->has_idr()) { + if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + packets.push_back(packet); + } + + for (int i = 0; i < msg->nn_samples(); i++) { + SrsSample* sample = msg->samples() + i; + + // We always ignore bframe here, if config to discard bframe, + // the bframe flag will not be set. + if (sample->bframe) { + continue; + } + + const int kRtpMaxPayloadSize = 1200; + if (sample->size <= kRtpMaxPayloadSize) { + if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { + return srs_error_wrap(err, "packet single nalu"); + } + + if (i == msg->nn_samples() - 1) { + packet->rtp_header.set_marker(true); + } + packets.push_back(packet); + } else { + if ((err = packet_fu_a(msg, sample, kRtpMaxPayloadSize, packets)) != srs_success) { + return srs_error_wrap(err, "packet fu-a"); + } + + if (i == msg->nn_samples() - 1) { + packets.back()->rtp_header.set_marker(true); + } + } + } + } + + *pnn_rtp_pkts += (int)packets.size(); + + for (int j = 0; j < (int)packets.size(); j++) { + SrsRtpPacket2* packet = packets[j]; + if ((err = send_packet(packet, skt)) != srs_success) { + srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); + } + srs_freep(packet); } return err; } -srs_error_t SrsRtcSenderThread::send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt) +srs_error_t SrsRtcSenderThread::send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt) { srs_error_t err = srs_success; @@ -766,7 +755,7 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** p return err; } -srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, vector& packets) +srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, vector& packets) { srs_error_t err = srs_success; @@ -775,9 +764,9 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* uint8_t header = sample->bytes[0]; uint8_t nal_type = header & kNalTypeMask; - int num_of_packet = 1 + (sample->size - 1) / kRtpMaxPayloadSize; + int num_of_packet = 1 + (sample->size - 1) / fu_payload_size; for (int i = 0; i < num_of_packet; ++i) { - int packet_size = srs_min(nb_left, kRtpMaxPayloadSize); + int packet_size = srs_min(nb_left, fu_payload_size); SrsRtpPacket2* packet = new SrsRtpPacket2(); packets.push_back(packet); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 1ecfd5998..3fef015c6 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -147,17 +147,17 @@ public: virtual srs_error_t start(); virtual void stop(); virtual void stop_loop(); -public: - virtual srs_error_t cycle(); public: void update_sendonly_socket(SrsUdpMuxSocket* skt); +public: + virtual srs_error_t cycle(); private: srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); - srs_error_t send_message2(SrsSharedPtrMessage* msg, bool is_video, bool is_audio, SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); + srs_error_t send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: - srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, std::vector& packets); + srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, std::vector& packets); srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket); srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket); }; From 756826756abe4b5059e7de68f70f1b9f340cf762 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 15:24:41 +0800 Subject: [PATCH 044/131] Refactor RTP encrypt --- trunk/src/app/srs_app_rtc_conn.cpp | 71 +++++++++++++++++------------- trunk/src/app/srs_app_rtc_conn.hpp | 5 ++- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index cd0e8b0b3..1d975ea74 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -386,7 +386,7 @@ srs_error_t SrsDtlsSession::protect_rtp(char* out_buf, const char* in_buf, int& return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); } -srs_error_t SrsDtlsSession::protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* pkt) +srs_error_t SrsDtlsSession::protect_rtp2(void* rtp_hdr, int* len_ptr) { srs_error_t err = srs_success; @@ -394,14 +394,7 @@ srs_error_t SrsDtlsSession::protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); } - SrsBuffer stream(buf, *pnn_buf); - if ((err = pkt->encode(&stream)) != srs_success) { - return srs_error_wrap(err, "encode packet"); - } - - *pnn_buf = stream.pos(); - - if (srtp_protect(srtp_send, buf, pnn_buf) != 0) { + if (srtp_protect(srtp_send, rtp_hdr, len_ptr) != 0) { return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); } @@ -587,14 +580,15 @@ srs_error_t SrsRtcSenderThread::cycle() continue; } - int nn = 0; int nn_rtp_pkts = 0; - if ((err = send_messages(source, msgs.msgs, msg_count, sendonly_ukt, &nn, &nn_rtp_pkts)) != srs_success) { + if ((err = send_messages(source, msgs.msgs, msg_count, sendonly_ukt, &nn_rtp_pkts)) != srs_success) { srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); } + int nn = 0; for (int i = 0; i < msg_count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; + nn += msg->size; srs_freep(msg); } @@ -608,7 +602,7 @@ srs_error_t SrsRtcSenderThread::cycle() srs_error_t SrsRtcSenderThread::send_messages( SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, - SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts + SrsUdpMuxSocket* skt, int* pnn_rtp_pkts ) { srs_error_t err = srs_success; @@ -618,10 +612,34 @@ srs_error_t SrsRtcSenderThread::send_messages( // Covert kernel messages to RTP packets. vector packets; + if ((err = messages_to_packets(source, msgs, nb_msgs, packets)) != srs_success) { + for (int j = 0; j < (int)packets.size(); j++) { + SrsRtpPacket2* packet = packets[j]; + srs_freep(packet); + } + return err; + } + + *pnn_rtp_pkts += (int)packets.size(); + + for (int j = 0; j < (int)packets.size(); j++) { + SrsRtpPacket2* packet = packets[j]; + if ((err = send_packet(packet, skt)) != srs_success) { + srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); + } + srs_freep(packet); + } + + return err; +} + +srs_error_t SrsRtcSenderThread::messages_to_packets( + SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, vector& packets +) { + srs_error_t err = srs_success; for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; - *pnn += msg->size; SrsRtpPacket2* packet = NULL; if (msg->is_audio()) { @@ -632,7 +650,6 @@ srs_error_t SrsRtcSenderThread::send_messages( } packets.push_back(packet); } - continue; } @@ -675,16 +692,6 @@ srs_error_t SrsRtcSenderThread::send_messages( } } - *pnn_rtp_pkts += (int)packets.size(); - - for (int j = 0; j < (int)packets.size(); j++) { - SrsRtpPacket2* packet = packets[j]; - if ((err = send_packet(packet, skt)) != srs_success) { - srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); - } - srs_freep(packet); - } - return err; } @@ -701,15 +708,10 @@ srs_error_t SrsRtcSenderThread::send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* return srs_error_wrap(err, "fetch msghdr"); } char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; - - // Length of iov, default size. int length = kRtpPacketSize; - if (rtc_session->encrypt) { - if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length, pkt)) != srs_success) { - return srs_error_wrap(err, "srtp protect"); - } - } else { + // Marshal packet to bytes. + if (true) { SrsBuffer stream(buf, length); if ((err = pkt->encode(&stream)) != srs_success) { return srs_error_wrap(err, "encode packet"); @@ -717,6 +719,13 @@ srs_error_t SrsRtcSenderThread::send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* length = stream.pos(); } + // Whether encrypt the RTP bytes. + if (rtc_session->encrypt) { + if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length)) != srs_success) { + return srs_error_wrap(err, "srtp protect"); + } + } + sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); socklen_t addrlen = (socklen_t)skt->peer_addrlen(); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 3fef015c6..a0c370942 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -105,7 +105,7 @@ public: srs_error_t on_dtls_application_data(const char* data, const int len); public: srs_error_t protect_rtp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); - srs_error_t protect_rtp2(char* buf, int* pnn_buf, SrsRtpPacket2* pkt); + srs_error_t protect_rtp2(void* rtp_hdr, int* len_ptr); srs_error_t unprotect_rtp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); srs_error_t protect_rtcp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); srs_error_t unprotect_rtcp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); @@ -152,7 +152,8 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn, int* pnn_rtp_pkts); + srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn_rtp_pkts); + srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, std::vector& packets); srs_error_t send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); From 048301d9eb906bd1c8a7a3902a478fc064d96491 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 15:37:32 +0800 Subject: [PATCH 045/131] Refactor RTP sender --- trunk/src/app/srs_app_rtc_conn.cpp | 80 +++++++++++++++--------------- trunk/src/app/srs_app_rtc_conn.hpp | 4 +- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 1d975ea74..922f81c38 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -581,7 +581,7 @@ srs_error_t SrsRtcSenderThread::cycle() } int nn_rtp_pkts = 0; - if ((err = send_messages(source, msgs.msgs, msg_count, sendonly_ukt, &nn_rtp_pkts)) != srs_success) { + if ((err = send_messages(sendonly_ukt, source, msgs.msgs, msg_count, &nn_rtp_pkts)) != srs_success) { srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); } @@ -601,8 +601,7 @@ srs_error_t SrsRtcSenderThread::cycle() } srs_error_t SrsRtcSenderThread::send_messages( - SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, - SrsUdpMuxSocket* skt, int* pnn_rtp_pkts + SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, int* pnn_rtp_pkts ) { srs_error_t err = srs_success; @@ -620,13 +619,12 @@ srs_error_t SrsRtcSenderThread::send_messages( return err; } + // Send out RTP packets *pnn_rtp_pkts += (int)packets.size(); + err = send_packets(skt, packets); for (int j = 0; j < (int)packets.size(); j++) { SrsRtpPacket2* packet = packets[j]; - if ((err = send_packet(packet, skt)) != srs_success) { - srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); - } srs_freep(packet); } @@ -695,48 +693,52 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( return err; } -srs_error_t SrsRtcSenderThread::send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt) +srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, vector& packets) { srs_error_t err = srs_success; - ISrsUdpSender* sender = skt->sender(); + for (vector::iterator it = packets.begin(); it != packets.end(); ++it) { + SrsRtpPacket2* packet = *it; + ISrsUdpSender* sender = skt->sender(); - // Fetch a cached message from queue. - // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. - mmsghdr* mhdr = NULL; - if ((err = sender->fetch(&mhdr)) != srs_success) { - return srs_error_wrap(err, "fetch msghdr"); - } - char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; - int length = kRtpPacketSize; - - // Marshal packet to bytes. - if (true) { - SrsBuffer stream(buf, length); - if ((err = pkt->encode(&stream)) != srs_success) { - return srs_error_wrap(err, "encode packet"); + // Fetch a cached message from queue. + // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. + mmsghdr* mhdr = NULL; + if ((err = sender->fetch(&mhdr)) != srs_success) { + return srs_error_wrap(err, "fetch msghdr"); } - length = stream.pos(); - } + char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; + int length = kRtpPacketSize; - // Whether encrypt the RTP bytes. - if (rtc_session->encrypt) { - if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length)) != srs_success) { - return srs_error_wrap(err, "srtp protect"); + // Marshal packet to bytes. + if (true) { + SrsBuffer stream(buf, length); + if ((err = packet->encode(&stream)) != srs_success) { + return srs_error_wrap(err, "encode packet"); + } + length = stream.pos(); + } + + // Whether encrypt the RTP bytes. + if (rtc_session->encrypt) { + if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length)) != srs_success) { + return srs_error_wrap(err, "srtp protect"); + } + } + + sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); + socklen_t addrlen = (socklen_t)skt->peer_addrlen(); + + mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; + mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; + mhdr->msg_hdr.msg_iov->iov_len = length; + mhdr->msg_len = 0; + + if ((err = sender->sendmmsg(mhdr)) != srs_success) { + return srs_error_wrap(err, "send msghdr"); } } - sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); - socklen_t addrlen = (socklen_t)skt->peer_addrlen(); - - mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; - mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; - mhdr->msg_hdr.msg_iov->iov_len = length; - mhdr->msg_len = 0; - - if ((err = sender->sendmmsg(mhdr)) != srs_success) { - return srs_error_wrap(err, "send msghdr"); - } return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index a0c370942..180872144 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -152,9 +152,9 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsUdpMuxSocket* skt, int* pnn_rtp_pkts); + srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, int* pnn_rtp_pkts); srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, std::vector& packets); - srs_error_t send_packet(SrsRtpPacket2* pkt, SrsUdpMuxSocket* skt); + srs_error_t send_packets(SrsUdpMuxSocket* skt, std::vector& packets); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: From 440089639536b75825d217ada0bdac6378d5b6ae Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 16:50:24 +0800 Subject: [PATCH 046/131] Refactor code for merge_nalus and gso --- trunk/conf/full.conf | 7 ++ trunk/src/app/srs_app_config.cpp | 36 +++++++++- trunk/src/app/srs_app_config.hpp | 2 + trunk/src/app/srs_app_rtc_conn.cpp | 105 +++++++++++++++++++++-------- trunk/src/app/srs_app_rtc_conn.hpp | 32 +++++++-- 5 files changed, 149 insertions(+), 33 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 7304edd06..64b920f5b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -435,6 +435,13 @@ rtc_server { # and net.core.rmem_default or just increase this to get larger UDP recv and send buffer. # default: 4 reuseport 4; + # Whether merge multiple NALUs into one. + # @see https://github.com/ossrs/srs/issues/307#issuecomment-612806318 + # default: off + merge_nalus off; + # Whether enable GSO to send out RTP packets. + # default: off + gso off; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index d3e790426..bc6c5c8bb 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3614,7 +3614,7 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" - && n != "sendmmsg" && n != "encrypt" && n != "reuseport") { + && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4772,6 +4772,40 @@ int SrsConfig::get_rtc_server_reuseport() return reuseport; } +bool SrsConfig::get_rtc_server_merge_nalus() +{ + static int DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("merge_nalus"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +bool SrsConfig::get_rtc_server_gso() +{ + static int DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("gso"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index ba46984e3..8093a50a4 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -528,6 +528,8 @@ public: virtual int get_rtc_server_sendmmsg(); virtual bool get_rtc_server_encrypt(); virtual int get_rtc_server_reuseport(); + virtual bool get_rtc_server_merge_nalus(); + virtual bool get_rtc_server_gso(); SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 922f81c38..bbf9b7990 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -449,6 +449,25 @@ srs_error_t SrsDtlsSession::unprotect_rtcp(char* out_buf, const char* in_buf, in return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); } +SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) +{ + is_gso = gso; + should_merge_nalus = merge_nalus; + + nn_rtp_pkts = nn_samples = 0; + nn_audios = nn_videos = 0; +} + +SrsRtcPackets::~SrsRtcPackets() +{ + vector::iterator it; + for (it = packets.begin(); it != packets.end(); ++it ) { + SrsRtpPacket2* packet = *it; + srs_freep(packet); + } + packets.clear(); +} + SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid) : sendonly_ukt(NULL) { @@ -457,15 +476,21 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int rtc_session = s; sendonly_ukt = u->copy_sendonly(); + gso = false; + merge_nalus = false; audio_timestamp = 0; audio_sequence = 0; video_sequence = 0; + + _srs_config->subscribe(this); } SrsRtcSenderThread::~SrsRtcSenderThread() { + _srs_config->unsubscribe(this); + srs_freep(trd); srs_freep(sendonly_ukt); } @@ -480,9 +505,35 @@ srs_error_t SrsRtcSenderThread::initialize(const uint32_t& vssrc, const uint32_t video_payload_type = v_pt; audio_payload_type = a_pt; + gso = _srs_config->get_rtc_server_gso(); + merge_nalus = _srs_config->get_rtc_server_merge_nalus(); + srs_trace("RTC sender video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), package(gso=%d, merge_nalus=%d)", + video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, gso, merge_nalus); + return err; } +srs_error_t SrsRtcSenderThread::on_reload_rtc_server() +{ + if (true) { + bool v = _srs_config->get_rtc_server_gso(); + if (gso != v) { + srs_trace("Reload gso %d=>%d", gso, v); + gso = v; + } + } + + if (true) { + bool v = _srs_config->get_rtc_server_merge_nalus(); + if (merge_nalus != v) { + srs_trace("Reload merge_nalus %d=>%d", merge_nalus, v); + merge_nalus = v; + } + } + + return srs_success; +} + int SrsRtcSenderThread::cid() { return trd->cid(); @@ -580,28 +631,27 @@ srs_error_t SrsRtcSenderThread::cycle() continue; } - int nn_rtp_pkts = 0; - if ((err = send_messages(sendonly_ukt, source, msgs.msgs, msg_count, &nn_rtp_pkts)) != srs_success) { + SrsRtcPackets pkts(gso, merge_nalus); + if ((err = send_messages(sendonly_ukt, source, msgs.msgs, msg_count, pkts)) != srs_success) { srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); } - int nn = 0; for (int i = 0; i < msg_count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; - nn += msg->size; srs_freep(msg); } pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d packets, %d bytes", msg_count, nn_rtp_pkts, nn); + srs_trace("-> RTC PLAY %d msgs, %d samples, %d packets, %d audios, %d videos, %d bytes", + msg_count, pkts.nn_samples, pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_videos, pkts.nn_bytes); } } } srs_error_t SrsRtcSenderThread::send_messages( - SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, int* pnn_rtp_pkts + SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets ) { srs_error_t err = srs_success; @@ -610,53 +660,53 @@ srs_error_t SrsRtcSenderThread::send_messages( } // Covert kernel messages to RTP packets. - vector packets; if ((err = messages_to_packets(source, msgs, nb_msgs, packets)) != srs_success) { - for (int j = 0; j < (int)packets.size(); j++) { - SrsRtpPacket2* packet = packets[j]; - srs_freep(packet); - } return err; } - // Send out RTP packets - *pnn_rtp_pkts += (int)packets.size(); - err = send_packets(skt, packets); + packets.nn_rtp_pkts = (int)packets.packets.size(); - for (int j = 0; j < (int)packets.size(); j++) { - SrsRtpPacket2* packet = packets[j]; - srs_freep(packet); + // Send out RTP packets + if ((err = send_packets(skt, packets)) != srs_success) { + return err; } return err; } srs_error_t SrsRtcSenderThread::messages_to_packets( - SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, vector& packets + SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets ) { srs_error_t err = srs_success; for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; + packets.nn_bytes += msg->size; + packets.nn_samples += msg->nn_extra_payloads() + msg->nn_samples(); + SrsRtpPacket2* packet = NULL; if (msg->is_audio()) { + packets.nn_audios++; + for (int i = 0; i < msg->nn_extra_payloads(); i++) { SrsSample* sample = msg->extra_payloads() + i; if ((err = packet_opus(sample, &packet)) != srs_success) { return srs_error_wrap(err, "opus package"); } - packets.push_back(packet); + packets.packets.push_back(packet); } continue; } + packets.nn_videos++; + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. if (msg->has_idr()) { if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { return srs_error_wrap(err, "packet stap-a"); } - packets.push_back(packet); + packets.packets.push_back(packet); } for (int i = 0; i < msg->nn_samples(); i++) { @@ -677,14 +727,14 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( if (i == msg->nn_samples() - 1) { packet->rtp_header.set_marker(true); } - packets.push_back(packet); + packets.packets.push_back(packet); } else { if ((err = packet_fu_a(msg, sample, kRtpMaxPayloadSize, packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } if (i == msg->nn_samples() - 1) { - packets.back()->rtp_header.set_marker(true); + packets.packets.back()->rtp_header.set_marker(true); } } } @@ -693,11 +743,12 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( return err; } -srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, vector& packets) +srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) { srs_error_t err = srs_success; - for (vector::iterator it = packets.begin(); it != packets.end(); ++it) { + vector::iterator it; + for (it = packets.packets.begin(); it != packets.packets.end(); ++it) { SrsRtpPacket2* packet = *it; ISrsUdpSender* sender = skt->sender(); @@ -766,7 +817,7 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** p return err; } -srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, vector& packets) +srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, SrsRtcPackets& packets) { srs_error_t err = srs_success; @@ -780,7 +831,7 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* int packet_size = srs_min(nb_left, fu_payload_size); SrsRtpPacket2* packet = new SrsRtpPacket2(); - packets.push_back(packet); + packets.packets.push_back(packet); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); @@ -1513,8 +1564,8 @@ srs_error_t SrsUdpMuxSender::on_reload_rtc_server() { int v = _srs_config->get_rtc_server_sendmmsg(); if (max_sendmmsg != v) { + srs_trace("Reload max_sendmmsg %d=>%d", max_sendmmsg, v); max_sendmmsg = v; - srs_trace("Reload max_sendmmsg=%d", max_sendmmsg); } return srs_success; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 180872144..906765888 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -117,7 +117,24 @@ private: srs_error_t srtp_recv_init(); }; -class SrsRtcSenderThread : public ISrsCoroutineHandler +class SrsRtcPackets +{ +public: + bool is_gso; + bool should_merge_nalus; +public: + int nn_bytes; + int nn_rtp_pkts; + int nn_samples; + int nn_audios; + int nn_videos; + std::vector packets; +public: + SrsRtcPackets(bool gso, bool merge_nalus); + virtual ~SrsRtcPackets(); +}; + +class SrsRtcSenderThread : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler { protected: SrsCoroutine* trd; @@ -136,11 +153,16 @@ private: uint16_t video_sequence; public: SrsUdpMuxSocket* sendonly_ukt; + bool merge_nalus; + bool gso; public: SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid); virtual ~SrsRtcSenderThread(); public: srs_error_t initialize(const uint32_t& vssrc, const uint32_t& assrc, const uint16_t& v_pt, const uint16_t& a_pt); +// interface ISrsReloadHandler +public: + virtual srs_error_t on_reload_rtc_server(); public: virtual int cid(); public: @@ -152,13 +174,13 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, int* pnn_rtp_pkts); - srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, std::vector& packets); - srs_error_t send_packets(SrsUdpMuxSocket* skt, std::vector& packets); + srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); + srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); + srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: - srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, std::vector& packets); + srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, SrsRtcPackets& packets); srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket); srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket); }; From 5d23bb6a8abecb0596ec47451e08490a90588111 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 17:11:46 +0800 Subject: [PATCH 047/131] Refactor code for merge_nalus --- trunk/src/app/srs_app_rtc_conn.cpp | 46 +++++++++++++++++++++--------- trunk/src/app/srs_app_rtc_conn.hpp | 2 ++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index bbf9b7990..2f4ef86c8 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -454,8 +454,9 @@ SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) is_gso = gso; should_merge_nalus = merge_nalus; - nn_rtp_pkts = nn_samples = 0; - nn_audios = nn_videos = 0; + nn_rtp_pkts = 0; + nn_audios = nn_extras = 0; + nn_videos = nn_samples = 0; } SrsRtcPackets::~SrsRtcPackets() @@ -644,8 +645,8 @@ srs_error_t SrsRtcSenderThread::cycle() pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d samples, %d packets, %d audios, %d videos, %d bytes", - msg_count, pkts.nn_samples, pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_videos, pkts.nn_bytes); + srs_trace("-> RTC PLAY %d msgs, %d packets, %d audios, %d extras, %d videos, %d samples, %d bytes", + msg_count, pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes); } } } @@ -682,14 +683,21 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; + // Update stats. packets.nn_bytes += msg->size; - packets.nn_samples += msg->nn_extra_payloads() + msg->nn_samples(); + int nn_extra_payloads = msg->nn_extra_payloads(); + packets.nn_extras += nn_extra_payloads; + + int nn_samples = msg->nn_samples(); + packets.nn_samples += nn_samples; + + // For audio, we transcoded AAC to opus in extra payloads. SrsRtpPacket2* packet = NULL; if (msg->is_audio()) { packets.nn_audios++; - for (int i = 0; i < msg->nn_extra_payloads(); i++) { + for (int i = 0; i < nn_extra_payloads; i++) { SrsSample* sample = msg->extra_payloads() + i; if ((err = packet_opus(sample, &packet)) != srs_success) { return srs_error_wrap(err, "opus package"); @@ -699,6 +707,7 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( continue; } + // For video, we should process all NALUs in samples. packets.nn_videos++; // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. @@ -709,6 +718,15 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( packets.packets.push_back(packet); } + // If merge Nalus, we pcakges all NALUs(samples) as one NALU, in a RTP or FUA packet. + if (packets.should_merge_nalus && nn_samples > 1) { + if ((err = packet_nalus(msg, packets)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + continue; + } + + // By default, we package each NALU(sample) to a RTP or FUA packet. for (int i = 0; i < msg->nn_samples(); i++) { SrsSample* sample = msg->samples() + i; @@ -723,19 +741,15 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } - - if (i == msg->nn_samples() - 1) { - packet->rtp_header.set_marker(true); - } packets.packets.push_back(packet); } else { if ((err = packet_fu_a(msg, sample, kRtpMaxPayloadSize, packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); } + } - if (i == msg->nn_samples() - 1) { - packets.packets.back()->rtp_header.set_marker(true); - } + if (i == nn_samples - 1) { + packets.packets.back()->rtp_header.set_marker(true); } } } @@ -793,6 +807,12 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets return err; } +srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets) +{ + srs_error_t err = srs_success; + return err; +} + srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 906765888..c10cc1305 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -126,6 +126,7 @@ public: int nn_bytes; int nn_rtp_pkts; int nn_samples; + int nn_extras; int nn_audios; int nn_videos; std::vector packets; @@ -181,6 +182,7 @@ private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, SrsRtcPackets& packets); + srs_error_t packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets); srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket); srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket); }; From 96059e0d420c1cfae109234fa6efe5f6d53c1425 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 19:23:17 +0800 Subject: [PATCH 048/131] For #307, support merge multiple slices/NALUs to one NALU/RTP/FUA --- trunk/conf/full.conf | 4 +- trunk/src/app/srs_app_config.cpp | 4 +- trunk/src/app/srs_app_rtc_conn.cpp | 93 ++++++++++++++++++++-- trunk/src/kernel/srs_kernel_codec.cpp | 8 ++ trunk/src/kernel/srs_kernel_codec.hpp | 2 + trunk/src/kernel/srs_kernel_rtp.cpp | 108 +++++++++++++++++++++++++- trunk/src/kernel/srs_kernel_rtp.hpp | 24 ++++++ 7 files changed, 230 insertions(+), 13 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 64b920f5b..caadce385 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -437,8 +437,8 @@ rtc_server { reuseport 4; # Whether merge multiple NALUs into one. # @see https://github.com/ossrs/srs/issues/307#issuecomment-612806318 - # default: off - merge_nalus off; + # default: on + merge_nalus on; # Whether enable GSO to send out RTP packets. # default: off gso off; diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index bc6c5c8bb..f60a1782e 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4774,7 +4774,7 @@ int SrsConfig::get_rtc_server_reuseport() bool SrsConfig::get_rtc_server_merge_nalus() { - static int DEFAULT = false; + static int DEFAULT = true; SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { @@ -4786,7 +4786,7 @@ bool SrsConfig::get_rtc_server_merge_nalus() return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + return SRS_CONF_PERFER_TRUE(conf->arg0()); } bool SrsConfig::get_rtc_server_gso() diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 2f4ef86c8..dfc3faf8e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -727,7 +727,7 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( } // By default, we package each NALU(sample) to a RTP or FUA packet. - for (int i = 0; i < msg->nn_samples(); i++) { + for (int i = 0; i < nn_samples; i++) { SrsSample* sample = msg->samples() + i; // We always ignore bframe here, if config to discard bframe, @@ -810,6 +810,81 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets) { srs_error_t err = srs_success; + + SrsRtpRawNALUs* raw = new SrsRtpRawNALUs(); + + for (int i = 0; i < msg->nn_samples(); i++) { + SrsSample* sample = msg->samples() + i; + + // We always ignore bframe here, if config to discard bframe, + // the bframe flag will not be set. + if (sample->bframe) { + continue; + } + + raw->push_back(sample->copy()); + } + + // Ignore empty. + int nn_bytes = raw->nb_bytes(); + if (nn_bytes <= 0) { + srs_freep(raw); + return err; + } + + const int kRtpMaxPayloadSize = 1200; + if (nn_bytes < kRtpMaxPayloadSize) { + // Package NALUs in a single RTP packet. + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packet->rtp_header.set_timestamp(msg->timestamp * 90); + packet->rtp_header.set_sequence(video_sequence++); + packet->rtp_header.set_ssrc(video_ssrc); + packet->rtp_header.set_payload_type(video_payload_type); + packet->payload = raw; + packets.packets.push_back(packet); + } else { + SrsAutoFree(SrsRtpRawNALUs, raw); + + // Package NALUs in FU-A RTP packets. + int fu_payload_size = kRtpMaxPayloadSize; + + // The first byte is store in FU-A header. + uint8_t header = raw->skip_first_byte(); + uint8_t nal_type = header & kNalTypeMask; + int nb_left = nn_bytes - 1; + + int num_of_packet = 1 + (nn_bytes - 1) / fu_payload_size; + for (int i = 0; i < num_of_packet; ++i) { + int packet_size = srs_min(nb_left, fu_payload_size); + + SrsRtpPacket2* packet = new SrsRtpPacket2(); + packets.packets.push_back(packet); + + packet->rtp_header.set_timestamp(msg->timestamp * 90); + packet->rtp_header.set_sequence(video_sequence++); + packet->rtp_header.set_ssrc(video_ssrc); + packet->rtp_header.set_payload_type(video_payload_type); + + SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); + packet->payload = fua; + + fua->nri = (SrsAvcNaluType)header; + fua->nalu_type = (SrsAvcNaluType)nal_type; + fua->start = bool(i == 0); + fua->end = bool(i == num_of_packet - 1); + + if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { + return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); + } + + nb_left -= packet_size; + } + } + + if (!packets.packets.empty()) { + packets.packets.back()->rtp_header.set_marker(true); + } + return err; } @@ -866,10 +941,10 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); - SrsSample* sample = new SrsSample(); - sample->bytes = p; - sample->size = packet_size; - fua->nalus.push_back(sample); + SrsSample* fragment_sample = new SrsSample(); + fragment_sample->bytes = p; + fragment_sample->size = packet_size; + fua->nalus.push_back(fragment_sample); p += packet_size; nb_left -= packet_size; @@ -889,11 +964,13 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, Srs packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + SrsRtpRawNALUs* raw = new SrsRtpRawNALUs(); packet->payload = raw; - raw->payload = sample->bytes; - raw->nn_payload = sample->size; + SrsSample* p = new SrsSample(); + p->bytes = sample->bytes; + p->size = sample->size; + raw->push_back(p); *ppacket = packet; diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index a351dcc52..e0789c236 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -409,6 +409,14 @@ srs_error_t SrsSample::parse_bframe() return err; } +SrsSample* SrsSample::copy() +{ + SrsSample* p = new SrsSample(); + p->bytes = bytes; + p->size = size; + return p; +} + SrsCodecConfig::SrsCodecConfig() { } diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 49447b5de..9c74e1387 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -542,6 +542,8 @@ public: public: // If we need to know whether sample is bframe, we have to parse the NALU payload. srs_error_t parse_bframe(); + // Copy sample, share the bytes pointer. + SrsSample* copy(); }; /** diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index d00140005..ae044d4a2 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -229,6 +229,112 @@ srs_error_t SrsRtpRawPayload::encode(SrsBuffer* buf) return srs_success; } +SrsRtpRawNALUs::SrsRtpRawNALUs() +{ + cursor = 0; + nn_bytes = 0; +} + +SrsRtpRawNALUs::~SrsRtpRawNALUs() +{ + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + srs_freep(p); + } + nalus.clear(); +} + +void SrsRtpRawNALUs::push_back(SrsSample* sample) +{ + if (sample->size <= 0) { + return; + } + + if (!nalus.empty()) { + SrsSample* p = new SrsSample(); + p->bytes = (char*)"\0\0\1"; + p->size = 3; + nn_bytes += 3; + nalus.push_back(p); + } + + nn_bytes += sample->size; + nalus.push_back(sample); +} + +uint8_t SrsRtpRawNALUs::skip_first_byte() +{ + srs_assert (cursor >= 0 && nn_bytes > 0 && cursor < nn_bytes); + cursor++; + return uint8_t(nalus[0]->bytes[0]); +} + +srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int size) +{ + if (cursor + size < 0 || cursor + size > nn_bytes) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cursor=%d, max=%d, size=%d", cursor, nn_bytes, size); + } + + int pos = cursor; + cursor += size; + int left = size; + + vector::iterator it; + for (it = nalus.begin(); it != nalus.end() && left > 0; ++it) { + SrsSample* p = *it; + + // Ignore previous consumed samples. + if (pos && pos - p->size >= 0) { + pos -= p->size; + continue; + } + + // Now, we are working at the sample. + int nn = srs_min(left, p->size - pos); + srs_assert(nn > 0); + + SrsSample* sample = new SrsSample(); + sample->bytes = p->bytes + pos; + sample->size = nn; + samples.push_back(sample); + + left -= nn; + pos = 0; + } + + return srs_success; +} + +int SrsRtpRawNALUs::nb_bytes() +{ + int size = 0; + + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + size += p->size; + } + + return size; +} + +srs_error_t SrsRtpRawNALUs::encode(SrsBuffer* buf) +{ + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + + if (!buf->require(p->size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size); + } + + buf->write_bytes(p->bytes, p->size); + } + + return srs_success; +} + SrsRtpSTAPPayload::SrsRtpSTAPPayload() { nri = (SrsAvcNaluType)0; @@ -339,7 +445,7 @@ srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf) for (it = nalus.begin(); it != nalus.end(); ++it) { SrsSample* p = *it; if (!buf->require(p->size)) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size); } buf->write_bytes(p->bytes, p->size); diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 975b2b463..7733b431f 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -95,6 +95,7 @@ public: virtual srs_error_t encode(SrsBuffer* buf); }; +// Single payload data. class SrsRtpRawPayload : public ISrsEncoder { public: @@ -110,6 +111,28 @@ public: virtual srs_error_t encode(SrsBuffer* buf); }; +// Multiple NALUs, automatically insert 001 between NALUs. +class SrsRtpRawNALUs : public ISrsEncoder +{ +private: + std::vector nalus; + int nn_bytes; + int cursor; +public: + SrsRtpRawNALUs(); + virtual ~SrsRtpRawNALUs(); +public: + void push_back(SrsSample* sample); +public: + uint8_t skip_first_byte(); + srs_error_t read_samples(std::vector& samples, int size); +// interface ISrsEncoder +public: + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer* buf); +}; + +// STAP-A, for multiple NALUs. class SrsRtpSTAPPayload : public ISrsEncoder { public: @@ -127,6 +150,7 @@ public: virtual srs_error_t encode(SrsBuffer* buf); }; +// FU-A, for one NALU with multiple fragments. class SrsRtpFUAPayload : public ISrsEncoder { public: From 3b7240b8e0a360ce7db09f9c183c7b4a59518dd1 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 23:40:30 +0800 Subject: [PATCH 049/131] For #307, support linux GSO for RTC --- trunk/conf/full.conf | 1 + trunk/src/app/srs_app_config.cpp | 10 +- trunk/src/app/srs_app_rtc_conn.cpp | 185 ++++++++++++++++++++++++++++- trunk/src/app/srs_app_rtc_conn.hpp | 4 +- 4 files changed, 193 insertions(+), 7 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index caadce385..57e64bf1b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -440,6 +440,7 @@ rtc_server { # default: on merge_nalus on; # Whether enable GSO to send out RTP packets. + # @remark Linux only, for other OS always disabled. # default: off gso off; } diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f60a1782e..f7f69a381 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4803,7 +4803,15 @@ bool SrsConfig::get_rtc_server_gso() return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + bool v = SRS_CONF_PERFER_FALSE(conf->arg0()); + +#ifdef SRS_AUTO_OSX + if (v) { + srs_warn("GSO is for Linux only"); + } + v = false; +#endif + return v; } SrsConfDirective* SrsConfig::get_rtc(string vhost) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index dfc3faf8e..b51cb236c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -33,6 +33,11 @@ using namespace std; #include #include +#include +#ifndef UDP_SEGMENT +#define UDP_SEGMENT 103 +#endif + #include #include @@ -451,7 +456,7 @@ srs_error_t SrsDtlsSession::unprotect_rtcp(char* out_buf, const char* in_buf, in SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) { - is_gso = gso; + use_gso = gso; should_merge_nalus = merge_nalus; nn_rtp_pkts = 0; @@ -662,15 +667,25 @@ srs_error_t SrsRtcSenderThread::send_messages( // Covert kernel messages to RTP packets. if ((err = messages_to_packets(source, msgs, nb_msgs, packets)) != srs_success) { - return err; + return srs_error_wrap(err, "messages to packets"); } packets.nn_rtp_pkts = (int)packets.packets.size(); - // Send out RTP packets - if ((err = send_packets(skt, packets)) != srs_success) { +#ifndef SRS_AUTO_OSX + // If enabled GSO, send out some packets in a msghdr. + if (packets.use_gso) { + if ((err = send_packets2(skt, packets)) != srs_success) { + return srs_error_wrap(err, "gso send"); + } return err; } +#endif + + // By default, we send packets by sendmmsg. + if ((err = send_packets(skt, packets)) != srs_success) { + return srs_error_wrap(err, "raw send"); + } return err; } @@ -761,10 +776,13 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets { srs_error_t err = srs_success; + ISrsUdpSender* sender = skt->sender(); + vector::iterator it; for (it = packets.packets.begin(); it != packets.packets.end(); ++it) { SrsRtpPacket2* packet = *it; - ISrsUdpSender* sender = skt->sender(); + + int nn_packet = packet->nb_bytes(); // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. @@ -807,6 +825,157 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets return err; } +// TODO: FIXME: We can gather and pad audios, because they have similar size. +srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) +{ + srs_error_t err = srs_success; + + ISrsUdpSender* sender = skt->sender(); + + // Previous handler, if has the same size, we can use GSO. + mmsghdr* gso_mhdr = NULL; int gso_size = 0; int gso_encrypt = 0; int gso_cursor = 0; + // GSO, N packets has same length, the final one may not. + bool use_gso = false; bool gso_final = false; + + int nn_packets = (int)packets.packets.size(); + for (int i = 0; i < nn_packets; i++) { + SrsRtpPacket2* packet = packets.packets[i]; + + // The handler to send message. + mmsghdr* mhdr = NULL; + + // Check whether we can use GSO to send it. + int nn_packet = packet->nb_bytes(); + + if ((gso_size && gso_size == nn_packet) || (use_gso && !gso_final)) { + use_gso = true; + gso_final = (gso_size && gso_size != nn_packet); + mhdr = gso_mhdr; + + // We need to increase the iov and cursor. + int nb_iovs = mhdr->msg_hdr.msg_iovlen; + if (gso_cursor >= nb_iovs - 1) { + int nn_new_iovs = nb_iovs; + mhdr->msg_hdr.msg_iovlen = nb_iovs + nn_new_iovs; + mhdr->msg_hdr.msg_iov = (iovec*)realloc(mhdr->msg_hdr.msg_iov, sizeof(iovec) * (nb_iovs + nn_new_iovs)); + memset(mhdr->msg_hdr.msg_iov + nb_iovs, 0, sizeof(iovec) * nn_new_iovs); + } + gso_cursor++; + + // Create payload cache for RTP packet. + iovec* p = mhdr->msg_hdr.msg_iov + gso_cursor; + if (!p->iov_base) { + p->iov_base = new char[kRtpPacketSize]; + p->iov_len = kRtpPacketSize; + } + } else { + // Fetch a cached message from queue. + // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. + if ((err = sender->fetch(&mhdr)) != srs_success) { + return srs_error_wrap(err, "fetch msghdr"); + } + + // Reset the iovec, we should never change the msg_iovlen. + for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { + iovec* p = mhdr->msg_hdr.msg_iov + j; + p->iov_len = 0; + } + + gso_mhdr = mhdr; + gso_size = nn_packet; + gso_cursor = 0; + } + + // Change the state according to the next packet. + if (i < nn_packets - 1) { + SrsRtpPacket2* next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL; + int nn_next_packet = next_packet? next_packet->nb_bytes() : 0; + + // If GSO, but next is bigger than this one, we must enter the final state. + if (use_gso && !gso_final) { + gso_final = (nn_packet < nn_next_packet); + } + + // If not GSO, maybe the first fresh packet, we should see whether the next packet is smaller than this one, + // if smaller, we can still enter GSO. + if (!use_gso) { + use_gso = (nn_packet >= nn_next_packet); + } + } + + // Marshal packet to bytes. + iovec* iov = mhdr->msg_hdr.msg_iov + gso_cursor; + iov->iov_len = kRtpPacketSize; + + if (true) { + SrsBuffer stream((char*)iov->iov_base, iov->iov_len); + if ((err = packet->encode(&stream)) != srs_success) { + return srs_error_wrap(err, "encode packet"); + } + iov->iov_len = stream.pos(); + } + + // Whether encrypt the RTP bytes. + if (rtc_session->encrypt) { + int nn_encrypt = (int)iov->iov_len; + if ((err = rtc_session->dtls_session->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) { + return srs_error_wrap(err, "srtp protect"); + } + iov->iov_len = (size_t)nn_encrypt; + } + + // If GSO, they must has same size, except the final one. + if (use_gso && !gso_final && gso_encrypt && gso_encrypt != (int)iov->iov_len) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "GSO size=%d/%d, encrypt=%d/%d", gso_size, nn_packet, gso_encrypt, iov->iov_len); + } + + if (use_gso && !gso_final) { + gso_encrypt = iov->iov_len; + } + + // If exceed the max GSO size, set to final. + if (use_gso && gso_cursor > 64) { + gso_final = true; + } + + // For last message, or final gso, or determined not using GSO, send it now. + if (i == nn_packets - 1 || gso_final || !use_gso) { + sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); + socklen_t addrlen = (socklen_t)skt->peer_addrlen(); + + mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; + mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; + mhdr->msg_hdr.msg_controllen = 0; + mhdr->msg_len = 0; + + if (use_gso) { +#ifndef SRS_AUTO_OSX + if (!mhdr->msg_hdr.msg_control) { + mhdr->msg_hdr.msg_control = new char[mhdr->msg_hdr.msg_controllen]; + } + mhdr->msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); + + cmsghdr* cm = CMSG_FIRSTHDR(&mhdr->msg_hdr); + cm->cmsg_level = SOL_UDP; + cm->cmsg_type = UDP_SEGMENT; + cm->cmsg_len = CMSG_LEN(sizeof(uint16_t)); + *((uint16_t*)CMSG_DATA(cm)) = gso_encrypt; +#endif + } + + if ((err = sender->sendmmsg(mhdr)) != srs_success) { + return srs_error_wrap(err, "send msghdr"); + } + + // Reset the GSO flag. + gso_mhdr = NULL; gso_size = 0; gso_encrypt = 0; gso_cursor = 0; + use_gso = gso_final = false; + } + } + + return err; +} + srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets) { srs_error_t err = srs_success; @@ -1536,6 +1705,11 @@ void SrsUdpMuxSender::free_mhdrs(std::vector& mhdrs) for (int i = 0; i < (int)mhdrs.size(); i++) { mmsghdr* hdr = &mhdrs[i]; + // Free control for GSO. + char* msg_control = (char*)hdr->msg_hdr.msg_control; + srs_freep(msg_control); + + // Free iovec. for (int j = (int)hdr->msg_hdr.msg_iovlen - 1; j >= 0 ; j--) { iovec* iov = hdr->msg_hdr.msg_iov + j; char* data = (char*)iov->iov_base; @@ -1543,6 +1717,7 @@ void SrsUdpMuxSender::free_mhdrs(std::vector& mhdrs) srs_freep(iov); } } + mhdrs.clear(); } srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index c10cc1305..748374290 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -120,7 +120,7 @@ private: class SrsRtcPackets { public: - bool is_gso; + bool use_gso; bool should_merge_nalus; public: int nn_bytes; @@ -129,6 +129,7 @@ public: int nn_extras; int nn_audios; int nn_videos; +public: std::vector packets; public: SrsRtcPackets(bool gso, bool merge_nalus); @@ -178,6 +179,7 @@ private: srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); + srs_error_t send_packets2(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: From 89a247d9bc7c6dd5391870fce2e818482bc0408d Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 Apr 2020 23:57:03 +0800 Subject: [PATCH 050/131] Remove unused code --- trunk/src/app/srs_app_rtc_conn.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b51cb236c..a5d8a886b 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -782,8 +782,6 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets for (it = packets.packets.begin(); it != packets.packets.end(); ++it) { SrsRtpPacket2* packet = *it; - int nn_packet = packet->nb_bytes(); - // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. mmsghdr* mhdr = NULL; From 8a71ce62db9d3222804c58823819f68c2d9016af Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 09:20:21 +0800 Subject: [PATCH 051/131] For #307, allow dedicated cache for GSO. --- trunk/conf/full.conf | 4 + trunk/src/app/srs_app_config.cpp | 28 +++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_http_api.cpp | 13 +- trunk/src/app/srs_app_listener.hpp | 4 + trunk/src/app/srs_app_rtc_conn.cpp | 209 ++++++++++++++++++++++------ trunk/src/app/srs_app_rtc_conn.hpp | 10 ++ trunk/src/app/srs_app_statistic.cpp | 74 +++++++++- trunk/src/app/srs_app_statistic.hpp | 8 +- 9 files changed, 303 insertions(+), 48 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 57e64bf1b..45156da17 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -443,6 +443,10 @@ rtc_server { # @remark Linux only, for other OS always disabled. # default: off gso off; + # Whether GSO uses dedicated cache. Share the same mmsghdr cache if not dedicated. + # For Linux 3.*, we must use dedicated cache for GSO. + # default: off + gso_dedicated off; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f7f69a381..9693a17fa 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3614,7 +3614,8 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" - && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus") { + && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus" + && n != "gso_dedicated") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4814,6 +4815,31 @@ bool SrsConfig::get_rtc_server_gso() return v; } +bool SrsConfig::get_rtc_server_gso_dedicated() +{ + static int DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("gso_dedicated"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + bool v = SRS_CONF_PERFER_FALSE(conf->arg0()); + +#ifdef SRS_AUTO_OSX + if (v != DEFAULT) { + srs_warn("GSO is for Linux only"); + } +#endif + + return v; +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 8093a50a4..bfc6f373f 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -530,6 +530,7 @@ public: virtual int get_rtc_server_reuseport(); virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_gso(); + virtual bool get_rtc_server_gso_dedicated(); SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 1f3749b7a..6d7df56fa 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1622,7 +1622,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* data->set("query", p); p->set("target", SrsJsonAny::str(target.c_str())); - p->set("help", SrsJsonAny::str("?target=writev|sendmmsg")); + p->set("help", SrsJsonAny::str("?target=writev|sendmmsg|gso|udp")); } if (target.empty() || target == "writev") { @@ -1634,7 +1634,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } - if (target.empty() || target == "sendmmsg") { + if (target.empty() || target == "sendmmsg" || target == "udp") { SrsJsonObject* p = SrsJsonAny::object(); data->set("sendmmsg", p); if ((err = stat->dumps_perf_sendmmsg(p)) != srs_success) { @@ -1643,6 +1643,15 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } + if (target.empty() || target == "gso" || target == "udp") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("gso", p); + if ((err = stat->dumps_perf_gso(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + return srs_api_response(w, r, obj->dumps()); } diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 8ef384dd9..ec503cf6b 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -139,6 +139,10 @@ public: public: // Fetch a mmsghdr from sender's cache. virtual srs_error_t fetch(mmsghdr** pphdr) = 0; + // For Linux kernel 3.*, we must use isolate APIs for GSO, + // that is, sendmmsg does not work with GSO. + // Fetch a mmsghdr from sender's cache. + virtual srs_error_t gso_fetch(mmsghdr** pphdr) = 0; // Notify the sender to send out the msg. virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0; }; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index a5d8a886b..cdf02d68c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -866,22 +866,6 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket p->iov_base = new char[kRtpPacketSize]; p->iov_len = kRtpPacketSize; } - } else { - // Fetch a cached message from queue. - // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. - if ((err = sender->fetch(&mhdr)) != srs_success) { - return srs_error_wrap(err, "fetch msghdr"); - } - - // Reset the iovec, we should never change the msg_iovlen. - for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { - iovec* p = mhdr->msg_hdr.msg_iov + j; - p->iov_len = 0; - } - - gso_mhdr = mhdr; - gso_size = nn_packet; - gso_cursor = 0; } // Change the state according to the next packet. @@ -901,6 +885,32 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket } } + // Now, we fetch the msg from cache. + if (!mhdr) { + // Fetch a cached message from queue. + // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. + if (use_gso) { + err = sender->gso_fetch(&mhdr); + } else { + err = sender->fetch(&mhdr); + } + if (err != srs_success) { + return srs_error_wrap(err, "fetch msghdr"); + } + + // Reset the iovec, we should never change the msg_iovlen. + for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { + iovec* p = mhdr->msg_hdr.msg_iov + j; + p->iov_len = 0; + } + + // Now, GSO will use this message and size. + if (use_gso) { + gso_mhdr = mhdr; + gso_size = nn_packet; + } + } + // Marshal packet to bytes. iovec* iov = mhdr->msg_hdr.msg_iov + gso_cursor; iov->iov_len = kRtpPacketSize; @@ -946,25 +956,37 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket mhdr->msg_hdr.msg_controllen = 0; mhdr->msg_len = 0; - if (use_gso) { #ifndef SRS_AUTO_OSX + if (use_gso) { + mhdr->msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); if (!mhdr->msg_hdr.msg_control) { mhdr->msg_hdr.msg_control = new char[mhdr->msg_hdr.msg_controllen]; } - mhdr->msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); cmsghdr* cm = CMSG_FIRSTHDR(&mhdr->msg_hdr); cm->cmsg_level = SOL_UDP; cm->cmsg_type = UDP_SEGMENT; cm->cmsg_len = CMSG_LEN(sizeof(uint16_t)); *((uint16_t*)CMSG_DATA(cm)) = gso_encrypt; -#endif + + // Private message, use it to store the cursor. + mhdr->msg_len = gso_cursor + 1; } +#endif if ((err = sender->sendmmsg(mhdr)) != srs_success) { return srs_error_wrap(err, "send msghdr"); } +#ifdef SRS_DEBUG + srs_warn("packet SN=%d %d bytes", nn_packet, packet->rtp_header.get_sequence()); + for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { + iovec* iov = mhdr->msg_hdr.msg_iov + j; + srs_warn("%s #%d/%d/%d, %d bytes, size %d/%d", (use_gso? "GSO":"RAW"), j, gso_cursor + 1, + mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); + } +#endif + // Reset the GSO flag. gso_mhdr = NULL; gso_size = 0; gso_encrypt = 0; gso_cursor = 0; use_gso = gso_final = false; @@ -1662,6 +1684,7 @@ SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) trd = new SrsDummyCoroutine(); cache_pos = 0; + gso_cache_pos = 0; _srs_config->subscribe(this); } @@ -1678,6 +1701,12 @@ SrsUdpMuxSender::~SrsUdpMuxSender() free_mhdrs(cache); cache.clear(); + + free_mhdrs(gso_hotspot); + gso_hotspot.clear(); + + free_mhdrs(gso_cache); + gso_cache.clear(); } srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) @@ -1693,7 +1722,10 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) } max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - srs_trace("UDP sender #%d init ok, max_sendmmsg=%d", srs_netfd_fileno(fd), max_sendmmsg); + bool gso = _srs_config->get_rtc_server_gso(); + gso_dedicated = _srs_config->get_rtc_server_gso_dedicated(); + srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d, gso-dedicated=%d", + srs_netfd_fileno(fd), max_sendmmsg, gso, gso_dedicated); return err; } @@ -1738,6 +1770,34 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) return srs_success; } +srs_error_t SrsUdpMuxSender::gso_fetch(mmsghdr** pphdr) +{ + // When GSO share cache, we use the same cache with non-GSO. + if (!gso_dedicated) { + return fetch(pphdr); + } + + // TODO: FIXME: Maybe need to shrink? + if (gso_cache_pos >= (int)gso_cache.size()) { + mmsghdr mhdr; + memset(&mhdr, 0, sizeof(mmsghdr)); + + mhdr.msg_hdr.msg_iovlen = 1; + mhdr.msg_hdr.msg_iov = new iovec(); + mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; + mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; + mhdr.msg_len = 0; + + mhdr.msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); + mhdr.msg_hdr.msg_control = new char[mhdr.msg_hdr.msg_controllen]; + + gso_cache.push_back(mhdr); + } + + *pphdr = &gso_cache[gso_cache_pos++]; + return srs_success; +} + srs_error_t SrsUdpMuxSender::sendmmsg(mmsghdr* hdr) { if (waiting_msgs) { @@ -1752,11 +1812,9 @@ srs_error_t SrsUdpMuxSender::cycle() { srs_error_t err = srs_success; - uint64_t nn_msgs = 0; - uint64_t nn_msgs_last = 0; - int nn_msgs_max = 0; - int nn_loop = 0; - int nn_wait = 0; + uint64_t nn_msgs = 0; uint64_t nn_msgs_last = 0; int nn_msgs_max = 0; + uint64_t nn_gso_msgs = 0; uint64_t nn_gso_iovs = 0; int nn_gso_msgs_max = 0; int nn_gso_iovs_max = 0; + int nn_loop = 0; int nn_wait = 0; srs_utime_t time_last = srs_get_system_time(); SrsStatistic* stat = SrsStatistic::instance(); @@ -1771,7 +1829,9 @@ srs_error_t SrsUdpMuxSender::cycle() nn_loop++; int pos = cache_pos; - if (pos <= 0) { + int gso_pos = gso_cache_pos; + int gso_iovs = 0; + if (pos <= 0 && gso_pos == 0) { waiting_msgs = true; nn_wait++; srs_cond_wait(cond); @@ -1782,22 +1842,73 @@ srs_error_t SrsUdpMuxSender::cycle() cache.swap(hotspot); cache_pos = 0; - mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; - for (; p < end; p += max_sendmmsg) { - int vlen = (int)(end - p); - vlen = srs_min(max_sendmmsg, vlen); + if (gso_dedicated) { + gso_cache.swap(gso_hotspot); + gso_cache_pos = 0; + } - int r0 = srs_sendmmsg(lfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); - if (r0 != vlen) { - srs_warn("sendmsg %d msgs, %d done", vlen, r0); + // Send out GSO in dedicated queue. + if (gso_dedicated && gso_pos > 0) { + mmsghdr* p = &gso_hotspot[0]; mmsghdr* end = p + gso_pos; + for (; p < end; p++) { + // Private message, use it to store the cursor. + int real_iovs = p->msg_len; + p->msg_len = 0; + + // Send out GSO message. + int r0 = srs_sendmsg(lfd, &p->msg_hdr, 0, SRS_UTIME_NO_TIMEOUT); + if (r0 < 0) { + srs_warn("sendmsg err, r0=%d", r0); + } + + nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; + stat->perf_gso_on_packets(real_iovs); + } + } + + // Send out all messages, may GSO if shared cache. + if (pos > 0) { + mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; + + // For shared GSO cache, stat the messages. + if (!gso_dedicated) { + for (p = &hotspot[0]; p < end; p++) { + if (!p->msg_len) { + continue; + } + + // Private message, use it to store the cursor. + int real_iovs = p->msg_len; + p->msg_len = 0; + + gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; + stat->perf_gso_on_packets(real_iovs); + } } - stat->perf_mw_on_packets(vlen); + // Send out all messages. + for (p = &hotspot[0]; p < end; p += max_sendmmsg) { + int vlen = (int)(end - p); + vlen = srs_min(max_sendmmsg, vlen); + + int r0 = srs_sendmmsg(lfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); + if (r0 != vlen) { + srs_warn("sendmmsg %d msgs, %d done", vlen, r0); + } + + stat->perf_sendmmsg_on_packets(vlen); + } } // Increase total messages. - nn_msgs += pos; - nn_msgs_max = srs_max(pos, nn_msgs_max); + int nn_pos = pos; + if (gso_dedicated) { + nn_pos = pos + gso_pos; + } + nn_msgs += nn_pos; + nn_msgs_max = srs_max(nn_pos, nn_msgs_max); + nn_gso_msgs_max = srs_max(gso_pos, nn_gso_msgs_max); + nn_gso_iovs_max = srs_max(gso_iovs, nn_gso_iovs_max); pprint->elapse(); if (pprint->can_print()) { @@ -1819,11 +1930,12 @@ srs_error_t SrsUdpMuxSender::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d by sendmmsg %d", - srs_netfd_fileno(lfd), pos, nn_msgs_max, nn_msgs, pps_average, pps_last, pps_unit.c_str(), nn_loop, nn_wait, - (int)server->nn_sessions(), (int)cache.size(), (int)hotspot.size(), max_sendmmsg); + srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", gso-iovs %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d, sendmmsg %d", + srs_netfd_fileno(lfd), nn_pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), + nn_loop, nn_wait, (int)server->nn_sessions(), (int)cache.size(), (int)gso_cache.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; + nn_gso_msgs_max = 0; nn_gso_iovs_max = 0; } } @@ -1832,10 +1944,21 @@ srs_error_t SrsUdpMuxSender::cycle() srs_error_t SrsUdpMuxSender::on_reload_rtc_server() { - int v = _srs_config->get_rtc_server_sendmmsg(); - if (max_sendmmsg != v) { - srs_trace("Reload max_sendmmsg %d=>%d", max_sendmmsg, v); - max_sendmmsg = v; + if (true) { + int v = _srs_config->get_rtc_server_sendmmsg(); + if (max_sendmmsg != v) { + srs_trace("Reload max_sendmmsg %d=>%d", max_sendmmsg, v); + max_sendmmsg = v; + } + } + + if (true) { + bool gso = _srs_config->get_rtc_server_gso(); + bool v = _srs_config->get_rtc_server_gso_dedicated(); + if (gso_dedicated != v) { + srs_trace("Reload gso=%d, gso-dedicated %d=>%d", gso, gso_dedicated, v); + gso_dedicated = v; + } } return srs_success; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 748374290..263420cd7 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -273,6 +273,15 @@ private: int cache_pos; // The max number of messages for sendmmsg. If 1, we use sendmsg to send. int max_sendmmsg; + // Whether GSO shares the same mmsghdr cache. + // If not shared, use dedicated cache for GSO. + bool gso_dedicated; +private: + // For Linux kernel 3.*, we must use isolate queue for GSO, + // that is, sendmmsg does not work with GSO. + std::vector gso_hotspot; + std::vector gso_cache; + int gso_cache_pos; public: SrsUdpMuxSender(SrsRtcServer* s); virtual ~SrsUdpMuxSender(); @@ -282,6 +291,7 @@ private: void free_mhdrs(std::vector& mhdrs); public: virtual srs_error_t fetch(mmsghdr** pphdr); + virtual srs_error_t gso_fetch(mmsghdr** pphdr); virtual srs_error_t sendmmsg(mmsghdr* hdr); virtual srs_error_t cycle(); // interface ISrsReloadHandler diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index be3874ff7..2e33b7cb6 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -267,6 +267,7 @@ SrsStatistic::SrsStatistic() perf_msgs = new SrsStatisticCategory(); perf_sys = new SrsStatisticCategory(); perf_sendmmsg = new SrsStatisticCategory(); + perf_gso = new SrsStatisticCategory(); } SrsStatistic::~SrsStatistic() @@ -305,6 +306,7 @@ SrsStatistic::~SrsStatistic() srs_freep(perf_msgs); srs_freep(perf_sys); srs_freep(perf_sendmmsg); + srs_freep(perf_gso); } SrsStatistic* SrsStatistic::instance() @@ -738,7 +740,7 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) return err; } -void SrsStatistic::perf_mw_on_packets(int nb_msgs) +void SrsStatistic::perf_sendmmsg_on_packets(int nb_msgs) { // For perf msgs, the nb_msgs stat. // a: =1 @@ -808,6 +810,76 @@ srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) return err; } +void SrsStatistic::perf_gso_on_packets(int nb_msgs) +{ + // For perf msgs, the nb_msgs stat. + // a: =1 + // b: <3 + // c: <6 + // d: <9 + // e: <16 + // f: <32 + // g: <64 + // h: <128 + // i: <512 + // j: >=512 + if (nb_msgs == 1) { + perf_gso->a++; + } else if (nb_msgs < 3) { + perf_gso->b++; + } else if (nb_msgs < 6) { + perf_gso->c++; + } else if (nb_msgs < 9) { + perf_gso->d++; + } else if (nb_msgs < 16) { + perf_gso->e++; + } else if (nb_msgs < 32) { + perf_gso->f++; + } else if (nb_msgs < 64) { + perf_gso->g++; + } else if (nb_msgs < 128) { + perf_gso->h++; + } else if (nb_msgs < 512) { + perf_gso->i++; + } else { + perf_gso->j++; + } +} + +srs_error_t SrsStatistic::dumps_perf_gso(SrsJsonObject* obj) +{ + srs_error_t err = srs_success; + + if (true) { + SrsJsonObject* p = SrsJsonAny::object(); + obj->set("msgs", p); + + // For perf msgs, the nb_msgs stat. + // a: =1 + // b: <3 + // c: <6 + // d: <9 + // e: <16 + // f: <32 + // g: <64 + // h: <128 + // i: <512 + // j: >=512 + p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); + p->set("lt_3", SrsJsonAny::integer(perf_gso->b)); + p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); + p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); + p->set("lt_16", SrsJsonAny::integer(perf_gso->e)); + p->set("lt_32", SrsJsonAny::integer(perf_gso->f)); + p->set("lt_64", SrsJsonAny::integer(perf_gso->g)); + p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); + p->set("lt_512", SrsJsonAny::integer(perf_gso->i)); + p->set("gt_512", SrsJsonAny::integer(perf_gso->j)); + } + + return err; +} + SrsStatisticVhost* SrsStatistic::create_vhost(SrsRequest* req) { SrsStatisticVhost* vhost = NULL; diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 339e95b26..553bc9650 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -170,6 +170,7 @@ private: SrsStatisticCategory* perf_msgs; SrsStatisticCategory* perf_sys; SrsStatisticCategory* perf_sendmmsg; + SrsStatisticCategory* perf_gso; private: SrsStatistic(); virtual ~SrsStatistic(); @@ -238,9 +239,14 @@ public: virtual srs_error_t dumps_perf_writev(SrsJsonObject* obj); public: // Stat for packets UDP sendmmsg, nb_msgs is the vlen for sendmmsg. - virtual void perf_mw_on_packets(int nb_msgs); + virtual void perf_sendmmsg_on_packets(int nb_msgs); // Dumps the perf statistic data for UDP sendmmsg, for performance analysis. virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); +public: + // Stat for packets UDP GSO, nb_msgs is the vlen for sendmmsg. + virtual void perf_gso_on_packets(int nb_msgs); + // Dumps the perf statistic data for UDP GSO, for performance analysis. + virtual srs_error_t dumps_perf_gso(SrsJsonObject* obj); private: virtual SrsStatisticVhost* create_vhost(SrsRequest* req); virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req); From 23c68a922c7f0d6cd974e87fe1447720d9770ef6 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 10:05:55 +0800 Subject: [PATCH 052/131] Refine GSO for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 94 ++++++++++++++++-------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index cdf02d68c..2d3726043 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -947,7 +947,21 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket } // For last message, or final gso, or determined not using GSO, send it now. - if (i == nn_packets - 1 || gso_final || !use_gso) { + bool do_send = (i == nn_packets - 1 || gso_final || !use_gso); + +#if defined(SRS_DEBUG) + srs_trace("packet SSRC=%d, SN=%d, %d bytes", packet->rtp_header.get_ssrc(), + packet->rtp_header.get_sequence(), nn_packet); + if (do_send) { + for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { + iovec* iov = mhdr->msg_hdr.msg_iov + j; + srs_trace("%s #%d/%d/%d, %d bytes, size %d/%d", (use_gso? "GSO":"RAW"), j, gso_cursor + 1, + mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); + } + } +#endif + + if (do_send) { sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); socklen_t addrlen = (socklen_t)skt->peer_addrlen(); @@ -978,15 +992,6 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket return srs_error_wrap(err, "send msghdr"); } -#ifdef SRS_DEBUG - srs_warn("packet SN=%d %d bytes", nn_packet, packet->rtp_header.get_sequence()); - for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { - iovec* iov = mhdr->msg_hdr.msg_iov + j; - srs_warn("%s #%d/%d/%d, %d bytes, size %d/%d", (use_gso? "GSO":"RAW"), j, gso_cursor + 1, - mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); - } -#endif - // Reset the GSO flag. gso_mhdr = NULL; gso_size = 0; gso_encrypt = 0; gso_cursor = 0; use_gso = gso_final = false; @@ -1847,6 +1852,41 @@ srs_error_t SrsUdpMuxSender::cycle() gso_cache_pos = 0; } + // Collect informations for GSO + if (!gso_dedicated && pos > 0) { + // For shared GSO cache, stat the messages. + mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; + for (p = &hotspot[0]; p < end; p++) { + if (!p->msg_len) { + continue; + } + + // Private message, use it to store the cursor. + int real_iovs = p->msg_len; + p->msg_len = 0; + + gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; + stat->perf_gso_on_packets(real_iovs); + } + } + + // Send out all messages, may GSO if shared cache. + if (false && pos > 0) { + // Send out all messages. + mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; + for (p = &hotspot[0]; p < end; p += max_sendmmsg) { + int vlen = (int)(end - p); + vlen = srs_min(max_sendmmsg, vlen); + + int r0 = srs_sendmmsg(lfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); + if (r0 != vlen) { + srs_warn("sendmmsg %d msgs, %d done", vlen, r0); + } + + stat->perf_sendmmsg_on_packets(vlen); + } + } + // Send out GSO in dedicated queue. if (gso_dedicated && gso_pos > 0) { mmsghdr* p = &gso_hotspot[0]; mmsghdr* end = p + gso_pos; @@ -1866,40 +1906,6 @@ srs_error_t SrsUdpMuxSender::cycle() } } - // Send out all messages, may GSO if shared cache. - if (pos > 0) { - mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; - - // For shared GSO cache, stat the messages. - if (!gso_dedicated) { - for (p = &hotspot[0]; p < end; p++) { - if (!p->msg_len) { - continue; - } - - // Private message, use it to store the cursor. - int real_iovs = p->msg_len; - p->msg_len = 0; - - gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; - stat->perf_gso_on_packets(real_iovs); - } - } - - // Send out all messages. - for (p = &hotspot[0]; p < end; p += max_sendmmsg) { - int vlen = (int)(end - p); - vlen = srs_min(max_sendmmsg, vlen); - - int r0 = srs_sendmmsg(lfd, p, (unsigned int)vlen, 0, SRS_UTIME_NO_TIMEOUT); - if (r0 != vlen) { - srs_warn("sendmmsg %d msgs, %d done", vlen, r0); - } - - stat->perf_sendmmsg_on_packets(vlen); - } - } - // Increase total messages. int nn_pos = pos; if (gso_dedicated) { From feaf98eb69bcdc99ab0bd102582cb0cd2520956d Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 10:58:53 +0800 Subject: [PATCH 053/131] For #307, remove dedicate GSO cache --- trunk/conf/full.conf | 6 +- trunk/src/app/srs_app_config.cpp | 28 +------- trunk/src/app/srs_app_config.hpp | 1 - trunk/src/app/srs_app_listener.hpp | 4 -- trunk/src/app/srs_app_rtc_conn.cpp | 100 ++++------------------------- trunk/src/app/srs_app_rtc_conn.hpp | 10 --- 6 files changed, 13 insertions(+), 136 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 45156da17..2e40a387e 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -440,13 +440,9 @@ rtc_server { # default: on merge_nalus on; # Whether enable GSO to send out RTP packets. - # @remark Linux only, for other OS always disabled. + # @remark Linux 4.18+ only, for other OS always disabled. # default: off gso off; - # Whether GSO uses dedicated cache. Share the same mmsghdr cache if not dedicated. - # For Linux 3.*, we must use dedicated cache for GSO. - # default: off - gso_dedicated off; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 9693a17fa..f7f69a381 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3614,8 +3614,7 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" - && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus" - && n != "gso_dedicated") { + && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4815,31 +4814,6 @@ bool SrsConfig::get_rtc_server_gso() return v; } -bool SrsConfig::get_rtc_server_gso_dedicated() -{ - static int DEFAULT = false; - - SrsConfDirective* conf = root->get("rtc_server"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("gso_dedicated"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - bool v = SRS_CONF_PERFER_FALSE(conf->arg0()); - -#ifdef SRS_AUTO_OSX - if (v != DEFAULT) { - srs_warn("GSO is for Linux only"); - } -#endif - - return v; -} - SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index bfc6f373f..8093a50a4 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -530,7 +530,6 @@ public: virtual int get_rtc_server_reuseport(); virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_gso(); - virtual bool get_rtc_server_gso_dedicated(); SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index ec503cf6b..8ef384dd9 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -139,10 +139,6 @@ public: public: // Fetch a mmsghdr from sender's cache. virtual srs_error_t fetch(mmsghdr** pphdr) = 0; - // For Linux kernel 3.*, we must use isolate APIs for GSO, - // that is, sendmmsg does not work with GSO. - // Fetch a mmsghdr from sender's cache. - virtual srs_error_t gso_fetch(mmsghdr** pphdr) = 0; // Notify the sender to send out the msg. virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0; }; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 2d3726043..773ac594c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -813,6 +813,7 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; mhdr->msg_hdr.msg_iov->iov_len = length; + mhdr->msg_hdr.msg_controllen = 0; mhdr->msg_len = 0; if ((err = sender->sendmmsg(mhdr)) != srs_success) { @@ -889,12 +890,7 @@ srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPacket if (!mhdr) { // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. - if (use_gso) { - err = sender->gso_fetch(&mhdr); - } else { - err = sender->fetch(&mhdr); - } - if (err != srs_success) { + if ((err = sender->fetch(&mhdr)) != srs_success) { return srs_error_wrap(err, "fetch msghdr"); } @@ -1689,7 +1685,6 @@ SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) trd = new SrsDummyCoroutine(); cache_pos = 0; - gso_cache_pos = 0; _srs_config->subscribe(this); } @@ -1706,12 +1701,6 @@ SrsUdpMuxSender::~SrsUdpMuxSender() free_mhdrs(cache); cache.clear(); - - free_mhdrs(gso_hotspot); - gso_hotspot.clear(); - - free_mhdrs(gso_cache); - gso_cache.clear(); } srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) @@ -1728,9 +1717,7 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); bool gso = _srs_config->get_rtc_server_gso(); - gso_dedicated = _srs_config->get_rtc_server_gso_dedicated(); - srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d, gso-dedicated=%d", - srs_netfd_fileno(fd), max_sendmmsg, gso, gso_dedicated); + srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d", srs_netfd_fileno(fd), max_sendmmsg, gso); return err; } @@ -1775,34 +1762,6 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) return srs_success; } -srs_error_t SrsUdpMuxSender::gso_fetch(mmsghdr** pphdr) -{ - // When GSO share cache, we use the same cache with non-GSO. - if (!gso_dedicated) { - return fetch(pphdr); - } - - // TODO: FIXME: Maybe need to shrink? - if (gso_cache_pos >= (int)gso_cache.size()) { - mmsghdr mhdr; - memset(&mhdr, 0, sizeof(mmsghdr)); - - mhdr.msg_hdr.msg_iovlen = 1; - mhdr.msg_hdr.msg_iov = new iovec(); - mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; - mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; - mhdr.msg_len = 0; - - mhdr.msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); - mhdr.msg_hdr.msg_control = new char[mhdr.msg_hdr.msg_controllen]; - - gso_cache.push_back(mhdr); - } - - *pphdr = &gso_cache[gso_cache_pos++]; - return srs_success; -} - srs_error_t SrsUdpMuxSender::sendmmsg(mmsghdr* hdr) { if (waiting_msgs) { @@ -1834,7 +1793,7 @@ srs_error_t SrsUdpMuxSender::cycle() nn_loop++; int pos = cache_pos; - int gso_pos = gso_cache_pos; + int gso_pos = 0; int gso_iovs = 0; if (pos <= 0 && gso_pos == 0) { waiting_msgs = true; @@ -1847,13 +1806,8 @@ srs_error_t SrsUdpMuxSender::cycle() cache.swap(hotspot); cache_pos = 0; - if (gso_dedicated) { - gso_cache.swap(gso_hotspot); - gso_cache_pos = 0; - } - // Collect informations for GSO - if (!gso_dedicated && pos > 0) { + if (pos > 0) { // For shared GSO cache, stat the messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p++) { @@ -1871,7 +1825,7 @@ srs_error_t SrsUdpMuxSender::cycle() } // Send out all messages, may GSO if shared cache. - if (false && pos > 0) { + if (pos > 0) { // Send out all messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p += max_sendmmsg) { @@ -1887,32 +1841,9 @@ srs_error_t SrsUdpMuxSender::cycle() } } - // Send out GSO in dedicated queue. - if (gso_dedicated && gso_pos > 0) { - mmsghdr* p = &gso_hotspot[0]; mmsghdr* end = p + gso_pos; - for (; p < end; p++) { - // Private message, use it to store the cursor. - int real_iovs = p->msg_len; - p->msg_len = 0; - - // Send out GSO message. - int r0 = srs_sendmsg(lfd, &p->msg_hdr, 0, SRS_UTIME_NO_TIMEOUT); - if (r0 < 0) { - srs_warn("sendmsg err, r0=%d", r0); - } - - nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; - stat->perf_gso_on_packets(real_iovs); - } - } - // Increase total messages. - int nn_pos = pos; - if (gso_dedicated) { - nn_pos = pos + gso_pos; - } - nn_msgs += nn_pos; - nn_msgs_max = srs_max(nn_pos, nn_msgs_max); + nn_msgs += pos; + nn_msgs_max = srs_max(pos, nn_msgs_max); nn_gso_msgs_max = srs_max(gso_pos, nn_gso_msgs_max); nn_gso_iovs_max = srs_max(gso_iovs, nn_gso_iovs_max); @@ -1936,9 +1867,9 @@ srs_error_t SrsUdpMuxSender::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", gso-iovs %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d/%d, sendmmsg %d", - srs_netfd_fileno(lfd), nn_pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), - nn_loop, nn_wait, (int)server->nn_sessions(), (int)cache.size(), (int)gso_cache.size(), max_sendmmsg); + srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", gso-iovs %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d, sendmmsg %d", + srs_netfd_fileno(lfd), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), + nn_loop, nn_wait, (int)server->nn_sessions(), (int)cache.size(), max_sendmmsg); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; nn_gso_msgs_max = 0; nn_gso_iovs_max = 0; @@ -1958,15 +1889,6 @@ srs_error_t SrsUdpMuxSender::on_reload_rtc_server() } } - if (true) { - bool gso = _srs_config->get_rtc_server_gso(); - bool v = _srs_config->get_rtc_server_gso_dedicated(); - if (gso_dedicated != v) { - srs_trace("Reload gso=%d, gso-dedicated %d=>%d", gso, gso_dedicated, v); - gso_dedicated = v; - } - } - return srs_success; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 263420cd7..748374290 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -273,15 +273,6 @@ private: int cache_pos; // The max number of messages for sendmmsg. If 1, we use sendmsg to send. int max_sendmmsg; - // Whether GSO shares the same mmsghdr cache. - // If not shared, use dedicated cache for GSO. - bool gso_dedicated; -private: - // For Linux kernel 3.*, we must use isolate queue for GSO, - // that is, sendmmsg does not work with GSO. - std::vector gso_hotspot; - std::vector gso_cache; - int gso_cache_pos; public: SrsUdpMuxSender(SrsRtcServer* s); virtual ~SrsUdpMuxSender(); @@ -291,7 +282,6 @@ private: void free_mhdrs(std::vector& mhdrs); public: virtual srs_error_t fetch(mmsghdr** pphdr); - virtual srs_error_t gso_fetch(mmsghdr** pphdr); virtual srs_error_t sendmmsg(mmsghdr* hdr); virtual srs_error_t cycle(); // interface ISrsReloadHandler From 2cd580f50061971e9ac22ecdd76c89f313fe80d0 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 11:26:45 +0800 Subject: [PATCH 054/131] For #307, disable GSO < linux 4.18.0 --- trunk/src/app/srs_app_config.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f7f69a381..39ef44a76 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -33,6 +33,10 @@ #include #include #include +#ifdef __linux__ +#include +#include +#endif #include #include @@ -4805,12 +4809,25 @@ bool SrsConfig::get_rtc_server_gso() bool v = SRS_CONF_PERFER_FALSE(conf->arg0()); -#ifdef SRS_AUTO_OSX - if (v) { - srs_warn("GSO is for Linux only"); - } - v = false; + bool gso_disabled = false; +#if !defined(__linux__) + gso_disabled = true; + srs_warn("GSO is for Linux 4.18+ only"); +#else + #if LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0) + utsname un = {0}; + int r0 = uname(&un); + if (r0 || strcmp(un.release, "4.18.0") < 0) { + gso_disabled = true; + } + srs_warn("GSO is for Linux 4.18+ only, r0=%d, %s", r0, un.release); + #endif #endif + + if (v && gso_disabled) { + v = false; + } + return v; } From 8ba3d78e868d6cc16922ac09a2f8c37278685a0b Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 11:30:21 +0800 Subject: [PATCH 055/131] Refine logs for GSO --- trunk/src/app/srs_app_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 39ef44a76..f50ab799e 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4812,7 +4812,7 @@ bool SrsConfig::get_rtc_server_gso() bool gso_disabled = false; #if !defined(__linux__) gso_disabled = true; - srs_warn("GSO is for Linux 4.18+ only"); + srs_warn("GSO is disabled, for Linux 4.18+ only"); #else #if LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0) utsname un = {0}; @@ -4820,7 +4820,7 @@ bool SrsConfig::get_rtc_server_gso() if (r0 || strcmp(un.release, "4.18.0") < 0) { gso_disabled = true; } - srs_warn("GSO is for Linux 4.18+ only, r0=%d, %s", r0, un.release); + srs_warn("GSO is disabled, for Linux 4.18+ only, r0=%d, kernel=%s", r0, un.release); #endif #endif From 24eb61156f6fd42329e42493f735041f520bb801 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 11:39:22 +0800 Subject: [PATCH 056/131] Refine logs for GSO --- trunk/src/app/srs_app_config.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index f50ab799e..d5b0022c3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4812,16 +4812,18 @@ bool SrsConfig::get_rtc_server_gso() bool gso_disabled = false; #if !defined(__linux__) gso_disabled = true; - srs_warn("GSO is disabled, for Linux 4.18+ only"); -#else - #if LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0) + if (v) { + srs_warn("GSO is disabled, for Linux 4.18+ only"); + } +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0) + if (v) { utsname un = {0}; int r0 = uname(&un); if (r0 || strcmp(un.release, "4.18.0") < 0) { gso_disabled = true; + srs_warn("GSO is disabled, for Linux 4.18+ only, r0=%d, kernel=%s", r0, un.release); } - srs_warn("GSO is disabled, for Linux 4.18+ only, r0=%d, kernel=%s", r0, un.release); - #endif + } #endif if (v && gso_disabled) { From b6a929f9cfb9096bfbca5207a50b4fbb2079708d Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 11:41:23 +0800 Subject: [PATCH 057/131] Enable GSO by default --- trunk/conf/full.conf | 4 ++-- trunk/src/app/srs_app_config.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 2e40a387e..581e4daa3 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -441,8 +441,8 @@ rtc_server { merge_nalus on; # Whether enable GSO to send out RTP packets. # @remark Linux 4.18+ only, for other OS always disabled. - # default: off - gso off; + # default: on + gso on; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index d5b0022c3..3d44d63f5 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4795,7 +4795,7 @@ bool SrsConfig::get_rtc_server_merge_nalus() bool SrsConfig::get_rtc_server_gso() { - static int DEFAULT = false; + static int DEFAULT = true; SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { @@ -4807,7 +4807,7 @@ bool SrsConfig::get_rtc_server_gso() return DEFAULT; } - bool v = SRS_CONF_PERFER_FALSE(conf->arg0()); + bool v = SRS_CONF_PERFER_TRUE(conf->arg0()); bool gso_disabled = false; #if !defined(__linux__) From 39853160d1b30f1191e1b3f0806d07d950180eae Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 11:49:59 +0800 Subject: [PATCH 058/131] Refactor default config --- trunk/src/app/srs_app_config.cpp | 55 ++++++++++++++++++-------------- trunk/src/app/srs_app_config.hpp | 7 +++- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 3d44d63f5..956bc99b0 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4751,12 +4751,20 @@ int SrsConfig::get_rtc_server_sendmmsg() int SrsConfig::get_rtc_server_reuseport() { -#if defined(SO_REUSEPORT) - static int DEFAULT = 4; -#else - static int DEFAULT = 1; + int v = get_rtc_server_reuseport2(); + +#if !defined(SO_REUSEPORT) + srs_warn("REUSEPORT not supported, reset %d to %d", reuseport, DEFAULT); + v = 1 #endif + return v; +} + +int SrsConfig::get_rtc_server_reuseport2() +{ + static int DEFAULT = 4; + SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { return DEFAULT; @@ -4767,13 +4775,7 @@ int SrsConfig::get_rtc_server_reuseport() return DEFAULT; } - int reuseport = ::atoi(conf->arg0().c_str()); -#if !defined(SO_REUSEPORT) - srs_warn("REUSEPORT not supported, reset %d to %d", reuseport, DEFAULT); - reuseport = DEFAULT -#endif - - return reuseport; + return ::atoi(conf->arg0().c_str()); } bool SrsConfig::get_rtc_server_merge_nalus() @@ -4795,19 +4797,7 @@ bool SrsConfig::get_rtc_server_merge_nalus() bool SrsConfig::get_rtc_server_gso() { - static int DEFAULT = true; - - SrsConfDirective* conf = root->get("rtc_server"); - if (!conf) { - return DEFAULT; - } - - conf = conf->get("gso"); - if (!conf || conf->arg0().empty()) { - return DEFAULT; - } - - bool v = SRS_CONF_PERFER_TRUE(conf->arg0()); + bool v = get_rtc_server_gso2(); bool gso_disabled = false; #if !defined(__linux__) @@ -4833,6 +4823,23 @@ bool SrsConfig::get_rtc_server_gso() return v; } +bool SrsConfig::get_rtc_server_gso2() +{ + static int DEFAULT = true; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("gso"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 8093a50a4..96524c33a 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -528,9 +528,14 @@ public: virtual int get_rtc_server_sendmmsg(); virtual bool get_rtc_server_encrypt(); virtual int get_rtc_server_reuseport(); +private: + virtual int get_rtc_server_reuseport2(); +public: virtual bool get_rtc_server_merge_nalus(); virtual bool get_rtc_server_gso(); - +private: + virtual bool get_rtc_server_gso2(); +public: SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); bool get_rtc_bframe_discard(std::string vhost); From 5b406d68d699ddd5488be45254dc16dcd8741f17 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 13:34:24 +0800 Subject: [PATCH 059/131] Refine pithy print --- trunk/src/app/srs_app_listener.cpp | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 10 +++++----- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index 2117983be..3294c79f5 100755 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -499,7 +499,7 @@ srs_error_t SrsUdpMuxListener::cycle() pps_unit = "(k)"; pps_last /= 10000; pps_average /= 10000; } - srs_trace("<- RTC #%d RECV %" PRId64 ", pps %d/%d%s, schedule %" PRId64, + srs_trace("<- RTC RECV #%d, udp %" PRId64 ", pps %d/%d%s, schedule %" PRId64, srs_netfd_fileno(lfd), nn_msgs_stage, pps_average, pps_last, pps_unit.c_str(), nn_loop); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = 0; nn_msgs_stage = 0; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 773ac594c..863bdb95d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -675,7 +675,7 @@ srs_error_t SrsRtcSenderThread::send_messages( #ifndef SRS_AUTO_OSX // If enabled GSO, send out some packets in a msghdr. if (packets.use_gso) { - if ((err = send_packets2(skt, packets)) != srs_success) { + if ((err = send_packets_gso(skt, packets)) != srs_success) { return srs_error_wrap(err, "gso send"); } return err; @@ -825,7 +825,7 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets } // TODO: FIXME: We can gather and pad audios, because they have similar size. -srs_error_t SrsRtcSenderThread::send_packets2(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) +srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) { srs_error_t err = srs_success; @@ -1867,9 +1867,9 @@ srs_error_t SrsUdpMuxSender::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC #%d SEND %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", gso-iovs %d/%d/%" PRId64 ", pps %d/%d%s, schedule %d/%d, sessions %d, cache %d, sendmmsg %d", - srs_netfd_fileno(lfd), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), - nn_loop, nn_wait, (int)server->nn_sessions(), (int)cache.size(), max_sendmmsg); + srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s", + srs_netfd_fileno(lfd), (int)server->nn_sessions(), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, + pps_average, pps_last, pps_unit.c_str()); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; nn_gso_msgs_max = 0; nn_gso_iovs_max = 0; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 748374290..89c46e916 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -179,7 +179,7 @@ private: srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); - srs_error_t send_packets2(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); + srs_error_t send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); private: srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); private: From 03a03e41748d7495d01ca1286626ab7b97b5856c Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 13:47:23 +0800 Subject: [PATCH 060/131] Refine stat for GSO --- trunk/src/app/srs_app_http_api.cpp | 6 +-- trunk/src/app/srs_app_rtc_conn.cpp | 4 ++ trunk/src/app/srs_app_statistic.cpp | 73 +++++++++------------------ trunk/src/app/srs_app_statistic.hpp | 4 -- trunk/src/protocol/srs_rtmp_stack.cpp | 5 -- trunk/src/protocol/srs_rtmp_stack.hpp | 3 -- 6 files changed, 31 insertions(+), 64 deletions(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 6d7df56fa..fd4e9b2bb 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1622,7 +1622,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* data->set("query", p); p->set("target", SrsJsonAny::str(target.c_str())); - p->set("help", SrsJsonAny::str("?target=writev|sendmmsg|gso|udp")); + p->set("help", SrsJsonAny::str("?target=writev|sendmmsg|gso")); } if (target.empty() || target == "writev") { @@ -1634,7 +1634,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } - if (target.empty() || target == "sendmmsg" || target == "udp") { + if (target.empty() || target == "sendmmsg") { SrsJsonObject* p = SrsJsonAny::object(); data->set("sendmmsg", p); if ((err = stat->dumps_perf_sendmmsg(p)) != srs_success) { @@ -1643,7 +1643,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } - if (target.empty() || target == "gso" || target == "udp") { + if (target.empty() || target == "gso") { SrsJsonObject* p = SrsJsonAny::object(); data->set("gso", p); if ((err = stat->dumps_perf_gso(p)) != srs_success) { diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 863bdb95d..f70cf279d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -609,6 +609,8 @@ srs_error_t SrsRtcSenderThread::cycle() SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); SrsAutoFree(SrsPithyPrint, pprint); + SrsStatistic* stat = SrsStatistic::instance(); + while (true) { if ((err = trd->pull()) != srs_success) { return srs_error_wrap(err, "rtc sender thread"); @@ -647,6 +649,8 @@ srs_error_t SrsRtcSenderThread::cycle() srs_freep(msg); } + stat->perf_mw_on_msgs(msg_count, pkts.nn_bytes, pkts.nn_rtp_pkts); + pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 2e33b7cb6..228fa8344 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -265,7 +265,6 @@ SrsStatistic::SrsStatistic() perf_iovs = new SrsStatisticCategory(); perf_msgs = new SrsStatisticCategory(); - perf_sys = new SrsStatisticCategory(); perf_sendmmsg = new SrsStatisticCategory(); perf_gso = new SrsStatisticCategory(); } @@ -304,7 +303,6 @@ SrsStatistic::~SrsStatistic() srs_freep(perf_iovs); srs_freep(perf_msgs); - srs_freep(perf_sys); srs_freep(perf_sendmmsg); srs_freep(perf_gso); } @@ -591,28 +589,28 @@ void SrsStatistic::perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) { // For perf msgs, the nb_msgs stat. // a: =1 - // b: <10 - // c: <100 - // d: <200 - // e: <300 - // f: <400 - // g: <500 + // b: <3 + // c: <6 + // d: <12 + // e: <128 + // f: <256 + // g: <512 // h: <600 // i: <1000 // j: >=1000 if (nb_msgs == 1) { perf_msgs->a++; - } else if (nb_msgs < 10) { + } else if (nb_msgs < 3) { perf_msgs->b++; - } else if (nb_msgs < 100) { + } else if (nb_msgs < 6) { perf_msgs->c++; - } else if (nb_msgs < 200) { + } else if (nb_msgs < 12) { perf_msgs->d++; - } else if (nb_msgs < 300) { + } else if (nb_msgs < 128) { perf_msgs->e++; - } else if (nb_msgs < 400) { + } else if (nb_msgs < 256) { perf_msgs->f++; - } else if (nb_msgs < 500) { + } else if (nb_msgs < 512) { perf_msgs->g++; } else if (nb_msgs < 600) { perf_msgs->h++; @@ -654,18 +652,6 @@ void SrsStatistic::perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) } else { perf_iovs->j++; } - - // Stat the syscalls. - // a: number of syscalls of msgs. - perf_sys->a++; -} - -void SrsStatistic::perf_mw_on_packets(int nb_pkts, int bytes_pkts, int nb_iovs) -{ - // Stat the syscalls. - // a: number of syscalls of msgs. - // b: number of syscalls of pkts. - perf_sys->b++; } srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) @@ -678,22 +664,22 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) // For perf msgs, the nb_msgs stat. // a: =1 - // b: <10 - // c: <100 - // d: <200 - // e: <300 - // f: <400 - // g: <500 + // b: <3 + // c: <6 + // d: <12 + // e: <128 + // f: <256 + // g: <512 // h: <600 // i: <1000 // j: >=1000 p->set("lt_2", SrsJsonAny::integer(perf_msgs->a)); - p->set("lt_10", SrsJsonAny::integer(perf_msgs->b)); - p->set("lt_100", SrsJsonAny::integer(perf_msgs->c)); - p->set("lt_200", SrsJsonAny::integer(perf_msgs->d)); - p->set("lt_300", SrsJsonAny::integer(perf_msgs->e)); - p->set("lt_400", SrsJsonAny::integer(perf_msgs->f)); - p->set("lt_500", SrsJsonAny::integer(perf_msgs->g)); + p->set("lt_3", SrsJsonAny::integer(perf_msgs->b)); + p->set("lt_6", SrsJsonAny::integer(perf_msgs->c)); + p->set("lt_12", SrsJsonAny::integer(perf_msgs->d)); + p->set("lt_128", SrsJsonAny::integer(perf_msgs->e)); + p->set("lt_256", SrsJsonAny::integer(perf_msgs->f)); + p->set("lt_512", SrsJsonAny::integer(perf_msgs->g)); p->set("lt_600", SrsJsonAny::integer(perf_msgs->h)); p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); @@ -726,17 +712,6 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) p->set("gt_1024", SrsJsonAny::integer(perf_iovs->j)); } - if (true) { - SrsJsonObject* p = SrsJsonAny::object(); - obj->set("sys", p); - - // Stat the syscalls. - // a: number of syscalls of msgs. - // b: number of syscalls of pkts. - p->set("msgs", SrsJsonAny::integer(perf_sys->a)); - p->set("pkts", SrsJsonAny::integer(perf_sys->b)); - } - return err; } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 553bc9650..ae73f49de 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -168,7 +168,6 @@ private: // The perf stat for mw(merged write). SrsStatisticCategory* perf_iovs; SrsStatisticCategory* perf_msgs; - SrsStatisticCategory* perf_sys; SrsStatisticCategory* perf_sendmmsg; SrsStatisticCategory* perf_gso; private: @@ -232,9 +231,6 @@ public: // Stat for packets merged written, nb_msgs is the number of RTMP messages, // bytes_msgs is the total bytes of RTMP messages, nb_iovs is the total number of iovec. virtual void perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs); - // Stat for packets merged written, nb_pkts is the number of or chunk packets, - // bytes_pkts is the total bytes of or chunk packets, nb_iovs is the total number of iovec. - virtual void perf_mw_on_packets(int nb_pkts, int bytes_pkts, int nb_iovs); // Dumps the perf statistic data for TCP writev, for performance analysis. virtual srs_error_t dumps_perf_writev(SrsJsonObject* obj); public: diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 6c0889d3f..835746805 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -627,11 +627,6 @@ srs_error_t SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msg if ((er = skt->writev(iovs, 2, NULL)) != srs_success) { return srs_error_wrap(err, "writev"); } - - // Notify about perf stat. - if (perf) { - perf->perf_mw_on_packets(1, payload_size, 2); - } } } diff --git a/trunk/src/protocol/srs_rtmp_stack.hpp b/trunk/src/protocol/srs_rtmp_stack.hpp index 470347cac..eea0c5a50 100644 --- a/trunk/src/protocol/srs_rtmp_stack.hpp +++ b/trunk/src/protocol/srs_rtmp_stack.hpp @@ -157,9 +157,6 @@ public: // Stat for packets merged written, nb_msgs is the number of RTMP messages, // bytes_msgs is the total bytes of RTMP messages, nb_iovs is the total number of iovec. virtual void perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) = 0; - // Stat for packets merged written, nb_pkts is the number of or chunk packets, - // bytes_pkts is the total bytes of or chunk packets, nb_iovs is the total number of iovec. - virtual void perf_mw_on_packets(int nb_pkts, int bytes_pkts, int nb_iovs) = 0; }; // The protocol provides the rtmp-message-protocol services, From fdc0c44b7e571f645da0e1f50af8117d63dd7116 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 13:55:55 +0800 Subject: [PATCH 061/131] For #307, for realtime, change wait messages from 0 to 2 --- trunk/src/app/srs_app_http_stream.cpp | 2 + trunk/src/app/srs_app_rtc_conn.cpp | 2 +- trunk/src/app/srs_app_rtmp_conn.cpp | 2 +- trunk/src/app/srs_app_statistic.cpp | 64 ++++++++++++------------- trunk/src/core/srs_core_performance.hpp | 4 ++ 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 6609c3852..95c1f03fd 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -680,6 +680,8 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess err = streaming_send_messages(enc, msgs.msgs, count); } + // TODO: FIXME: Update the stat. + // free the messages. for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index f70cf279d..abee62bc0 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -619,7 +619,7 @@ srs_error_t SrsRtcSenderThread::cycle() #ifdef SRS_PERF_QUEUE_COND_WAIT if (realtime) { // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(0, mw_sleep); + consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); } else { // for no-realtime, got some msgs then send. consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index d312d4ab2..d06d79a42 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -732,7 +732,7 @@ srs_error_t SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, Sr // @see https://github.com/ossrs/srs/issues/257 if (realtime) { // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(0, mw_sleep); + consumer->wait(SRS_PERF_MW_MIN_MSGS_REALTIME, mw_sleep); } else { // for no-realtime, got some msgs then send. consumer->wait(SRS_PERF_MW_MIN_MSGS, mw_sleep); diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 228fa8344..62ba28764 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -588,31 +588,31 @@ srs_error_t SrsStatistic::dumps_clients(SrsJsonArray* arr, int start, int count) void SrsStatistic::perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) { // For perf msgs, the nb_msgs stat. - // a: =1 - // b: <3 - // c: <6 - // d: <12 - // e: <128 - // f: <256 - // g: <512 - // h: <600 + // a: <3 + // b: <5 + // c: <9 + // d: <16 + // e: <32 + // f: <64 + // g: <128 + // h: <256 // i: <1000 // j: >=1000 - if (nb_msgs == 1) { + if (nb_msgs < 3) { perf_msgs->a++; - } else if (nb_msgs < 3) { + } else if (nb_msgs < 5) { perf_msgs->b++; - } else if (nb_msgs < 6) { + } else if (nb_msgs < 9) { perf_msgs->c++; - } else if (nb_msgs < 12) { + } else if (nb_msgs < 16) { perf_msgs->d++; - } else if (nb_msgs < 128) { + } else if (nb_msgs < 32) { perf_msgs->e++; - } else if (nb_msgs < 256) { + } else if (nb_msgs < 64) { perf_msgs->f++; - } else if (nb_msgs < 512) { + } else if (nb_msgs < 128) { perf_msgs->g++; - } else if (nb_msgs < 600) { + } else if (nb_msgs < 256) { perf_msgs->h++; } else if (nb_msgs < 1000) { perf_msgs->i++; @@ -663,24 +663,24 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) obj->set("msgs", p); // For perf msgs, the nb_msgs stat. - // a: =1 - // b: <3 - // c: <6 - // d: <12 - // e: <128 - // f: <256 - // g: <512 - // h: <600 + // a: <3 + // b: <5 + // c: <9 + // d: <16 + // e: <32 + // f: <64 + // g: <128 + // h: <256 // i: <1000 // j: >=1000 - p->set("lt_2", SrsJsonAny::integer(perf_msgs->a)); - p->set("lt_3", SrsJsonAny::integer(perf_msgs->b)); - p->set("lt_6", SrsJsonAny::integer(perf_msgs->c)); - p->set("lt_12", SrsJsonAny::integer(perf_msgs->d)); - p->set("lt_128", SrsJsonAny::integer(perf_msgs->e)); - p->set("lt_256", SrsJsonAny::integer(perf_msgs->f)); - p->set("lt_512", SrsJsonAny::integer(perf_msgs->g)); - p->set("lt_600", SrsJsonAny::integer(perf_msgs->h)); + p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); + p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); + p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); + p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); + p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); + p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); + p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); + p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); } diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 07c1e1539..adc38f3fa 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -127,8 +127,12 @@ */ #define SRS_PERF_QUEUE_COND_WAIT #ifdef SRS_PERF_QUEUE_COND_WAIT + // For RTMP, use larger wait queue. #define SRS_PERF_MW_MIN_MSGS 8 + #define SRS_PERF_MW_MIN_MSGS_REALTIME 4 + // For RTC, use smaller wait queue. #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 4 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 2 #endif /** * the default value of vhost for From 7574dbefb1c8fada887986591d21a49a706f941a Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 14:02:54 +0800 Subject: [PATCH 062/131] For #307, support sendmmsg, GSO and reuseport. 4.0.23 --- README.md | 1 + trunk/src/app/srs_app_statistic.cpp | 80 ++++++++++++------------- trunk/src/core/srs_core_performance.hpp | 4 +- trunk/src/core/srs_core_version4.hpp | 2 +- 4 files changed, 44 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 728152999..270a7569a 100755 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ For previous versions, please read: ## V4 changes +* v4.0, 2020-04-14, For [#307][bug #307], support sendmmsg, GSO and reuseport. 4.0.23 * v4.0, 2020-04-05, For [#307][bug #307], SRTP ASM only works with openssl-1.0, auto detect it. 4.0.22 * v4.0, 2020-04-04, Merge RTC and GB28181, with bugs fixed. 4.0.21 * v4.0, 2020-04-04, For [#307][bug #307], refine RTC latency from 600ms to 200ms. 4.0.20 diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 62ba28764..92284c329 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -673,16 +673,16 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) // h: <256 // i: <1000 // j: >=1000 - p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); - p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); - p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); - p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); - p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); - p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); - p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); - p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); - p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); - p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); + if (perf_msgs->a) p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); + if (perf_msgs->b) p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); + if (perf_msgs->c) p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); + if (perf_msgs->d) p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); + if (perf_msgs->e) p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); + if (perf_msgs->f) p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); + if (perf_msgs->g) p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); + if (perf_msgs->h) p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); + if (perf_msgs->i) p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); + if (perf_msgs->j) p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); } if (true) { @@ -700,16 +700,16 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) // h: <900 // i: <1024 // j: >=1024 - p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); - p->set("lt_10", SrsJsonAny::integer(perf_iovs->b)); - p->set("lt_20", SrsJsonAny::integer(perf_iovs->c)); - p->set("lt_200", SrsJsonAny::integer(perf_iovs->d)); - p->set("lt_300", SrsJsonAny::integer(perf_iovs->e)); - p->set("lt_500", SrsJsonAny::integer(perf_iovs->f)); - p->set("lt_700", SrsJsonAny::integer(perf_iovs->g)); - p->set("lt_900", SrsJsonAny::integer(perf_iovs->h)); - p->set("lt_1024", SrsJsonAny::integer(perf_iovs->i)); - p->set("gt_1024", SrsJsonAny::integer(perf_iovs->j)); + if (perf_iovs->a) p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); + if (perf_iovs->b) p->set("lt_10", SrsJsonAny::integer(perf_iovs->b)); + if (perf_iovs->c) p->set("lt_20", SrsJsonAny::integer(perf_iovs->c)); + if (perf_iovs->d) p->set("lt_200", SrsJsonAny::integer(perf_iovs->d)); + if (perf_iovs->e) p->set("lt_300", SrsJsonAny::integer(perf_iovs->e)); + if (perf_iovs->f) p->set("lt_500", SrsJsonAny::integer(perf_iovs->f)); + if (perf_iovs->g) p->set("lt_700", SrsJsonAny::integer(perf_iovs->g)); + if (perf_iovs->h) p->set("lt_900", SrsJsonAny::integer(perf_iovs->h)); + if (perf_iovs->i) p->set("lt_1024", SrsJsonAny::integer(perf_iovs->i)); + if (perf_iovs->j) p->set("gt_1024", SrsJsonAny::integer(perf_iovs->j)); } return err; @@ -770,16 +770,16 @@ srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) // h: <600 // i: <1000 // j: >=1000 - p->set("lt_2", SrsJsonAny::integer(perf_sendmmsg->a)); - p->set("lt_10", SrsJsonAny::integer(perf_sendmmsg->b)); - p->set("lt_100", SrsJsonAny::integer(perf_sendmmsg->c)); - p->set("lt_200", SrsJsonAny::integer(perf_sendmmsg->d)); - p->set("lt_300", SrsJsonAny::integer(perf_sendmmsg->e)); - p->set("lt_400", SrsJsonAny::integer(perf_sendmmsg->f)); - p->set("lt_500", SrsJsonAny::integer(perf_sendmmsg->g)); - p->set("lt_600", SrsJsonAny::integer(perf_sendmmsg->h)); - p->set("lt_1000", SrsJsonAny::integer(perf_sendmmsg->i)); - p->set("gt_1000", SrsJsonAny::integer(perf_sendmmsg->j)); + if (perf_sendmmsg->a) p->set("lt_2", SrsJsonAny::integer(perf_sendmmsg->a)); + if (perf_sendmmsg->b) p->set("lt_10", SrsJsonAny::integer(perf_sendmmsg->b)); + if (perf_sendmmsg->c) p->set("lt_100", SrsJsonAny::integer(perf_sendmmsg->c)); + if (perf_sendmmsg->d) p->set("lt_200", SrsJsonAny::integer(perf_sendmmsg->d)); + if (perf_sendmmsg->e) p->set("lt_300", SrsJsonAny::integer(perf_sendmmsg->e)); + if (perf_sendmmsg->f) p->set("lt_400", SrsJsonAny::integer(perf_sendmmsg->f)); + if (perf_sendmmsg->g) p->set("lt_500", SrsJsonAny::integer(perf_sendmmsg->g)); + if (perf_sendmmsg->h) p->set("lt_600", SrsJsonAny::integer(perf_sendmmsg->h)); + if (perf_sendmmsg->i) p->set("lt_1000", SrsJsonAny::integer(perf_sendmmsg->i)); + if (perf_sendmmsg->j) p->set("gt_1000", SrsJsonAny::integer(perf_sendmmsg->j)); } return err; @@ -840,16 +840,16 @@ srs_error_t SrsStatistic::dumps_perf_gso(SrsJsonObject* obj) // h: <128 // i: <512 // j: >=512 - p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); - p->set("lt_3", SrsJsonAny::integer(perf_gso->b)); - p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); - p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); - p->set("lt_16", SrsJsonAny::integer(perf_gso->e)); - p->set("lt_32", SrsJsonAny::integer(perf_gso->f)); - p->set("lt_64", SrsJsonAny::integer(perf_gso->g)); - p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); - p->set("lt_512", SrsJsonAny::integer(perf_gso->i)); - p->set("gt_512", SrsJsonAny::integer(perf_gso->j)); + if (perf_gso->a) p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); + if (perf_gso->b) p->set("lt_3", SrsJsonAny::integer(perf_gso->b)); + if (perf_gso->c) p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); + if (perf_gso->d) p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); + if (perf_gso->e) p->set("lt_16", SrsJsonAny::integer(perf_gso->e)); + if (perf_gso->f) p->set("lt_32", SrsJsonAny::integer(perf_gso->f)); + if (perf_gso->g) p->set("lt_64", SrsJsonAny::integer(perf_gso->g)); + if (perf_gso->h) p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); + if (perf_gso->i) p->set("lt_512", SrsJsonAny::integer(perf_gso->i)); + if (perf_gso->j) p->set("gt_512", SrsJsonAny::integer(perf_gso->j)); } return err; diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index adc38f3fa..ea077b89b 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -131,8 +131,8 @@ #define SRS_PERF_MW_MIN_MSGS 8 #define SRS_PERF_MW_MIN_MSGS_REALTIME 4 // For RTC, use smaller wait queue. - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 4 - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 2 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 3 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 1 #endif /** * the default value of vhost for diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 34fd22900..e47dfdc68 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -24,6 +24,6 @@ #ifndef SRS_CORE_VERSION4_HPP #define SRS_CORE_VERSION4_HPP -#define SRS_VERSION4_REVISION 22 +#define SRS_VERSION4_REVISION 23 #endif From ba3d293bfd8850135603900b8fa1cf83710d3c5e Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 14:22:30 +0800 Subject: [PATCH 063/131] Refactor stat for frames --- trunk/src/app/srs_app_http_api.cpp | 6 +-- trunk/src/app/srs_app_statistic.cpp | 76 ++++++++++++++--------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index fd4e9b2bb..e3f36604c 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1622,12 +1622,12 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* data->set("query", p); p->set("target", SrsJsonAny::str(target.c_str())); - p->set("help", SrsJsonAny::str("?target=writev|sendmmsg|gso")); + p->set("help", SrsJsonAny::str("?target=frames|sendmmsg|gso")); } - if (target.empty() || target == "writev") { + if (target.empty() || target == "frames") { SrsJsonObject* p = SrsJsonAny::object(); - data->set("writev", p); + data->set("frames", p); if ((err = stat->dumps_perf_writev(p)) != srs_success) { int code = srs_error_code(err); srs_error_reset(err); return srs_api_response_code(w, r, code); diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 92284c329..3b122ff81 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -621,33 +621,33 @@ void SrsStatistic::perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) } // For perf iovs, the nb_iovs stat. - // a: <=2 - // b: <10 - // c: <20 - // d: <200 - // e: <300 - // f: <500 - // g: <700 - // h: <900 - // i: <1024 - // j: >=1024 - if (nb_iovs <= 2) { + // a: <3 + // b: <5 + // c: <9 + // d: <16 + // e: <32 + // f: <64 + // g: <128 + // h: <256 + // i: <1000 + // j: >=1000 + if (nb_iovs < 3) { perf_iovs->a++; - } else if (nb_iovs < 10) { + } else if (nb_iovs < 5) { perf_iovs->b++; - } else if (nb_iovs < 20) { + } else if (nb_iovs < 9) { perf_iovs->c++; - } else if (nb_iovs < 200) { + } else if (nb_iovs < 16) { perf_iovs->d++; - } else if (nb_iovs < 300) { + } else if (nb_iovs < 32) { perf_iovs->e++; - } else if (nb_iovs < 500) { + } else if (nb_iovs < 64) { perf_iovs->f++; - } else if (nb_iovs < 700) { + } else if (nb_iovs < 128) { perf_iovs->g++; - } else if (nb_iovs < 900) { + } else if (nb_iovs < 256) { perf_iovs->h++; - } else if (nb_iovs < 1024) { + } else if (nb_iovs < 1000) { perf_iovs->i++; } else { perf_iovs->j++; @@ -690,26 +690,26 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) obj->set("iovs", p); // For perf iovs, the nb_iovs stat. - // a: <=2 - // b: <10 - // c: <20 - // d: <200 - // e: <300 - // f: <500 - // g: <700 - // h: <900 - // i: <1024 - // j: >=1024 + // a: <3 + // b: <5 + // c: <9 + // d: <16 + // e: <32 + // f: <64 + // g: <128 + // h: <256 + // i: <1000 + // j: >=1000 if (perf_iovs->a) p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); - if (perf_iovs->b) p->set("lt_10", SrsJsonAny::integer(perf_iovs->b)); - if (perf_iovs->c) p->set("lt_20", SrsJsonAny::integer(perf_iovs->c)); - if (perf_iovs->d) p->set("lt_200", SrsJsonAny::integer(perf_iovs->d)); - if (perf_iovs->e) p->set("lt_300", SrsJsonAny::integer(perf_iovs->e)); - if (perf_iovs->f) p->set("lt_500", SrsJsonAny::integer(perf_iovs->f)); - if (perf_iovs->g) p->set("lt_700", SrsJsonAny::integer(perf_iovs->g)); - if (perf_iovs->h) p->set("lt_900", SrsJsonAny::integer(perf_iovs->h)); - if (perf_iovs->i) p->set("lt_1024", SrsJsonAny::integer(perf_iovs->i)); - if (perf_iovs->j) p->set("gt_1024", SrsJsonAny::integer(perf_iovs->j)); + if (perf_iovs->b) p->set("lt_5", SrsJsonAny::integer(perf_iovs->b)); + if (perf_iovs->c) p->set("lt_9", SrsJsonAny::integer(perf_iovs->c)); + if (perf_iovs->d) p->set("lt_16", SrsJsonAny::integer(perf_iovs->d)); + if (perf_iovs->e) p->set("lt_32", SrsJsonAny::integer(perf_iovs->e)); + if (perf_iovs->f) p->set("lt_64", SrsJsonAny::integer(perf_iovs->f)); + if (perf_iovs->g) p->set("lt_128", SrsJsonAny::integer(perf_iovs->g)); + if (perf_iovs->h) p->set("lt_256", SrsJsonAny::integer(perf_iovs->h)); + if (perf_iovs->i) p->set("lt_1000", SrsJsonAny::integer(perf_iovs->i)); + if (perf_iovs->j) p->set("gt_1000", SrsJsonAny::integer(perf_iovs->j)); } return err; From 8d5f91f777e64ddea922302677115780543bb4f0 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 18:15:07 +0800 Subject: [PATCH 064/131] For rtc player, use target to overwrite server, vhost and eip. --- trunk/research/players/js/srs.page.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/trunk/research/players/js/srs.page.js b/trunk/research/players/js/srs.page.js index 56ff81e45..3f3b1f6ca 100755 --- a/trunk/research/players/js/srs.page.js +++ b/trunk/research/players/js/srs.page.js @@ -207,6 +207,14 @@ function build_default_hls_url() { } function build_default_rtc_url(query) { + // Use target to overwrite server, vhost and eip. + console.log('?target=x.x.x.x to overwrite server, vhost and eip.'); + if (query.target) { + query.server = query.vhost = query.eip = query.target; + query.user_query.eip = query.target; + delete query.target; + } + var server = (!query.server)? window.location.hostname:query.server; var vhost = (!query.vhost)? window.location.hostname:query.vhost; var app = (!query.app)? "live":query.app; From de343d654762ed044bcf46263a73e8d7510af829 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 18:48:57 +0800 Subject: [PATCH 065/131] Add tool for GSO --- trunk/scripts/perf_gso.py | 35 +++++++++++++++++++++ trunk/src/app/srs_app_statistic.cpp | 48 ++++++++++++++--------------- 2 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 trunk/scripts/perf_gso.py diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py new file mode 100644 index 000000000..a1e329275 --- /dev/null +++ b/trunk/scripts/perf_gso.py @@ -0,0 +1,35 @@ +import urllib, sys, json + +url = "http://localhost:1985/api/v1/perf" +if len(sys.argv) > 1: + url = sys.argv[1] +print "Open %s"%(url) + +f = urllib.urlopen(url) +s = f.read() +f.close() +print "Repsonse %s"%(s) + +obj = json.loads(s) +keys = [3, 5, 9, 16, 32, 64, 128, 256, 1000] + +print "" +print("AVFrames"), +for k in keys: + k2 = 'lt_%s'%(k) + p = obj['data']['writev']['msgs'] + if k2 in p: + print(p[k2]), + else: + print(0), + +print "" +print("RTP-Packets"), +for k in keys: + k2 = 'lt_%s'%(k) + p = obj['data']['writev']['iovs'] + if k2 in p: + print(p[k2]), + else: + print(0), + diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 3b122ff81..a58d5f57a 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -673,16 +673,16 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) // h: <256 // i: <1000 // j: >=1000 - if (perf_msgs->a) p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); - if (perf_msgs->b) p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); - if (perf_msgs->c) p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); - if (perf_msgs->d) p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); - if (perf_msgs->e) p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); - if (perf_msgs->f) p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); - if (perf_msgs->g) p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); - if (perf_msgs->h) p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); - if (perf_msgs->i) p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); - if (perf_msgs->j) p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); + if (perf_msgs->a) p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); + if (perf_msgs->b) p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); + if (perf_msgs->c) p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); + if (perf_msgs->d) p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); + if (perf_msgs->e) p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); + if (perf_msgs->f) p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); + if (perf_msgs->g) p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); + if (perf_msgs->h) p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); + if (perf_msgs->i) p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); + if (perf_msgs->j) p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); } if (true) { @@ -700,16 +700,16 @@ srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) // h: <256 // i: <1000 // j: >=1000 - if (perf_iovs->a) p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); - if (perf_iovs->b) p->set("lt_5", SrsJsonAny::integer(perf_iovs->b)); - if (perf_iovs->c) p->set("lt_9", SrsJsonAny::integer(perf_iovs->c)); - if (perf_iovs->d) p->set("lt_16", SrsJsonAny::integer(perf_iovs->d)); - if (perf_iovs->e) p->set("lt_32", SrsJsonAny::integer(perf_iovs->e)); - if (perf_iovs->f) p->set("lt_64", SrsJsonAny::integer(perf_iovs->f)); - if (perf_iovs->g) p->set("lt_128", SrsJsonAny::integer(perf_iovs->g)); - if (perf_iovs->h) p->set("lt_256", SrsJsonAny::integer(perf_iovs->h)); - if (perf_iovs->i) p->set("lt_1000", SrsJsonAny::integer(perf_iovs->i)); - if (perf_iovs->j) p->set("gt_1000", SrsJsonAny::integer(perf_iovs->j)); + if (perf_iovs->a) p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); + if (perf_iovs->b) p->set("lt_5", SrsJsonAny::integer(perf_iovs->b)); + if (perf_iovs->c) p->set("lt_9", SrsJsonAny::integer(perf_iovs->c)); + if (perf_iovs->d) p->set("lt_16", SrsJsonAny::integer(perf_iovs->d)); + if (perf_iovs->e) p->set("lt_32", SrsJsonAny::integer(perf_iovs->e)); + if (perf_iovs->f) p->set("lt_64", SrsJsonAny::integer(perf_iovs->f)); + if (perf_iovs->g) p->set("lt_128", SrsJsonAny::integer(perf_iovs->g)); + if (perf_iovs->h) p->set("lt_256", SrsJsonAny::integer(perf_iovs->h)); + if (perf_iovs->i) p->set("lt_1000", SrsJsonAny::integer(perf_iovs->i)); + if (perf_iovs->j) p->set("gt_1000", SrsJsonAny::integer(perf_iovs->j)); } return err; @@ -840,14 +840,14 @@ srs_error_t SrsStatistic::dumps_perf_gso(SrsJsonObject* obj) // h: <128 // i: <512 // j: >=512 - if (perf_gso->a) p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); + if (perf_gso->a) p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); if (perf_gso->b) p->set("lt_3", SrsJsonAny::integer(perf_gso->b)); - if (perf_gso->c) p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); - if (perf_gso->d) p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); + if (perf_gso->c) p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); + if (perf_gso->d) p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); if (perf_gso->e) p->set("lt_16", SrsJsonAny::integer(perf_gso->e)); if (perf_gso->f) p->set("lt_32", SrsJsonAny::integer(perf_gso->f)); if (perf_gso->g) p->set("lt_64", SrsJsonAny::integer(perf_gso->g)); - if (perf_gso->h) p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); + if (perf_gso->h) p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); if (perf_gso->i) p->set("lt_512", SrsJsonAny::integer(perf_gso->i)); if (perf_gso->j) p->set("gt_512", SrsJsonAny::integer(perf_gso->j)); } From 7c3522dcb13b1bed5349368f6fe035236ca6b842 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 18:49:26 +0800 Subject: [PATCH 066/131] Add tool for GSO --- trunk/scripts/perf_gso.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 trunk/scripts/perf_gso.py diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py old mode 100644 new mode 100755 From 4be1d785b684bbd281fa0dc86903886d61c9d524 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 18:50:21 +0800 Subject: [PATCH 067/131] Add tool for GSO --- trunk/scripts/perf_gso.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index a1e329275..9df63a77c 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -1,3 +1,27 @@ +#!/usr/bin/python +''' +The MIT License (MIT) + +Copyright (c) 2013-2016 SRS(ossrs) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +''' + import urllib, sys, json url = "http://localhost:1985/api/v1/perf" From bda7bdee54487bd0c465763b8e16cea83379ee15 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 19:19:46 +0800 Subject: [PATCH 068/131] Change RTC realtime to 0 cache --- trunk/src/core/srs_core_performance.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index ea077b89b..7cafa055e 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -129,10 +129,10 @@ #ifdef SRS_PERF_QUEUE_COND_WAIT // For RTMP, use larger wait queue. #define SRS_PERF_MW_MIN_MSGS 8 - #define SRS_PERF_MW_MIN_MSGS_REALTIME 4 + #define SRS_PERF_MW_MIN_MSGS_REALTIME 0 // For RTC, use smaller wait queue. - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 3 - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 1 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 2 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 0 #endif /** * the default value of vhost for From 97cfae624c9d1eb13cbcfdbd268f5775f68711c1 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 19:23:15 +0800 Subject: [PATCH 069/131] Fix CentOS8 build warnings --- trunk/src/kernel/srs_kernel_flv.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 00e289feb..28b2d938b 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -383,7 +383,7 @@ void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payload ptr->nn_extra_payloads = nn_payloads; ptr->extra_payloads = new SrsSample[nn_payloads]; - memcpy(ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample)); + memcpy((void*)ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample)); } void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples) @@ -394,7 +394,7 @@ void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples) ptr->nn_samples = nn_samples; ptr->samples = new SrsSample[nn_samples]; - memcpy(ptr->samples, samples, nn_samples * sizeof(SrsSample)); + memcpy((void*)ptr->samples, samples, nn_samples * sizeof(SrsSample)); } #endif From 88b1e14db427d93c7baf36d673d9cd7a6c563049 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 19:30:35 +0800 Subject: [PATCH 070/131] Update perf api tool --- trunk/scripts/perf_gso.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 9df63a77c..5c6f92746 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -41,7 +41,10 @@ print "" print("AVFrames"), for k in keys: k2 = 'lt_%s'%(k) - p = obj['data']['writev']['msgs'] + if 'frames' in obj['data']: + p = obj['data']['frames']['msgs'] + else: + p = obj['data']['writev']['msgs'] if k2 in p: print(p[k2]), else: @@ -51,7 +54,10 @@ print "" print("RTP-Packets"), for k in keys: k2 = 'lt_%s'%(k) - p = obj['data']['writev']['iovs'] + if 'frames' in obj['data']: + p = obj['data']['frames']['iovs'] + else: + p = obj['data']['writev']['iovs'] if k2 in p: print(p[k2]), else: From 9d5c855727fe08c5c80020c79ca47079b9ce01b9 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 19:36:43 +0800 Subject: [PATCH 071/131] Update perf api tool --- trunk/scripts/perf_gso.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 5c6f92746..95ef027b5 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -38,7 +38,7 @@ obj = json.loads(s) keys = [3, 5, 9, 16, 32, 64, 128, 256, 1000] print "" -print("AVFrames"), +print("AV---Frames"), for k in keys: k2 = 'lt_%s'%(k) if 'frames' in obj['data']: From 8e4ef986298119b6de65b689a160cb53ebaa7644 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 20:12:14 +0800 Subject: [PATCH 072/131] For #307, correct the RTP packet stat. --- trunk/src/app/srs_app_rtc_conn.cpp | 25 ++++++++++++++++++------- trunk/src/app/srs_app_rtc_conn.hpp | 9 +++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index abee62bc0..811cad324 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -654,8 +654,9 @@ srs_error_t SrsRtcSenderThread::cycle() pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d packets, %d audios, %d extras, %d videos, %d samples, %d bytes", - msg_count, pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes); + srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes", + msg_count, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + pkts.nn_samples, pkts.nn_bytes); } } } @@ -674,8 +675,6 @@ srs_error_t SrsRtcSenderThread::send_messages( return srs_error_wrap(err, "messages to packets"); } - packets.nn_rtp_pkts = (int)packets.packets.size(); - #ifndef SRS_AUTO_OSX // If enabled GSO, send out some packets in a msghdr. if (packets.use_gso) { @@ -820,6 +819,9 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets mhdr->msg_hdr.msg_controllen = 0; mhdr->msg_len = 0; + // When we send out a packet, we commit a RTP packet. + packets.nn_rtp_pkts++; + if ((err = sender->sendmmsg(mhdr)) != srs_success) { return srs_error_wrap(err, "send msghdr"); } @@ -833,13 +835,12 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac { srs_error_t err = srs_success; - ISrsUdpSender* sender = skt->sender(); - // Previous handler, if has the same size, we can use GSO. mmsghdr* gso_mhdr = NULL; int gso_size = 0; int gso_encrypt = 0; int gso_cursor = 0; // GSO, N packets has same length, the final one may not. bool use_gso = false; bool gso_final = false; + ISrsUdpSender* sender = skt->sender(); int nn_packets = (int)packets.packets.size(); for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.packets[i]; @@ -950,7 +951,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac bool do_send = (i == nn_packets - 1 || gso_final || !use_gso); #if defined(SRS_DEBUG) - srs_trace("packet SSRC=%d, SN=%d, %d bytes", packet->rtp_header.get_ssrc(), + bool is_video = packet->rtp_header.get_payload_type() == video_payload_type; + srs_trace("Packet %s SSRC=%d, SN=%d, %d bytes", is_video? "Video":"Audio", packet->rtp_header.get_ssrc(), packet->rtp_header.get_sequence(), nn_packet); if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { @@ -988,6 +990,9 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #endif + // When we send out a packet, we commit a RTP packet. + packets.nn_rtp_pkts++; + if ((err = sender->sendmmsg(mhdr)) != srs_success) { return srs_error_wrap(err, "send msghdr"); } @@ -998,6 +1003,11 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } } +#if defined(SRS_DEBUG) + srs_trace("GSO packets, rtp %d/%d, videos %d/%d", packets.packets.size(), + packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras); +#endif + return err; } @@ -1816,6 +1826,7 @@ srs_error_t SrsUdpMuxSender::cycle() mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p++) { if (!p->msg_len) { + stat->perf_gso_on_packets(1); continue; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 89c46e916..2ffe75441 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -117,17 +117,26 @@ private: srs_error_t srtp_recv_init(); }; +// A group of RTP packets. class SrsRtcPackets { public: bool use_gso; bool should_merge_nalus; public: + // The total bytes of RTP packets. int nn_bytes; + // The RTP packets send out by sendmmsg or sendmsg. Note that if many packets group to + // one msghdr by GSO, it's only one RTP packet, because we only send once. int nn_rtp_pkts; + // For video, the samples or NALUs. int nn_samples; + // For audio, the generated extra audio packets. + // For example, when transcoding AAC to opus, may many extra payloads for a audio. int nn_extras; + // The original audio messages. int nn_audios; + // The original video messages. int nn_videos; public: std::vector packets; From a80084289b39266fa7a7023bf6237357e02fd7a8 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 20:12:33 +0800 Subject: [PATCH 073/131] Support debug --- trunk/auto/auto_headers.sh | 6 ++++++ trunk/auto/options.sh | 4 ++++ trunk/scripts/perf_gso.py | 2 +- trunk/src/core/srs_core.hpp | 5 +++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/trunk/auto/auto_headers.sh b/trunk/auto/auto_headers.sh index 84b64319b..d77325395 100755 --- a/trunk/auto/auto_headers.sh +++ b/trunk/auto/auto_headers.sh @@ -171,6 +171,12 @@ else srs_undefine_macro "SRS_AUTO_HAS_SENDMMSG" $SRS_AUTO_HEADERS_H fi +if [ $SRS_DEBUG = YES ]; then + srs_define_macro "SRS_AUTO_DEBUG" $SRS_AUTO_HEADERS_H +else + srs_undefine_macro "SRS_AUTO_DEBUG" $SRS_AUTO_HEADERS_H +fi + # prefix echo "" >> $SRS_AUTO_HEADERS_H echo "#define SRS_AUTO_PREFIX \"${SRS_PREFIX}\"" >> $SRS_AUTO_HEADERS_H diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 0e31b05fd..69293fce3 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -122,6 +122,7 @@ SRS_NASM=YES SRS_SRTP_ASM=YES SRS_SENDMMSG=YES SRS_HAS_SENDMMSG=YES +SRS_DEBUG=NO ##################################################################################### # menu @@ -162,6 +163,7 @@ Features: --prefix= The absolute installation path for srs. Default: $SRS_PREFIX --static Whether add '-static' to link options. --gcov Whether enable the GCOV compiler options. + --debug Whether enable the debug code, may hurt performance. --jobs[=N] Allow N jobs at once; infinite jobs with no arg. Used for make in the configure, for example, to make ffmpeg. --log-verbose Whether enable the log verbose level. default: no. @@ -293,6 +295,7 @@ function parse_user_option() { --log-info) SRS_LOG_INFO=YES ;; --log-trace) SRS_LOG_TRACE=YES ;; --gcov) SRS_GCOV=YES ;; + --debug) SRS_DEBUG=YES ;; --arm) SRS_CROSS_BUILD=YES ;; --mips) SRS_CROSS_BUILD=YES ;; @@ -623,6 +626,7 @@ function regenerate_options() { if [ $SRS_LOG_INFO = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --log-info"; fi if [ $SRS_LOG_TRACE = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --log-trace"; fi if [ $SRS_GCOV = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --gcov"; fi + if [ $SRS_DEBUG = YES ]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --debug"; fi if [[ $SRS_EXTRA_FLAGS != '' ]]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --extra-flags=\\\"$SRS_EXTRA_FLAGS\\\""; fi if [[ $SRS_BUILD_TAG != '' ]]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --build-tag=\\\"$SRS_BUILD_TAG\\\""; fi if [[ $SRS_TOOL_CC != '' ]]; then SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cc=$SRS_TOOL_CC"; fi diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 95ef027b5..75df5e527 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -35,7 +35,7 @@ f.close() print "Repsonse %s"%(s) obj = json.loads(s) -keys = [3, 5, 9, 16, 32, 64, 128, 256, 1000] +keys = [1, 3, 5, 9, 16, 32, 64, 256, 1000] print "" print("AV---Frames"), diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index c846214b2..725c1bff4 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -33,6 +33,11 @@ // The macros generated by configure script. #include +// Alias for debug. +#ifdef SRS_AUTO_DEBUG +#define SRS_DEBUG +#endif + // To convert macro values to string. // @see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification #define SRS_INTERNAL_STR(v) #v From 6cf9933bf38ccb3e24dff8b7f5e104bc8d7c3742 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 21:49:49 +0800 Subject: [PATCH 074/131] For #307, refine gperf api --- trunk/scripts/perf_gso.py | 36 ++- trunk/src/app/srs_app_http_api.cpp | 41 +++- trunk/src/app/srs_app_rtc_conn.cpp | 14 +- trunk/src/app/srs_app_statistic.cpp | 329 ++++++++------------------ trunk/src/app/srs_app_statistic.hpp | 42 +++- trunk/src/protocol/srs_rtmp_stack.cpp | 6 +- trunk/src/protocol/srs_rtmp_stack.hpp | 5 +- 7 files changed, 206 insertions(+), 267 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 75df5e527..7b9ef4749 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -35,16 +35,25 @@ f.close() print "Repsonse %s"%(s) obj = json.loads(s) -keys = [1, 3, 5, 9, 16, 32, 64, 256, 1000] + +# 2, 3, 5, 9, 16, 32, 64, 128, 256 +keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] print "" print("AV---Frames"), for k in keys: - k2 = 'lt_%s'%(k) - if 'frames' in obj['data']: - p = obj['data']['frames']['msgs'] + k2 = '%s'%(k) + p = obj['data']['avframes'] + if k2 in p: + print(p[k2]), else: - p = obj['data']['writev']['msgs'] + print(0), + +print "" +print("RTC--Frames"), +for k in keys: + k2 = '%s'%(k) + p = obj['data']['rtc'] if k2 in p: print(p[k2]), else: @@ -53,11 +62,18 @@ for k in keys: print "" print("RTP-Packets"), for k in keys: - k2 = 'lt_%s'%(k) - if 'frames' in obj['data']: - p = obj['data']['frames']['iovs'] - else: - p = obj['data']['writev']['iovs'] + k2 = '%s'%(k) + p = obj['data']['rtp'] + if k2 in p: + print(p[k2]), + else: + print(0), + +print "" +print("GSO-Packets"), +for k in keys: + k2 = '%s'%(k) + p = obj['data']['gso'] if k2 in p: print(p[k2]), else: diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index e3f36604c..6a83f7a8c 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1622,13 +1622,40 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* data->set("query", p); p->set("target", SrsJsonAny::str(target.c_str())); - p->set("help", SrsJsonAny::str("?target=frames|sendmmsg|gso")); + p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg")); } - if (target.empty() || target == "frames") { + if (target.empty() || target == "avframes") { SrsJsonObject* p = SrsJsonAny::object(); - data->set("frames", p); - if ((err = stat->dumps_perf_writev(p)) != srs_success) { + data->set("avframes", p); + if ((err = stat->dumps_perf_msgs(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + + if (target.empty() || target == "rtc") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("rtc", p); + if ((err = stat->dumps_perf_rtc_packets(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + + if (target.empty() || target == "rtp") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("rtp", p); + if ((err = stat->dumps_perf_rtp_packets(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + + if (target.empty() || target == "gso") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("gso", p); + if ((err = stat->dumps_perf_gso(p)) != srs_success) { int code = srs_error_code(err); srs_error_reset(err); return srs_api_response_code(w, r, code); } @@ -1643,10 +1670,10 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } - if (target.empty() || target == "gso") { + if (target.empty() || target == "writev_iovs") { SrsJsonObject* p = SrsJsonAny::object(); - data->set("gso", p); - if ((err = stat->dumps_perf_gso(p)) != srs_success) { + data->set("writev_iovs", p); + if ((err = stat->dumps_perf_writev_iovs(p)) != srs_success) { int code = srs_error_code(err); srs_error_reset(err); return srs_api_response_code(w, r, code); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 811cad324..4a00f0c22 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -649,7 +649,14 @@ srs_error_t SrsRtcSenderThread::cycle() srs_freep(msg); } - stat->perf_mw_on_msgs(msg_count, pkts.nn_bytes, pkts.nn_rtp_pkts); + // Stat the original RAW AV frame, maybe h264+aac. + stat->perf_on_msgs(msg_count); + // Stat the RTC packets, RAW AV frame, maybe h.264+opus. + stat->perf_on_rtc_packets(srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos); + // Stat the RAW RTP packets, which maybe group by GSO. + stat->perf_on_rtp_packets(pkts.packets.size()); + // Stat the RTP packets going into kernel. + stat->perf_gso_on_packets(pkts.nn_rtp_pkts); pprint->elapse(); if (pprint->can_print()) { @@ -957,6 +964,9 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* iov = mhdr->msg_hdr.msg_iov + j; + if (iov->iov_len <= 0) { + break; + } srs_trace("%s #%d/%d/%d, %d bytes, size %d/%d", (use_gso? "GSO":"RAW"), j, gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); } @@ -1004,7 +1014,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("GSO packets, rtp %d/%d, videos %d/%d", packets.packets.size(), + srs_trace("Summary packets, rtp %d/%d, videos %d/%d, audios %d/%d", packets.packets.size(), packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras); #endif diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index a58d5f57a..8c8d628cf 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -267,6 +267,8 @@ SrsStatistic::SrsStatistic() perf_msgs = new SrsStatisticCategory(); perf_sendmmsg = new SrsStatisticCategory(); perf_gso = new SrsStatisticCategory(); + perf_rtp = new SrsStatisticCategory(); + perf_rtc = new SrsStatisticCategory(); } SrsStatistic::~SrsStatistic() @@ -305,6 +307,8 @@ SrsStatistic::~SrsStatistic() srs_freep(perf_msgs); srs_freep(perf_sendmmsg); srs_freep(perf_gso); + srs_freep(perf_rtp); + srs_freep(perf_rtc); } SrsStatistic* SrsStatistic::instance() @@ -585,272 +589,131 @@ srs_error_t SrsStatistic::dumps_clients(SrsJsonArray* arr, int start, int count) return err; } -void SrsStatistic::perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) +void SrsStatistic::perf_on_msgs(int nb_msgs) { - // For perf msgs, the nb_msgs stat. - // a: <3 - // b: <5 - // c: <9 - // d: <16 - // e: <32 - // f: <64 - // g: <128 - // h: <256 - // i: <1000 - // j: >=1000 - if (nb_msgs < 3) { - perf_msgs->a++; - } else if (nb_msgs < 5) { - perf_msgs->b++; - } else if (nb_msgs < 9) { - perf_msgs->c++; - } else if (nb_msgs < 16) { - perf_msgs->d++; - } else if (nb_msgs < 32) { - perf_msgs->e++; - } else if (nb_msgs < 64) { - perf_msgs->f++; - } else if (nb_msgs < 128) { - perf_msgs->g++; - } else if (nb_msgs < 256) { - perf_msgs->h++; - } else if (nb_msgs < 1000) { - perf_msgs->i++; - } else { - perf_msgs->j++; - } - - // For perf iovs, the nb_iovs stat. - // a: <3 - // b: <5 - // c: <9 - // d: <16 - // e: <32 - // f: <64 - // g: <128 - // h: <256 - // i: <1000 - // j: >=1000 - if (nb_iovs < 3) { - perf_iovs->a++; - } else if (nb_iovs < 5) { - perf_iovs->b++; - } else if (nb_iovs < 9) { - perf_iovs->c++; - } else if (nb_iovs < 16) { - perf_iovs->d++; - } else if (nb_iovs < 32) { - perf_iovs->e++; - } else if (nb_iovs < 64) { - perf_iovs->f++; - } else if (nb_iovs < 128) { - perf_iovs->g++; - } else if (nb_iovs < 256) { - perf_iovs->h++; - } else if (nb_iovs < 1000) { - perf_iovs->i++; - } else { - perf_iovs->j++; - } + perf_on_packets(perf_msgs, nb_msgs); } -srs_error_t SrsStatistic::dumps_perf_writev(SrsJsonObject* obj) +srs_error_t SrsStatistic::dumps_perf_msgs(SrsJsonObject* obj) { - srs_error_t err = srs_success; - - if (true) { - SrsJsonObject* p = SrsJsonAny::object(); - obj->set("msgs", p); - - // For perf msgs, the nb_msgs stat. - // a: <3 - // b: <5 - // c: <9 - // d: <16 - // e: <32 - // f: <64 - // g: <128 - // h: <256 - // i: <1000 - // j: >=1000 - if (perf_msgs->a) p->set("lt_3", SrsJsonAny::integer(perf_msgs->a)); - if (perf_msgs->b) p->set("lt_5", SrsJsonAny::integer(perf_msgs->b)); - if (perf_msgs->c) p->set("lt_9", SrsJsonAny::integer(perf_msgs->c)); - if (perf_msgs->d) p->set("lt_16", SrsJsonAny::integer(perf_msgs->d)); - if (perf_msgs->e) p->set("lt_32", SrsJsonAny::integer(perf_msgs->e)); - if (perf_msgs->f) p->set("lt_64", SrsJsonAny::integer(perf_msgs->f)); - if (perf_msgs->g) p->set("lt_128", SrsJsonAny::integer(perf_msgs->g)); - if (perf_msgs->h) p->set("lt_256", SrsJsonAny::integer(perf_msgs->h)); - if (perf_msgs->i) p->set("lt_1000", SrsJsonAny::integer(perf_msgs->i)); - if (perf_msgs->j) p->set("gt_1000", SrsJsonAny::integer(perf_msgs->j)); - } - - if (true) { - SrsJsonObject* p = SrsJsonAny::object(); - obj->set("iovs", p); - - // For perf iovs, the nb_iovs stat. - // a: <3 - // b: <5 - // c: <9 - // d: <16 - // e: <32 - // f: <64 - // g: <128 - // h: <256 - // i: <1000 - // j: >=1000 - if (perf_iovs->a) p->set("lt_3", SrsJsonAny::integer(perf_iovs->a)); - if (perf_iovs->b) p->set("lt_5", SrsJsonAny::integer(perf_iovs->b)); - if (perf_iovs->c) p->set("lt_9", SrsJsonAny::integer(perf_iovs->c)); - if (perf_iovs->d) p->set("lt_16", SrsJsonAny::integer(perf_iovs->d)); - if (perf_iovs->e) p->set("lt_32", SrsJsonAny::integer(perf_iovs->e)); - if (perf_iovs->f) p->set("lt_64", SrsJsonAny::integer(perf_iovs->f)); - if (perf_iovs->g) p->set("lt_128", SrsJsonAny::integer(perf_iovs->g)); - if (perf_iovs->h) p->set("lt_256", SrsJsonAny::integer(perf_iovs->h)); - if (perf_iovs->i) p->set("lt_1000", SrsJsonAny::integer(perf_iovs->i)); - if (perf_iovs->j) p->set("gt_1000", SrsJsonAny::integer(perf_iovs->j)); - } - - return err; + return dumps_perf(perf_msgs, obj); } -void SrsStatistic::perf_sendmmsg_on_packets(int nb_msgs) +void SrsStatistic::perf_on_rtc_packets(int nb_packets) { - // For perf msgs, the nb_msgs stat. - // a: =1 - // b: <10 - // c: <100 - // d: <200 - // e: <300 - // f: <400 - // g: <500 - // h: <600 - // i: <1000 - // j: >=1000 - if (nb_msgs == 1) { - perf_sendmmsg->a++; - } else if (nb_msgs < 10) { - perf_sendmmsg->b++; - } else if (nb_msgs < 100) { - perf_sendmmsg->c++; - } else if (nb_msgs < 200) { - perf_sendmmsg->d++; - } else if (nb_msgs < 300) { - perf_sendmmsg->e++; - } else if (nb_msgs < 400) { - perf_sendmmsg->f++; - } else if (nb_msgs < 500) { - perf_sendmmsg->g++; - } else if (nb_msgs < 600) { - perf_sendmmsg->h++; - } else if (nb_msgs < 1000) { - perf_sendmmsg->i++; - } else { - perf_sendmmsg->j++; - } + perf_on_packets(perf_rtc, nb_packets); +} + +srs_error_t SrsStatistic::dumps_perf_rtc_packets(SrsJsonObject* obj) +{ + return dumps_perf(perf_rtc, obj); +} + +void SrsStatistic::perf_on_rtp_packets(int nb_packets) +{ + perf_on_packets(perf_rtp, nb_packets); +} + +srs_error_t SrsStatistic::dumps_perf_rtp_packets(SrsJsonObject* obj) +{ + return dumps_perf(perf_rtp, obj); +} + +void SrsStatistic::perf_gso_on_packets(int nb_packets) +{ + perf_on_packets(perf_gso, nb_packets); +} + +srs_error_t SrsStatistic::dumps_perf_gso(SrsJsonObject* obj) +{ + return dumps_perf(perf_gso, obj); +} + +void SrsStatistic::perf_on_writev_iovs(int nb_iovs) +{ + perf_on_packets(perf_iovs, nb_iovs); +} + +srs_error_t SrsStatistic::dumps_perf_writev_iovs(SrsJsonObject* obj) +{ + return dumps_perf(perf_iovs, obj); +} + +void SrsStatistic::perf_sendmmsg_on_packets(int nb_packets) +{ + perf_on_packets(perf_sendmmsg, nb_packets); } srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) { - srs_error_t err = srs_success; - - if (true) { - SrsJsonObject* p = SrsJsonAny::object(); - obj->set("msgs", p); - - // For perf msgs, the nb_msgs stat. - // a: =1 - // b: <10 - // c: <100 - // d: <200 - // e: <300 - // f: <400 - // g: <500 - // h: <600 - // i: <1000 - // j: >=1000 - if (perf_sendmmsg->a) p->set("lt_2", SrsJsonAny::integer(perf_sendmmsg->a)); - if (perf_sendmmsg->b) p->set("lt_10", SrsJsonAny::integer(perf_sendmmsg->b)); - if (perf_sendmmsg->c) p->set("lt_100", SrsJsonAny::integer(perf_sendmmsg->c)); - if (perf_sendmmsg->d) p->set("lt_200", SrsJsonAny::integer(perf_sendmmsg->d)); - if (perf_sendmmsg->e) p->set("lt_300", SrsJsonAny::integer(perf_sendmmsg->e)); - if (perf_sendmmsg->f) p->set("lt_400", SrsJsonAny::integer(perf_sendmmsg->f)); - if (perf_sendmmsg->g) p->set("lt_500", SrsJsonAny::integer(perf_sendmmsg->g)); - if (perf_sendmmsg->h) p->set("lt_600", SrsJsonAny::integer(perf_sendmmsg->h)); - if (perf_sendmmsg->i) p->set("lt_1000", SrsJsonAny::integer(perf_sendmmsg->i)); - if (perf_sendmmsg->j) p->set("gt_1000", SrsJsonAny::integer(perf_sendmmsg->j)); - } - - return err; + return dumps_perf(perf_sendmmsg, obj); } -void SrsStatistic::perf_gso_on_packets(int nb_msgs) +void SrsStatistic::perf_on_packets(SrsStatisticCategory* p, int nb_msgs) { - // For perf msgs, the nb_msgs stat. - // a: =1 + // The range for stat: + // 2, 3, 5, 9, 16, 32, 64, 128, 256 + // that is: + // a: <2 // b: <3 - // c: <6 + // c: <5 // d: <9 // e: <16 // f: <32 // g: <64 // h: <128 - // i: <512 - // j: >=512 - if (nb_msgs == 1) { - perf_gso->a++; + // i: <256 + // j: >=256 + if (nb_msgs < 2) { + p->a++; } else if (nb_msgs < 3) { - perf_gso->b++; - } else if (nb_msgs < 6) { - perf_gso->c++; + p->b++; + } else if (nb_msgs < 5) { + p->c++; } else if (nb_msgs < 9) { - perf_gso->d++; + p->d++; } else if (nb_msgs < 16) { - perf_gso->e++; + p->e++; } else if (nb_msgs < 32) { - perf_gso->f++; + p->f++; } else if (nb_msgs < 64) { - perf_gso->g++; + p->g++; } else if (nb_msgs < 128) { - perf_gso->h++; - } else if (nb_msgs < 512) { - perf_gso->i++; + p->h++; + } else if (nb_msgs < 256) { + p->i++; } else { - perf_gso->j++; + p->j++; } } -srs_error_t SrsStatistic::dumps_perf_gso(SrsJsonObject* obj) +srs_error_t SrsStatistic::dumps_perf(SrsStatisticCategory* p, SrsJsonObject* obj) { srs_error_t err = srs_success; - if (true) { - SrsJsonObject* p = SrsJsonAny::object(); - obj->set("msgs", p); - - // For perf msgs, the nb_msgs stat. - // a: =1 - // b: <3 - // c: <6 - // d: <9 - // e: <16 - // f: <32 - // g: <64 - // h: <128 - // i: <512 - // j: >=512 - if (perf_gso->a) p->set("lt_2", SrsJsonAny::integer(perf_gso->a)); - if (perf_gso->b) p->set("lt_3", SrsJsonAny::integer(perf_gso->b)); - if (perf_gso->c) p->set("lt_6", SrsJsonAny::integer(perf_gso->c)); - if (perf_gso->d) p->set("lt_9", SrsJsonAny::integer(perf_gso->d)); - if (perf_gso->e) p->set("lt_16", SrsJsonAny::integer(perf_gso->e)); - if (perf_gso->f) p->set("lt_32", SrsJsonAny::integer(perf_gso->f)); - if (perf_gso->g) p->set("lt_64", SrsJsonAny::integer(perf_gso->g)); - if (perf_gso->h) p->set("lt_128", SrsJsonAny::integer(perf_gso->h)); - if (perf_gso->i) p->set("lt_512", SrsJsonAny::integer(perf_gso->i)); - if (perf_gso->j) p->set("gt_512", SrsJsonAny::integer(perf_gso->j)); - } + // The range for stat: + // 2, 3, 5, 9, 16, 32, 64, 128, 256 + // that is: + // a: <2 + // b: <3 + // c: <5 + // d: <9 + // e: <16 + // f: <32 + // g: <64 + // h: <128 + // i: <256 + // j: >=256 + if (p->a) obj->set("lt_2", SrsJsonAny::integer(p->a)); + if (p->b) obj->set("lt_3", SrsJsonAny::integer(p->b)); + if (p->c) obj->set("lt_5", SrsJsonAny::integer(p->c)); + if (p->d) obj->set("lt_9", SrsJsonAny::integer(p->d)); + if (p->e) obj->set("lt_16", SrsJsonAny::integer(p->e)); + if (p->f) obj->set("lt_32", SrsJsonAny::integer(p->f)); + if (p->g) obj->set("lt_64", SrsJsonAny::integer(p->g)); + if (p->h) obj->set("lt_128", SrsJsonAny::integer(p->h)); + if (p->i) obj->set("lt_256", SrsJsonAny::integer(p->i)); + if (p->j) obj->set("gt_256", SrsJsonAny::integer(p->j)); return err; } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index ae73f49de..4626e2d82 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -170,6 +170,8 @@ private: SrsStatisticCategory* perf_msgs; SrsStatisticCategory* perf_sendmmsg; SrsStatisticCategory* perf_gso; + SrsStatisticCategory* perf_rtp; + SrsStatisticCategory* perf_rtc; private: SrsStatistic(); virtual ~SrsStatistic(); @@ -228,21 +230,39 @@ public: // @param count the max count of clients to dump. virtual srs_error_t dumps_clients(SrsJsonArray* arr, int start, int count); public: - // Stat for packets merged written, nb_msgs is the number of RTMP messages, - // bytes_msgs is the total bytes of RTMP messages, nb_iovs is the total number of iovec. - virtual void perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs); - // Dumps the perf statistic data for TCP writev, for performance analysis. - virtual srs_error_t dumps_perf_writev(SrsJsonObject* obj); + // Stat for packets merged written, nb_msgs is the number of RTMP messages. + // For example, publish by FFMPEG, Audio and Video frames. + virtual void perf_on_msgs(int nb_msgs); + virtual srs_error_t dumps_perf_msgs(SrsJsonObject* obj); public: - // Stat for packets UDP sendmmsg, nb_msgs is the vlen for sendmmsg. - virtual void perf_sendmmsg_on_packets(int nb_msgs); - // Dumps the perf statistic data for UDP sendmmsg, for performance analysis. - virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); + // Stat for packets merged written, nb_packets is the number of RTC packets. + // For example, a RTMP/AAC audio packet maybe transcoded to two RTC/opus packets. + virtual void perf_on_rtc_packets(int nb_packets); + virtual srs_error_t dumps_perf_rtc_packets(SrsJsonObject* obj); public: - // Stat for packets UDP GSO, nb_msgs is the vlen for sendmmsg. - virtual void perf_gso_on_packets(int nb_msgs); + // Stat for packets merged written, nb_packets is the number of RTP packets. + // For example, a RTC/opus packet maybe package to three RTP packets. + virtual void perf_on_rtp_packets(int nb_packets); + // Dumps the perf statistic data for RTP packets, for performance analysis. + virtual srs_error_t dumps_perf_rtp_packets(SrsJsonObject* obj); +public: + // Stat for packets UDP GSO, nb_packets is the merged RTP packets. + // For example, three RTP/audio packets maybe GSO to one msghdr. + virtual void perf_gso_on_packets(int nb_packets); // Dumps the perf statistic data for UDP GSO, for performance analysis. virtual srs_error_t dumps_perf_gso(SrsJsonObject* obj); +public: + // Stat for TCP writev, nb_iovs is the total number of iovec. + virtual void perf_on_writev_iovs(int nb_iovs); + virtual srs_error_t dumps_perf_writev_iovs(SrsJsonObject* obj); +public: + // Stat for packets UDP sendmmsg, nb_packets is the vlen for sendmmsg. + virtual void perf_sendmmsg_on_packets(int nb_packets); + // Dumps the perf statistic data for UDP sendmmsg, for performance analysis. + virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); +private: + virtual void perf_on_packets(SrsStatisticCategory* p, int nb_msgs); + virtual srs_error_t dumps_perf(SrsStatisticCategory* p, SrsJsonObject* obj); private: virtual SrsStatisticVhost* create_vhost(SrsRequest* req); virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req); diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 835746805..4b11e5ec3 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -548,7 +548,8 @@ srs_error_t SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msg // Notify about perf stat. if (perf) { - perf->perf_mw_on_msgs(nb_msgs_merged_written, bytes_msgs_merged_written, iov_index); + perf->perf_on_msgs(nb_msgs_merged_written); + perf->perf_on_writev_iovs(iov_index); nb_msgs_merged_written = 0; bytes_msgs_merged_written = 0; } @@ -576,7 +577,8 @@ srs_error_t SrsProtocol::do_send_messages(SrsSharedPtrMessage** msgs, int nb_msg // Notify about perf stat. if (perf) { - perf->perf_mw_on_msgs(nb_msgs_merged_written, bytes_msgs_merged_written, iov_index); + perf->perf_on_msgs(nb_msgs_merged_written); + perf->perf_on_writev_iovs(iov_index); nb_msgs_merged_written = 0; bytes_msgs_merged_written = 0; } diff --git a/trunk/src/protocol/srs_rtmp_stack.hpp b/trunk/src/protocol/srs_rtmp_stack.hpp index eea0c5a50..6f311383f 100644 --- a/trunk/src/protocol/srs_rtmp_stack.hpp +++ b/trunk/src/protocol/srs_rtmp_stack.hpp @@ -155,8 +155,9 @@ public: virtual ~ISrsProtocolPerf(); public: // Stat for packets merged written, nb_msgs is the number of RTMP messages, - // bytes_msgs is the total bytes of RTMP messages, nb_iovs is the total number of iovec. - virtual void perf_mw_on_msgs(int nb_msgs, int bytes_msgs, int nb_iovs) = 0; + virtual void perf_on_msgs(int nb_msgs) = 0; + // Stat for TCP writev, nb_iovs is the total number of iovec. + virtual void perf_on_writev_iovs(int nb_iovs) = 0; }; // The protocol provides the rtmp-message-protocol services, From 649f2042daa310c58a873b743c033d10f1783c4d Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 14 Apr 2020 22:16:14 +0800 Subject: [PATCH 075/131] Update perf tool --- trunk/scripts/perf_gso.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 7b9ef4749..560763e4c 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -25,8 +25,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import urllib, sys, json url = "http://localhost:1985/api/v1/perf" -if len(sys.argv) > 1: - url = sys.argv[1] +if len(sys.argv) < 2: + print "Usage: %s "%(sys.argv[0]) + print "For example:" + print " %s http://localhost:1985/api/v1/perf"%(sys.argv[0]) + sys.exit(-1) + +url = sys.argv[1] print "Open %s"%(url) f = urllib.urlopen(url) From dd7b5cf53f583d77a9a765618002b864d2db4566 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 06:44:09 +0800 Subject: [PATCH 076/131] Fix GSO stat bug --- trunk/src/app/srs_app_rtc_conn.cpp | 4 +--- trunk/src/app/srs_app_statistic.cpp | 2 +- trunk/src/app/srs_app_statistic.hpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 4a00f0c22..6cb23f552 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -656,7 +656,7 @@ srs_error_t SrsRtcSenderThread::cycle() // Stat the RAW RTP packets, which maybe group by GSO. stat->perf_on_rtp_packets(pkts.packets.size()); // Stat the RTP packets going into kernel. - stat->perf_gso_on_packets(pkts.nn_rtp_pkts); + stat->perf_on_gso_packets(pkts.nn_rtp_pkts); pprint->elapse(); if (pprint->can_print()) { @@ -1836,7 +1836,6 @@ srs_error_t SrsUdpMuxSender::cycle() mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p++) { if (!p->msg_len) { - stat->perf_gso_on_packets(1); continue; } @@ -1845,7 +1844,6 @@ srs_error_t SrsUdpMuxSender::cycle() p->msg_len = 0; gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; - stat->perf_gso_on_packets(real_iovs); } } diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 8c8d628cf..ccbdabfe8 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -619,7 +619,7 @@ srs_error_t SrsStatistic::dumps_perf_rtp_packets(SrsJsonObject* obj) return dumps_perf(perf_rtp, obj); } -void SrsStatistic::perf_gso_on_packets(int nb_packets) +void SrsStatistic::perf_on_gso_packets(int nb_packets) { perf_on_packets(perf_gso, nb_packets); } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 4626e2d82..0926fce0c 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -248,7 +248,7 @@ public: public: // Stat for packets UDP GSO, nb_packets is the merged RTP packets. // For example, three RTP/audio packets maybe GSO to one msghdr. - virtual void perf_gso_on_packets(int nb_packets); + virtual void perf_on_gso_packets(int nb_packets); // Dumps the perf statistic data for UDP GSO, for performance analysis. virtual srs_error_t dumps_perf_gso(SrsJsonObject* obj); public: From c143c80fd644e3a78d4e7dc19532693b4b9adb1a Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 07:10:41 +0800 Subject: [PATCH 077/131] Fix GSO stat bug --- trunk/scripts/perf_gso.py | 12 ++++++++---- trunk/src/app/srs_app_rtc_conn.cpp | 10 ++++++++-- trunk/src/app/srs_app_statistic.cpp | 6 ++++++ trunk/src/app/srs_app_statistic.hpp | 2 ++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 560763e4c..707e6c6b5 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -46,41 +46,45 @@ keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt print "" print("AV---Frames"), +p = obj['data']['avframes'] for k in keys: k2 = '%s'%(k) - p = obj['data']['avframes'] if k2 in p: print(p[k2]), else: print(0), +print(p['nn']), print "" print("RTC--Frames"), +p = obj['data']['rtc'] for k in keys: k2 = '%s'%(k) - p = obj['data']['rtc'] if k2 in p: print(p[k2]), else: print(0), +print(p['nn']), print "" print("RTP-Packets"), +p = obj['data']['rtp'] for k in keys: k2 = '%s'%(k) - p = obj['data']['rtp'] if k2 in p: print(p[k2]), else: print(0), +print(p['nn']), print "" print("GSO-Packets"), +p = obj['data']['gso'] for k in keys: k2 = '%s'%(k) - p = obj['data']['gso'] if k2 in p: print(p[k2]), else: print(0), +print(p['nn']), diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 6cb23f552..a01e6305c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -652,11 +652,17 @@ srs_error_t SrsRtcSenderThread::cycle() // Stat the original RAW AV frame, maybe h264+aac. stat->perf_on_msgs(msg_count); // Stat the RTC packets, RAW AV frame, maybe h.264+opus. - stat->perf_on_rtc_packets(srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos); + int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; + stat->perf_on_rtc_packets(nn_rtc_packets); // Stat the RAW RTP packets, which maybe group by GSO. stat->perf_on_rtp_packets(pkts.packets.size()); // Stat the RTP packets going into kernel. stat->perf_on_gso_packets(pkts.nn_rtp_pkts); +#if defined(SRS_DEBUG) + srs_trace("RTC PLAY packets, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes", + msg_count, nn_rtc_packets, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + pkts.nn_samples, pkts.nn_bytes); +#endif pprint->elapse(); if (pprint->can_print()) { @@ -1014,7 +1020,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("Summary packets, rtp %d/%d, videos %d/%d, audios %d/%d", packets.packets.size(), + srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d", packets.packets.size(), packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras); #endif diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index ccbdabfe8..01abcd446 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -236,6 +236,8 @@ srs_error_t SrsStatisticClient::dumps(SrsJsonObject* obj) SrsStatisticCategory::SrsStatisticCategory() { + nn = 0; + a = 0; b = 0; c = 0; @@ -685,6 +687,8 @@ void SrsStatistic::perf_on_packets(SrsStatisticCategory* p, int nb_msgs) } else { p->j++; } + + p->nn += nb_msgs; } srs_error_t SrsStatistic::dumps_perf(SrsStatisticCategory* p, SrsJsonObject* obj) @@ -715,6 +719,8 @@ srs_error_t SrsStatistic::dumps_perf(SrsStatisticCategory* p, SrsJsonObject* obj if (p->i) obj->set("lt_256", SrsJsonAny::integer(p->i)); if (p->j) obj->set("gt_256", SrsJsonAny::integer(p->j)); + obj->set("nn", SrsJsonAny::integer(p->nn)); + return err; } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 0926fce0c..0d9905f75 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -124,6 +124,8 @@ public: class SrsStatisticCategory { +public: + uint64_t nn; public: uint64_t a; uint64_t b; From 6e9e0d6ce3c6543050799de00e090074d02429ed Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 10:35:38 +0800 Subject: [PATCH 078/131] Fix build script --- trunk/auto/depends.sh | 20 +++++++++++--------- trunk/auto/options.sh | 1 + trunk/src/app/srs_app_http_api.cpp | 10 +++++++++- trunk/src/app/srs_app_statistic.hpp | 3 +++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index f2d3e378c..8fd54333c 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -84,15 +84,6 @@ function Ubuntu_prepare() echo "The unzip is installed." fi - if [[ $SRS_NASM == YES ]]; then - nasm -v >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then - echo "Installing nasm." - require_sudoer "sudo apt-get install -y --force-yes nasm" - sudo apt-get install -y --force-yes nasm; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi - echo "The nasm is installed." - fi - fi - if [[ $SRS_VALGRIND == YES ]]; then valgrind --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then echo "Installing valgrind." @@ -281,6 +272,10 @@ function OSX_prepare() echo "install unzip success" fi + pkg-config --version >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + echo "Please install pkg-config"; exit -1; + fi + echo "OSX install tools success" return 0 } @@ -614,9 +609,16 @@ fi ##################################################################################### if [[ $SRS_EXPORT_LIBRTMP_PROJECT == NO && $SRS_RTC == YES ]]; then FFMPEG_OPTIONS="" + + # If disable nasm, disable all ASMs. if [[ $SRS_NASM == NO ]]; then FFMPEG_OPTIONS="--disable-asm --disable-x86asm --disable-inline-asm" fi + # If no nasm, we disable the x86asm. + nasm -v >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then + FFMPEG_OPTIONS="--disable-x86asm" + fi + if [[ -f ${SRS_OBJS}/${SRS_PLATFORM}/ffmpeg/lib/libavcodec.a ]]; then echo "The ffmpeg-4.2-fit is ok."; else diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 69293fce3..f2b0cb7e6 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -569,6 +569,7 @@ function apply_user_detail_options() { # Detect whether has sendmmsg. # @see http://man7.org/linux/man-pages/man2/sendmmsg.2.html + mkdir -p ${SRS_OBJS} && echo "#include " > ${SRS_OBJS}/_tmp_sendmmsg_detect.c echo "int main(int argc, char** argv) {" >> ${SRS_OBJS}/_tmp_sendmmsg_detect.c echo " struct mmsghdr hdr;" >> ${SRS_OBJS}/_tmp_sendmmsg_detect.c diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 6a83f7a8c..fdfbf8747 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1615,14 +1615,22 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* SrsStatistic* stat = SrsStatistic::instance(); string target = r->query_get("target"); - srs_trace("query target=%s", target.c_str()); + string reset = r->query_get("reset"); + srs_trace("query target=%s, reset=%s", target.c_str(), reset.c_str()); if (true) { SrsJsonObject* p = SrsJsonAny::object(); data->set("query", p); p->set("target", SrsJsonAny::str(target.c_str())); + p->set("reset", SrsJsonAny::str(reset.c_str())); p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg")); + p->set("help2", SrsJsonAny::str("?reset=all")); + } + + if (!reset.empty()) { + stat->reset_perf(); + return srs_api_response(w, r, obj->dumps()); } if (target.empty() || target == "avframes") { diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 0d9905f75..c0344989f 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -262,6 +262,9 @@ public: virtual void perf_sendmmsg_on_packets(int nb_packets); // Dumps the perf statistic data for UDP sendmmsg, for performance analysis. virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); +public: + // Reset all perf stat data. + virtual void reset_perf(); private: virtual void perf_on_packets(SrsStatisticCategory* p, int nb_msgs); virtual srs_error_t dumps_perf(SrsStatisticCategory* p, SrsJsonObject* obj); From 095e7c5a4ea08a33324a91d8daef2decc0fc5349 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 10:36:39 +0800 Subject: [PATCH 079/131] Fix build script --- trunk/auto/depends.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 8fd54333c..c8817eb67 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -162,13 +162,6 @@ function Centos_prepare() echo "The unzip is installed." fi - nasm -v >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then - echo "Installing nasm." - require_sudoer "sudo yum install -y nasm" - sudo yum install -y nasm; ret=$?; if [[ 0 -ne $ret ]]; then return $ret; fi - echo "The nasm is installed." - fi - if [[ $SRS_VALGRIND == YES ]]; then valgrind --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then echo "Installing valgrind." From ab53c34945a1b9f00d236a761339ab03a7992486 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 10:44:26 +0800 Subject: [PATCH 080/131] For #307: Change the RTP payload to 1400 --- trunk/src/app/srs_app_rtc_conn.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index a01e6305c..973270204 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -60,6 +60,12 @@ using namespace std; #include #include +// The RTP payload max size, reserved some paddings for SRTP as such: +// kRtpPacketSize = kRtpMaxPayloadSize + paddings +// For example, if kRtpPacketSize is 1500, recommend to set kRtpMaxPayloadSize to 1400, +// which reserves 100 bytes for SRTP or paddings. +const int kRtpMaxPayloadSize = kRtpPacketSize - 100; + static bool is_stun(const uint8_t* data, const int size) { return data != NULL && size > 0 && (data[0] == 0 || data[0] == 1); @@ -767,7 +773,6 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( continue; } - const int kRtpMaxPayloadSize = 1200; if (sample->size <= kRtpMaxPayloadSize) { if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); @@ -1052,7 +1057,6 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac return err; } - const int kRtpMaxPayloadSize = 1200; if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. SrsRtpPacket2* packet = new SrsRtpPacket2(); From b5f2c842feb6778c76336a34b06ce47bf45c323f Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 10:50:56 +0800 Subject: [PATCH 081/131] Fix perf api bug --- trunk/src/app/srs_app_statistic.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 01abcd446..98c7ec8ab 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -651,6 +651,23 @@ srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) return dumps_perf(perf_sendmmsg, obj); } +void SrsStatistic::reset_perf() +{ + srs_freep(perf_iovs); + srs_freep(perf_msgs); + srs_freep(perf_sendmmsg); + srs_freep(perf_gso); + srs_freep(perf_rtp); + srs_freep(perf_rtc); + + perf_iovs = new SrsStatisticCategory(); + perf_msgs = new SrsStatisticCategory(); + perf_sendmmsg = new SrsStatisticCategory(); + perf_gso = new SrsStatisticCategory(); + perf_rtp = new SrsStatisticCategory(); + perf_rtc = new SrsStatisticCategory(); +} + void SrsStatistic::perf_on_packets(SrsStatisticCategory* p, int nb_msgs) { // The range for stat: From bfc70d648210df0c75119a09df0fd725deb2015d Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 12:05:27 +0800 Subject: [PATCH 082/131] For #307: Change the RTP payload to 1300 --- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 973270204..c890d5866 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -64,7 +64,7 @@ using namespace std; // kRtpPacketSize = kRtpMaxPayloadSize + paddings // For example, if kRtpPacketSize is 1500, recommend to set kRtpMaxPayloadSize to 1400, // which reserves 100 bytes for SRTP or paddings. -const int kRtpMaxPayloadSize = kRtpPacketSize - 100; +const int kRtpMaxPayloadSize = kRtpPacketSize - 200; static bool is_stun(const uint8_t* data, const int size) { From 6869ccca50616d76527fd8cb5e458e1af300ac9e Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 14:19:00 +0800 Subject: [PATCH 083/131] Fix RTP padding bug --- trunk/src/kernel/srs_kernel_rtp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index ae044d4a2..83dcf6071 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -97,7 +97,7 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream) uint8_t v = 0x80 | cc; if (padding) { - v |= 0x40; + v |= 0x20; } if (extension) { v |= 0x10; @@ -192,7 +192,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) if (!buf->require(padding)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", padding); } - memset(buf->data(), padding, padding); + memset(buf->data() + buf->pos(), padding, padding); buf->skip(padding); } From bbdd2d7eed9fc1e60d9d02bbd3caf5080715a5c3 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 15:58:17 +0800 Subject: [PATCH 084/131] For #307, support padding for GSO --- trunk/conf/full.conf | 4 +++ trunk/src/app/srs_app_config.cpp | 20 ++++++++++- trunk/src/app/srs_app_config.hpp | 3 ++ trunk/src/app/srs_app_rtc_conn.cpp | 55 +++++++++++++++++++++--------- trunk/src/app/srs_app_rtc_conn.hpp | 3 ++ 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 581e4daa3..66a8a27ab 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -443,6 +443,10 @@ rtc_server { # @remark Linux 4.18+ only, for other OS always disabled. # default: on gso on; + # Whether pad first packet for GSO for padding bytes. + # If 0, disable padding for GSO. + # default: 0 + padding 0; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 956bc99b0..85c70f87b 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3618,7 +3618,8 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" - && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus") { + && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus" + && n != "padding") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4840,6 +4841,23 @@ bool SrsConfig::get_rtc_server_gso2() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +int SrsConfig::get_rtc_server_padding() +{ + static int DEFAULT = 0; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("padding"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return srs_min(16, ::atoi(conf->arg0().c_str())); +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 96524c33a..8d31ef86e 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -535,6 +535,9 @@ public: virtual bool get_rtc_server_gso(); private: virtual bool get_rtc_server_gso2(); +public: + virtual int get_rtc_server_padding(); + public: SrsConfDirective* get_rtc(std::string vhost); bool get_rtc_enabled(std::string vhost); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c890d5866..c6e585665 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -468,6 +468,7 @@ SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; + nn_paddings = 0; } SrsRtcPackets::~SrsRtcPackets() @@ -490,6 +491,7 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int sendonly_ukt = u->copy_sendonly(); gso = false; merge_nalus = false; + max_padding = 0; audio_timestamp = 0; audio_sequence = 0; @@ -519,8 +521,9 @@ srs_error_t SrsRtcSenderThread::initialize(const uint32_t& vssrc, const uint32_t gso = _srs_config->get_rtc_server_gso(); merge_nalus = _srs_config->get_rtc_server_merge_nalus(); - srs_trace("RTC sender video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), package(gso=%d, merge_nalus=%d)", - video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, gso, merge_nalus); + max_padding = _srs_config->get_rtc_server_padding(); + srs_trace("RTC sender video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), package(gso=%d, merge_nalus=%d), padding=%d", + video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, gso, merge_nalus, max_padding); return err; } @@ -543,6 +546,14 @@ srs_error_t SrsRtcSenderThread::on_reload_rtc_server() } } + if (true) { + bool v = _srs_config->get_rtc_server_padding(); + if (max_padding != v) { + srs_trace("Reload padding %d=>%d", max_padding, v); + max_padding = v; + } + } + return srs_success; } @@ -665,7 +676,7 @@ srs_error_t SrsRtcSenderThread::cycle() // Stat the RTP packets going into kernel. stat->perf_on_gso_packets(pkts.nn_rtp_pkts); #if defined(SRS_DEBUG) - srs_trace("RTC PLAY packets, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes", + srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes", msg_count, nn_rtc_packets, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes); #endif @@ -673,9 +684,9 @@ srs_error_t SrsRtcSenderThread::cycle() pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes", + srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes, %d pad", msg_count, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes); + pkts.nn_samples, pkts.nn_bytes, pkts.nn_paddings); } } } @@ -862,13 +873,28 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac int nn_packets = (int)packets.packets.size(); for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.packets[i]; - - // The handler to send message. - mmsghdr* mhdr = NULL; - - // Check whether we can use GSO to send it. int nn_packet = packet->nb_bytes(); + SrsRtpPacket2* next_packet = NULL; + int nn_next_packet = 0; + if (i < nn_packets - 1) { + next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL; + nn_next_packet = next_packet? next_packet->nb_bytes() : 0; + } + + // Padding the first packet if size is similar to the next one. + if (i == 0 && max_padding > 0 && next_packet && nn_packet < nn_next_packet && nn_next_packet - nn_packet < max_padding) { +#if defined(SRS_DEBUG) + srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", nn_next_packet - nn_packet, + nn_packet, nn_next_packet, nn_packets, max_padding); +#endif + packet->set_padding(nn_next_packet - nn_packet); + nn_packet = nn_next_packet; + packets.nn_paddings++; + } + + // Check whether we can use GSO to send it. + mmsghdr* mhdr = NULL; if ((gso_size && gso_size == nn_packet) || (use_gso && !gso_final)) { use_gso = true; gso_final = (gso_size && gso_size != nn_packet); @@ -893,10 +919,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } // Change the state according to the next packet. - if (i < nn_packets - 1) { - SrsRtpPacket2* next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL; - int nn_next_packet = next_packet? next_packet->nb_bytes() : 0; - + if (next_packet) { // If GSO, but next is bigger than this one, we must enter the final state. if (use_gso && !gso_final) { gso_final = (nn_packet < nn_next_packet); @@ -1025,8 +1048,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d", packets.packets.size(), - packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras); + srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.packets.size(), packets.nn_rtp_pkts, + packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings); #endif return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 2ffe75441..978681ccb 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -138,6 +138,8 @@ public: int nn_audios; // The original video messages. int nn_videos; + // The number of padded packet. + int nn_paddings; public: std::vector packets; public: @@ -166,6 +168,7 @@ public: SrsUdpMuxSocket* sendonly_ukt; bool merge_nalus; bool gso; + int max_padding; public: SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid); virtual ~SrsRtcSenderThread(); From c95a8517e73a59c73c8c20f148eaf4c38f4314c2 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 17:48:52 +0800 Subject: [PATCH 085/131] For #307, padding to next packet or GSO size --- trunk/src/app/srs_app_rtc_conn.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c6e585665..42f448724 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -882,15 +882,25 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac nn_next_packet = next_packet? next_packet->nb_bytes() : 0; } - // Padding the first packet if size is similar to the next one. - if (i == 0 && max_padding > 0 && next_packet && nn_packet < nn_next_packet && nn_next_packet - nn_packet < max_padding) { + // Padding the packet to next or GSO size. + if (max_padding > 0 && next_packet) { + // Padding to the next packet to merge with it. + int padding = nn_next_packet - nn_packet; + + // If the next one could merge to this GSO stage, padding current to GSO size. + if (use_gso && nn_next_packet < gso_size) { + padding = gso_size - nn_packet; + } + + if (padding > 0 && padding < max_padding) { #if defined(SRS_DEBUG) - srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", nn_next_packet - nn_packet, - nn_packet, nn_next_packet, nn_packets, max_padding); + srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", padding, nn_packet + padding, + nn_next_packet, nn_packets, max_padding); #endif - packet->set_padding(nn_next_packet - nn_packet); - nn_packet = nn_next_packet; - packets.nn_paddings++; + packet->set_padding(padding); + nn_packet += padding; + packets.nn_paddings++; + } } // Check whether we can use GSO to send it. From 7c6583684e58048d4cfe5127e5e436e7e735478e Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 19:53:23 +0800 Subject: [PATCH 086/131] RTC: Reorder AV for GSO --- trunk/src/app/srs_app_rtc_conn.cpp | 111 ++++++++++++++++++++++++++++- trunk/src/app/srs_app_rtc_conn.hpp | 1 + 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 42f448724..a11706327 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -701,8 +701,17 @@ srs_error_t SrsRtcSenderThread::send_messages( } // Covert kernel messages to RTP packets. - if ((err = messages_to_packets(source, msgs, nb_msgs, packets)) != srs_success) { - return srs_error_wrap(err, "messages to packets"); + // For GSO and small amount of packets, process video then audio. + // TODO: FIXME: Magic number. + if (packets.use_gso && nb_msgs <= 6) { + if ((err = messages_to_packets_gso(source, msgs, nb_msgs, packets)) != srs_success) { + return srs_error_wrap(err, "messages to packets"); + } + } else { + // By default, we process the packets in its original sequence. + if ((err = messages_to_packets(source, msgs, nb_msgs, packets)) != srs_success) { + return srs_error_wrap(err, "messages to packets"); + } } #ifndef SRS_AUTO_OSX @@ -804,6 +813,104 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( return err; } +srs_error_t SrsRtcSenderThread::messages_to_packets_gso( + SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets +) { + srs_error_t err = srs_success; + + SrsRtpPacket2* packet = NULL; + + // For GSO, process video first. + for (int i = 0; i < nb_msgs; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + // Ignore audio when processing video. + if (msg->is_audio()) { + continue; + } + + // Update stats. + packets.nn_bytes += msg->size; + + int nn_samples = msg->nn_samples(); + packets.nn_samples += nn_samples; + + // For video, we should process all NALUs in samples. + packets.nn_videos++; + + // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. + if (msg->has_idr()) { + if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + packets.packets.push_back(packet); + } + + // If merge Nalus, we pcakges all NALUs(samples) as one NALU, in a RTP or FUA packet. + if (packets.should_merge_nalus && nn_samples > 1) { + if ((err = packet_nalus(msg, packets)) != srs_success) { + return srs_error_wrap(err, "packet stap-a"); + } + continue; + } + + // By default, we package each NALU(sample) to a RTP or FUA packet. + for (int i = 0; i < nn_samples; i++) { + SrsSample* sample = msg->samples() + i; + + // We always ignore bframe here, if config to discard bframe, + // the bframe flag will not be set. + if (sample->bframe) { + continue; + } + + if (sample->size <= kRtpMaxPayloadSize) { + if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { + return srs_error_wrap(err, "packet single nalu"); + } + packets.packets.push_back(packet); + } else { + if ((err = packet_fu_a(msg, sample, kRtpMaxPayloadSize, packets)) != srs_success) { + return srs_error_wrap(err, "packet fu-a"); + } + } + + if (i == nn_samples - 1) { + packets.packets.back()->rtp_header.set_marker(true); + } + } + } + + // For GSO, process audio after video. + for (int i = 0; i < nb_msgs; i++) { + SrsSharedPtrMessage* msg = msgs[i]; + + // Ignore video when processing audio. + if (!msg->is_audio()) { + continue; + } + + // Update stats. + packets.nn_bytes += msg->size; + + int nn_extra_payloads = msg->nn_extra_payloads(); + packets.nn_extras += nn_extra_payloads; + + // For audio, we transcoded AAC to opus in extra payloads. + packets.nn_audios++; + + for (int i = 0; i < nn_extra_payloads; i++) { + SrsSample* sample = msg->extra_payloads() + i; + if ((err = packet_opus(sample, &packet)) != srs_success) { + return srs_error_wrap(err, "opus package"); + } + packets.packets.push_back(packet); + } + } + + return err; +} + srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 978681ccb..479d47624 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -190,6 +190,7 @@ public: private: srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); + srs_error_t messages_to_packets_gso(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); srs_error_t send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); private: From d692f2d9c4427fe524d3f6975dd14a301039508f Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 21:37:46 +0800 Subject: [PATCH 087/131] Fix build failed when RTC disabled. --- trunk/src/kernel/srs_kernel_flv.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index 28b2d938b..b05b3adbf 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -227,9 +227,10 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::~SrsSharedPtrPayload() srs_memory_unwatch(payload); #endif srs_freepa(payload); - srs_freepa(samples); #ifdef SRS_AUTO_RTC + srs_freepa(samples); + for (int i = 0; i < nn_extra_payloads; i++) { SrsSample* p = extra_payloads + i; srs_freep(p->bytes); From c96ffd272c524793b906f39cebde6136aa07aade Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 21:59:27 +0800 Subject: [PATCH 088/131] Cache RTP packet vector --- trunk/auto/depends.sh | 5 +++-- trunk/src/app/srs_app_rtc_conn.cpp | 20 ++++++++++++++++---- trunk/src/app/srs_app_rtc_conn.hpp | 4 +++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index c8817eb67..557de4bb3 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -214,15 +214,16 @@ function OSX_prepare() fi OS_IS_OSX=YES - echo "OSX detected, install tools if needed" # requires the osx when os if [ $OS_IS_OSX = YES ]; then if [ $SRS_OSX = NO ]; then - echo "OSX detected, must specifies the --osx" + echo "OSX detected, please use: ./configure --osx" exit 1 fi fi + echo "OSX detected, install tools if needed" + brew --help >/dev/null 2>&1; ret=$?; if [[ 0 -ne $ret ]]; then echo "install brew" echo "ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"" diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 42f448724..218e6b6d5 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -460,10 +460,10 @@ srs_error_t SrsDtlsSession::unprotect_rtcp(char* out_buf, const char* in_buf, in return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); } -SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) +SrsRtcPackets::SrsRtcPackets() { - use_gso = gso; - should_merge_nalus = merge_nalus; + use_gso = false; + should_merge_nalus = false; nn_rtp_pkts = 0; nn_audios = nn_extras = 0; @@ -473,6 +473,14 @@ SrsRtcPackets::SrsRtcPackets(bool gso, bool merge_nalus) SrsRtcPackets::~SrsRtcPackets() { + reset(use_gso, should_merge_nalus); +} + +void SrsRtcPackets::reset(bool gso, bool merge_nalus) +{ + use_gso = gso; + should_merge_nalus = merge_nalus; + vector::iterator it; for (it = packets.begin(); it != packets.end(); ++it ) { SrsRtpPacket2* packet = *it; @@ -621,6 +629,7 @@ srs_error_t SrsRtcSenderThread::cycle() bool realtime = _srs_config->get_realtime_enabled(req->vhost, true); srs_utime_t mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); + SrsRtcPackets pkts; SrsMessageArray msgs(SRS_PERF_MW_MSGS); SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); @@ -656,11 +665,14 @@ srs_error_t SrsRtcSenderThread::cycle() continue; } - SrsRtcPackets pkts(gso, merge_nalus); + // Transmux and send out messages. + pkts.reset(gso, merge_nalus); + if ((err = send_messages(sendonly_ukt, source, msgs.msgs, msg_count, pkts)) != srs_success) { srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); } + // Do cleanup messages. for (int i = 0; i < msg_count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; srs_freep(msg); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 978681ccb..c2edcd625 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -143,8 +143,10 @@ public: public: std::vector packets; public: - SrsRtcPackets(bool gso, bool merge_nalus); + SrsRtcPackets(); virtual ~SrsRtcPackets(); +public: + void reset(bool gso, bool merge_nalus); }; class SrsRtcSenderThread : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler From 7b68f55edc258ffc29759126622694440df4f99b Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 22:11:03 +0800 Subject: [PATCH 089/131] Refactor GSO mmsghdr alloc --- trunk/src/app/srs_app_rtc_conn.cpp | 23 +++++++++++++++++------ trunk/src/core/srs_core_performance.hpp | 3 +++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 218e6b6d5..e63be65dc 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -925,7 +925,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // We need to increase the iov and cursor. int nb_iovs = mhdr->msg_hdr.msg_iovlen; if (gso_cursor >= nb_iovs - 1) { - int nn_new_iovs = nb_iovs; + int nn_new_iovs = 1; mhdr->msg_hdr.msg_iovlen = nb_iovs + nn_new_iovs; mhdr->msg_hdr.msg_iov = (iovec*)realloc(mhdr->msg_hdr.msg_iov, sizeof(iovec) * (nb_iovs + nn_new_iovs)); memset(mhdr->msg_hdr.msg_iov + nb_iovs, 0, sizeof(iovec) * nn_new_iovs); @@ -965,6 +965,10 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Reset the iovec, we should never change the msg_iovlen. for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* p = mhdr->msg_hdr.msg_iov + j; + + if (!p->iov_len) { + break; + } p->iov_len = 0; } @@ -1020,6 +1024,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* iov = mhdr->msg_hdr.msg_iov + j; + if (iov->iov_len <= 0) { break; } @@ -1815,7 +1820,7 @@ void SrsUdpMuxSender::free_mhdrs(std::vector& mhdrs) iovec* iov = hdr->msg_hdr.msg_iov + j; char* data = (char*)iov->iov_base; srs_freep(data); - srs_freep(iov); + srs_freepa(iov); } } mhdrs.clear(); @@ -1828,12 +1833,18 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) mmsghdr mhdr; memset(&mhdr, 0, sizeof(mmsghdr)); - mhdr.msg_hdr.msg_iovlen = 1; - mhdr.msg_hdr.msg_iov = new iovec(); - mhdr.msg_hdr.msg_iov->iov_base = new char[kRtpPacketSize]; - mhdr.msg_hdr.msg_iov->iov_len = kRtpPacketSize; mhdr.msg_len = 0; + mhdr.msg_hdr.msg_iovlen = SRS_PERF_RTC_GSO_IOVS; + mhdr.msg_hdr.msg_iov = new iovec[mhdr.msg_hdr.msg_iovlen]; + + for (int i = 0; i < (int)mhdr.msg_hdr.msg_iovlen; i++) { + iovec* p = mhdr.msg_hdr.msg_iov + i; + + p->iov_base = new char[kRtpPacketSize]; + p->iov_len = kRtpPacketSize; + } + cache.push_back(mhdr); } diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 7cafa055e..cbfddf1dc 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -192,5 +192,8 @@ #define SRS_PERF_GLIBC_MEMORY_CHECK #undef SRS_PERF_GLIBC_MEMORY_CHECK +// For RTC, how many iovs we alloc for each mmsghdr for GSO. +#define SRS_PERF_RTC_GSO_IOVS 4 + #endif From 1064429c7e758fd3f29e3bd4b5ea09967d0cf0f9 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 15 Apr 2020 22:46:06 +0800 Subject: [PATCH 090/131] Cache RTP packets --- trunk/src/app/srs_app_rtc_conn.cpp | 123 +++++++++++++++++----------- trunk/src/app/srs_app_rtc_conn.hpp | 13 ++- trunk/src/kernel/srs_kernel_rtp.cpp | 7 ++ trunk/src/kernel/srs_kernel_rtp.hpp | 4 +- 4 files changed, 94 insertions(+), 53 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e63be65dc..e4f57800d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -469,6 +469,8 @@ SrsRtcPackets::SrsRtcPackets() nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; nn_paddings = 0; + + cursor = 0; } SrsRtcPackets::~SrsRtcPackets() @@ -481,12 +483,38 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) use_gso = gso; should_merge_nalus = merge_nalus; - vector::iterator it; - for (it = packets.begin(); it != packets.end(); ++it ) { - SrsRtpPacket2* packet = *it; - srs_freep(packet); + for (int i = 0; i < cursor; i++) { + SrsRtpPacket2* packet = packets[i]; + packet->reset(); } - packets.clear(); + + cursor = 0; +} + +SrsRtpPacket2* SrsRtcPackets::fetch() +{ + if (cursor >= (int)packets.size()) { + packets.push_back(new SrsRtpPacket2()); + } + + return packets[cursor++]; +} + +SrsRtpPacket2* SrsRtcPackets::back() +{ + srs_assert(cursor > 0); + return packets[cursor - 1]; +} + +int SrsRtcPackets::size() +{ + return cursor; +} + +SrsRtpPacket2* SrsRtcPackets::at(int index) +{ + srs_assert(index < cursor); + return packets[index]; } SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid) @@ -684,12 +712,12 @@ srs_error_t SrsRtcSenderThread::cycle() int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; stat->perf_on_rtc_packets(nn_rtc_packets); // Stat the RAW RTP packets, which maybe group by GSO. - stat->perf_on_rtp_packets(pkts.packets.size()); + stat->perf_on_rtp_packets(pkts.size()); // Stat the RTP packets going into kernel. stat->perf_on_gso_packets(pkts.nn_rtp_pkts); #if defined(SRS_DEBUG) srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes", - msg_count, nn_rtc_packets, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes); #endif @@ -697,7 +725,7 @@ srs_error_t SrsRtcSenderThread::cycle() if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes, %d pad", - msg_count, pkts.packets.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + msg_count, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, pkts.nn_paddings); } } @@ -753,16 +781,14 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( packets.nn_samples += nn_samples; // For audio, we transcoded AAC to opus in extra payloads. - SrsRtpPacket2* packet = NULL; if (msg->is_audio()) { packets.nn_audios++; for (int i = 0; i < nn_extra_payloads; i++) { SrsSample* sample = msg->extra_payloads() + i; - if ((err = packet_opus(sample, &packet)) != srs_success) { + if ((err = packet_opus(sample, packets)) != srs_success) { return srs_error_wrap(err, "opus package"); } - packets.packets.push_back(packet); } continue; } @@ -772,10 +798,9 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( // Well, for each IDR, we append a SPS/PPS before it, which is packaged in STAP-A. if (msg->has_idr()) { - if ((err = packet_stap_a(source, msg, &packet)) != srs_success) { + if ((err = packet_stap_a(source, msg, packets)) != srs_success) { return srs_error_wrap(err, "packet stap-a"); } - packets.packets.push_back(packet); } // If merge Nalus, we pcakges all NALUs(samples) as one NALU, in a RTP or FUA packet. @@ -797,10 +822,9 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( } if (sample->size <= kRtpMaxPayloadSize) { - if ((err = packet_single_nalu(msg, sample, &packet)) != srs_success) { + if ((err = packet_single_nalu(msg, sample, packets)) != srs_success) { return srs_error_wrap(err, "packet single nalu"); } - packets.packets.push_back(packet); } else { if ((err = packet_fu_a(msg, sample, kRtpMaxPayloadSize, packets)) != srs_success) { return srs_error_wrap(err, "packet fu-a"); @@ -808,7 +832,7 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( } if (i == nn_samples - 1) { - packets.packets.back()->rtp_header.set_marker(true); + packets.back()->rtp_header.set_marker(true); } } } @@ -822,9 +846,9 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets ISrsUdpSender* sender = skt->sender(); - vector::iterator it; - for (it = packets.packets.begin(); it != packets.packets.end(); ++it) { - SrsRtpPacket2* packet = *it; + int nn_packets = packets.size(); + for (int i = 0; i < nn_packets; i++) { + SrsRtpPacket2* packet = packets.at(i); // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. @@ -832,6 +856,17 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets if ((err = sender->fetch(&mhdr)) != srs_success) { return srs_error_wrap(err, "fetch msghdr"); } + + // Reset the iovec, we should never change the msg_iovlen. + for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { + iovec* p = mhdr->msg_hdr.msg_iov + j; + + if (!p->iov_len) { + break; + } + p->iov_len = 0; + } + char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; int length = kRtpPacketSize; @@ -882,15 +917,15 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac bool use_gso = false; bool gso_final = false; ISrsUdpSender* sender = skt->sender(); - int nn_packets = (int)packets.packets.size(); + int nn_packets = packets.size(); for (int i = 0; i < nn_packets; i++) { - SrsRtpPacket2* packet = packets.packets[i]; + SrsRtpPacket2* packet = packets.at(i); int nn_packet = packet->nb_bytes(); SrsRtpPacket2* next_packet = NULL; int nn_next_packet = 0; if (i < nn_packets - 1) { - next_packet = (i < nn_packets - 1)? packets.packets[i + 1]:NULL; + next_packet = (i < nn_packets - 1)? packets.at(i + 1):NULL; nn_next_packet = next_packet? next_packet->nb_bytes() : 0; } @@ -1075,7 +1110,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.packets.size(), packets.nn_rtp_pkts, + srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.size(), packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings); #endif @@ -1109,13 +1144,12 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. - SrsRtpPacket2* packet = new SrsRtpPacket2(); + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); packet->payload = raw; - packets.packets.push_back(packet); } else { SrsAutoFree(SrsRtpRawNALUs, raw); @@ -1131,15 +1165,19 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); - SrsRtpPacket2* packet = new SrsRtpPacket2(); - packets.packets.push_back(packet); + SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); + if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { + srs_freep(fua); + return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); + } + + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); packet->payload = fua; fua->nri = (SrsAvcNaluType)header; @@ -1147,26 +1185,22 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); - if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { - return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); - } - nb_left -= packet_size; } } - if (!packets.packets.empty()) { - packets.packets.back()->rtp_header.set_marker(true); + if (packets.size() > 0) { + packets.back()->rtp_header.set_marker(true); } return err; } -srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket) +srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& packets) { srs_error_t err = srs_success; - SrsRtpPacket2* packet = new SrsRtpPacket2(); + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_marker(true); packet->rtp_header.set_timestamp(audio_timestamp); packet->rtp_header.set_sequence(audio_sequence++); @@ -1181,8 +1215,6 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtpPacket2** p // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; - *ppacket = packet; - return err; } @@ -1199,8 +1231,7 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); - SrsRtpPacket2* packet = new SrsRtpPacket2(); - packets.packets.push_back(packet); + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); @@ -1228,11 +1259,11 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* } // Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6 -srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket) +srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtcPackets& packets) { srs_error_t err = srs_success; - SrsRtpPacket2* packet = new SrsRtpPacket2(); + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); @@ -1246,12 +1277,10 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, Srs p->size = sample->size; raw->push_back(p); - *ppacket = packet; - return err; } -srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket) +srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtcPackets& packets) { srs_error_t err = srs_success; @@ -1271,7 +1300,7 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes return srs_error_new(ERROR_RTC_RTP_MUXER, "sps/pps empty"); } - SrsRtpPacket2* packet = new SrsRtpPacket2(); + SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_marker(false); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); @@ -1298,8 +1327,6 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes stap->nalus.push_back(sample); } - *ppacket = packet; - return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index c2edcd625..7dbf8eefb 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -140,13 +140,18 @@ public: int nn_videos; // The number of padded packet. int nn_paddings; -public: +private: + int cursor; std::vector packets; public: SrsRtcPackets(); virtual ~SrsRtcPackets(); public: void reset(bool gso, bool merge_nalus); + SrsRtpPacket2* fetch(); + SrsRtpPacket2* back(); + int size(); + SrsRtpPacket2* at(int index); }; class SrsRtcSenderThread : virtual public ISrsCoroutineHandler, virtual public ISrsReloadHandler @@ -195,12 +200,12 @@ private: srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); srs_error_t send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); private: - srs_error_t packet_opus(SrsSample* sample, SrsRtpPacket2** ppacket); + srs_error_t packet_opus(SrsSample* sample, SrsRtcPackets& packets); private: srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, SrsRtcPackets& packets); srs_error_t packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets); - srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtpPacket2** ppacket); - srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtpPacket2** ppacket); + srs_error_t packet_single_nalu(SrsSharedPtrMessage* msg, SrsSample* sample, SrsRtcPackets& packets); + srs_error_t packet_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtcPackets& packets); }; class SrsRtcSession diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 83dcf6071..ef33c057a 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -171,6 +171,13 @@ void SrsRtpPacket2::set_padding(int size) padding = size; } +void SrsRtpPacket2::reset() +{ + memset((void*)&rtp_header, 0, sizeof(SrsRtpHeader)); + padding = 0; + srs_freep(payload); +} + int SrsRtpPacket2::nb_bytes() { return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 7733b431f..1b4fd2de6 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -88,7 +88,9 @@ public: virtual ~SrsRtpPacket2(); public: // Append size of bytes as padding. - virtual void set_padding(int size); + void set_padding(int size); + // Reset RTP packet. + void reset(); // interface ISrsEncoder public: virtual int nb_bytes(); From 7d1be87124127082f5d887cf8e91851bc041e6a9 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 08:30:57 +0800 Subject: [PATCH 091/131] Fix RTP packet cache bug --- trunk/src/app/srs_app_rtc_conn.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e4f57800d..48fd770fe 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -475,7 +475,12 @@ SrsRtcPackets::SrsRtcPackets() SrsRtcPackets::~SrsRtcPackets() { - reset(use_gso, should_merge_nalus); + vector::iterator it; + for (it = packets.begin(); it != packets.end(); ++it) { + SrsRtpPacket2* p = *it; + srs_freep(p); + } + packets.clear(); } void SrsRtcPackets::reset(bool gso, bool merge_nalus) From a4dbf3ca8a67d84f17c84af3a08c9b1f2a8ca797 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 08:43:54 +0800 Subject: [PATCH 092/131] Fix RTP packet cache bug --- trunk/scripts/perf_gso.py | 1 + trunk/src/app/srs_app_rtc_conn.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 707e6c6b5..2158659e0 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -43,6 +43,7 @@ obj = json.loads(s) # 2, 3, 5, 9, 16, 32, 64, 128, 256 keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] +print("\n----------- 1 2 [3,4] [5,8] [9,15] [16,31] [32,63] [64,127] [128,255] [256,+)"), print "" print("AV---Frames"), diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 48fd770fe..03497c08f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -485,13 +485,18 @@ SrsRtcPackets::~SrsRtcPackets() void SrsRtcPackets::reset(bool gso, bool merge_nalus) { - use_gso = gso; - should_merge_nalus = merge_nalus; - for (int i = 0; i < cursor; i++) { SrsRtpPacket2* packet = packets[i]; packet->reset(); } + + use_gso = gso; + should_merge_nalus = merge_nalus; + + nn_rtp_pkts = 0; + nn_audios = nn_extras = 0; + nn_videos = nn_samples = 0; + nn_paddings = 0; cursor = 0; } From ef48507e8040e12dd56b4ca7cbba78f75c83f9d9 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 09:07:42 +0800 Subject: [PATCH 093/131] Support padding max to 127 --- trunk/conf/full.conf | 1 + trunk/scripts/perf_gso.py | 2 +- trunk/src/app/srs_app_config.cpp | 2 +- trunk/src/app/srs_app_rtc_conn.cpp | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 66a8a27ab..6dfb8eca5 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -445,6 +445,7 @@ rtc_server { gso on; # Whether pad first packet for GSO for padding bytes. # If 0, disable padding for GSO. + # @remark The max padding size is 0x7f(127). # default: 0 padding 0; } diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 2158659e0..f09014143 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -43,7 +43,7 @@ obj = json.loads(s) # 2, 3, 5, 9, 16, 32, 64, 128, 256 keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] -print("\n----------- 1 2 [3,4] [5,8] [9,15] [16,31] [32,63] [64,127] [128,255] [256,+)"), +print("\n----------- 1 2 [3,4] [5,8] [9,15] [16,31] [32,63] [64,127] [128,255] [256,+) Packets"), print "" print("AV---Frames"), diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 85c70f87b..8df22fea4 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4855,7 +4855,7 @@ int SrsConfig::get_rtc_server_padding() return DEFAULT; } - return srs_min(16, ::atoi(conf->arg0().c_str())); + return srs_min(127, ::atoi(conf->arg0().c_str())); } SrsConfDirective* SrsConfig::get_rtc(string vhost) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 03497c08f..f17cd6ea6 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -489,7 +489,7 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) SrsRtpPacket2* packet = packets[i]; packet->reset(); } - + use_gso = gso; should_merge_nalus = merge_nalus; From 56995db6a50fa48e89ef08cb62d3f902367af1bd Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 09:09:10 +0800 Subject: [PATCH 094/131] Refine debug info --- trunk/src/app/srs_app_rtc_conn.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index f17cd6ea6..913d7b245 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -951,8 +951,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (padding > 0 && padding < max_padding) { #if defined(SRS_DEBUG) - srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", padding, nn_packet + padding, - nn_next_packet, nn_packets, max_padding); + srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", padding, nn_packet, nn_packet + padding, nn_packets, max_padding); #endif packet->set_padding(padding); nn_packet += padding; From b7dab00f369be8f38c2c5c4bea83cb0b17ce4696 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 09:25:18 +0800 Subject: [PATCH 095/131] Add debug_id for GSO --- trunk/src/app/srs_app_rtc_conn.cpp | 23 ++++++++++++++++------- trunk/src/app/srs_app_rtc_conn.hpp | 4 ++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 913d7b245..bde3d0c04 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -462,6 +462,10 @@ srs_error_t SrsDtlsSession::unprotect_rtcp(char* out_buf, const char* in_buf, in SrsRtcPackets::SrsRtcPackets() { +#if defined(SRS_DEBUG) + debug_id = 0; +#endif + use_gso = false; should_merge_nalus = false; @@ -490,6 +494,10 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) packet->reset(); } +#if defined(SRS_DEBUG) + debug_id++; +#endif + use_gso = gso; should_merge_nalus = merge_nalus; @@ -951,7 +959,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (padding > 0 && padding < max_padding) { #if defined(SRS_DEBUG) - srs_trace("Padding %d bytes %d=>%d, packets %d, max_padding %d", padding, nn_packet, nn_packet + padding, nn_packets, max_padding); + srs_trace("#%d, Padding %d bytes %d=>%d, packets %d, max_padding %d", packets.debug_id, + padding, nn_packet, nn_packet + padding, nn_packets, max_padding); #endif packet->set_padding(padding); nn_packet += padding; @@ -1063,8 +1072,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac #if defined(SRS_DEBUG) bool is_video = packet->rtp_header.get_payload_type() == video_payload_type; - srs_trace("Packet %s SSRC=%d, SN=%d, %d bytes", is_video? "Video":"Audio", packet->rtp_header.get_ssrc(), - packet->rtp_header.get_sequence(), nn_packet); + srs_trace("#%d, Packet %s SSRC=%d, SN=%d, %d bytes", packets.debug_id, is_video? "Video":"Audio", + packet->rtp_header.get_ssrc(), packet->rtp_header.get_sequence(), nn_packet); if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* iov = mhdr->msg_hdr.msg_iov + j; @@ -1072,8 +1081,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (iov->iov_len <= 0) { break; } - srs_trace("%s #%d/%d/%d, %d bytes, size %d/%d", (use_gso? "GSO":"RAW"), j, gso_cursor + 1, - mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); + srs_trace("#%d, %s #%d/%d/%d, %d bytes, size %d/%d", packets.debug_id, (use_gso? "GSO":"RAW"), j, + gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); } } #endif @@ -1119,8 +1128,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.size(), packets.nn_rtp_pkts, - packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings); + srs_trace("#%d, RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.debug_id, packets.size(), + packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings); #endif return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 7dbf8eefb..9f3378273 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -124,6 +124,10 @@ public: bool use_gso; bool should_merge_nalus; public: +#if defined(SRS_DEBUG) + // Debug id. + uint32_t debug_id; +#endif // The total bytes of RTP packets. int nn_bytes; // The RTP packets send out by sendmmsg or sendmsg. Note that if many packets group to From 5ad99b119dcb8ca5eecef68e19ccccc5b80f4eb8 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 10:05:17 +0800 Subject: [PATCH 096/131] Stat bytes --- trunk/src/app/srs_app_http_api.cpp | 11 ++++++++++- trunk/src/app/srs_app_rtc_conn.cpp | 22 +++++++++++++--------- trunk/src/app/srs_app_rtc_conn.hpp | 4 ++++ trunk/src/app/srs_app_statistic.cpp | 26 +++++++++++++++++++++++++- trunk/src/app/srs_app_statistic.hpp | 10 ++++++---- 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index fdfbf8747..6c9b9fbc5 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1624,7 +1624,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* p->set("target", SrsJsonAny::str(target.c_str())); p->set("reset", SrsJsonAny::str(reset.c_str())); - p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg")); + p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg|bytes")); p->set("help2", SrsJsonAny::str("?reset=all")); } @@ -1687,6 +1687,15 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } + if (target.empty() || target == "bytes") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("bytes", p); + if ((err = stat->dumps_perf_bytes(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + return srs_api_response(w, r, obj->dumps()); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index bde3d0c04..e4159b3aa 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -472,7 +472,7 @@ SrsRtcPackets::SrsRtcPackets() nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; - nn_paddings = 0; + nn_padding_bytes = nn_paddings = 0; cursor = 0; } @@ -504,7 +504,7 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; - nn_paddings = 0; + nn_padding_bytes = nn_paddings = 0; cursor = 0; } @@ -733,18 +733,20 @@ srs_error_t SrsRtcSenderThread::cycle() stat->perf_on_rtp_packets(pkts.size()); // Stat the RTP packets going into kernel. stat->perf_on_gso_packets(pkts.nn_rtp_pkts); + // Stat the bytes and paddings. + stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); #if defined(SRS_DEBUG) - srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d bytes", + srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes); + pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes); #endif pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d bytes, %d pad", + srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad", msg_count, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes, pkts.nn_paddings); + pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes, pkts.nn_paddings); } } } @@ -965,6 +967,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac packet->set_padding(padding); nn_packet += padding; packets.nn_paddings++; + packets.nn_padding_bytes += padding; } } @@ -1128,8 +1131,9 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } #if defined(SRS_DEBUG) - srs_trace("#%d, RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d", packets.debug_id, packets.size(), - packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings); + srs_trace("#%d, RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d/%d", packets.debug_id, packets.size(), + packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings, + packets.nn_padding_bytes); #endif return err; @@ -1971,7 +1975,7 @@ srs_error_t SrsUdpMuxSender::cycle() srs_warn("sendmmsg %d msgs, %d done", vlen, r0); } - stat->perf_sendmmsg_on_packets(vlen); + stat->perf_on_sendmmsg_packets(vlen); } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 9f3378273..c08446e34 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -128,8 +128,12 @@ public: // Debug id. uint32_t debug_id; #endif +public: // The total bytes of RTP packets. int nn_bytes; + // The total padded bytes. + int nn_padding_bytes; +public: // The RTP packets send out by sendmmsg or sendmsg. Note that if many packets group to // one msghdr by GSO, it's only one RTP packet, because we only send once. int nn_rtp_pkts; diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 98c7ec8ab..4bf58aa99 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -271,6 +271,7 @@ SrsStatistic::SrsStatistic() perf_gso = new SrsStatisticCategory(); perf_rtp = new SrsStatisticCategory(); perf_rtc = new SrsStatisticCategory(); + perf_bytes = new SrsStatisticCategory(); } SrsStatistic::~SrsStatistic() @@ -311,6 +312,7 @@ SrsStatistic::~SrsStatistic() srs_freep(perf_gso); srs_freep(perf_rtp); srs_freep(perf_rtc); + srs_freep(perf_bytes); } SrsStatistic* SrsStatistic::instance() @@ -641,7 +643,7 @@ srs_error_t SrsStatistic::dumps_perf_writev_iovs(SrsJsonObject* obj) return dumps_perf(perf_iovs, obj); } -void SrsStatistic::perf_sendmmsg_on_packets(int nb_packets) +void SrsStatistic::perf_on_sendmmsg_packets(int nb_packets) { perf_on_packets(perf_sendmmsg, nb_packets); } @@ -651,6 +653,26 @@ srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) return dumps_perf(perf_sendmmsg, obj); } +void SrsStatistic::perf_on_rtc_bytes(int nn_bytes, int nn_padding) +{ + // a: RTC bytes. + // b: RTC paddings. + perf_bytes->a += nn_bytes; + perf_bytes->b += nn_padding; + + perf_bytes->nn += nn_bytes + nn_padding; +} + +srs_error_t SrsStatistic::dumps_perf_bytes(SrsJsonObject* obj) +{ + obj->set("rtc_bytes", SrsJsonAny::integer(perf_bytes->a)); + obj->set("rtc_padding", SrsJsonAny::integer(perf_bytes->b)); + + obj->set("nn", SrsJsonAny::integer(perf_bytes->nn)); + + return srs_success; +} + void SrsStatistic::reset_perf() { srs_freep(perf_iovs); @@ -659,6 +681,7 @@ void SrsStatistic::reset_perf() srs_freep(perf_gso); srs_freep(perf_rtp); srs_freep(perf_rtc); + srs_freep(perf_bytes); perf_iovs = new SrsStatisticCategory(); perf_msgs = new SrsStatisticCategory(); @@ -666,6 +689,7 @@ void SrsStatistic::reset_perf() perf_gso = new SrsStatisticCategory(); perf_rtp = new SrsStatisticCategory(); perf_rtc = new SrsStatisticCategory(); + perf_bytes = new SrsStatisticCategory(); } void SrsStatistic::perf_on_packets(SrsStatisticCategory* p, int nb_msgs) diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index c0344989f..50fbb8516 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -174,6 +174,7 @@ private: SrsStatisticCategory* perf_gso; SrsStatisticCategory* perf_rtp; SrsStatisticCategory* perf_rtc; + SrsStatisticCategory* perf_bytes; private: SrsStatistic(); virtual ~SrsStatistic(); @@ -245,13 +246,11 @@ public: // Stat for packets merged written, nb_packets is the number of RTP packets. // For example, a RTC/opus packet maybe package to three RTP packets. virtual void perf_on_rtp_packets(int nb_packets); - // Dumps the perf statistic data for RTP packets, for performance analysis. virtual srs_error_t dumps_perf_rtp_packets(SrsJsonObject* obj); public: // Stat for packets UDP GSO, nb_packets is the merged RTP packets. // For example, three RTP/audio packets maybe GSO to one msghdr. virtual void perf_on_gso_packets(int nb_packets); - // Dumps the perf statistic data for UDP GSO, for performance analysis. virtual srs_error_t dumps_perf_gso(SrsJsonObject* obj); public: // Stat for TCP writev, nb_iovs is the total number of iovec. @@ -259,9 +258,12 @@ public: virtual srs_error_t dumps_perf_writev_iovs(SrsJsonObject* obj); public: // Stat for packets UDP sendmmsg, nb_packets is the vlen for sendmmsg. - virtual void perf_sendmmsg_on_packets(int nb_packets); - // Dumps the perf statistic data for UDP sendmmsg, for performance analysis. + virtual void perf_on_sendmmsg_packets(int nb_packets); virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); +public: + // Stat for bytes, nn_bytes is the size of bytes, nb_padding is padding bytes. + virtual void perf_on_rtc_bytes(int nn_bytes, int nn_padding); + virtual srs_error_t dumps_perf_bytes(SrsJsonObject* obj); public: // Reset all perf stat data. virtual void reset_perf(); From b91e07f4754c15c55dbbf3ed7c14045c0648185e Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 10:25:12 +0800 Subject: [PATCH 097/131] For #307, change max padding to 127 for GSO. --- trunk/conf/full.conf | 4 ++-- trunk/src/app/srs_app_config.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 6dfb8eca5..646d82b2b 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -446,8 +446,8 @@ rtc_server { # Whether pad first packet for GSO for padding bytes. # If 0, disable padding for GSO. # @remark The max padding size is 0x7f(127). - # default: 0 - padding 0; + # default: 127 + padding 127; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 8df22fea4..fcea9fde3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4843,7 +4843,7 @@ bool SrsConfig::get_rtc_server_gso2() int SrsConfig::get_rtc_server_padding() { - static int DEFAULT = 0; + static int DEFAULT = 127; SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { From 4dced0b07781022761086a55d0afc3b9b4cb83ba Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 10:58:20 +0800 Subject: [PATCH 098/131] For #307, fix apdding algorithm bug. --- trunk/src/app/srs_app_rtc_conn.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index e4159b3aa..b754f6e5a 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -954,9 +954,14 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Padding to the next packet to merge with it. int padding = nn_next_packet - nn_packet; - // If the next one could merge to this GSO stage, padding current to GSO size. - if (use_gso && nn_next_packet < gso_size) { - padding = gso_size - nn_packet; + if (use_gso) { + // If the next one could merge to this GSO stage, padding current to GSO size. + if (nn_next_packet < gso_size) { + padding = gso_size - nn_packet; + } else { + // If the next one could not merge to this GSO stage, never padding. + padding = 0; + } } if (padding > 0 && padding < max_padding) { From 34fec09bc09b7876c14d70cbab37521e0d9d569c Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 11:22:25 +0800 Subject: [PATCH 099/131] Refactor padding --- trunk/src/app/srs_app_rtc_conn.cpp | 11 ++++++----- trunk/src/kernel/srs_kernel_rtp.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b754f6e5a..ff488ec71 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -941,6 +941,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.at(i); int nn_packet = packet->nb_bytes(); + int padding = 0; SrsRtpPacket2* next_packet = NULL; int nn_next_packet = 0; @@ -952,7 +953,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Padding the packet to next or GSO size. if (max_padding > 0 && next_packet) { // Padding to the next packet to merge with it. - int padding = nn_next_packet - nn_packet; + padding = nn_next_packet - nn_packet; if (use_gso) { // If the next one could merge to this GSO stage, padding current to GSO size. @@ -1080,8 +1081,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac #if defined(SRS_DEBUG) bool is_video = packet->rtp_header.get_payload_type() == video_payload_type; - srs_trace("#%d, Packet %s SSRC=%d, SN=%d, %d bytes", packets.debug_id, is_video? "Video":"Audio", - packet->rtp_header.get_ssrc(), packet->rtp_header.get_sequence(), nn_packet); + srs_trace("#%d, Packet %s SSRC=%d, SN=%d, %d/%d bytes", packets.debug_id, is_video? "Video":"Audio", + packet->rtp_header.get_ssrc(), packet->rtp_header.get_sequence(), nn_packet - padding, padding); if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* iov = mhdr->msg_hdr.msg_iov + j; @@ -1089,8 +1090,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (iov->iov_len <= 0) { break; } - srs_trace("#%d, %s #%d/%d/%d, %d bytes, size %d/%d", packets.debug_id, (use_gso? "GSO":"RAW"), j, - gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, gso_size, gso_encrypt); + srs_trace("#%d, %s #%d/%d/%d, %d/%d bytes, size %d/%d", packets.debug_id, (use_gso? "GSO":"RAW"), j, + gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, padding, gso_size, gso_encrypt); } } #endif diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index ef33c057a..870b292ee 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -195,7 +195,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) return srs_error_wrap(err, "encode payload"); } - if (padding) { + if (padding > 0) { if (!buf->require(padding)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", padding); } From 92419f9836b44e0c9b0263133610e97a00a12cfa Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 11:57:11 +0800 Subject: [PATCH 100/131] For #307, refine GSO padding algorithm --- trunk/src/app/srs_app_rtc_conn.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ff488ec71..15e27ca5e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -952,20 +952,24 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Padding the packet to next or GSO size. if (max_padding > 0 && next_packet) { - // Padding to the next packet to merge with it. - padding = nn_next_packet - nn_packet; - - if (use_gso) { - // If the next one could merge to this GSO stage, padding current to GSO size. + if (!use_gso) { + // Padding to the next packet to merge with it. + if (nn_next_packet > nn_packet) { + padding = nn_next_packet - nn_packet; + } + } else { + // Padding to GSO size for next one to merge with us. if (nn_next_packet < gso_size) { padding = gso_size - nn_packet; - } else { - // If the next one could not merge to this GSO stage, never padding. - padding = 0; } } - if (padding > 0 && padding < max_padding) { + // Reset padding if exceed max. + if (padding > max_padding) { + padding = 0; + } + + if (padding > 0) { #if defined(SRS_DEBUG) srs_trace("#%d, Padding %d bytes %d=>%d, packets %d, max_padding %d", packets.debug_id, padding, nn_packet, nn_packet + padding, nn_packets, max_padding); From cc831be985f616e6f512ea3b2da9ba4498d7fff8 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 12:18:52 +0800 Subject: [PATCH 101/131] Refactor variable name for GSO --- trunk/src/app/srs_app_rtc_conn.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 15e27ca5e..b03a121ee 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -934,7 +934,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Previous handler, if has the same size, we can use GSO. mmsghdr* gso_mhdr = NULL; int gso_size = 0; int gso_encrypt = 0; int gso_cursor = 0; // GSO, N packets has same length, the final one may not. - bool use_gso = false; bool gso_final = false; + bool using_gso = false; bool gso_final = false; ISrsUdpSender* sender = skt->sender(); int nn_packets = packets.size(); @@ -952,7 +952,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Padding the packet to next or GSO size. if (max_padding > 0 && next_packet) { - if (!use_gso) { + if (!using_gso) { // Padding to the next packet to merge with it. if (nn_next_packet > nn_packet) { padding = nn_next_packet - nn_packet; @@ -983,8 +983,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Check whether we can use GSO to send it. mmsghdr* mhdr = NULL; - if ((gso_size && gso_size == nn_packet) || (use_gso && !gso_final)) { - use_gso = true; + if ((gso_size && gso_size == nn_packet) || (using_gso && !gso_final)) { + using_gso = true; gso_final = (gso_size && gso_size != nn_packet); mhdr = gso_mhdr; @@ -1009,14 +1009,14 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Change the state according to the next packet. if (next_packet) { // If GSO, but next is bigger than this one, we must enter the final state. - if (use_gso && !gso_final) { + if (using_gso && !gso_final) { gso_final = (nn_packet < nn_next_packet); } // If not GSO, maybe the first fresh packet, we should see whether the next packet is smaller than this one, // if smaller, we can still enter GSO. - if (!use_gso) { - use_gso = (nn_packet >= nn_next_packet); + if (!using_gso) { + using_gso = (nn_packet >= nn_next_packet); } } @@ -1039,7 +1039,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } // Now, GSO will use this message and size. - if (use_gso) { + if (using_gso) { gso_mhdr = mhdr; gso_size = nn_packet; } @@ -1067,21 +1067,21 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac } // If GSO, they must has same size, except the final one. - if (use_gso && !gso_final && gso_encrypt && gso_encrypt != (int)iov->iov_len) { + if (using_gso && !gso_final && gso_encrypt && gso_encrypt != (int)iov->iov_len) { return srs_error_new(ERROR_RTC_RTP_MUXER, "GSO size=%d/%d, encrypt=%d/%d", gso_size, nn_packet, gso_encrypt, iov->iov_len); } - if (use_gso && !gso_final) { + if (using_gso && !gso_final) { gso_encrypt = iov->iov_len; } // If exceed the max GSO size, set to final. - if (use_gso && gso_cursor > 64) { + if (using_gso && gso_cursor > 64) { gso_final = true; } // For last message, or final gso, or determined not using GSO, send it now. - bool do_send = (i == nn_packets - 1 || gso_final || !use_gso); + bool do_send = (i == nn_packets - 1 || gso_final || !using_gso); #if defined(SRS_DEBUG) bool is_video = packet->rtp_header.get_payload_type() == video_payload_type; @@ -1094,7 +1094,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac if (iov->iov_len <= 0) { break; } - srs_trace("#%d, %s #%d/%d/%d, %d/%d bytes, size %d/%d", packets.debug_id, (use_gso? "GSO":"RAW"), j, + srs_trace("#%d, %s #%d/%d/%d, %d/%d bytes, size %d/%d", packets.debug_id, (using_gso? "GSO":"RAW"), j, gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, padding, gso_size, gso_encrypt); } } @@ -1110,7 +1110,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac mhdr->msg_len = 0; #ifndef SRS_AUTO_OSX - if (use_gso) { + if (using_gso) { mhdr->msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t)); if (!mhdr->msg_hdr.msg_control) { mhdr->msg_hdr.msg_control = new char[mhdr->msg_hdr.msg_controllen]; @@ -1136,7 +1136,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // Reset the GSO flag. gso_mhdr = NULL; gso_size = 0; gso_encrypt = 0; gso_cursor = 0; - use_gso = gso_final = false; + using_gso = gso_final = false; } } From b4a7566684c54990b90c73130211be09ba070064 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 12:35:36 +0800 Subject: [PATCH 102/131] Print the rtp packets cache capacity --- trunk/src/app/srs_app_rtc_conn.cpp | 13 +++++++++---- trunk/src/app/srs_app_rtc_conn.hpp | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b03a121ee..b1b92abaf 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -529,6 +529,11 @@ int SrsRtcPackets::size() return cursor; } +int SrsRtcPackets::capacity() +{ + return (int)packets.size(); +} + SrsRtpPacket2* SrsRtcPackets::at(int index) { srs_assert(index < cursor); @@ -736,7 +741,7 @@ srs_error_t SrsRtcSenderThread::cycle() // Stat the bytes and paddings. stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); #if defined(SRS_DEBUG) - srs_trace("RTC PLAY done, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", + srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes); #endif @@ -744,9 +749,9 @@ srs_error_t SrsRtcSenderThread::cycle() pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad", - msg_count, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes, pkts.nn_paddings); + srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad, %d/%d cache", + msg_count, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, + pkts.nn_padding_bytes, pkts.nn_paddings, pkts.size(), pkts.capacity()); } } } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index c08446e34..0af9d0b5e 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -159,6 +159,7 @@ public: SrsRtpPacket2* fetch(); SrsRtpPacket2* back(); int size(); + int capacity(); SrsRtpPacket2* at(int index); }; From e90f0629ed2d801eb5ad5ff0360253dc11fde455 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 13:13:02 +0800 Subject: [PATCH 103/131] Refactor RTP cache reset --- trunk/src/kernel/srs_kernel_rtp.cpp | 30 +++++++++-------------------- trunk/src/kernel/srs_kernel_rtp.hpp | 3 +-- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 870b292ee..6f2918abb 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -55,27 +55,15 @@ SrsRtpHeader::SrsRtpHeader() extension_length = 0; } -SrsRtpHeader::SrsRtpHeader(const SrsRtpHeader& rhs) +void SrsRtpHeader::reset() { - operator=(rhs); -} - -SrsRtpHeader& SrsRtpHeader::operator=(const SrsRtpHeader& rhs) -{ - padding = rhs.padding; - extension = rhs.extension; - cc = rhs.cc; - marker = rhs.marker; - payload_type = rhs.payload_type; - sequence = rhs.sequence; - timestamp = rhs.timestamp; - ssrc = rhs.ssrc; - for (size_t i = 0; i < cc; ++i) { - csrc[i] = rhs.csrc[i]; - } - extension_length = rhs.extension_length; - - return *this; + // We only reset the optional fields, the required field such as ssrc + // will always be set by user. + padding = false; + extension = false; + cc = 0; + marker = false; + extension_length = 0; } SrsRtpHeader::~SrsRtpHeader() @@ -173,7 +161,7 @@ void SrsRtpPacket2::set_padding(int size) void SrsRtpPacket2::reset() { - memset((void*)&rtp_header, 0, sizeof(SrsRtpHeader)); + rtp_header.reset(); padding = 0; srs_freep(payload); } diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 1b4fd2de6..57fdbd706 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -56,8 +56,7 @@ private: public: SrsRtpHeader(); virtual ~SrsRtpHeader(); - SrsRtpHeader(const SrsRtpHeader& rhs); - SrsRtpHeader& operator=(const SrsRtpHeader& rhs); + void reset(); public: srs_error_t decode(SrsBuffer* stream); srs_error_t encode(SrsBuffer* stream); From bbe4b3797d24b8f6c686d47025379488ec1134f2 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 13:49:37 +0800 Subject: [PATCH 104/131] Refactor stat logs for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b1b92abaf..8a4d4cc8d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1960,7 +1960,7 @@ srs_error_t SrsUdpMuxSender::cycle() cache.swap(hotspot); cache_pos = 0; - // Collect informations for GSO + // Collect informations for GSO. if (pos > 0) { // For shared GSO cache, stat the messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; @@ -1977,7 +1977,7 @@ srs_error_t SrsUdpMuxSender::cycle() } } - // Send out all messages, may GSO if shared cache. + // Send out all messages. if (pos > 0) { // Send out all messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; @@ -2020,9 +2020,15 @@ srs_error_t SrsUdpMuxSender::cycle() pps_unit = "(k)"; pps_last /= 1000; pps_average /= 1000; } - srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s", - srs_netfd_fileno(lfd), (int)server->nn_sessions(), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, nn_gso_iovs_max, nn_gso_iovs, - pps_average, pps_last, pps_unit.c_str()); + int nn_cache = 0; + for (vector::iterator it = hotspot.begin(); it < hotspot.end(); ++it) { + mmsghdr& hdr = *it; + nn_cache += hdr.msg_hdr.msg_iovlen; + } + + srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s, cache %d/%d", + srs_netfd_fileno(lfd), (int)server->nn_sessions(), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, + nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), (int)hotspot.size(), nn_cache); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; nn_gso_msgs_max = 0; nn_gso_iovs_max = 0; From d906ced5c3b23e22ccb29308b1d3d34f5717efd4 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 14:13:09 +0800 Subject: [PATCH 105/131] For #307, set cache to about 1.4GB when clients is 2k --- trunk/src/core/srs_core_performance.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index cbfddf1dc..6958aed4f 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -193,7 +193,15 @@ #undef SRS_PERF_GLIBC_MEMORY_CHECK // For RTC, how many iovs we alloc for each mmsghdr for GSO. -#define SRS_PERF_RTC_GSO_IOVS 4 +// Assume that there are 2400 clients, say, 60000 msgs in queue to send, the memory is: +// 2 # We have two queue, cache and hotspot. +// * 4 # We have reuseport, each have msg cache queue. +// * (64 + SRS_PERF_RTC_GSO_IOVS * 1500) # Each message size. +// * 60000 # Total messages. +// = 715MB # For SRS_PERF_RTC_GSO_IOVS = 1 +// = 1402MB # For SRS_PERF_RTC_GSO_IOVS = 2 +// = 2775MB # For SRS_PERF_RTC_GSO_IOVS = 4 +#define SRS_PERF_RTC_GSO_IOVS 2 #endif From d5c514cdcb3dd186c7cb66c983eddb6700071cda Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 14:28:59 +0800 Subject: [PATCH 106/131] For #307, reuse raw cache payload for RTP --- trunk/src/app/srs_app_rtc_conn.cpp | 3 +-- trunk/src/kernel/srs_kernel_rtp.cpp | 20 ++++++++++++++++++++ trunk/src/kernel/srs_kernel_rtp.hpp | 5 +++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 8a4d4cc8d..3c80902ce 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1244,10 +1244,9 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& pa packet->rtp_header.set_ssrc(audio_ssrc); packet->rtp_header.set_payload_type(audio_payload_type); - SrsRtpRawPayload* raw = new SrsRtpRawPayload(); + SrsRtpRawPayload* raw = packet->reuse_raw(); raw->payload = sample->bytes; raw->nn_payload = sample->size; - packet->payload = raw; // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 6f2918abb..c298b9a68 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -146,11 +146,19 @@ SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; padding = 0; + + cache_raw = new SrsRtpRawPayload(); } SrsRtpPacket2::~SrsRtpPacket2() { + // We may use the cache as payload. + if (payload == cache_raw) { + payload = NULL; + } + srs_freep(payload); + srs_freep(cache_raw); } void SrsRtpPacket2::set_padding(int size) @@ -163,9 +171,21 @@ void SrsRtpPacket2::reset() { rtp_header.reset(); padding = 0; + + // We may use the cache as payload. + if (payload == cache_raw) { + payload = NULL; + } + srs_freep(payload); } +SrsRtpRawPayload* SrsRtpPacket2::reuse_raw() +{ + payload = cache_raw; + return cache_raw; +} + int SrsRtpPacket2::nb_bytes() { return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 57fdbd706..2212853eb 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -38,6 +38,7 @@ const uint8_t kRtpMarker = 0x80; const uint8_t kNalTypeMask = 0x1F; class SrsBuffer; +class SrsRtpRawPayload; class SrsRtpHeader { @@ -82,6 +83,8 @@ public: SrsRtpHeader rtp_header; ISrsEncoder* payload; int padding; +private: + SrsRtpRawPayload* cache_raw; public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); @@ -90,6 +93,8 @@ public: void set_padding(int size); // Reset RTP packet. void reset(); + // Reuse the cached raw message as payload. + SrsRtpRawPayload* reuse_raw(); // interface ISrsEncoder public: virtual int nb_bytes(); From 3bd56bb3a3bca297be51438b3a424acbb8948d81 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 14:51:36 +0800 Subject: [PATCH 107/131] For #307, reuse fua cache payload for RTP --- trunk/src/app/srs_app_rtc_conn.cpp | 27 +++++++++++---------------- trunk/src/kernel/srs_kernel_rtp.cpp | 22 ++++++++++++++++++++-- trunk/src/kernel/srs_kernel_rtp.hpp | 6 ++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 3c80902ce..87f664590 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1182,10 +1182,12 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. SrsRtpPacket2* packet = packets.fetch(); + packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); + packet->payload = raw; } else { SrsAutoFree(SrsRtpRawNALUs, raw); @@ -1202,12 +1204,6 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac for (int i = 0; i < num_of_packet; ++i) { int packet_size = srs_min(nb_left, fu_payload_size); - SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); - if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { - srs_freep(fua); - return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); - } - SrsRtpPacket2* packet = packets.fetch(); packet->rtp_header.set_timestamp(msg->timestamp * 90); @@ -1215,13 +1211,17 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - packet->payload = fua; + SrsRtpFUAPayload* fua = packet->reuse_fua(); fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); + if ((err = raw->read_samples(fua->nalus, packet_size)) != srs_success) { + return srs_error_wrap(err, "read samples %d bytes, left %d, total %d", packet_size, nb_left, nn_bytes); + } + nb_left -= packet_size; } } @@ -1274,8 +1274,7 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); - packet->payload = fua; + SrsRtpFUAPayload* fua = packet->reuse_fua(); fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; @@ -1305,13 +1304,9 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, Srs packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpRawNALUs* raw = new SrsRtpRawNALUs(); - packet->payload = raw; - - SrsSample* p = new SrsSample(); - p->bytes = sample->bytes; - p->size = sample->size; - raw->push_back(p); + SrsRtpRawPayload* raw = packet->reuse_raw(); + raw->payload = sample->bytes; + raw->nn_payload = sample->size; return err; } diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index c298b9a68..c6b071de8 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -148,12 +148,13 @@ SrsRtpPacket2::SrsRtpPacket2() padding = 0; cache_raw = new SrsRtpRawPayload(); + cache_fua = new SrsRtpFUAPayload(); } SrsRtpPacket2::~SrsRtpPacket2() { // We may use the cache as payload. - if (payload == cache_raw) { + if (payload == cache_raw || payload == cache_fua) { payload = NULL; } @@ -173,7 +174,7 @@ void SrsRtpPacket2::reset() padding = 0; // We may use the cache as payload. - if (payload == cache_raw) { + if (payload == cache_raw || payload == cache_fua) { payload = NULL; } @@ -186,6 +187,13 @@ SrsRtpRawPayload* SrsRtpPacket2::reuse_raw() return cache_raw; } +SrsRtpFUAPayload* SrsRtpPacket2::reuse_fua() +{ + payload = cache_fua; + cache_fua->reset(); + return cache_fua; +} + int SrsRtpPacket2::nb_bytes() { return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; @@ -421,6 +429,16 @@ SrsRtpFUAPayload::~SrsRtpFUAPayload() nalus.clear(); } +void SrsRtpFUAPayload::reset() +{ + vector::iterator it; + for (it = nalus.begin(); it != nalus.end(); ++it) { + SrsSample* p = *it; + srs_freep(p); + } + nalus.clear(); +} + int SrsRtpFUAPayload::nb_bytes() { int size = 2; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 2212853eb..f093f72bf 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -39,6 +39,7 @@ const uint8_t kNalTypeMask = 0x1F; class SrsBuffer; class SrsRtpRawPayload; +class SrsRtpFUAPayload; class SrsRtpHeader { @@ -85,6 +86,7 @@ public: int padding; private: SrsRtpRawPayload* cache_raw; + SrsRtpFUAPayload* cache_fua; public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); @@ -95,6 +97,8 @@ public: void reset(); // Reuse the cached raw message as payload. SrsRtpRawPayload* reuse_raw(); + // Reuse the cached fua message as payload. + SrsRtpFUAPayload* reuse_fua(); // interface ISrsEncoder public: virtual int nb_bytes(); @@ -172,6 +176,8 @@ public: public: SrsRtpFUAPayload(); virtual ~SrsRtpFUAPayload(); +public: + void reset(); // interface ISrsEncoder public: virtual int nb_bytes(); From 634225f92fcde8091bf2631ecc1451842a671995 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 18:04:56 +0800 Subject: [PATCH 108/131] Improve perforance of marshaling RTP header --- trunk/src/kernel/srs_kernel_rtp.cpp | 45 ++++++++++++++++++++++++----- trunk/src/kernel/srs_kernel_rtp.hpp | 2 +- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index c6b071de8..3798fe987 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -83,6 +83,12 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream) { srs_error_t err = srs_success; + // Encode the RTP fix header, 12bytes. + // @see https://tools.ietf.org/html/rfc1889#section-5.1 + char* op = stream->data() + stream->pos(); + char* p = op; + + // The version, padding, extension and cc, total 1 byte. uint8_t v = 0x80 | cc; if (padding) { v |= 0x20; @@ -90,25 +96,50 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream) if (extension) { v |= 0x10; } - stream->write_1bytes(v); + *p++ = v; + // The marker and payload type, total 1 byte. v = payload_type; if (marker) { v |= kRtpMarker; } - stream->write_1bytes(v); + *p++ = v; - stream->write_2bytes(sequence); - stream->write_4bytes(timestamp); - stream->write_4bytes(ssrc); + // The sequence number, 2 bytes. + char* pp = (char*)&sequence; + *p++ = pp[1]; + *p++ = pp[0]; + + // The timestamp, 4 bytes. + pp = (char*)×tamp; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; + + // The SSRC, 4 bytes. + pp = (char*)&ssrc; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; + + // The CSRC list: 0 to 15 items, each is 4 bytes. for (size_t i = 0; i < cc; ++i) { - stream->write_4bytes(csrc[i]); + pp = (char*)&csrc[i]; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; } // TODO: Write exteinsion field. if (extension) { } + // Consume the data. + stream->skip(p - op); + return err; } @@ -134,7 +165,7 @@ void SrsRtpHeader::set_sequence(uint16_t sequence) void SrsRtpHeader::set_timestamp(int64_t timestamp) { - this->timestamp = timestamp; + this->timestamp = (uint32_t)timestamp; } void SrsRtpHeader::set_ssrc(uint32_t ssrc) diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index f093f72bf..615194a3d 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -50,7 +50,7 @@ private: bool marker; uint8_t payload_type; uint16_t sequence; - int64_t timestamp; + int32_t timestamp; uint32_t ssrc; uint32_t csrc[15]; uint16_t extension_length; From 810b32138e8592d56970d4df61b9a8bb16db5268 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 18:25:11 +0800 Subject: [PATCH 109/131] Refactor code --- trunk/src/app/srs_app_rtc_conn.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 87f664590..c1804f62e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1967,7 +1967,8 @@ srs_error_t SrsUdpMuxSender::cycle() int real_iovs = p->msg_len; p->msg_len = 0; - gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; + gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; + gso_iovs += real_iovs; } } @@ -2015,9 +2016,10 @@ srs_error_t SrsUdpMuxSender::cycle() } int nn_cache = 0; - for (vector::iterator it = hotspot.begin(); it < hotspot.end(); ++it) { - mmsghdr& hdr = *it; - nn_cache += hdr.msg_hdr.msg_iovlen; + int nn_hotspot_size = (int)hotspot.size(); + for (int i = 0; i < nn_hotspot_size; i++) { + mmsghdr* hdr = &hotspot[i]; + nn_cache += hdr->msg_hdr.msg_iovlen; } srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s, cache %d/%d", From 1a6e055f7fbc20da9469a7984fdddca99787d72b Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 18:37:37 +0800 Subject: [PATCH 110/131] Support config to disable stat to improve performance. --- trunk/conf/full.conf | 3 +++ trunk/src/app/srs_app_config.cpp | 19 ++++++++++++++++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_http_api.cpp | 3 ++- trunk/src/app/srs_app_rtc_conn.cpp | 34 ++++++++++++++++++------------ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 646d82b2b..7cc2c5593 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -448,6 +448,9 @@ rtc_server { # @remark The max padding size is 0x7f(127). # default: 127 padding 127; + # Whether enable the perf stat at http://localhost:1985/api/v1/perf + # default: off + perf_stat off; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index fcea9fde3..66e5942e5 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3619,7 +3619,7 @@ srs_error_t SrsConfig::check_normal_config() string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus" - && n != "padding") { + && n != "padding" && n != "perf_stat") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4858,6 +4858,23 @@ int SrsConfig::get_rtc_server_padding() return srs_min(127, ::atoi(conf->arg0().c_str())); } +bool SrsConfig::get_rtc_server_perf_stat() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("perf_stat"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 8d31ef86e..0d2d0c4cc 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -537,6 +537,7 @@ private: virtual bool get_rtc_server_gso2(); public: virtual int get_rtc_server_padding(); + virtual bool get_rtc_server_perf_stat(); public: SrsConfDirective* get_rtc(std::string vhost); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 6c9b9fbc5..e994b9982 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1616,7 +1616,8 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* string target = r->query_get("target"); string reset = r->query_get("reset"); - srs_trace("query target=%s, reset=%s", target.c_str(), reset.c_str()); + srs_trace("query target=%s, reset=%s, rtc_stat_enabled=%d", target.c_str(), reset.c_str(), + _srs_config->get_rtc_server_perf_stat()); if (true) { SrsJsonObject* p = SrsJsonAny::object(); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c1804f62e..d35290f0f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -686,6 +686,7 @@ srs_error_t SrsRtcSenderThread::cycle() SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); SrsAutoFree(SrsPithyPrint, pprint); + bool stat_enabled = _srs_config->get_rtc_server_perf_stat(); SrsStatistic* stat = SrsStatistic::instance(); while (true) { @@ -729,17 +730,20 @@ srs_error_t SrsRtcSenderThread::cycle() srs_freep(msg); } - // Stat the original RAW AV frame, maybe h264+aac. - stat->perf_on_msgs(msg_count); - // Stat the RTC packets, RAW AV frame, maybe h.264+opus. - int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; - stat->perf_on_rtc_packets(nn_rtc_packets); - // Stat the RAW RTP packets, which maybe group by GSO. - stat->perf_on_rtp_packets(pkts.size()); - // Stat the RTP packets going into kernel. - stat->perf_on_gso_packets(pkts.nn_rtp_pkts); - // Stat the bytes and paddings. - stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); + // Stat for performance analysis. + if (stat_enabled) { + // Stat the original RAW AV frame, maybe h264+aac. + stat->perf_on_msgs(msg_count); + // Stat the RTC packets, RAW AV frame, maybe h.264+opus. + int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; + stat->perf_on_rtc_packets(nn_rtc_packets); + // Stat the RAW RTP packets, which maybe group by GSO. + stat->perf_on_rtp_packets(pkts.size()); + // Stat the RTP packets going into kernel. + stat->perf_on_gso_packets(pkts.nn_rtp_pkts); + // Stat the bytes and paddings. + stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); + } #if defined(SRS_DEBUG) srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, @@ -1928,6 +1932,8 @@ srs_error_t SrsUdpMuxSender::cycle() uint64_t nn_gso_msgs = 0; uint64_t nn_gso_iovs = 0; int nn_gso_msgs_max = 0; int nn_gso_iovs_max = 0; int nn_loop = 0; int nn_wait = 0; srs_utime_t time_last = srs_get_system_time(); + + bool stat_enabled = _srs_config->get_rtc_server_perf_stat(); SrsStatistic* stat = SrsStatistic::instance(); SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_send(srs_netfd_fileno(lfd)); @@ -1955,7 +1961,7 @@ srs_error_t SrsUdpMuxSender::cycle() cache_pos = 0; // Collect informations for GSO. - if (pos > 0) { + if (pos > 0 && stat_enabled) { // For shared GSO cache, stat the messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p++) { @@ -1985,7 +1991,9 @@ srs_error_t SrsUdpMuxSender::cycle() srs_warn("sendmmsg %d msgs, %d done", vlen, r0); } - stat->perf_on_sendmmsg_packets(vlen); + if (stat_enabled) { + stat->perf_on_sendmmsg_packets(vlen); + } } } From 32f43a992091be567821cb727873903b61b6e279 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 18:52:17 +0800 Subject: [PATCH 111/131] For RTC, always try to read message first, to improve performance --- trunk/src/app/srs_app_rtc_conn.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d35290f0f..c3232a476 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -694,26 +694,24 @@ srs_error_t SrsRtcSenderThread::cycle() return srs_error_wrap(err, "rtc sender thread"); } -#ifdef SRS_PERF_QUEUE_COND_WAIT - if (realtime) { - // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); - } else { - // for no-realtime, got some msgs then send. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); - } -#endif - int msg_count = 0; if ((err = consumer->dump_packets(&msgs, msg_count)) != srs_success) { continue; } - if (msg_count <= 0) { -#ifndef SRS_PERF_QUEUE_COND_WAIT + // For RTC, we always try to read messages, only wait when no message. + if (msg_count <= 0) { +#ifdef SRS_PERF_QUEUE_COND_WAIT + if (realtime) { + // for realtime, min required msgs is 0, send when got one+ msgs. + consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); + } else { + // for no-realtime, got some msgs then send. + consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); + } +#else srs_usleep(mw_sleep); #endif - // ignore when nothing got. continue; } From 8383f1b27a6561ff7fd837e4eace375caeb97e33 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 16 Apr 2020 19:33:10 +0800 Subject: [PATCH 112/131] Improve performance for GSO --- trunk/src/app/srs_app_rtc_conn.cpp | 45 +++++++++++++++++------------- trunk/src/app/srs_app_rtc_conn.hpp | 8 ++++-- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index c3232a476..d84ead035 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -548,6 +548,8 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int rtc_session = s; sendonly_ukt = u->copy_sendonly(); + sender = u->sender(); + gso = false; merge_nalus = false; max_padding = 0; @@ -652,6 +654,7 @@ void SrsRtcSenderThread::update_sendonly_socket(SrsUdpMuxSocket* skt) srs_freep(sendonly_ukt); sendonly_ukt = skt->copy_sendonly(); + sender = skt->sender(); } srs_error_t SrsRtcSenderThread::cycle() @@ -701,6 +704,8 @@ srs_error_t SrsRtcSenderThread::cycle() // For RTC, we always try to read messages, only wait when no message. if (msg_count <= 0) { + srs_usleep(0); + #ifdef SRS_PERF_QUEUE_COND_WAIT if (realtime) { // for realtime, min required msgs is 0, send when got one+ msgs. @@ -718,7 +723,7 @@ srs_error_t SrsRtcSenderThread::cycle() // Transmux and send out messages. pkts.reset(gso, merge_nalus); - if ((err = send_messages(sendonly_ukt, source, msgs.msgs, msg_count, pkts)) != srs_success) { + if ((err = send_messages(source, msgs.msgs, msg_count, pkts)) != srs_success) { srs_warn("send err %s", srs_error_summary(err).c_str()); srs_error_reset(err); } @@ -759,7 +764,7 @@ srs_error_t SrsRtcSenderThread::cycle() } srs_error_t SrsRtcSenderThread::send_messages( - SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets + SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets ) { srs_error_t err = srs_success; @@ -775,7 +780,7 @@ srs_error_t SrsRtcSenderThread::send_messages( #ifndef SRS_AUTO_OSX // If enabled GSO, send out some packets in a msghdr. if (packets.use_gso) { - if ((err = send_packets_gso(skt, packets)) != srs_success) { + if ((err = send_packets_gso(packets)) != srs_success) { return srs_error_wrap(err, "gso send"); } return err; @@ -783,7 +788,7 @@ srs_error_t SrsRtcSenderThread::send_messages( #endif // By default, we send packets by sendmmsg. - if ((err = send_packets(skt, packets)) != srs_success) { + if ((err = send_packets(packets)) != srs_success) { return srs_error_wrap(err, "raw send"); } @@ -867,12 +872,10 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( return err; } -srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) +srs_error_t SrsRtcSenderThread::send_packets(SrsRtcPackets& packets) { srs_error_t err = srs_success; - ISrsUdpSender* sender = skt->sender(); - int nn_packets = packets.size(); for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.at(i); @@ -913,8 +916,8 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets } } - sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); - socklen_t addrlen = (socklen_t)skt->peer_addrlen(); + sockaddr_in* addr = (sockaddr_in*)sendonly_ukt->peer_addr(); + socklen_t addrlen = (socklen_t)sendonly_ukt->peer_addrlen(); mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; @@ -934,7 +937,7 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets } // TODO: FIXME: We can gather and pad audios, because they have similar size. -srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets) +srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) { srs_error_t err = srs_success; @@ -943,7 +946,6 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac // GSO, N packets has same length, the final one may not. bool using_gso = false; bool gso_final = false; - ISrsUdpSender* sender = skt->sender(); int nn_packets = packets.size(); for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.at(i); @@ -1108,8 +1110,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPac #endif if (do_send) { - sockaddr_in* addr = (sockaddr_in*)skt->peer_addr(); - socklen_t addrlen = (socklen_t)skt->peer_addrlen(); + sockaddr_in* addr = (sockaddr_in*)sendonly_ukt->peer_addr(); + socklen_t addrlen = (socklen_t)sendonly_ukt->peer_addrlen(); mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; @@ -1945,13 +1947,17 @@ srs_error_t SrsUdpMuxSender::cycle() nn_loop++; int pos = cache_pos; - int gso_pos = 0; int gso_iovs = 0; - if (pos <= 0 && gso_pos == 0) { - waiting_msgs = true; - nn_wait++; - srs_cond_wait(cond); - continue; + if (pos <= 0) { + srs_usleep(0); + if (pos <= 0) { + waiting_msgs = true; + nn_wait++; + srs_cond_wait(cond); + } + if (pos <= 0) { + continue; + } } // We are working on hotspot now. @@ -1959,6 +1965,7 @@ srs_error_t SrsUdpMuxSender::cycle() cache_pos = 0; // Collect informations for GSO. + int gso_pos = 0; if (pos > 0 && stat_enabled) { // For shared GSO cache, stat the messages. mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 0af9d0b5e..a1fe62514 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -50,6 +50,7 @@ class SrsRtcSession; class SrsSharedPtrMessage; class SrsSource; class SrsRtpPacket2; +class ISrsUdpSender; const uint8_t kSR = 200; const uint8_t kRR = 201; @@ -182,6 +183,7 @@ private: uint16_t video_sequence; public: SrsUdpMuxSocket* sendonly_ukt; + ISrsUdpSender* sender; bool merge_nalus; bool gso; int max_padding; @@ -204,10 +206,10 @@ public: public: virtual srs_error_t cycle(); private: - srs_error_t send_messages(SrsUdpMuxSocket* skt, SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); + srs_error_t send_messages(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); srs_error_t messages_to_packets(SrsSource* source, SrsSharedPtrMessage** msgs, int nb_msgs, SrsRtcPackets& packets); - srs_error_t send_packets(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); - srs_error_t send_packets_gso(SrsUdpMuxSocket* skt, SrsRtcPackets& packets); + srs_error_t send_packets(SrsRtcPackets& packets); + srs_error_t send_packets_gso(SrsRtcPackets& packets); private: srs_error_t packet_opus(SrsSample* sample, SrsRtcPackets& packets); private: From f0015a7cc1caf6b0c63c0917bc34d0f11f943731 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 07:10:16 +0800 Subject: [PATCH 113/131] For #307, refine GSO performance, alloc iovs --- trunk/src/app/srs_app_rtc_conn.cpp | 130 +++++++++--------------- trunk/src/core/srs_core_performance.hpp | 9 +- trunk/src/service/srs_service_st.cpp | 2 + 3 files changed, 58 insertions(+), 83 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d84ead035..d18602ed5 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -704,8 +704,6 @@ srs_error_t SrsRtcSenderThread::cycle() // For RTC, we always try to read messages, only wait when no message. if (msg_count <= 0) { - srs_usleep(0); - #ifdef SRS_PERF_QUEUE_COND_WAIT if (realtime) { // for realtime, min required msgs is 0, send when got one+ msgs. @@ -887,43 +885,40 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsRtcPackets& packets) return srs_error_wrap(err, "fetch msghdr"); } - // Reset the iovec, we should never change the msg_iovlen. - for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { - iovec* p = mhdr->msg_hdr.msg_iov + j; + // For this message, select the first iovec. + iovec* iov = mhdr->msg_hdr.msg_iov; + mhdr->msg_hdr.msg_iovlen = 1; - if (!p->iov_len) { - break; - } - p->iov_len = 0; + if (!iov->iov_base) { + iov->iov_base = new char[kRtpPacketSize]; } + iov->iov_len = kRtpPacketSize; - char* buf = (char*)mhdr->msg_hdr.msg_iov->iov_base; - int length = kRtpPacketSize; - - // Marshal packet to bytes. + // Marshal packet to bytes in iovec. if (true) { - SrsBuffer stream(buf, length); + SrsBuffer stream((char*)iov->iov_base, iov->iov_len); if ((err = packet->encode(&stream)) != srs_success) { return srs_error_wrap(err, "encode packet"); } - length = stream.pos(); + iov->iov_len = stream.pos(); } // Whether encrypt the RTP bytes. if (rtc_session->encrypt) { - if ((err = rtc_session->dtls_session->protect_rtp2(buf, &length)) != srs_success) { + int nn_encrypt = (int)iov->iov_len; + if ((err = rtc_session->dtls_session->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) { return srs_error_wrap(err, "srtp protect"); } + iov->iov_len = (size_t)nn_encrypt; } + // Set the address and control information. sockaddr_in* addr = (sockaddr_in*)sendonly_ukt->peer_addr(); socklen_t addrlen = (socklen_t)sendonly_ukt->peer_addrlen(); mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; - mhdr->msg_hdr.msg_iov->iov_len = length; mhdr->msg_hdr.msg_controllen = 0; - mhdr->msg_len = 0; // When we send out a packet, we commit a RTP packet. packets.nn_rtp_pkts++; @@ -996,23 +991,6 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) using_gso = true; gso_final = (gso_size && gso_size != nn_packet); mhdr = gso_mhdr; - - // We need to increase the iov and cursor. - int nb_iovs = mhdr->msg_hdr.msg_iovlen; - if (gso_cursor >= nb_iovs - 1) { - int nn_new_iovs = 1; - mhdr->msg_hdr.msg_iovlen = nb_iovs + nn_new_iovs; - mhdr->msg_hdr.msg_iov = (iovec*)realloc(mhdr->msg_hdr.msg_iov, sizeof(iovec) * (nb_iovs + nn_new_iovs)); - memset(mhdr->msg_hdr.msg_iov + nb_iovs, 0, sizeof(iovec) * nn_new_iovs); - } - gso_cursor++; - - // Create payload cache for RTP packet. - iovec* p = mhdr->msg_hdr.msg_iov + gso_cursor; - if (!p->iov_base) { - p->iov_base = new char[kRtpPacketSize]; - p->iov_len = kRtpPacketSize; - } } // Change the state according to the next packet. @@ -1037,16 +1015,6 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) return srs_error_wrap(err, "fetch msghdr"); } - // Reset the iovec, we should never change the msg_iovlen. - for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { - iovec* p = mhdr->msg_hdr.msg_iov + j; - - if (!p->iov_len) { - break; - } - p->iov_len = 0; - } - // Now, GSO will use this message and size. if (using_gso) { gso_mhdr = mhdr; @@ -1054,10 +1022,17 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } } - // Marshal packet to bytes. + // For this message, select a new iovec. iovec* iov = mhdr->msg_hdr.msg_iov + gso_cursor; + mhdr->msg_hdr.msg_iovlen = gso_cursor + 1; + gso_cursor++; + + if (!iov->iov_base) { + iov->iov_base = new char[kRtpPacketSize]; + } iov->iov_len = kRtpPacketSize; + // Marshal packet to bytes in iovec. if (true) { SrsBuffer stream((char*)iov->iov_base, iov->iov_len); if ((err = packet->encode(&stream)) != srs_success) { @@ -1085,7 +1060,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } // If exceed the max GSO size, set to final. - if (using_gso && gso_cursor > 64) { + if (using_gso && gso_cursor + 1 >= SRS_PERF_RTC_GSO_MAX) { gso_final = true; } @@ -1099,10 +1074,6 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) if (do_send) { for (int j = 0; j < (int)mhdr->msg_hdr.msg_iovlen; j++) { iovec* iov = mhdr->msg_hdr.msg_iov + j; - - if (iov->iov_len <= 0) { - break; - } srs_trace("#%d, %s #%d/%d/%d, %d/%d bytes, size %d/%d", packets.debug_id, (using_gso? "GSO":"RAW"), j, gso_cursor + 1, mhdr->msg_hdr.msg_iovlen, iov->iov_len, padding, gso_size, gso_encrypt); } @@ -1110,13 +1081,13 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) #endif if (do_send) { + // Set the address and control information. sockaddr_in* addr = (sockaddr_in*)sendonly_ukt->peer_addr(); socklen_t addrlen = (socklen_t)sendonly_ukt->peer_addrlen(); mhdr->msg_hdr.msg_name = (sockaddr_in*)addr; mhdr->msg_hdr.msg_namelen = (socklen_t)addrlen; mhdr->msg_hdr.msg_controllen = 0; - mhdr->msg_len = 0; #ifndef SRS_AUTO_OSX if (using_gso) { @@ -1130,9 +1101,6 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) cm->cmsg_type = UDP_SEGMENT; cm->cmsg_len = CMSG_LEN(sizeof(uint16_t)); *((uint16_t*)CMSG_DATA(cm)) = gso_encrypt; - - // Private message, use it to store the cursor. - mhdr->msg_len = gso_cursor + 1; } #endif @@ -1870,18 +1838,21 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) void SrsUdpMuxSender::free_mhdrs(std::vector& mhdrs) { - for (int i = 0; i < (int)mhdrs.size(); i++) { + int nn_mhdrs = (int)mhdrs.size(); + for (int i = 0; i < nn_mhdrs; i++) { + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg mmsghdr* hdr = &mhdrs[i]; // Free control for GSO. char* msg_control = (char*)hdr->msg_hdr.msg_control; - srs_freep(msg_control); + srs_freepa(msg_control); // Free iovec. - for (int j = (int)hdr->msg_hdr.msg_iovlen - 1; j >= 0 ; j--) { + for (int j = SRS_PERF_RTC_GSO_MAX - 1; j >= 0 ; j--) { iovec* iov = hdr->msg_hdr.msg_iov + j; char* data = (char*)iov->iov_base; - srs_freep(data); + srs_freepa(data); srs_freepa(iov); } } @@ -1892,19 +1863,21 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) { // TODO: FIXME: Maybe need to shrink? if (cache_pos >= (int)cache.size()) { + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg mmsghdr mhdr; - memset(&mhdr, 0, sizeof(mmsghdr)); mhdr.msg_len = 0; + mhdr.msg_hdr.msg_flags = 0; + mhdr.msg_hdr.msg_control = NULL; - mhdr.msg_hdr.msg_iovlen = SRS_PERF_RTC_GSO_IOVS; + mhdr.msg_hdr.msg_iovlen = SRS_PERF_RTC_GSO_MAX; mhdr.msg_hdr.msg_iov = new iovec[mhdr.msg_hdr.msg_iovlen]; + memset((void*)mhdr.msg_hdr.msg_iov, 0, sizeof(iovec) * mhdr.msg_hdr.msg_iovlen); - for (int i = 0; i < (int)mhdr.msg_hdr.msg_iovlen; i++) { + for (int i = 0; i < SRS_PERF_RTC_GSO_IOVS; i++) { iovec* p = mhdr.msg_hdr.msg_iov + i; - p->iov_base = new char[kRtpPacketSize]; - p->iov_len = kRtpPacketSize; } cache.push_back(mhdr); @@ -1949,15 +1922,10 @@ srs_error_t SrsUdpMuxSender::cycle() int pos = cache_pos; int gso_iovs = 0; if (pos <= 0) { - srs_usleep(0); - if (pos <= 0) { - waiting_msgs = true; - nn_wait++; - srs_cond_wait(cond); - } - if (pos <= 0) { - continue; - } + waiting_msgs = true; + nn_wait++; + srs_cond_wait(cond); + continue; } // We are working on hotspot now. @@ -1968,16 +1936,12 @@ srs_error_t SrsUdpMuxSender::cycle() int gso_pos = 0; if (pos > 0 && stat_enabled) { // For shared GSO cache, stat the messages. - mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; - for (p = &hotspot[0]; p < end; p++) { - if (!p->msg_len) { - continue; - } - - // Private message, use it to store the cursor. - int real_iovs = p->msg_len; - p->msg_len = 0; + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg + for (int i = 0; i < pos; i++) { + mmsghdr* mhdr = &hotspot[i]; + int real_iovs = mhdr->msg_hdr.msg_iovlen; gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; gso_iovs += real_iovs; } @@ -1986,6 +1950,8 @@ srs_error_t SrsUdpMuxSender::cycle() // Send out all messages. if (pos > 0) { // Send out all messages. + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg mmsghdr* p = &hotspot[0]; mmsghdr* end = p + pos; for (p = &hotspot[0]; p < end; p += max_sendmmsg) { int vlen = (int)(end - p); diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 6958aed4f..01c6138f7 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -201,7 +201,14 @@ // = 715MB # For SRS_PERF_RTC_GSO_IOVS = 1 // = 1402MB # For SRS_PERF_RTC_GSO_IOVS = 2 // = 2775MB # For SRS_PERF_RTC_GSO_IOVS = 4 -#define SRS_PERF_RTC_GSO_IOVS 2 +#if defined(__linux__) + #define SRS_PERF_RTC_GSO_IOVS 2 +#else + #define SRS_PERF_RTC_GSO_IOVS 1 +#endif + +// For RTC, the max iovs in msghdr, the max packets sent in a msghdr. +#define SRS_PERF_RTC_GSO_MAX 64 #endif diff --git a/trunk/src/service/srs_service_st.cpp b/trunk/src/service/srs_service_st.cpp index 4e1e1bc01..da54a5dae 100644 --- a/trunk/src/service/srs_service_st.cpp +++ b/trunk/src/service/srs_service_st.cpp @@ -436,6 +436,8 @@ int srs_sendmmsg(srs_netfd_t stfd, struct mmsghdr *msgvec, unsigned int vlen, in } msgvec->msg_len = r0; #else + msgvec->msg_len = 0; + int tolen = (int)msgvec->msg_hdr.msg_namelen; const struct sockaddr* to = (const struct sockaddr*)msgvec->msg_hdr.msg_name; for (int i = 0; i < (int)msgvec->msg_hdr.msg_iovlen; i++) { From 21ede1f08417502eca564fe8b2e61988c539a553 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 07:57:52 +0800 Subject: [PATCH 114/131] Enable perf stat by default --- trunk/conf/full.conf | 4 ++-- trunk/src/app/srs_app_config.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 7cc2c5593..643c364c8 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -449,8 +449,8 @@ rtc_server { # default: 127 padding 127; # Whether enable the perf stat at http://localhost:1985/api/v1/perf - # default: off - perf_stat off; + # default: on + perf_stat on; } vhost rtc.vhost.srs.com { diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 66e5942e5..d2fae574d 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -4860,7 +4860,7 @@ int SrsConfig::get_rtc_server_padding() bool SrsConfig::get_rtc_server_perf_stat() { - static bool DEFAULT = false; + static bool DEFAULT = true; SrsConfDirective* conf = root->get("rtc_server"); if (!conf) { @@ -4872,7 +4872,7 @@ bool SrsConfig::get_rtc_server_perf_stat() return DEFAULT; } - return SRS_CONF_PERFER_FALSE(conf->arg0()); + return SRS_CONF_PERFER_TRUE(conf->arg0()); } SrsConfDirective* SrsConfig::get_rtc(string vhost) From acc471b0a9acae80f464f5d378b27f720158f9e6 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 07:58:11 +0800 Subject: [PATCH 115/131] For #307, refine the GSO for performance --- trunk/src/app/srs_app_rtc_conn.cpp | 41 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d18602ed5..5b802684a 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -940,6 +940,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) mmsghdr* gso_mhdr = NULL; int gso_size = 0; int gso_encrypt = 0; int gso_cursor = 0; // GSO, N packets has same length, the final one may not. bool using_gso = false; bool gso_final = false; + // The message will marshal in iovec. + iovec* iov = NULL; int nn_packets = packets.size(); for (int i = 0; i < nn_packets; i++) { @@ -986,28 +988,25 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } // Check whether we can use GSO to send it. - mmsghdr* mhdr = NULL; - if ((gso_size && gso_size == nn_packet) || (using_gso && !gso_final)) { - using_gso = true; - gso_final = (gso_size && gso_size != nn_packet); - mhdr = gso_mhdr; + if (using_gso && !gso_final) { + gso_final = (gso_size != nn_packet); } - // Change the state according to the next packet. if (next_packet) { - // If GSO, but next is bigger than this one, we must enter the final state. - if (using_gso && !gso_final) { - gso_final = (nn_packet < nn_next_packet); - } - // If not GSO, maybe the first fresh packet, we should see whether the next packet is smaller than this one, // if smaller, we can still enter GSO. if (!using_gso) { using_gso = (nn_packet >= nn_next_packet); } + + // If GSO, but next is bigger than this one, we must enter the final state. + if (using_gso && !gso_final) { + gso_final = (nn_packet < nn_next_packet); + } } - // Now, we fetch the msg from cache. + // For GSO, reuse mhdr if possible. + mmsghdr* mhdr = gso_mhdr; if (!mhdr) { // Fetch a cached message from queue. // TODO: FIXME: Maybe encrypt in async, so the state of mhdr maybe not ready. @@ -1016,18 +1015,20 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } // Now, GSO will use this message and size. - if (using_gso) { - gso_mhdr = mhdr; - gso_size = nn_packet; - } + gso_mhdr = mhdr; + gso_size = nn_packet; } // For this message, select a new iovec. - iovec* iov = mhdr->msg_hdr.msg_iov + gso_cursor; - mhdr->msg_hdr.msg_iovlen = gso_cursor + 1; + if (!iov) { + iov = mhdr->msg_hdr.msg_iov; + } else { + iov++; + } gso_cursor++; + mhdr->msg_hdr.msg_iovlen = gso_cursor; - if (!iov->iov_base) { + if (gso_cursor > SRS_PERF_RTC_GSO_IOVS && !iov->iov_base) { iov->iov_base = new char[kRtpPacketSize]; } iov->iov_len = kRtpPacketSize; @@ -1113,7 +1114,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) // Reset the GSO flag. gso_mhdr = NULL; gso_size = 0; gso_encrypt = 0; gso_cursor = 0; - using_gso = gso_final = false; + using_gso = gso_final = false; iov = NULL; } } From 606f8873b322c9f3e18c0c5cbe4ecd612555ebc0 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 10:42:04 +0800 Subject: [PATCH 116/131] Refactor code --- trunk/src/app/srs_app_rtc_conn.cpp | 60 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 5b802684a..239909c59 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -951,39 +951,41 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) SrsRtpPacket2* next_packet = NULL; int nn_next_packet = 0; - if (i < nn_packets - 1) { - next_packet = (i < nn_packets - 1)? packets.at(i + 1):NULL; - nn_next_packet = next_packet? next_packet->nb_bytes() : 0; - } - - // Padding the packet to next or GSO size. - if (max_padding > 0 && next_packet) { - if (!using_gso) { - // Padding to the next packet to merge with it. - if (nn_next_packet > nn_packet) { - padding = nn_next_packet - nn_packet; - } - } else { - // Padding to GSO size for next one to merge with us. - if (nn_next_packet < gso_size) { - padding = gso_size - nn_packet; - } + if (max_padding > 0) { + if (i < nn_packets - 1) { + next_packet = (i < nn_packets - 1)? packets.at(i + 1):NULL; + nn_next_packet = next_packet? next_packet->nb_bytes() : 0; } - // Reset padding if exceed max. - if (padding > max_padding) { - padding = 0; - } + // Padding the packet to next or GSO size. + if (next_packet) { + if (!using_gso) { + // Padding to the next packet to merge with it. + if (nn_next_packet > nn_packet) { + padding = nn_next_packet - nn_packet; + } + } else { + // Padding to GSO size for next one to merge with us. + if (nn_next_packet < gso_size) { + padding = gso_size - nn_packet; + } + } - if (padding > 0) { + // Reset padding if exceed max. + if (padding > max_padding) { + padding = 0; + } + + if (padding > 0) { #if defined(SRS_DEBUG) - srs_trace("#%d, Padding %d bytes %d=>%d, packets %d, max_padding %d", packets.debug_id, - padding, nn_packet, nn_packet + padding, nn_packets, max_padding); + srs_trace("#%d, Padding %d bytes %d=>%d, packets %d, max_padding %d", packets.debug_id, + padding, nn_packet, nn_packet + padding, nn_packets, max_padding); #endif - packet->set_padding(padding); - nn_packet += padding; - packets.nn_paddings++; - packets.nn_padding_bytes += padding; + packet->set_padding(padding); + nn_packet += padding; + packets.nn_paddings++; + packets.nn_padding_bytes += padding; + } } } @@ -1970,7 +1972,7 @@ srs_error_t SrsUdpMuxSender::cycle() } // Increase total messages. - nn_msgs += pos; + nn_msgs += pos + gso_iovs; nn_msgs_max = srs_max(pos, nn_msgs_max); nn_gso_msgs_max = srs_max(gso_pos, nn_gso_msgs_max); nn_gso_iovs_max = srs_max(gso_iovs, nn_gso_iovs_max); From 14e3ec2fe82c5ee7e6c3c114b73f166ea0b53175 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 12:30:53 +0800 Subject: [PATCH 117/131] For #307, drop frame when VBR too high --- trunk/conf/full.conf | 7 +++++++ trunk/scripts/perf_gso.py | 4 ++++ trunk/src/app/srs_app_config.cpp | 19 +++++++++++++++++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_http_api.cpp | 11 ++++++++++- trunk/src/app/srs_app_listener.hpp | 2 ++ trunk/src/app/srs_app_rtc_conn.cpp | 30 ++++++++++++++++++++++++----- trunk/src/app/srs_app_rtc_conn.hpp | 7 ++++++- trunk/src/app/srs_app_statistic.cpp | 27 ++++++++++++++++++++++++++ trunk/src/app/srs_app_statistic.hpp | 5 +++++ 10 files changed, 105 insertions(+), 8 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 643c364c8..98a8792dc 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -451,6 +451,13 @@ rtc_server { # Whether enable the perf stat at http://localhost:1985/api/v1/perf # default: on perf_stat on; + # The queue length, in number of mmsghdr, in messages. + # For example, 30 means we will cache 30K messages at most. + # If exceed, we will drop messages. + # @remark Each reuseport use a dedicated queue, if queue is 2000, reuseport is 4, + # then system queue is 2000*4 = 8k, user can incrase reuseport to incrase the queue. + # default: 2000 + queue_length 2000; } vhost rtc.vhost.srs.com { diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index f09014143..7180c7e4b 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -41,6 +41,10 @@ print "Repsonse %s"%(s) obj = json.loads(s) +print "" +p = obj['data']['dropped'] +print('RTC Frame Dropped: %s'%(100.0 * p['rtc_dropeed'] / p['rtc_frames'])) + # 2, 3, 5, 9, 16, 32, 64, 128, 256 keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] print("\n----------- 1 2 [3,4] [5,8] [9,15] [16,31] [32,63] [64,127] [128,255] [256,+) Packets"), diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index d2fae574d..eef0a325c 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3619,7 +3619,7 @@ srs_error_t SrsConfig::check_normal_config() string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" && n != "sendmmsg" && n != "encrypt" && n != "reuseport" && n != "gso" && n != "merge_nalus" - && n != "padding" && n != "perf_stat") { + && n != "padding" && n != "perf_stat" && n != "queue_length") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -4875,6 +4875,23 @@ bool SrsConfig::get_rtc_server_perf_stat() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +int SrsConfig::get_rtc_server_queue_length() +{ + static int DEFAULT = 2000; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("queue_length"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return ::atoi(conf->arg0().c_str()); +} + SrsConfDirective* SrsConfig::get_rtc(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 0d2d0c4cc..bc9417d76 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -538,6 +538,7 @@ private: public: virtual int get_rtc_server_padding(); virtual bool get_rtc_server_perf_stat(); + virtual int get_rtc_server_queue_length(); public: SrsConfDirective* get_rtc(std::string vhost); diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index e994b9982..fa0a7d9f5 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1625,7 +1625,7 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* p->set("target", SrsJsonAny::str(target.c_str())); p->set("reset", SrsJsonAny::str(reset.c_str())); - p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg|bytes")); + p->set("help", SrsJsonAny::str("?target=avframes|rtc|rtp|gso|writev_iovs|sendmmsg|bytes|dropped")); p->set("help2", SrsJsonAny::str("?reset=all")); } @@ -1697,6 +1697,15 @@ srs_error_t SrsGoApiPerf::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* } } + if (target.empty() || target == "dropped") { + SrsJsonObject* p = SrsJsonAny::object(); + data->set("dropped", p); + if ((err = stat->dumps_perf_dropped(p)) != srs_success) { + int code = srs_error_code(err); srs_error_reset(err); + return srs_api_response_code(w, r, code); + } + } + return srs_api_response(w, r, obj->dumps()); } diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 8ef384dd9..d096e5910 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -141,6 +141,8 @@ public: virtual srs_error_t fetch(mmsghdr** pphdr) = 0; // Notify the sender to send out the msg. virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0; + // Whether sender exceed the max queue, that is, overflow. + virtual bool overflow() = 0; }; class SrsUdpMuxSocket diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 239909c59..ad87e622e 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -473,6 +473,7 @@ SrsRtcPackets::SrsRtcPackets() nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; nn_padding_bytes = nn_paddings = 0; + nn_dropped = 0; cursor = 0; } @@ -505,6 +506,7 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; nn_padding_bytes = nn_paddings = 0; + nn_dropped = 0; cursor = 0; } @@ -744,6 +746,8 @@ srs_error_t SrsRtcSenderThread::cycle() stat->perf_on_gso_packets(pkts.nn_rtp_pkts); // Stat the bytes and paddings. stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); + // Stat the messages and dropped count. + stat->perf_on_dropped(msg_count, nn_rtc_packets, pkts.nn_dropped); } #if defined(SRS_DEBUG) srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", @@ -754,8 +758,8 @@ srs_error_t SrsRtcSenderThread::cycle() pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad, %d/%d cache", - msg_count, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, + srs_trace("-> RTC PLAY %d/%d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad, %d/%d cache", + msg_count, pkts.nn_dropped, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes, pkts.nn_paddings, pkts.size(), pkts.capacity()); } } @@ -766,6 +770,7 @@ srs_error_t SrsRtcSenderThread::send_messages( ) { srs_error_t err = srs_success; + // If DTLS is not OK, drop all messages. if (!rtc_session->dtls_session) { return err; } @@ -801,6 +806,12 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; + // If overflow, drop all messages. + if (sender->overflow()) { + packets.nn_dropped += nb_msgs - i; + return err; + } + // Update stats. packets.nn_bytes += msg->size; @@ -1802,6 +1813,8 @@ SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) trd = new SrsDummyCoroutine(); cache_pos = 0; + max_sendmmsg = 0; + queue_length = 0; _srs_config->subscribe(this); } @@ -1820,7 +1833,7 @@ SrsUdpMuxSender::~SrsUdpMuxSender() cache.clear(); } -srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) +srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd, int senders) { srs_error_t err = srs_success; @@ -1834,7 +1847,9 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd) max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); bool gso = _srs_config->get_rtc_server_gso(); - srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d", srs_netfd_fileno(fd), max_sendmmsg, gso); + queue_length = srs_max(128, _srs_config->get_rtc_server_queue_length()); + srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d, queue_max=%dx%d", srs_netfd_fileno(fd), + max_sendmmsg, gso, queue_length, senders); return err; } @@ -1890,6 +1905,11 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) return srs_success; } +bool SrsUdpMuxSender::overflow() +{ + return cache_pos > queue_length; +} + srs_error_t SrsUdpMuxSender::sendmmsg(mmsghdr* hdr) { if (waiting_msgs) { @@ -2098,7 +2118,7 @@ srs_error_t SrsRtcServer::listen_udp() return srs_error_wrap(err, "listen %s:%d", ip.c_str(), port); } - if ((err = sender->initialize(listener->stfd())) != srs_success) { + if ((err = sender->initialize(listener->stfd(), nn_listeners)) != srs_success) { return srs_error_wrap(err, "init sender"); } diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index a1fe62514..9f771028f 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -149,6 +149,8 @@ public: int nn_videos; // The number of padded packet. int nn_paddings; + // The number of dropped messages. + int nn_dropped; private: int cursor; std::vector packets; @@ -303,16 +305,19 @@ private: int cache_pos; // The max number of messages for sendmmsg. If 1, we use sendmsg to send. int max_sendmmsg; + // The total queue length, share with all senders. + int queue_length; public: SrsUdpMuxSender(SrsRtcServer* s); virtual ~SrsUdpMuxSender(); public: - virtual srs_error_t initialize(srs_netfd_t fd); + virtual srs_error_t initialize(srs_netfd_t fd, int senders); private: void free_mhdrs(std::vector& mhdrs); public: virtual srs_error_t fetch(mmsghdr** pphdr); virtual srs_error_t sendmmsg(mmsghdr* hdr); + virtual bool overflow(); virtual srs_error_t cycle(); // interface ISrsReloadHandler public: diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 4bf58aa99..6116c9f50 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -272,6 +272,7 @@ SrsStatistic::SrsStatistic() perf_rtp = new SrsStatisticCategory(); perf_rtc = new SrsStatisticCategory(); perf_bytes = new SrsStatisticCategory(); + perf_dropped = new SrsStatisticCategory(); } SrsStatistic::~SrsStatistic() @@ -313,6 +314,7 @@ SrsStatistic::~SrsStatistic() srs_freep(perf_rtp); srs_freep(perf_rtc); srs_freep(perf_bytes); + srs_freep(perf_dropped); } SrsStatistic* SrsStatistic::instance() @@ -673,6 +675,29 @@ srs_error_t SrsStatistic::dumps_perf_bytes(SrsJsonObject* obj) return srs_success; } +void SrsStatistic::perf_on_dropped(int nn_msgs, int nn_rtc, int nn_dropped) +{ + // a: System AVFrames. + // b: RTC frames. + // c: Dropped frames. + perf_dropped->a += nn_msgs; + perf_dropped->b += nn_rtc; + perf_dropped->c += nn_dropped; + + perf_dropped->nn += nn_dropped; +} + +srs_error_t SrsStatistic::dumps_perf_dropped(SrsJsonObject* obj) +{ + obj->set("avframes", SrsJsonAny::integer(perf_dropped->a)); + obj->set("rtc_frames", SrsJsonAny::integer(perf_dropped->b)); + obj->set("rtc_dropeed", SrsJsonAny::integer(perf_dropped->c)); + + obj->set("nn", SrsJsonAny::integer(perf_dropped->nn)); + + return srs_success; +} + void SrsStatistic::reset_perf() { srs_freep(perf_iovs); @@ -682,6 +707,7 @@ void SrsStatistic::reset_perf() srs_freep(perf_rtp); srs_freep(perf_rtc); srs_freep(perf_bytes); + srs_freep(perf_dropped); perf_iovs = new SrsStatisticCategory(); perf_msgs = new SrsStatisticCategory(); @@ -690,6 +716,7 @@ void SrsStatistic::reset_perf() perf_rtp = new SrsStatisticCategory(); perf_rtc = new SrsStatisticCategory(); perf_bytes = new SrsStatisticCategory(); + perf_dropped = new SrsStatisticCategory(); } void SrsStatistic::perf_on_packets(SrsStatisticCategory* p, int nb_msgs) diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 50fbb8516..919322098 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -175,6 +175,7 @@ private: SrsStatisticCategory* perf_rtp; SrsStatisticCategory* perf_rtc; SrsStatisticCategory* perf_bytes; + SrsStatisticCategory* perf_dropped; private: SrsStatistic(); virtual ~SrsStatistic(); @@ -264,6 +265,10 @@ public: // Stat for bytes, nn_bytes is the size of bytes, nb_padding is padding bytes. virtual void perf_on_rtc_bytes(int nn_bytes, int nn_padding); virtual srs_error_t dumps_perf_bytes(SrsJsonObject* obj); +public: + // Stat for rtc messages, nn_rtc is rtc messages, nn_dropped is dropped messages. + virtual void perf_on_dropped(int nn_msgs, int nn_rtc, int nn_dropped); + virtual srs_error_t dumps_perf_dropped(SrsJsonObject* obj); public: // Reset all perf stat data. virtual void reset_perf(); From cac5bbddf6e13b01f8f8e064f773df279c0fc09b Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 12:48:05 +0800 Subject: [PATCH 118/131] Refine comments --- trunk/scripts/perf_gso.py | 2 +- trunk/src/app/srs_app_rtc_conn.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 7180c7e4b..4d817f8bc 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -43,7 +43,7 @@ obj = json.loads(s) print "" p = obj['data']['dropped'] -print('RTC Frame Dropped: %s'%(100.0 * p['rtc_dropeed'] / p['rtc_frames'])) +print('RTC Frame Dropped: %s%s'%(10000.0 * p['rtc_dropeed'] / p['rtc_frames'], '%%')) # 2, 3, 5, 9, 16, 32, 64, 128, 256 keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 9f771028f..158b1e02f 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -305,7 +305,7 @@ private: int cache_pos; // The max number of messages for sendmmsg. If 1, we use sendmsg to send. int max_sendmmsg; - // The total queue length, share with all senders. + // The total queue length, for each sender. int queue_length; public: SrsUdpMuxSender(SrsRtcServer* s); From 54b6a9faa7447f3b2188064c5a27c6bba8bb93c4 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 13:02:54 +0800 Subject: [PATCH 119/131] Refactor for performance --- trunk/src/app/srs_app_rtc_conn.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ad87e622e..daf5317b9 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -885,6 +885,9 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsRtcPackets& packets) { srs_error_t err = srs_success; + // Cache the encrypt flag. + bool encrypt = rtc_session->encrypt; + int nn_packets = packets.size(); for (int i = 0; i < nn_packets; i++) { SrsRtpPacket2* packet = packets.at(i); @@ -915,7 +918,7 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsRtcPackets& packets) } // Whether encrypt the RTP bytes. - if (rtc_session->encrypt) { + if (encrypt) { int nn_encrypt = (int)iov->iov_len; if ((err = rtc_session->dtls_session->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) { return srs_error_wrap(err, "srtp protect"); @@ -947,6 +950,9 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) { srs_error_t err = srs_success; + // Cache the encrypt flag. + bool encrypt = rtc_session->encrypt; + // Previous handler, if has the same size, we can use GSO. mmsghdr* gso_mhdr = NULL; int gso_size = 0; int gso_encrypt = 0; int gso_cursor = 0; // GSO, N packets has same length, the final one may not. @@ -1056,7 +1062,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } // Whether encrypt the RTP bytes. - if (rtc_session->encrypt) { + if (encrypt) { int nn_encrypt = (int)iov->iov_len; if ((err = rtc_session->dtls_session->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) { return srs_error_wrap(err, "srtp protect"); From 36d06edab3940497936ff22d85a992ada535f269 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 14:24:24 +0800 Subject: [PATCH 120/131] Refine performance --- trunk/src/app/srs_app_rtc_conn.cpp | 6 ++++++ trunk/src/app/srs_app_rtc_conn.hpp | 3 +++ trunk/src/kernel/srs_kernel_error.hpp | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index daf5317b9..41033f0d0 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1854,6 +1854,12 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd, int senders) max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); bool gso = _srs_config->get_rtc_server_gso(); queue_length = srs_max(128, _srs_config->get_rtc_server_queue_length()); + + // For no GSO, we need larger queue. + if (!gso) { + queue_length *= 2; + } + srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d, queue_max=%dx%d", srs_netfd_fileno(fd), max_sendmmsg, gso, queue_length, senders); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 158b1e02f..51b4c00b6 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -185,10 +185,13 @@ private: uint16_t video_sequence; public: SrsUdpMuxSocket* sendonly_ukt; +private: ISrsUdpSender* sender; +private: bool merge_nalus; bool gso; int max_padding; + public: SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid); virtual ~SrsRtcSenderThread(); diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 5a6b8c6e5..c5421d640 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -422,7 +422,7 @@ public: }; // Error helpers, should use these functions to new or wrap an error. -#define srs_success SrsCplxError::success() +#define srs_success 0 // SrsCplxError::success() #define srs_error_new(ret, fmt, ...) SrsCplxError::create(__FUNCTION__, __FILE__, __LINE__, ret, fmt, ##__VA_ARGS__) #define srs_error_wrap(err, fmt, ...) SrsCplxError::wrap(__FUNCTION__, __FILE__, __LINE__, err, fmt, ##__VA_ARGS__) #define srs_error_copy(err) SrsCplxError::copy(err) From e4eb501c57f5340e6367fdf39d4f73fe46ef20bf Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 16:36:56 +0800 Subject: [PATCH 121/131] Fix the perf stat bytes bug --- trunk/scripts/perf_gso.py | 4 +++- trunk/src/app/srs_app_rtc_conn.cpp | 25 ++++++++++++++++--------- trunk/src/app/srs_app_rtc_conn.hpp | 4 +++- trunk/src/app/srs_app_statistic.cpp | 17 ++++++++++------- trunk/src/app/srs_app_statistic.hpp | 2 +- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/trunk/scripts/perf_gso.py b/trunk/scripts/perf_gso.py index 4d817f8bc..3e20e5a05 100755 --- a/trunk/scripts/perf_gso.py +++ b/trunk/scripts/perf_gso.py @@ -43,7 +43,9 @@ obj = json.loads(s) print "" p = obj['data']['dropped'] -print('RTC Frame Dropped: %s%s'%(10000.0 * p['rtc_dropeed'] / p['rtc_frames'], '%%')) +print('RTC Frame Dropped: %.4f%s'%(10000.0 * p['rtc_dropeed'] / p['rtc_frames'], '%%')) +p = obj['data']['bytes'] +print('Padding Overload: %.4f%s %.2fMB'%(10000.0 * p['rtc_padding'] / p['rtc_bytes'], '%%', p['rtc_padding']/1024/1024)) # 2, 3, 5, 9, 16, 32, 64, 128, 256 keys = ['lt_2', 'lt_3', 'lt_5', 'lt_9', 'lt_16', 'lt_32', 'lt_64', 'lt_128', 'lt_256', 'gt_256'] diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 41033f0d0..0b5ce34ae 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -472,6 +472,7 @@ SrsRtcPackets::SrsRtcPackets() nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; + nn_bytes = nn_rtp_bytes = 0; nn_padding_bytes = nn_paddings = 0; nn_dropped = 0; @@ -505,6 +506,7 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) nn_rtp_pkts = 0; nn_audios = nn_extras = 0; nn_videos = nn_samples = 0; + nn_bytes = nn_rtp_bytes = 0; nn_padding_bytes = nn_paddings = 0; nn_dropped = 0; @@ -745,22 +747,23 @@ srs_error_t SrsRtcSenderThread::cycle() // Stat the RTP packets going into kernel. stat->perf_on_gso_packets(pkts.nn_rtp_pkts); // Stat the bytes and paddings. - stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_padding_bytes); + stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); // Stat the messages and dropped count. stat->perf_on_dropped(msg_count, nn_rtc_packets, pkts.nn_dropped); - } + #if defined(SRS_DEBUG) - srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d bytes", - msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes, pkts.nn_padding_bytes); + srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d/%d bytes", + msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + pkts.nn_samples, pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); #endif + } pprint->elapse(); if (pprint->can_print()) { // TODO: FIXME: Print stat like frame/s, packet/s, loss_packets. - srs_trace("-> RTC PLAY %d/%d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d bytes, %d pad, %d/%d cache", + srs_trace("-> RTC PLAY %d/%d msgs, %d/%d packets, %d audios, %d extras, %d videos, %d samples, %d/%d/%d bytes, %d pad, %d/%d cache", msg_count, pkts.nn_dropped, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, pkts.nn_samples, pkts.nn_bytes, - pkts.nn_padding_bytes, pkts.nn_paddings, pkts.size(), pkts.capacity()); + pkts.nn_rtp_bytes, pkts.nn_padding_bytes, pkts.nn_paddings, pkts.size(), pkts.capacity()); } } } @@ -926,6 +929,8 @@ srs_error_t SrsRtcSenderThread::send_packets(SrsRtcPackets& packets) iov->iov_len = (size_t)nn_encrypt; } + packets.nn_rtp_bytes += (int)iov->iov_len; + // Set the address and control information. sockaddr_in* addr = (sockaddr_in*)sendonly_ukt->peer_addr(); socklen_t addrlen = (socklen_t)sendonly_ukt->peer_addrlen(); @@ -1070,6 +1075,8 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) iov->iov_len = (size_t)nn_encrypt; } + packets.nn_rtp_bytes += (int)iov->iov_len; + // If GSO, they must has same size, except the final one. if (using_gso && !gso_final && gso_encrypt && gso_encrypt != (int)iov->iov_len) { return srs_error_new(ERROR_RTC_RTP_MUXER, "GSO size=%d/%d, encrypt=%d/%d", gso_size, nn_packet, gso_encrypt, iov->iov_len); @@ -1138,9 +1145,9 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) } #if defined(SRS_DEBUG) - srs_trace("#%d, RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d/%d", packets.debug_id, packets.size(), + srs_trace("#%d, RTC PLAY summary, rtp %d/%d, videos %d/%d, audios %d/%d, pad %d/%d/%d", packets.debug_id, packets.size(), packets.nn_rtp_pkts, packets.nn_videos, packets.nn_samples, packets.nn_audios, packets.nn_extras, packets.nn_paddings, - packets.nn_padding_bytes); + packets.nn_padding_bytes, packets.nn_rtp_bytes); #endif return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 51b4c00b6..40c341fdf 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -130,8 +130,10 @@ public: uint32_t debug_id; #endif public: - // The total bytes of RTP packets. + // The total bytes of AVFrame packets. int nn_bytes; + // The total bytes of RTP packets. + int nn_rtp_bytes; // The total padded bytes. int nn_padding_bytes; public: diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 6116c9f50..890e43746 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -655,20 +655,23 @@ srs_error_t SrsStatistic::dumps_perf_sendmmsg(SrsJsonObject* obj) return dumps_perf(perf_sendmmsg, obj); } -void SrsStatistic::perf_on_rtc_bytes(int nn_bytes, int nn_padding) +void SrsStatistic::perf_on_rtc_bytes(int nn_bytes, int nn_rtp_bytes, int nn_padding) { - // a: RTC bytes. - // b: RTC paddings. + // a: AVFrame bytes. + // b: RTC bytes. + // c: RTC paddings. perf_bytes->a += nn_bytes; - perf_bytes->b += nn_padding; + perf_bytes->b += nn_rtp_bytes; + perf_bytes->c += nn_padding; - perf_bytes->nn += nn_bytes + nn_padding; + perf_bytes->nn += nn_rtp_bytes; } srs_error_t SrsStatistic::dumps_perf_bytes(SrsJsonObject* obj) { - obj->set("rtc_bytes", SrsJsonAny::integer(perf_bytes->a)); - obj->set("rtc_padding", SrsJsonAny::integer(perf_bytes->b)); + obj->set("avframe_bytes", SrsJsonAny::integer(perf_bytes->a)); + obj->set("rtc_bytes", SrsJsonAny::integer(perf_bytes->b)); + obj->set("rtc_padding", SrsJsonAny::integer(perf_bytes->c)); obj->set("nn", SrsJsonAny::integer(perf_bytes->nn)); diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 919322098..81ed9e27d 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -263,7 +263,7 @@ public: virtual srs_error_t dumps_perf_sendmmsg(SrsJsonObject* obj); public: // Stat for bytes, nn_bytes is the size of bytes, nb_padding is padding bytes. - virtual void perf_on_rtc_bytes(int nn_bytes, int nn_padding); + virtual void perf_on_rtc_bytes(int nn_bytes, int nn_rtp_bytes, int nn_padding); virtual srs_error_t dumps_perf_bytes(SrsJsonObject* obj); public: // Stat for rtc messages, nn_rtc is rtc messages, nn_dropped is dropped messages. From cf52390cf277eff93f41f317735d2b3b3ebda31c Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 17 Apr 2020 18:04:52 +0800 Subject: [PATCH 122/131] Support fast padding --- trunk/src/app/srs_app_rtc.cpp | 4 ++++ trunk/src/app/srs_app_rtc_conn.cpp | 18 +++++++++++++++--- trunk/src/app/srs_app_rtc_conn.hpp | 3 +-- trunk/src/kernel/srs_kernel_flv.cpp | 1 + trunk/src/kernel/srs_kernel_flv.hpp | 7 +++++++ trunk/src/kernel/srs_kernel_rtp.cpp | 6 ++++++ trunk/src/kernel/srs_kernel_rtp.hpp | 4 +++- 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/trunk/src/app/srs_app_rtc.cpp b/trunk/src/app/srs_app_rtc.cpp index 7d2d44e82..95cfea597 100644 --- a/trunk/src/app/srs_app_rtc.cpp +++ b/trunk/src/app/srs_app_rtc.cpp @@ -195,15 +195,19 @@ srs_error_t SrsRtpOpusMuxer::transcode(SrsSharedPtrMessage* shared_audio, char* return err; } + int nn_max_extra_payload = 0; SrsSample samples[nn_opus_packets]; for (int i = 0; i < nn_opus_packets; i++) { SrsSample* p = samples + i; p->size = opus_sizes[i]; p->bytes = new char[p->size]; memcpy(p->bytes, opus_payloads[i], p->size); + + nn_max_extra_payload = srs_max(nn_max_extra_payload, p->size); } shared_audio->set_extra_payloads(samples, nn_opus_packets); + shared_audio->set_max_extra_payload(nn_max_extra_payload); return err; } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 0b5ce34ae..24c19663c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -830,7 +830,7 @@ srs_error_t SrsRtcSenderThread::messages_to_packets( for (int i = 0; i < nn_extra_payloads; i++) { SrsSample* sample = msg->extra_payloads() + i; - if ((err = packet_opus(sample, packets)) != srs_success) { + if ((err = packet_opus(sample, packets, msg->nn_max_extra_payloads())) != srs_success) { return srs_error_wrap(err, "opus package"); } } @@ -1003,7 +1003,7 @@ srs_error_t SrsRtcSenderThread::send_packets_gso(SrsRtcPackets& packets) srs_trace("#%d, Padding %d bytes %d=>%d, packets %d, max_padding %d", packets.debug_id, padding, nn_packet, nn_packet + padding, nn_packets, max_padding); #endif - packet->set_padding(padding); + packet->add_padding(padding); nn_packet += padding; packets.nn_paddings++; packets.nn_padding_bytes += padding; @@ -1232,7 +1232,7 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac return err; } -srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& packets) +srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& packets, int nn_max_payload) { srs_error_t err = srs_success; @@ -1247,6 +1247,18 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& pa raw->payload = sample->bytes; raw->nn_payload = sample->size; + if (max_padding > 0) { + if (sample->size < nn_max_payload && nn_max_payload - sample->size < max_padding) { + int padding = nn_max_payload - sample->size; + packet->set_padding(padding); + +#if defined(SRS_DEBUG) + srs_trace("#%d, Fast Padding %d bytes %d=>%d, SN=%d, max_payload %d, max_padding %d", packets.debug_id, + padding, sample->size, sample->size + padding, packet->rtp_header.get_sequence(), nn_max_payload, max_padding); +#endif + } + } + // TODO: FIXME: Why 960? Need Refactoring? audio_timestamp += 960; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 40c341fdf..a563a4e2a 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -193,7 +193,6 @@ private: bool merge_nalus; bool gso; int max_padding; - public: SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid); virtual ~SrsRtcSenderThread(); @@ -218,7 +217,7 @@ private: srs_error_t send_packets(SrsRtcPackets& packets); srs_error_t send_packets_gso(SrsRtcPackets& packets); private: - srs_error_t packet_opus(SrsSample* sample, SrsRtcPackets& packets); + srs_error_t packet_opus(SrsSample* sample, SrsRtcPackets& packets, int nn_max_payload); private: srs_error_t packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* sample, int fu_payload_size, SrsRtcPackets& packets); srs_error_t packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPackets& packets); diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp index b05b3adbf..eead02374 100644 --- a/trunk/src/kernel/srs_kernel_flv.cpp +++ b/trunk/src/kernel/srs_kernel_flv.cpp @@ -218,6 +218,7 @@ SrsSharedPtrMessage::SrsSharedPtrPayload::SrsSharedPtrPayload() extra_payloads = NULL; nn_extra_payloads = 0; + nn_max_extra_payloads = 0; #endif } diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp index 84d7d34d9..8cfda3557 100644 --- a/trunk/src/kernel/srs_kernel_flv.hpp +++ b/trunk/src/kernel/srs_kernel_flv.hpp @@ -310,10 +310,14 @@ private: int nn_samples; // For RTC video, whether NALUs has IDR. bool has_idr; + public: // For RTC audio, we may need to transcode AAC to opus, // so there must be an extra payloads, which is transformed from payload. SrsSample* extra_payloads; int nn_extra_payloads; + // The max size payload in extras. + // @remark For GSO to fast guess the best padding. + int nn_max_extra_payloads; #endif public: SrsSharedPtrPayload(); @@ -363,6 +367,9 @@ public: void set_extra_payloads(SrsSample* payloads, int nn_payloads); int nn_extra_payloads() { return ptr->nn_extra_payloads; } SrsSample* extra_payloads() { return ptr->extra_payloads; } + // The max extra payload size. + void set_max_extra_payload(int v) { ptr->nn_max_extra_payloads = v; } + int nn_max_extra_payloads() { return ptr->nn_max_extra_payloads; } // Whether samples has idr. bool has_idr() { return ptr->has_idr; } void set_has_idr(bool v) { ptr->has_idr = v; } diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 3798fe987..b9659174e 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -199,6 +199,12 @@ void SrsRtpPacket2::set_padding(int size) padding = size; } +void SrsRtpPacket2::add_padding(int size) +{ + rtp_header.set_padding(padding + size > 0); + padding += size; +} + void SrsRtpPacket2::reset() { rtp_header.reset(); diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 615194a3d..973de2205 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -91,8 +91,10 @@ public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); public: - // Append size of bytes as padding. + // Set the padding of RTP packet. void set_padding(int size); + // Increase the padding of RTP packet. + void add_padding(int size); // Reset RTP packet. void reset(); // Reuse the cached raw message as payload. From 170b7453f4480cdfd68cec56dab7be0075a0c796 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 08:10:28 +0800 Subject: [PATCH 123/131] Refine for performance --- trunk/src/core/srs_core_performance.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 01c6138f7..08b006c10 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -193,16 +193,17 @@ #undef SRS_PERF_GLIBC_MEMORY_CHECK // For RTC, how many iovs we alloc for each mmsghdr for GSO. -// Assume that there are 2400 clients, say, 60000 msgs in queue to send, the memory is: +// Assume that there are 3300 clients, say, 10000 msgs in queue to send, the memory is: // 2 # We have two queue, cache and hotspot. // * 4 # We have reuseport, each have msg cache queue. -// * (64 + SRS_PERF_RTC_GSO_IOVS * 1500) # Each message size. -// * 60000 # Total messages. -// = 715MB # For SRS_PERF_RTC_GSO_IOVS = 1 -// = 1402MB # For SRS_PERF_RTC_GSO_IOVS = 2 -// = 2775MB # For SRS_PERF_RTC_GSO_IOVS = 4 +// * (64 + 16*SRS_PERF_RTC_GSO_MAX + SRS_PERF_RTC_GSO_IOVS * 1500) # Each message size. +// * 10000 # Total messages. +// = 197MB # For SRS_PERF_RTC_GSO_IOVS = 1 +// = 311MB # For SRS_PERF_RTC_GSO_IOVS = 2 +// = 540MB # For SRS_PERF_RTC_GSO_IOVS = 4 +// = 998MB # For SRS_PERF_RTC_GSO_IOVS = 8 #if defined(__linux__) - #define SRS_PERF_RTC_GSO_IOVS 2 + #define SRS_PERF_RTC_GSO_IOVS 4 #else #define SRS_PERF_RTC_GSO_IOVS 1 #endif From b0566d51ef38cd1b36198385e8b74359bc4f2f6c Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 08:33:35 +0800 Subject: [PATCH 124/131] Refine play consume message for RTC --- trunk/src/app/srs_app_rtc_conn.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 24c19663c..a2d7c9c7a 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -701,22 +701,25 @@ srs_error_t SrsRtcSenderThread::cycle() return srs_error_wrap(err, "rtc sender thread"); } +#ifdef SRS_PERF_QUEUE_COND_WAIT + // Wait for amount of messages or a duration. + if (realtime) { + // for realtime, min required msgs is 0, send when got one+ msgs. + consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); + } else { + // for no-realtime, got some msgs then send. + consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); + } +#endif + + // Try to read some messages. int msg_count = 0; if ((err = consumer->dump_packets(&msgs, msg_count)) != srs_success) { continue; } - // For RTC, we always try to read messages, only wait when no message. if (msg_count <= 0) { -#ifdef SRS_PERF_QUEUE_COND_WAIT - if (realtime) { - // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); - } else { - // for no-realtime, got some msgs then send. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); - } -#else +#ifndef SRS_PERF_QUEUE_COND_WAIT srs_usleep(mw_sleep); #endif continue; From 08312ddc42808e03ec9389f348d82e9c352b71f9 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 10:04:45 +0800 Subject: [PATCH 125/131] Support config the mw_sleep and mw_msgs --- trunk/conf/full.conf | 21 ++++++-- trunk/src/app/srs_app_config.cpp | 37 ++++++++++++- trunk/src/app/srs_app_config.hpp | 4 ++ trunk/src/app/srs_app_http_api.cpp | 8 +++ trunk/src/app/srs_app_http_stream.cpp | 3 +- trunk/src/app/srs_app_rtc_conn.cpp | 71 +++++++++++++------------ trunk/src/app/srs_app_rtc_conn.hpp | 6 +++ trunk/src/app/srs_app_rtmp_conn.cpp | 43 +++++++-------- trunk/src/app/srs_app_rtmp_conn.hpp | 4 +- trunk/src/core/srs_core_performance.hpp | 6 +-- 10 files changed, 132 insertions(+), 71 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 98a8792dc..39f02bd7f 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -484,12 +484,16 @@ vhost rtc.vhost.srs.com { stun_strict_check on; } # whether enable min delay mode for vhost. - # For RTC, we recommend to set to on. + # default: on, for RTC. min_latency on; play { # set the MW(merged-write) latency in ms. - # For RTC, we recommend lower value, such as 0. + # default: 0 (For WebRTC) mw_latency 0; + # Set the MW(merged-write) min messages. + # default: 0 (For Real-Time, min_latency on) + # default: 1 (For WebRTC, min_latency off) + mw_msgs 0; } } @@ -716,10 +720,16 @@ vhost play.srs.com { # SRS always set mw on, so we just set the latency value. # the latency of stream >= mw_latency + mr_latency # the value recomment is [300, 1800] - # default: 350 (for RTMP/HTTP-FLV) - # default: 0 (for WebRTC) + # default: 350 (For RTMP/HTTP-FLV) + # default: 0 (For WebRTC) mw_latency 350; + # Set the MW(merged-write) min messages. + # default: 0 (For Real-Time, min_latency on) + # default: 1 (For WebRTC, min_latency off) + # default: 8 (For RTMP/HTTP-FLV, min_latency off). + mw_msgs 8; + # the minimal packets send interval in ms, # used to control the ndiff of stream by srs_rtmp_dump, # for example, some device can only accept some stream which @@ -776,6 +786,7 @@ vhost mrw.srs.com { # @see play.srs.com play { mw_latency 350; + mw_msgs 8; } # @see publish.srs.com @@ -795,6 +806,7 @@ vhost min.delay.com { # @see play.srs.com play { mw_latency 100; + mw_msgs 4; gop_cache off; queue_length 10; } @@ -823,6 +835,7 @@ vhost stream.control.com { # @see play.srs.com play { mw_latency 100; + mw_msgs 4; queue_length 10; send_min_interval 10.0; reduce_sequence_header on; diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index eef0a325c..e9b89a346 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3785,7 +3785,8 @@ srs_error_t SrsConfig::check_normal_config() for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name; if (m != "time_jitter" && m != "mix_correct" && m != "atc" && m != "atc_auto" && m != "mw_latency" - && m != "gop_cache" && m != "queue_length" && m != "send_min_interval" && m != "reduce_sequence_header") { + && m != "gop_cache" && m != "queue_length" && m != "send_min_interval" && m != "reduce_sequence_header" + && m != "mw_msgs") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.play.%s of %s", m.c_str(), vhost->arg0().c_str()); } } @@ -5423,6 +5424,40 @@ srs_utime_t SrsConfig::get_mw_sleep(string vhost, bool is_rtc) return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); } +int SrsConfig::get_mw_msgs(string vhost, bool is_realtime, bool is_rtc) +{ + int DEFAULT = SRS_PERF_MW_MIN_MSGS; + if (is_rtc) { + DEFAULT = SRS_PERF_MW_MIN_MSGS_FOR_RTC; + } + if (is_realtime) { + DEFAULT = SRS_PERF_MW_MIN_MSGS_REALTIME; + } + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("play"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("mw_msgs"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + int v = ::atoi(conf->arg0().c_str()); + if (v > SRS_PERF_MW_MSGS) { + srs_warn("reset mw_msgs %d to max %d", v, SRS_PERF_MW_MSGS); + v = SRS_PERF_MW_MSGS; + } + + return v; +} + bool SrsConfig::get_realtime_enabled(string vhost, bool is_rtc) { static bool SYS_DEFAULT = SRS_PERF_MIN_LATENCY_ENABLED; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index bc9417d76..a905949b1 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -630,6 +630,10 @@ public: // @param vhost, the vhost to get the mw sleep time. // TODO: FIXME: add utest for mw config. virtual srs_utime_t get_mw_sleep(std::string vhost, bool is_rtc = false); + // Get the mw_msgs, mw wait time in packets for vhost. + // @param vhost, the vhost to get the mw sleep msgs. + // TODO: FIXME: add utest for mw config. + virtual int get_mw_msgs(std::string vhost, bool is_realtime, bool is_rtc = false); // Whether min latency mode enabled. // @param vhost, the vhost to get the min_latency. // TODO: FIXME: add utest for min_latency. diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index fa0a7d9f5..61552def2 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -869,6 +869,7 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe api = prop->to_str(); } + // TODO: FIXME: Parse vhost. // Parse app and stream from streamurl. string app; string stream_name; @@ -909,6 +910,13 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe request.app = app; request.stream = stream_name; + // TODO: FIXME: Parse vhost. + // discovery vhost, resolve the vhost from config + SrsConfDirective* parsed_vhost = _srs_config->get_vhost(""); + if (parsed_vhost) { + request.vhost = parsed_vhost->arg0(); + } + // TODO: FIXME: Maybe need a better name? // TODO: FIXME: When server enabled, but vhost disabled, should report error. SrsRtcSession* rtc_session = rtc_server->create_rtc_session(request, remote_sdp, local_sdp, eip); diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 95c1f03fd..95a67c21a 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -660,7 +660,8 @@ srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess if ((err = consumer->dump_packets(&msgs, count)) != srs_success) { return srs_error_wrap(err, "consumer dump packets"); } - + + // TODO: FIXME: Support merged-write wait. if (count <= 0) { // Directly use sleep, donot use consumer wait, because we couldn't awake consumer. srs_usleep(mw_sleep); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index a2d7c9c7a..890540c1c 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -563,6 +563,10 @@ SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int video_sequence = 0; + mw_sleep = 0; + mw_msgs = 0; + realtime = true; + _srs_config->subscribe(this); } @@ -595,33 +599,37 @@ srs_error_t SrsRtcSenderThread::initialize(const uint32_t& vssrc, const uint32_t srs_error_t SrsRtcSenderThread::on_reload_rtc_server() { - if (true) { - bool v = _srs_config->get_rtc_server_gso(); - if (gso != v) { - srs_trace("Reload gso %d=>%d", gso, v); - gso = v; - } - } + gso = _srs_config->get_rtc_server_gso(); + merge_nalus = _srs_config->get_rtc_server_merge_nalus(); + max_padding = _srs_config->get_rtc_server_padding(); - if (true) { - bool v = _srs_config->get_rtc_server_merge_nalus(); - if (merge_nalus != v) { - srs_trace("Reload merge_nalus %d=>%d", merge_nalus, v); - merge_nalus = v; - } - } - - if (true) { - bool v = _srs_config->get_rtc_server_padding(); - if (max_padding != v) { - srs_trace("Reload padding %d=>%d", max_padding, v); - max_padding = v; - } - } + srs_trace("Reload rtc_server gso=%d, merge_nalus=%d, max_padding=%d", gso, merge_nalus, max_padding); return srs_success; } +srs_error_t SrsRtcSenderThread::on_reload_vhost_play(string vhost) +{ + SrsRequest* req = &rtc_session->request; + + if (req->vhost != vhost) { + return srs_success; + } + + realtime = _srs_config->get_realtime_enabled(req->vhost, true); + mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime, true); + mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); + + srs_trace("Reload play realtime=%d, mw_msgs=%d, mw_sleep=%d", realtime, mw_msgs, mw_sleep); + + return srs_success; +} + +srs_error_t SrsRtcSenderThread::on_reload_vhost_realtime(string vhost) +{ + return on_reload_vhost_play(vhost); +} + int SrsRtcSenderThread::cid() { return trd->cid(); @@ -673,9 +681,6 @@ srs_error_t SrsRtcSenderThread::cycle() return srs_error_wrap(err, "rtc fetch source failed"); } - srs_trace("source url=%s, source_id=[%d][%d], encrypt=%d", - rtc_session->request.get_stream_url().c_str(), ::getpid(), source->source_id(), rtc_session->encrypt); - SrsConsumer* consumer = NULL; SrsAutoFree(SrsConsumer, consumer); if ((err = source->create_consumer(NULL, consumer)) != srs_success) { @@ -684,8 +689,12 @@ srs_error_t SrsRtcSenderThread::cycle() // TODO: FIXME: Support reload. SrsRequest* req = &rtc_session->request; - bool realtime = _srs_config->get_realtime_enabled(req->vhost, true); - srs_utime_t mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); + realtime = _srs_config->get_realtime_enabled(req->vhost, true); + mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); + mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime, true); + + srs_trace("RTC source url=%s, source_id=[%d][%d], encrypt=%d, realtime=%d, mw_sleep=%dms, mw_msgs=%d", rtc_session->request.get_stream_url().c_str(), + ::getpid(), source->source_id(), rtc_session->encrypt, realtime, srsu2msi(mw_sleep), mw_msgs); SrsRtcPackets pkts; SrsMessageArray msgs(SRS_PERF_MW_MSGS); @@ -703,13 +712,7 @@ srs_error_t SrsRtcSenderThread::cycle() #ifdef SRS_PERF_QUEUE_COND_WAIT // Wait for amount of messages or a duration. - if (realtime) { - // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME, mw_sleep); - } else { - // for no-realtime, got some msgs then send. - consumer->wait(SRS_PERF_MW_MIN_MSGS_FOR_RTC, mw_sleep); - } + consumer->wait(mw_msgs, mw_sleep); #endif // Try to read some messages. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index a563a4e2a..4cf19d727 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -193,6 +193,10 @@ private: bool merge_nalus; bool gso; int max_padding; +private: + srs_utime_t mw_sleep; + int mw_msgs; + bool realtime; public: SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid); virtual ~SrsRtcSenderThread(); @@ -201,6 +205,8 @@ public: // interface ISrsReloadHandler public: virtual srs_error_t on_reload_rtc_server(); + virtual srs_error_t on_reload_vhost_play(std::string vhost); + virtual srs_error_t on_reload_vhost_realtime(std::string vhost); public: virtual int cid(); public: diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index d06d79a42..0f8b1012a 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -116,7 +116,7 @@ SrsRtmpConn::SrsRtmpConn(SrsServer* svr, srs_netfd_t c, string cip) : SrsConnect wakable = NULL; mw_sleep = SRS_PERF_MW_SLEEP; - mw_enabled = false; + mw_msgs = 0; realtime = SRS_PERF_MIN_LATENCY_ENABLED; send_min_interval = 0; tcp_nodelay = false; @@ -264,6 +264,10 @@ srs_error_t SrsRtmpConn::on_reload_vhost_play(string vhost) send_min_interval = v; } } + + mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime); + mw_sleep = _srs_config->get_mw_sleep(req->vhost); + set_socket_buffer(mw_sleep); return err; } @@ -298,6 +302,10 @@ srs_error_t SrsRtmpConn::on_reload_vhost_realtime(string vhost) srs_trace("realtime changed %d=>%d", realtime, realtime_enabled); realtime = realtime_enabled; } + + mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime); + mw_sleep = _srs_config->get_mw_sleep(req->vhost); + set_socket_buffer(mw_sleep); return err; } @@ -689,18 +697,19 @@ srs_error_t SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, Sr SrsMessageArray msgs(SRS_PERF_MW_MSGS); bool user_specified_duration_to_stop = (req->duration > 0); int64_t starttime = -1; - + // setup the realtime. realtime = _srs_config->get_realtime_enabled(req->vhost); // setup the mw config. // when mw_sleep changed, resize the socket send buffer. - mw_enabled = true; - change_mw_sleep(_srs_config->get_mw_sleep(req->vhost)); + mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime); + mw_sleep = _srs_config->get_mw_sleep(req->vhost); + set_socket_buffer(mw_sleep); // initialize the send_min_interval send_min_interval = _srs_config->get_send_min_interval(req->vhost); - srs_trace("start play smi=%dms, mw_sleep=%d, mw_enabled=%d, realtime=%d, tcp_nodelay=%d", - srsu2msi(send_min_interval), srsu2msi(mw_sleep), mw_enabled, realtime, tcp_nodelay); + srs_trace("start play smi=%dms, mw_sleep=%d, mw_msgs=%d, realtime=%d, tcp_nodelay=%d", + srsu2msi(send_min_interval), srsu2msi(mw_sleep), mw_msgs, realtime, tcp_nodelay); while (true) { // when source is set to expired, disconnect it. @@ -730,13 +739,7 @@ srs_error_t SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, Sr // wait for message to incoming. // @see https://github.com/ossrs/srs/issues/251 // @see https://github.com/ossrs/srs/issues/257 - if (realtime) { - // for realtime, min required msgs is 0, send when got one+ msgs. - consumer->wait(SRS_PERF_MW_MIN_MSGS_REALTIME, mw_sleep); - } else { - // for no-realtime, got some msgs then send. - consumer->wait(SRS_PERF_MW_MIN_MSGS, mw_sleep); - } + consumer->wait(mw_msgs, mw_sleep); #endif // get messages from consumer. @@ -750,9 +753,9 @@ srs_error_t SrsRtmpConn::do_playing(SrsSource* source, SrsConsumer* consumer, Sr // reportable if (pprint->can_print()) { kbps->sample(); - srs_trace("-> " SRS_CONSTS_LOG_PLAY " time=%d, msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d, mw=%d", + srs_trace("-> " SRS_CONSTS_LOG_PLAY " time=%d, msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d, mw=%d/%d", (int)pprint->age(), count, kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(), - kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m(), srsu2msi(mw_sleep)); + kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m(), srsu2msi(mw_sleep), mw_msgs); } if (count <= 0) { @@ -1114,16 +1117,6 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsConsumer* consumer, SrsComm return err; } -void SrsRtmpConn::change_mw_sleep(srs_utime_t sleep_v) -{ - if (!mw_enabled) { - return; - } - - set_socket_buffer(sleep_v); - mw_sleep = sleep_v; -} - void SrsRtmpConn::set_sock_options() { SrsRequest* req = info->req; diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp index ac4b7efb9..c58111f04 100644 --- a/trunk/src/app/srs_app_rtmp_conn.hpp +++ b/trunk/src/app/srs_app_rtmp_conn.hpp @@ -102,8 +102,7 @@ private: srs_utime_t duration; // The MR(merged-write) sleep time in srs_utime_t. srs_utime_t mw_sleep; - // The MR(merged-write) only enabled for play. - int mw_enabled; + int mw_msgs; // For realtime // @see https://github.com/ossrs/srs/issues/257 bool realtime; @@ -149,7 +148,6 @@ private: virtual srs_error_t handle_publish_message(SrsSource* source, SrsCommonMessage* msg); virtual srs_error_t process_publish_message(SrsSource* source, SrsCommonMessage* msg); virtual srs_error_t process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); - virtual void change_mw_sleep(srs_utime_t sleep_v); virtual void set_sock_options(); private: virtual srs_error_t check_edge_token_traverse_auth(); diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 08b006c10..4d71ccdf8 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -129,10 +129,10 @@ #ifdef SRS_PERF_QUEUE_COND_WAIT // For RTMP, use larger wait queue. #define SRS_PERF_MW_MIN_MSGS 8 - #define SRS_PERF_MW_MIN_MSGS_REALTIME 0 // For RTC, use smaller wait queue. - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 2 - #define SRS_PERF_MW_MIN_MSGS_FOR_RTC_REALTIME 0 + #define SRS_PERF_MW_MIN_MSGS_FOR_RTC 1 + // For Real-Time, never wait messages. + #define SRS_PERF_MW_MIN_MSGS_REALTIME 0 #endif /** * the default value of vhost for From c1464f5aeee0545a86cf3e45cd570362a8798433 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 10:35:30 +0800 Subject: [PATCH 126/131] Use extra queue when set mw_msgs --- trunk/src/app/srs_app_listener.hpp | 3 +++ trunk/src/app/srs_app_rtc_conn.cpp | 43 +++++++++++++++++++++++------- trunk/src/app/srs_app_rtc_conn.hpp | 8 ++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index d096e5910..cc20cc756 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -143,6 +143,9 @@ public: virtual srs_error_t sendmmsg(mmsghdr* hdr) = 0; // Whether sender exceed the max queue, that is, overflow. virtual bool overflow() = 0; + // Set the queue extra ratio, for example, when mw_msgs > 0, we need larger queue. + // For r, 100 means x1, 200 means x2. + virtual void set_extra_ratio(int r) = 0; }; class SrsUdpMuxSocket diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 890540c1c..9414741ab 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -674,26 +674,32 @@ srs_error_t SrsRtcSenderThread::cycle() srs_error_t err = srs_success; SrsSource* source = NULL; + SrsRequest* req = &rtc_session->request; // TODO: FIXME: Should refactor it, directly use http server as handler. ISrsSourceHandler* handler = _srs_hybrid->srs()->instance(); - if ((err = _srs_sources->fetch_or_create(&rtc_session->request, handler, &source)) != srs_success) { + if ((err = _srs_sources->fetch_or_create(req, handler, &source)) != srs_success) { return srs_error_wrap(err, "rtc fetch source failed"); } SrsConsumer* consumer = NULL; SrsAutoFree(SrsConsumer, consumer); if ((err = source->create_consumer(NULL, consumer)) != srs_success) { - return srs_error_wrap(err, "rtc create consumer, source url=%s", rtc_session->request.get_stream_url().c_str()); + return srs_error_wrap(err, "rtc create consumer, source url=%s", req->get_stream_url().c_str()); } - // TODO: FIXME: Support reload. - SrsRequest* req = &rtc_session->request; realtime = _srs_config->get_realtime_enabled(req->vhost, true); mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime, true); - srs_trace("RTC source url=%s, source_id=[%d][%d], encrypt=%d, realtime=%d, mw_sleep=%dms, mw_msgs=%d", rtc_session->request.get_stream_url().c_str(), + // We merged write more messages, so we need larger queue. + if (mw_msgs > 2) { + sender->set_extra_ratio(150); + } else if (mw_msgs > 0) { + sender->set_extra_ratio(80); + } + + srs_trace("RTC source url=%s, source_id=[%d][%d], encrypt=%d, realtime=%d, mw_sleep=%dms, mw_msgs=%d", req->get_stream_url().c_str(), ::getpid(), source->source_id(), rtc_session->encrypt, realtime, srsu2msi(mw_sleep), mw_msgs); SrsRtcPackets pkts; @@ -1846,6 +1852,10 @@ SrsUdpMuxSender::SrsUdpMuxSender(SrsRtcServer* s) cache_pos = 0; max_sendmmsg = 0; queue_length = 0; + extra_ratio = 0; + extra_queue = 0; + gso = false; + nn_senders = 0; _srs_config->subscribe(this); } @@ -1877,16 +1887,17 @@ srs_error_t SrsUdpMuxSender::initialize(srs_netfd_t fd, int senders) } max_sendmmsg = _srs_config->get_rtc_server_sendmmsg(); - bool gso = _srs_config->get_rtc_server_gso(); + gso = _srs_config->get_rtc_server_gso(); queue_length = srs_max(128, _srs_config->get_rtc_server_queue_length()); + nn_senders = senders; // For no GSO, we need larger queue. if (!gso) { queue_length *= 2; } - srs_trace("UDP sender #%d init ok, max_sendmmsg=%d, gso=%d, queue_max=%dx%d", srs_netfd_fileno(fd), - max_sendmmsg, gso, queue_length, senders); + srs_trace("RTC sender #%d init ok, max_sendmmsg=%d, gso=%d, queue_max=%dx%d, extra_ratio=%d/%d", srs_netfd_fileno(fd), + max_sendmmsg, gso, queue_length, nn_senders, extra_ratio, extra_queue); return err; } @@ -1944,7 +1955,21 @@ srs_error_t SrsUdpMuxSender::fetch(mmsghdr** pphdr) bool SrsUdpMuxSender::overflow() { - return cache_pos > queue_length; + return cache_pos > queue_length + extra_queue; +} + +void SrsUdpMuxSender::set_extra_ratio(int r) +{ + // We use the larger extra ratio, because all vhosts shares the senders. + if (extra_ratio > r) { + return; + } + + extra_ratio = r; + extra_queue = queue_length * r / 100; + + srs_trace("RTC sender #%d extra queue, max_sendmmsg=%d, gso=%d, queue_max=%dx%d, extra_ratio=%d/%d, cache=%d/%d/%d", srs_netfd_fileno(lfd), + max_sendmmsg, gso, queue_length, nn_senders, extra_ratio, extra_queue, cache_pos, (int)cache.size(), (int)hotspot.size()); } srs_error_t SrsUdpMuxSender::sendmmsg(mmsghdr* hdr) diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 4cf19d727..3ad6a1072 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -307,6 +307,9 @@ private: private: srs_cond_t cond; bool waiting_msgs; + bool gso; + int nn_senders; +private: // Hotspot msgs, we are working on it. // @remark We will wait util all messages are ready. std::vector hotspot; @@ -317,6 +320,9 @@ private: int max_sendmmsg; // The total queue length, for each sender. int queue_length; + // The extra queue ratio. + int extra_ratio; + int extra_queue; public: SrsUdpMuxSender(SrsRtcServer* s); virtual ~SrsUdpMuxSender(); @@ -328,6 +334,8 @@ public: virtual srs_error_t fetch(mmsghdr** pphdr); virtual srs_error_t sendmmsg(mmsghdr* hdr); virtual bool overflow(); + virtual void set_extra_ratio(int r); +public: virtual srs_error_t cycle(); // interface ISrsReloadHandler public: From c93cd86ce4684a53b70c141e12c204d219c8c631 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 20:37:08 +0800 Subject: [PATCH 127/131] For #307, refine performance --- trunk/conf/full.conf | 2 + trunk/src/app/srs_app_config.cpp | 8 +- trunk/src/app/srs_app_rtc_conn.cpp | 139 +++++++++------- trunk/src/app/srs_app_rtc_conn.hpp | 5 +- trunk/src/app/srs_app_source.cpp | 53 ++++-- trunk/src/app/srs_app_source.hpp | 12 +- trunk/src/core/srs_core_performance.hpp | 3 + trunk/src/kernel/srs_kernel_buffer.cpp | 5 - trunk/src/kernel/srs_kernel_buffer.hpp | 3 +- trunk/src/kernel/srs_kernel_rtp.cpp | 210 ++++++++++++++---------- trunk/src/kernel/srs_kernel_rtp.hpp | 58 +++++-- 11 files changed, 323 insertions(+), 175 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 39f02bd7f..2c1089665 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -488,6 +488,7 @@ vhost rtc.vhost.srs.com { min_latency on; play { # set the MW(merged-write) latency in ms. + # @remark For WebRTC, we enable pass-timestamp mode, so we ignore this config. # default: 0 (For WebRTC) mw_latency 0; # Set the MW(merged-write) min messages. @@ -720,6 +721,7 @@ vhost play.srs.com { # SRS always set mw on, so we just set the latency value. # the latency of stream >= mw_latency + mr_latency # the value recomment is [300, 1800] + # @remark For WebRTC, we enable pass-timestamp mode, so we ignore this config. # default: 350 (For RTMP/HTTP-FLV) # default: 0 (For WebRTC) mw_latency 350; diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index e9b89a346..2a8454633 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -5420,8 +5420,14 @@ srs_utime_t SrsConfig::get_mw_sleep(string vhost, bool is_rtc) if (!conf || conf->arg0().empty()) { return DEFAULT; } + + int v = ::atoi(conf->arg0().c_str()); + if (is_rtc && v > 0) { + srs_warn("For RTC, we ignore mw_latency"); + return 0; + } - return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); + return (srs_utime_t)(v * SRS_UTIME_MILLISECONDS); } int SrsConfig::get_mw_msgs(string vhost, bool is_realtime, bool is_rtc) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 9414741ab..230ea2e49 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -460,7 +460,7 @@ srs_error_t SrsDtlsSession::unprotect_rtcp(char* out_buf, const char* in_buf, in return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); } -SrsRtcPackets::SrsRtcPackets() +SrsRtcPackets::SrsRtcPackets(int nn_cache_max) { #if defined(SRS_DEBUG) debug_id = 0; @@ -477,22 +477,20 @@ SrsRtcPackets::SrsRtcPackets() nn_dropped = 0; cursor = 0; + nn_cache = nn_cache_max; + cache = new SrsRtpPacket2[nn_cache]; } SrsRtcPackets::~SrsRtcPackets() { - vector::iterator it; - for (it = packets.begin(); it != packets.end(); ++it) { - SrsRtpPacket2* p = *it; - srs_freep(p); - } - packets.clear(); + srs_freepa(cache); + nn_cache = 0; } void SrsRtcPackets::reset(bool gso, bool merge_nalus) { for (int i = 0; i < cursor; i++) { - SrsRtpPacket2* packet = packets[i]; + SrsRtpPacket2* packet = cache + i; packet->reset(); } @@ -515,17 +513,16 @@ void SrsRtcPackets::reset(bool gso, bool merge_nalus) SrsRtpPacket2* SrsRtcPackets::fetch() { - if (cursor >= (int)packets.size()) { - packets.push_back(new SrsRtpPacket2()); + if (cursor >= nn_cache) { + return NULL; } - - return packets[cursor++]; + return cache + (cursor++); } SrsRtpPacket2* SrsRtcPackets::back() { srs_assert(cursor > 0); - return packets[cursor - 1]; + return cache + cursor - 1; } int SrsRtcPackets::size() @@ -535,13 +532,13 @@ int SrsRtcPackets::size() int SrsRtcPackets::capacity() { - return (int)packets.size(); + return nn_cache; } SrsRtpPacket2* SrsRtcPackets::at(int index) { srs_assert(index < cursor); - return packets[index]; + return cache + index; } SrsRtcSenderThread::SrsRtcSenderThread(SrsRtcSession* s, SrsUdpMuxSocket* u, int parent_cid) @@ -688,6 +685,13 @@ srs_error_t SrsRtcSenderThread::cycle() return srs_error_wrap(err, "rtc create consumer, source url=%s", req->get_stream_url().c_str()); } + // For RTC, we enable pass-timestamp mode, ignore the timestamp in queue, never depends on the duration, + // because RTC allows the audio and video has its own timebase, that is the audio timestamp and video timestamp + // maybe not monotonically increase. + // In this mode, we use mw_msgs to set the delay. We never shrink the consumer queue, instead, we dumps the + // messages and drop them if the shared sender queue is full. + consumer->enable_pass_timestamp(); + realtime = _srs_config->get_realtime_enabled(req->vhost, true); mw_sleep = _srs_config->get_mw_sleep(req->vhost, true); mw_msgs = _srs_config->get_mw_msgs(req->vhost, realtime, true); @@ -702,8 +706,8 @@ srs_error_t SrsRtcSenderThread::cycle() srs_trace("RTC source url=%s, source_id=[%d][%d], encrypt=%d, realtime=%d, mw_sleep=%dms, mw_msgs=%d", req->get_stream_url().c_str(), ::getpid(), source->source_id(), rtc_session->encrypt, realtime, srsu2msi(mw_sleep), mw_msgs); - SrsRtcPackets pkts; SrsMessageArray msgs(SRS_PERF_MW_MSGS); + SrsRtcPackets pkts(SRS_PERF_RTC_RTP_PACKETS); SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); SrsAutoFree(SrsPithyPrint, pprint); @@ -748,27 +752,29 @@ srs_error_t SrsRtcSenderThread::cycle() } // Stat for performance analysis. - if (stat_enabled) { - // Stat the original RAW AV frame, maybe h264+aac. - stat->perf_on_msgs(msg_count); - // Stat the RTC packets, RAW AV frame, maybe h.264+opus. - int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; - stat->perf_on_rtc_packets(nn_rtc_packets); - // Stat the RAW RTP packets, which maybe group by GSO. - stat->perf_on_rtp_packets(pkts.size()); - // Stat the RTP packets going into kernel. - stat->perf_on_gso_packets(pkts.nn_rtp_pkts); - // Stat the bytes and paddings. - stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); - // Stat the messages and dropped count. - stat->perf_on_dropped(msg_count, nn_rtc_packets, pkts.nn_dropped); + if (!stat_enabled) { + continue; + } + + // Stat the original RAW AV frame, maybe h264+aac. + stat->perf_on_msgs(msg_count); + // Stat the RTC packets, RAW AV frame, maybe h.264+opus. + int nn_rtc_packets = srs_max(pkts.nn_audios, pkts.nn_extras) + pkts.nn_videos; + stat->perf_on_rtc_packets(nn_rtc_packets); + // Stat the RAW RTP packets, which maybe group by GSO. + stat->perf_on_rtp_packets(pkts.size()); + // Stat the RTP packets going into kernel. + stat->perf_on_gso_packets(pkts.nn_rtp_pkts); + // Stat the bytes and paddings. + stat->perf_on_rtc_bytes(pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); + // Stat the messages and dropped count. + stat->perf_on_dropped(msg_count, nn_rtc_packets, pkts.nn_dropped); #if defined(SRS_DEBUG) - srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d/%d bytes", - msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, - pkts.nn_samples, pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); + srs_trace("RTC PLAY perf, msgs %d/%d, rtp %d, gso %d, %d audios, %d extras, %d videos, %d samples, %d/%d/%d bytes", + msg_count, nn_rtc_packets, pkts.size(), pkts.nn_rtp_pkts, pkts.nn_audios, pkts.nn_extras, pkts.nn_videos, + pkts.nn_samples, pkts.nn_bytes, pkts.nn_rtp_bytes, pkts.nn_padding_bytes); #endif - } pprint->elapse(); if (pprint->can_print()) { @@ -1193,6 +1199,10 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + srs_freep(raw); + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); @@ -1216,13 +1226,19 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac int packet_size = srs_min(nb_left, fu_payload_size); SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + srs_freep(raw); + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } + packet->extra_payload = raw; packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpFUAPayload* fua = packet->reuse_fua(); + SrsRtpFUAPayload* fua = new SrsRtpFUAPayload(); + packet->payload = fua; fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; @@ -1249,6 +1265,9 @@ srs_error_t SrsRtcSenderThread::packet_opus(SrsSample* sample, SrsRtcPackets& pa srs_error_t err = srs_success; SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } packet->rtp_header.set_marker(true); packet->rtp_header.set_timestamp(audio_timestamp); packet->rtp_header.set_sequence(audio_sequence++); @@ -1291,23 +1310,24 @@ srs_error_t SrsRtcSenderThread::packet_fu_a(SrsSharedPtrMessage* msg, SrsSample* int packet_size = srs_min(nb_left, fu_payload_size); SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); packet->rtp_header.set_payload_type(video_payload_type); - SrsRtpFUAPayload* fua = packet->reuse_fua(); + SrsRtpFUAPayload2* fua = packet->reuse_fua(); fua->nri = (SrsAvcNaluType)header; fua->nalu_type = (SrsAvcNaluType)nal_type; fua->start = bool(i == 0); fua->end = bool(i == num_of_packet - 1); - SrsSample* fragment_sample = new SrsSample(); - fragment_sample->bytes = p; - fragment_sample->size = packet_size; - fua->nalus.push_back(fragment_sample); + fua->payload = p; + fua->size = packet_size; p += packet_size; nb_left -= packet_size; @@ -1322,6 +1342,9 @@ srs_error_t SrsRtcSenderThread::packet_single_nalu(SrsSharedPtrMessage* msg, Srs srs_error_t err = srs_success; SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); packet->rtp_header.set_ssrc(video_ssrc); @@ -1355,6 +1378,9 @@ srs_error_t SrsRtcSenderThread::packet_stap_a(SrsSource* source, SrsSharedPtrMes } SrsRtpPacket2* packet = packets.fetch(); + if (!packet) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); + } packet->rtp_header.set_marker(false); packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); @@ -2017,23 +2043,22 @@ srs_error_t SrsUdpMuxSender::cycle() cache.swap(hotspot); cache_pos = 0; - // Collect informations for GSO. int gso_pos = 0; - if (pos > 0 && stat_enabled) { - // For shared GSO cache, stat the messages. - // @see https://linux.die.net/man/2/sendmmsg - // @see https://linux.die.net/man/2/sendmsg - for (int i = 0; i < pos; i++) { - mmsghdr* mhdr = &hotspot[i]; - - int real_iovs = mhdr->msg_hdr.msg_iovlen; - gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; - gso_iovs += real_iovs; - } - } - - // Send out all messages. if (pos > 0) { + // Collect informations for GSO. + if (stat_enabled) { + // For shared GSO cache, stat the messages. + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg + for (int i = 0; i < pos; i++) { + mmsghdr* mhdr = &hotspot[i]; + + int real_iovs = mhdr->msg_hdr.msg_iovlen; + gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; + gso_iovs += real_iovs; + } + } + // Send out all messages. // @see https://linux.die.net/man/2/sendmmsg // @see https://linux.die.net/man/2/sendmsg @@ -2053,6 +2078,10 @@ srs_error_t SrsUdpMuxSender::cycle() } } + if (!stat_enabled) { + continue; + } + // Increase total messages. nn_msgs += pos + gso_iovs; nn_msgs_max = srs_max(pos, nn_msgs_max); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 3ad6a1072..c3796c711 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -155,9 +155,10 @@ public: int nn_dropped; private: int cursor; - std::vector packets; + int nn_cache; + SrsRtpPacket2* cache; public: - SrsRtcPackets(); + SrsRtcPackets(int nn_cache_max); virtual ~SrsRtcPackets(); public: void reset(bool gso, bool merge_nalus); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index fcf3b071e..c0548708f 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -269,9 +269,17 @@ void SrsMessageQueue::set_queue_size(srs_utime_t queue_size) max_queue_size = queue_size; } -srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg, bool* is_overflow) +srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg, bool* is_overflow, bool pass_timestamp) { srs_error_t err = srs_success; + + msgs.push_back(msg); + + // For RTC, we never care about the timestamp and duration, so we never shrink queue here, + // but we will drop messages in each consumer coroutine. + if (pass_timestamp) { + return err; + } if (msg->is_av()) { if (av_start_time == -1) { @@ -281,8 +289,6 @@ srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg, bool* is_overflow av_end_time = srs_utime_t(msg->timestamp * SRS_UTIME_MILLISECONDS); } - msgs.push_back(msg); - while (av_end_time - av_start_time > max_queue_size) { // notice the caller queue already overflow and shrinked. if (is_overflow) { @@ -295,7 +301,7 @@ srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg, bool* is_overflow return err; } -srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count) +srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count, bool pass_timestamp) { srs_error_t err = srs_success; @@ -308,13 +314,15 @@ srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage** p count = srs_min(max_count, nb_msgs); SrsSharedPtrMessage** omsgs = msgs.data(); - for (int i = 0; i < count; i++) { - pmsgs[i] = omsgs[i]; + memcpy(pmsgs, omsgs, count * sizeof(SrsSharedPtrMessage*)); + + // For RTC, we enable pass_timestamp mode, which never care about the timestamp and duration, + // so we do not have to update the start time here. + if (!pass_timestamp) { + SrsSharedPtrMessage* last = omsgs[count - 1]; + av_start_time = srs_utime_t(last->timestamp * SRS_UTIME_MILLISECONDS); } - SrsSharedPtrMessage* last = omsgs[count - 1]; - av_start_time = srs_utime_t(last->timestamp * SRS_UTIME_MILLISECONDS); - if (count >= nb_msgs) { // the pmsgs is big enough and clear msgs at most time. msgs.clear(); @@ -433,6 +441,8 @@ SrsConsumer::SrsConsumer(SrsSource* s, SrsConnection* c) mw_duration = 0; mw_waiting = false; #endif + + pass_timestamp = false; } SrsConsumer::~SrsConsumer() @@ -466,20 +476,35 @@ srs_error_t SrsConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsR srs_error_t err = srs_success; SrsSharedPtrMessage* msg = shared_msg->copy(); - - if (!atc) { + + // For RTC, we enable pass_timestamp mode, which never correct or depends on monotonic increasing of + // timestamp. And in RTC, the audio and video timebase can be different, so we ignore time_jitter here. + if (!pass_timestamp && !atc) { if ((err = jitter->correct(msg, ag)) != srs_success) { return srs_error_wrap(err, "consume message"); } } - - if ((err = queue->enqueue(msg, NULL)) != srs_success) { + + // Put message in queue, here we may enable pass_timestamp mode. + if ((err = queue->enqueue(msg, NULL, pass_timestamp)) != srs_success) { return srs_error_wrap(err, "enqueue message"); } #ifdef SRS_PERF_QUEUE_COND_WAIT // fire the mw when msgs is enough. if (mw_waiting) { + // For RTC, we use pass_timestamp mode, we don't care about the timestamp in queue, + // so we only check the messages in queue. + if (pass_timestamp) { + if (queue->size() > mw_min_msgs) { + srs_cond_signal(mw_wait); + mw_waiting = false; + return err; + } + return err; + } + + // For RTMP, we wait for messages and duration. srs_utime_t duration = queue->duration(); bool match_min_msgs = queue->size() > mw_min_msgs; @@ -529,7 +554,7 @@ srs_error_t SrsConsumer::dump_packets(SrsMessageArray* msgs, int& count) } // pump msgs from queue. - if ((err = queue->dump_packets(max, msgs->msgs, count)) != srs_success) { + if ((err = queue->dump_packets(max, msgs->msgs, count, pass_timestamp)) != srs_success) { return srs_error_wrap(err, "dump packets"); } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 6e64e9b21..fdfe9c789 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -151,12 +151,13 @@ public: // Enqueue the message, the timestamp always monotonically. // @param msg, the msg to enqueue, user never free it whatever the return code. // @param is_overflow, whether overflow and shrinked. NULL to ignore. - virtual srs_error_t enqueue(SrsSharedPtrMessage* msg, bool* is_overflow = NULL); + // @remark If pass_timestamp, we never shrink and never care about the timestamp or duration. + virtual srs_error_t enqueue(SrsSharedPtrMessage* msg, bool* is_overflow = NULL, bool pass_timestamp = false); // Get packets in consumer queue. // @pmsgs SrsSharedPtrMessage*[], used to store the msgs, user must alloc it. // @count the count in array, output param. // @max_count the max count to dequeue, must be positive. - virtual srs_error_t dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count); + virtual srs_error_t dump_packets(int max_count, SrsSharedPtrMessage** pmsgs, int& count, bool pass_timestamp = false); // Dumps packets to consumer, use specified args. // @remark the atc/tba/tbv/ag are same to SrsConsumer.enqueue(). virtual srs_error_t dump_packets(SrsConsumer* consumer, bool atc, SrsRtmpJitterAlgorithm ag); @@ -203,10 +204,17 @@ private: int mw_min_msgs; srs_utime_t mw_duration; #endif +private: + // For RTC, we never use jitter to correct timestamp. + // But we should not change the atc or time_jitter for source or RTMP. + // @remark In this mode, we also never check the queue by timstamp, but only by count. + bool pass_timestamp; public: SrsConsumer(SrsSource* s, SrsConnection* c); virtual ~SrsConsumer(); public: + // Use pass timestamp mode. + void enable_pass_timestamp() { pass_timestamp = true; } // Set the size of queue. virtual void set_queue_size(srs_utime_t queue_size); // when source id changed, notice client to print. diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 4d71ccdf8..39493646a 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -211,5 +211,8 @@ // For RTC, the max iovs in msghdr, the max packets sent in a msghdr. #define SRS_PERF_RTC_GSO_MAX 64 +// For RTC, the max count of RTP packets we process in one loop. +#define SRS_PERF_RTC_RTP_PACKETS 1024 + #endif diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index 73c6cafe1..be94d0bcb 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -67,11 +67,6 @@ SrsBuffer::~SrsBuffer() { } -char* SrsBuffer::data() -{ - return bytes; -} - int SrsBuffer::size() { return nb_bytes; diff --git a/trunk/src/kernel/srs_kernel_buffer.hpp b/trunk/src/kernel/srs_kernel_buffer.hpp index 870da9ef8..532375f8d 100644 --- a/trunk/src/kernel/srs_kernel_buffer.hpp +++ b/trunk/src/kernel/srs_kernel_buffer.hpp @@ -113,7 +113,8 @@ public: * get data of stream, set by initialize. * current bytes = data() + pos() */ - virtual char* data(); + inline char* data() { return bytes; } + inline char* head() { return p; } /** * the total stream size, set by initialize. * left bytes = size() - pos(). diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index b9659174e..fa98c5957 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -85,7 +85,7 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream) // Encode the RTP fix header, 12bytes. // @see https://tools.ietf.org/html/rfc1889#section-5.1 - char* op = stream->data() + stream->pos(); + char* op = stream->head(); char* p = op; // The version, padding, extension and cc, total 1 byte. @@ -148,60 +148,45 @@ size_t SrsRtpHeader::header_size() return kRtpHeaderFixedSize + cc * 4 + (extension ? (extension_length + 1) * 4 : 0); } -void SrsRtpHeader::set_marker(bool marker) -{ - this->marker = marker; -} - -void SrsRtpHeader::set_payload_type(uint8_t payload_type) -{ - this->payload_type = payload_type; -} - -void SrsRtpHeader::set_sequence(uint16_t sequence) -{ - this->sequence = sequence; -} - -void SrsRtpHeader::set_timestamp(int64_t timestamp) -{ - this->timestamp = (uint32_t)timestamp; -} - -void SrsRtpHeader::set_ssrc(uint32_t ssrc) -{ - this->ssrc = ssrc; -} - SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; + extra_payload = NULL; padding = 0; cache_raw = new SrsRtpRawPayload(); - cache_fua = new SrsRtpFUAPayload(); + cache_fua = new SrsRtpFUAPayload2(); + cache_payload = 0; + using_cache = false; } SrsRtpPacket2::~SrsRtpPacket2() { // We may use the cache as payload. - if (payload == cache_raw || payload == cache_fua) { + if (using_cache) { payload = NULL; } srs_freep(payload); + srs_freep(extra_payload); srs_freep(cache_raw); } void SrsRtpPacket2::set_padding(int size) { rtp_header.set_padding(size > 0); + if (cache_payload) { + cache_payload += size - padding; + } padding = size; } void SrsRtpPacket2::add_padding(int size) { rtp_header.set_padding(padding + size > 0); + if (cache_payload) { + cache_payload += size; + } padding += size; } @@ -209,31 +194,39 @@ void SrsRtpPacket2::reset() { rtp_header.reset(); padding = 0; + cache_payload = 0; + srs_freep(extra_payload); // We may use the cache as payload. - if (payload == cache_raw || payload == cache_fua) { + if (using_cache) { payload = NULL; + } else { + srs_freep(payload); } - srs_freep(payload); + using_cache = false; } SrsRtpRawPayload* SrsRtpPacket2::reuse_raw() { + using_cache = true; payload = cache_raw; return cache_raw; } -SrsRtpFUAPayload* SrsRtpPacket2::reuse_fua() +SrsRtpFUAPayload2* SrsRtpPacket2::reuse_fua() { + using_cache = true; payload = cache_fua; - cache_fua->reset(); return cache_fua; } int SrsRtpPacket2::nb_bytes() { - return rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; + if (!cache_payload) { + cache_payload = rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding; + } + return cache_payload; } srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf) @@ -297,12 +290,20 @@ SrsRtpRawNALUs::SrsRtpRawNALUs() SrsRtpRawNALUs::~SrsRtpRawNALUs() { - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; - srs_freep(p); + if (true) { + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; + srs_freep(p); + } + } + if (true) { + int nn_nalus = (int)extra_nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = extra_nalus[i]; + srs_freep(p); + } } - nalus.clear(); } void SrsRtpRawNALUs::push_back(SrsSample* sample) @@ -330,19 +331,19 @@ uint8_t SrsRtpRawNALUs::skip_first_byte() return uint8_t(nalus[0]->bytes[0]); } -srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int size) +srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int packet_size) { - if (cursor + size < 0 || cursor + size > nn_bytes) { - return srs_error_new(ERROR_RTC_RTP_MUXER, "cursor=%d, max=%d, size=%d", cursor, nn_bytes, size); + if (cursor + packet_size < 0 || cursor + packet_size > nn_bytes) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "cursor=%d, max=%d, size=%d", cursor, nn_bytes, packet_size); } int pos = cursor; - cursor += size; - int left = size; + cursor += packet_size; + int left = packet_size; - vector::iterator it; - for (it = nalus.begin(); it != nalus.end() && left > 0; ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; // Ignore previous consumed samples. if (pos && pos - p->size >= 0) { @@ -355,9 +356,11 @@ srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int size) srs_assert(nn > 0); SrsSample* sample = new SrsSample(); + extra_nalus.push_back(sample); + samples.push_back(sample); + sample->bytes = p->bytes + pos; sample->size = nn; - samples.push_back(sample); left -= nn; pos = 0; @@ -370,9 +373,9 @@ int SrsRtpRawNALUs::nb_bytes() { int size = 0; - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; size += p->size; } @@ -381,9 +384,9 @@ int SrsRtpRawNALUs::nb_bytes() srs_error_t SrsRtpRawNALUs::encode(SrsBuffer* buf) { - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; if (!buf->require(p->size)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size); @@ -402,21 +405,20 @@ SrsRtpSTAPPayload::SrsRtpSTAPPayload() SrsRtpSTAPPayload::~SrsRtpSTAPPayload() { - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; srs_freep(p); } - nalus.clear(); } int SrsRtpSTAPPayload::nb_bytes() { int size = 1; - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; size += 2 + p->size; } @@ -436,9 +438,10 @@ srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf) buf->write_1bytes(v); // NALUs. - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; + if (!buf->require(2 + p->size)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size); } @@ -458,31 +461,20 @@ SrsRtpFUAPayload::SrsRtpFUAPayload() SrsRtpFUAPayload::~SrsRtpFUAPayload() { - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; srs_freep(p); } - nalus.clear(); -} - -void SrsRtpFUAPayload::reset() -{ - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; - srs_freep(p); - } - nalus.clear(); } int SrsRtpFUAPayload::nb_bytes() { int size = 2; - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; size += p->size; } @@ -511,9 +503,10 @@ srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf) buf->write_1bytes(fu_header); // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 - vector::iterator it; - for (it = nalus.begin(); it != nalus.end(); ++it) { - SrsSample* p = *it; + int nn_nalus = (int)nalus.size(); + for (int i = 0; i < nn_nalus; i++) { + SrsSample* p = nalus[i]; + if (!buf->require(p->size)) { return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size); } @@ -524,6 +517,57 @@ srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf) return srs_success; } +SrsRtpFUAPayload2::SrsRtpFUAPayload2() +{ + start = end = false; + nri = nalu_type = (SrsAvcNaluType)0; + + payload = NULL; + size = 0; +} + +SrsRtpFUAPayload2::~SrsRtpFUAPayload2() +{ +} + +int SrsRtpFUAPayload2::nb_bytes() +{ + return 2 + size; +} + +srs_error_t SrsRtpFUAPayload2::encode(SrsBuffer* buf) +{ + if (!buf->require(2 + size)) { + return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1); + } + + // Fast encoding. + char* p = buf->head(); + + // FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_indicate = kFuA; + fu_indicate |= (nri & (~kNalTypeMask)); + *p++ = fu_indicate; + + // FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8 + uint8_t fu_header = nalu_type; + if (start) { + fu_header |= kStart; + } + if (end) { + fu_header |= kEnd; + } + *p++ = fu_header; + + // FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8 + memcpy(p, payload, size); + + // Consume bytes. + buf->skip(2 + size); + + return srs_success; +} + SrsRtpSharedPacket::SrsRtpSharedPacketPayload::SrsRtpSharedPacketPayload() { payload = NULL; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 973de2205..53601d126 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -39,7 +39,7 @@ const uint8_t kNalTypeMask = 0x1F; class SrsBuffer; class SrsRtpRawPayload; -class SrsRtpFUAPayload; +class SrsRtpFUAPayload2; class SrsRtpHeader { @@ -65,17 +65,17 @@ public: public: size_t header_size(); public: - void set_marker(bool marker); + inline void set_marker(bool v) { marker = v; } bool get_marker() const { return marker; } - void set_payload_type(uint8_t payload_type); + inline void set_payload_type(uint8_t v) { payload_type = v; } uint8_t get_payload_type() const { return payload_type; } - void set_sequence(uint16_t sequence); + inline void set_sequence(uint16_t v) { sequence = v; } uint16_t get_sequence() const { return sequence; } - void set_timestamp(int64_t timestamp); + inline void set_timestamp(int64_t v) { timestamp = (uint32_t)v; } int64_t get_timestamp() const { return timestamp; } - void set_ssrc(uint32_t ssrc); + inline void set_ssrc(uint32_t v) { ssrc = v; } uint32_t get_ssrc() const { return ssrc; } - void set_padding(bool v) { padding = v; } + inline void set_padding(bool v) { padding = v; } }; class SrsRtpPacket2 @@ -84,9 +84,16 @@ public: SrsRtpHeader rtp_header; ISrsEncoder* payload; int padding; +public: + // User can set an extra payload, we will free it. + // For example, when reassemble NALUs by SrsRtpRawNALUs, we can set the extra payload to + // SrsRtpRawNALUs, then we can use SrsRtpFUAPayload which never free samples. + ISrsEncoder* extra_payload; private: SrsRtpRawPayload* cache_raw; - SrsRtpFUAPayload* cache_fua; + SrsRtpFUAPayload2* cache_fua; + bool using_cache; + int cache_payload; public: SrsRtpPacket2(); virtual ~SrsRtpPacket2(); @@ -100,7 +107,7 @@ public: // Reuse the cached raw message as payload. SrsRtpRawPayload* reuse_raw(); // Reuse the cached fua message as payload. - SrsRtpFUAPayload* reuse_fua(); + SrsRtpFUAPayload2* reuse_fua(); // interface ISrsEncoder public: virtual int nb_bytes(); @@ -111,7 +118,8 @@ public: class SrsRtpRawPayload : public ISrsEncoder { public: - // @remark We only refer to the memory, user must free it. + // The RAW payload, directly point to the shared memory. + // @remark We only refer to the memory, user must free its bytes. char* payload; int nn_payload; public: @@ -127,6 +135,9 @@ public: class SrsRtpRawNALUs : public ISrsEncoder { private: + // The returned samples. + std::vector extra_nalus; + // We will manage the samples, but the sample itself point to the shared memory. std::vector nalus; int nn_bytes; int cursor; @@ -137,7 +148,8 @@ public: void push_back(SrsSample* sample); public: uint8_t skip_first_byte(); - srs_error_t read_samples(std::vector& samples, int size); + // We will manage the returned samples, if user want to manage it, please copy it. + srs_error_t read_samples(std::vector& samples, int packet_size); // interface ISrsEncoder public: virtual int nb_bytes(); @@ -163,6 +175,7 @@ public: }; // FU-A, for one NALU with multiple fragments. +// With more than one payload. class SrsRtpFUAPayload : public ISrsEncoder { public: @@ -178,8 +191,29 @@ public: public: SrsRtpFUAPayload(); virtual ~SrsRtpFUAPayload(); +// interface ISrsEncoder public: - void reset(); + virtual int nb_bytes(); + virtual srs_error_t encode(SrsBuffer* buf); +}; + +// FU-A, for one NALU with multiple fragments. +// With only one payload. +class SrsRtpFUAPayload2 : public ISrsEncoder +{ +public: + // The NRI in NALU type. + SrsAvcNaluType nri; + // The FUA header. + bool start; + bool end; + SrsAvcNaluType nalu_type; + // The payload and size, + char* payload; + int size; +public: + SrsRtpFUAPayload2(); + virtual ~SrsRtpFUAPayload2(); // interface ISrsEncoder public: virtual int nb_bytes(); From ce36a970ff075d631c221fca66b1affa41faaf38 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 18 Apr 2020 22:55:38 +0800 Subject: [PATCH 128/131] Refine perf stat --- trunk/3rdparty/st-srs/README.md | 8 ++++++ trunk/src/app/srs_app_rtc_conn.cpp | 39 ++++++++++++++++++------------ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/trunk/3rdparty/st-srs/README.md b/trunk/3rdparty/st-srs/README.md index 60fc1a651..522d3c761 100644 --- a/trunk/3rdparty/st-srs/README.md +++ b/trunk/3rdparty/st-srs/README.md @@ -22,6 +22,8 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche - [x] Patch [st.osx10.14.build.patch](https://github.com/ossrs/srs/blob/2.0release/trunk/3rdparty/patches/6.st.osx10.14.build.patch), for osx 10.14 build. - [x] Support macro `MD_ST_NO_ASM` to disable ASM, [#8](https://github.com/ossrs/state-threads/issues/8). - [x] Merge patch [srs#1282](https://github.com/ossrs/srs/issues/1282#issuecomment-445539513) to support aarch64, [#9](https://github.com/ossrs/state-threads/issues/9). +- [x] Support OSX for Apple Darwin, macOS, [#11](https://github.com/ossrs/state-threads/issues/11). +- [x] Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). ## Docs @@ -85,4 +87,10 @@ Important cli options: 1. `--track-origins= [default: no]`, Controls whether Memcheck tracks the origin of uninitialised values. By default, it does not, which means that although it can tell you that an uninitialised value is being used in a dangerous way, it cannot tell you where the uninitialised value came from. This often makes it difficult to track down the root problem. 1. `--show-reachable= , --show-possibly-lost=`, to show the using memory. +## Analysis + +1. About setjmp and longjmp, read [setjmp](https://gitee.com/winlinvip/srs-wiki/raw/master/images/st-setjmp.jpg). +1. About the stack structure, read [stack](https://gitee.com/winlinvip/srs-wiki/raw/master/images/st-stack.jpg) +1. About asm code comments, read [#91d530e](https://github.com/ossrs/state-threads/commit/91d530e#diff-ed9428b14ff6afda0e9ab04cc91d4445R25). + Winlin 2016 diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 230ea2e49..5b79be9ca 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -2013,6 +2013,7 @@ srs_error_t SrsUdpMuxSender::cycle() srs_error_t err = srs_success; uint64_t nn_msgs = 0; uint64_t nn_msgs_last = 0; int nn_msgs_max = 0; + uint64_t nn_bytes = 0; int nn_bytes_max = 0; uint64_t nn_gso_msgs = 0; uint64_t nn_gso_iovs = 0; int nn_gso_msgs_max = 0; int nn_gso_iovs_max = 0; int nn_loop = 0; int nn_wait = 0; srs_utime_t time_last = srs_get_system_time(); @@ -2044,21 +2045,8 @@ srs_error_t SrsUdpMuxSender::cycle() cache_pos = 0; int gso_pos = 0; + int nn_writen = 0; if (pos > 0) { - // Collect informations for GSO. - if (stat_enabled) { - // For shared GSO cache, stat the messages. - // @see https://linux.die.net/man/2/sendmmsg - // @see https://linux.die.net/man/2/sendmsg - for (int i = 0; i < pos; i++) { - mmsghdr* mhdr = &hotspot[i]; - - int real_iovs = mhdr->msg_hdr.msg_iovlen; - gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; - gso_iovs += real_iovs; - } - } - // Send out all messages. // @see https://linux.die.net/man/2/sendmmsg // @see https://linux.die.net/man/2/sendmsg @@ -2076,6 +2064,22 @@ srs_error_t SrsUdpMuxSender::cycle() stat->perf_on_sendmmsg_packets(vlen); } } + + // Collect informations for GSO. + if (stat_enabled) { + // Stat the messages, iovs and bytes. + // @see https://linux.die.net/man/2/sendmmsg + // @see https://linux.die.net/man/2/sendmsg + for (int i = 0; i < pos; i++) { + mmsghdr* mhdr = &hotspot[i]; + + nn_writen += (int)mhdr->msg_len; + + int real_iovs = mhdr->msg_hdr.msg_iovlen; + gso_pos++; nn_gso_msgs++; nn_gso_iovs += real_iovs; + gso_iovs += real_iovs; + } + } } if (!stat_enabled) { @@ -2085,6 +2089,8 @@ srs_error_t SrsUdpMuxSender::cycle() // Increase total messages. nn_msgs += pos + gso_iovs; nn_msgs_max = srs_max(pos, nn_msgs_max); + nn_bytes += nn_writen; + nn_bytes_max = srs_max(nn_bytes_max, nn_writen); nn_gso_msgs_max = srs_max(gso_pos, nn_gso_msgs_max); nn_gso_iovs_max = srs_max(gso_iovs, nn_gso_iovs_max); @@ -2115,12 +2121,13 @@ srs_error_t SrsUdpMuxSender::cycle() nn_cache += hdr->msg_hdr.msg_iovlen; } - srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s, cache %d/%d", + srs_trace("-> RTC SEND #%d, sessions %d, udp %d/%d/%" PRId64 ", gso %d/%d/%" PRId64 ", iovs %d/%d/%" PRId64 ", pps %d/%d%s, cache %d/%d, bytes %d/%" PRId64, srs_netfd_fileno(lfd), (int)server->nn_sessions(), pos, nn_msgs_max, nn_msgs, gso_pos, nn_gso_msgs_max, nn_gso_msgs, gso_iovs, - nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), (int)hotspot.size(), nn_cache); + nn_gso_iovs_max, nn_gso_iovs, pps_average, pps_last, pps_unit.c_str(), (int)hotspot.size(), nn_cache, nn_bytes_max, nn_bytes); nn_msgs_last = nn_msgs; time_last = srs_get_system_time(); nn_loop = nn_wait = nn_msgs_max = 0; nn_gso_msgs_max = 0; nn_gso_iovs_max = 0; + nn_bytes_max = 0; } } From b1df04cb09205fbd7a87c09a62a95451e101d18d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Apr 2020 09:32:09 +0800 Subject: [PATCH 129/131] Fix double free bug for RTP --- trunk/src/app/srs_app_rtc_conn.cpp | 1 + trunk/src/kernel/srs_kernel_rtp.cpp | 8 -------- trunk/src/kernel/srs_kernel_rtp.hpp | 6 ++---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 5b79be9ca..401ecc01f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -478,6 +478,7 @@ SrsRtcPackets::SrsRtcPackets(int nn_cache_max) cursor = 0; nn_cache = nn_cache_max; + // TODO: FIXME: We should allocate a smaller cache, and increase it when exhausted. cache = new SrsRtpPacket2[nn_cache]; } diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index fa98c5957..0215cb1a6 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -297,13 +297,6 @@ SrsRtpRawNALUs::~SrsRtpRawNALUs() srs_freep(p); } } - if (true) { - int nn_nalus = (int)extra_nalus.size(); - for (int i = 0; i < nn_nalus; i++) { - SrsSample* p = extra_nalus[i]; - srs_freep(p); - } - } } void SrsRtpRawNALUs::push_back(SrsSample* sample) @@ -356,7 +349,6 @@ srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int packet srs_assert(nn > 0); SrsSample* sample = new SrsSample(); - extra_nalus.push_back(sample); samples.push_back(sample); sample->bytes = p->bytes + pos; diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 53601d126..eb811ee29 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -135,8 +135,6 @@ public: class SrsRtpRawNALUs : public ISrsEncoder { private: - // The returned samples. - std::vector extra_nalus; // We will manage the samples, but the sample itself point to the shared memory. std::vector nalus; int nn_bytes; @@ -162,7 +160,7 @@ class SrsRtpSTAPPayload : public ISrsEncoder public: // The NRI in NALU type. SrsAvcNaluType nri; - // The NALU samples. + // The NALU samples, we will manage the samples. // @remark We only refer to the memory, user must free its bytes. std::vector nalus; public: @@ -185,7 +183,7 @@ public: bool start; bool end; SrsAvcNaluType nalu_type; - // The NALU samples. + // The NALU samples, we manage the samples. // @remark We only refer to the memory, user must free its bytes. std::vector nalus; public: From 6a4e0433498ef783ed7fca4168ea2b5d6d0d6791 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Apr 2020 11:22:18 +0800 Subject: [PATCH 130/131] Fix the double free bug --- trunk/src/app/srs_app_rtc_conn.cpp | 2 -- trunk/src/kernel/srs_kernel_rtp.cpp | 13 ++++--------- trunk/src/kernel/srs_kernel_rtp.hpp | 1 - 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 401ecc01f..ffab0f6e5 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1212,8 +1212,6 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac packet->payload = raw; } else { - SrsAutoFree(SrsRtpRawNALUs, raw); - // Package NALUs in FU-A RTP packets. int fu_payload_size = kRtpMaxPayloadSize; diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index 0215cb1a6..a61b360a3 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -157,19 +157,19 @@ SrsRtpPacket2::SrsRtpPacket2() cache_raw = new SrsRtpRawPayload(); cache_fua = new SrsRtpFUAPayload2(); cache_payload = 0; - using_cache = false; } SrsRtpPacket2::~SrsRtpPacket2() { // We may use the cache as payload. - if (using_cache) { + if (payload == cache_raw || payload == cache_fua) { payload = NULL; } srs_freep(payload); srs_freep(extra_payload); srs_freep(cache_raw); + srs_freep(cache_fua); } void SrsRtpPacket2::set_padding(int size) @@ -198,25 +198,20 @@ void SrsRtpPacket2::reset() srs_freep(extra_payload); // We may use the cache as payload. - if (using_cache) { + if (payload == cache_raw || payload == cache_fua) { payload = NULL; - } else { - srs_freep(payload); } - - using_cache = false; + srs_freep(payload); } SrsRtpRawPayload* SrsRtpPacket2::reuse_raw() { - using_cache = true; payload = cache_raw; return cache_raw; } SrsRtpFUAPayload2* SrsRtpPacket2::reuse_fua() { - using_cache = true; payload = cache_fua; return cache_fua; } diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index eb811ee29..31b59ec85 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -92,7 +92,6 @@ public: private: SrsRtpRawPayload* cache_raw; SrsRtpFUAPayload2* cache_fua; - bool using_cache; int cache_payload; public: SrsRtpPacket2(); From 32879eaf477cbd01b6d397c1281e91f456e70939 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Apr 2020 13:16:48 +0800 Subject: [PATCH 131/131] Fix double free bug for RTP --- trunk/src/app/srs_app_rtc_conn.cpp | 5 ++++- trunk/src/kernel/srs_kernel_rtp.cpp | 5 +---- trunk/src/kernel/srs_kernel_rtp.hpp | 5 ----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index ffab0f6e5..dd9a791b2 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1212,6 +1212,10 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac packet->payload = raw; } else { + // We must free it, should never use RTP packets to free it, + // because more than one RTP packet will refer to it. + SrsAutoFree(SrsRtpRawNALUs, raw); + // Package NALUs in FU-A RTP packets. int fu_payload_size = kRtpMaxPayloadSize; @@ -1229,7 +1233,6 @@ srs_error_t SrsRtcSenderThread::packet_nalus(SrsSharedPtrMessage* msg, SrsRtcPac srs_freep(raw); return srs_error_new(ERROR_RTC_RTP_MUXER, "cache empty"); } - packet->extra_payload = raw; packet->rtp_header.set_timestamp(msg->timestamp * 90); packet->rtp_header.set_sequence(video_sequence++); diff --git a/trunk/src/kernel/srs_kernel_rtp.cpp b/trunk/src/kernel/srs_kernel_rtp.cpp index a61b360a3..5c23cbd34 100644 --- a/trunk/src/kernel/srs_kernel_rtp.cpp +++ b/trunk/src/kernel/srs_kernel_rtp.cpp @@ -151,7 +151,6 @@ size_t SrsRtpHeader::header_size() SrsRtpPacket2::SrsRtpPacket2() { payload = NULL; - extra_payload = NULL; padding = 0; cache_raw = new SrsRtpRawPayload(); @@ -167,7 +166,6 @@ SrsRtpPacket2::~SrsRtpPacket2() } srs_freep(payload); - srs_freep(extra_payload); srs_freep(cache_raw); srs_freep(cache_fua); } @@ -195,7 +193,6 @@ void SrsRtpPacket2::reset() rtp_header.reset(); padding = 0; cache_payload = 0; - srs_freep(extra_payload); // We may use the cache as payload. if (payload == cache_raw || payload == cache_fua) { @@ -330,7 +327,7 @@ srs_error_t SrsRtpRawNALUs::read_samples(vector& samples, int packet int left = packet_size; int nn_nalus = (int)nalus.size(); - for (int i = 0; i < nn_nalus; i++) { + for (int i = 0; left > 0 && i < nn_nalus; i++) { SrsSample* p = nalus[i]; // Ignore previous consumed samples. diff --git a/trunk/src/kernel/srs_kernel_rtp.hpp b/trunk/src/kernel/srs_kernel_rtp.hpp index 31b59ec85..349c388a5 100644 --- a/trunk/src/kernel/srs_kernel_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtp.hpp @@ -84,11 +84,6 @@ public: SrsRtpHeader rtp_header; ISrsEncoder* payload; int padding; -public: - // User can set an extra payload, we will free it. - // For example, when reassemble NALUs by SrsRtpRawNALUs, we can set the extra payload to - // SrsRtpRawNALUs, then we can use SrsRtpFUAPayload which never free samples. - ISrsEncoder* extra_payload; private: SrsRtpRawPayload* cache_raw; SrsRtpFUAPayload2* cache_fua;