diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index d1192b7b3..80f9fe659 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1125,6 +1125,13 @@ srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) return srs_error_new(ERROR_RTC_RTP, "unknown ssrc=%u", ssrc); } + // Check then send NACK every each RTP packet, to make it more efficient. + // For example, NACK of video track maybe triggered by audio RTP packets. + if ((err = check_send_nacks()) != srs_success) { + srs_warn("ignore nack err %s", srs_error_desc(err).c_str()); + srs_freep(err); + } + if (_srs_rtc_hijacker) { // TODO: FIXME: copy pkt by hijacker itself if ((err = _srs_rtc_hijacker->on_rtp_packet(session_, this, req, pkt->copy())) != srs_success) { @@ -1135,6 +1142,27 @@ srs_error_t SrsRtcPublishStream::do_on_rtp(char* plaintext, int nb_plaintext) return err; } +srs_error_t SrsRtcPublishStream::check_send_nacks() +{ + srs_error_t err = srs_success; + + for (int i = 0; i < (int)video_tracks_.size(); ++i) { + SrsRtcVideoRecvTrack* track = video_tracks_.at(i); + if ((err = track->check_send_nacks()) != srs_success) { + return srs_error_wrap(err, "video track=%s", track->get_track_id().c_str()); + } + } + + for (int i = 0; i < (int)audio_tracks_.size(); ++i) { + SrsRtcAudioRecvTrack* track = audio_tracks_.at(i); + if ((err = track->check_send_nacks()) != srs_success) { + return srs_error_wrap(err, "audio track=%s", track->get_track_id().c_str()); + } + } + + return err; +} + void SrsRtcPublishStream::on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload) { // No payload, ignore. diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index f616fd752..66e450105 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -314,6 +314,7 @@ public: srs_error_t on_rtp(char* buf, int nb_buf); private: srs_error_t do_on_rtp(char* plaintext, int nb_plaintext); + srs_error_t check_send_nacks(); public: virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsRtpPayloader** ppayload); private: diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 8f4f319dc..18664ae15 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1719,6 +1719,18 @@ srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) return err; } +srs_error_t SrsRtcRecvTrack::check_send_nacks() +{ + srs_error_t err = srs_success; + + uint32_t sent_nacks = 0; + uint32_t timeout_nacks = 0; + session_->check_send_nacks(nack_receiver_, track_desc_->ssrc_, sent_nacks); + statistic_->nacks += sent_nacks; + + return err; +} + SrsRtcAudioRecvTrack::SrsRtcAudioRecvTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc) : SrsRtcRecvTrack(session, track_desc, true) { diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 491501ec0..31528b97c 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -501,6 +501,7 @@ protected: srs_error_t on_nack(SrsRtpPacket2* pkt); public: virtual srs_error_t on_rtp(SrsRtcStream* source, SrsRtpPacket2* pkt) = 0; + virtual srs_error_t check_send_nacks(); }; class SrsRtcAudioRecvTrack : public SrsRtcRecvTrack