From 1a7c98b5fce09d1f36f78cc98749ca0daa84502c Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 9 Apr 2020 15:20:32 +0800 Subject: [PATCH 01/43] 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 02/43] 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 03/43] 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 04/43] 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 05/43] 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 06/43] 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 07/43] 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 08/43] 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 09/43] 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 10/43] 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 11/43] 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 12/43] 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 13/43] 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 14/43] 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 15/43] 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 16/43] 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 17/43] 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 18/43] 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 19/43] 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 20/43] 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 21/43] 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 22/43] 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 23/43] 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 24/43] 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 25/43] 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 26/43] 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 27/43] 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 28/43] 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 29/43] 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 30/43] 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 31/43] 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 32/43] 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 33/43] 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 34/43] 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 35/43] 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 36/43] 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 37/43] 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 38/43] 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 39/43] 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 40/43] 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 41/43] 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 42/43] 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 43/43] 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); };