Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rtcp sr and rr for rtc play #3748

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
103 changes: 92 additions & 11 deletions trunk/src/app/srs_app_rtc_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,8 @@ SrsRtcPlayStream::SrsRtcPlayStream(SrsRtcConnection* s, const SrsContextId& cid)

cache_ssrc0_ = cache_ssrc1_ = cache_ssrc2_ = 0;
cache_track0_ = cache_track1_ = cache_track2_ = NULL;

timer_rtcp_ = new SrsRtcPlayRtcpTimer(this);
}

SrsRtcPlayStream::~SrsRtcPlayStream()
Expand All @@ -448,6 +450,7 @@ SrsRtcPlayStream::~SrsRtcPlayStream()

_srs_config->unsubscribe(this);

srs_freep(timer_rtcp_);
srs_freep(nack_epp);
srs_freep(pli_worker_);
srs_freep(trd_);
Expand Down Expand Up @@ -681,6 +684,26 @@ srs_error_t SrsRtcPlayStream::cycle()
}
}

srs_error_t SrsRtcPlayStream::send_rtcp_sr(srs_utime_t now_ms)
{
srs_error_t err = srs_success;
for(std::map<uint32_t, SrsRtcVideoSendTrack*>::iterator iter = video_tracks_.begin(); iter != video_tracks_.end(); iter++) {
SrsRtcVideoSendTrack* track = iter->second;
if ((err = track->send_rtcp_sr(now_ms)) != srs_success) {
return srs_error_wrap(err, "video send rtcp sr error track=%s", track->get_track_id().c_str());
}
}

for(std::map<uint32_t, SrsRtcAudioSendTrack*>::iterator iter = audio_tracks_.begin(); iter != audio_tracks_.end(); iter++) {
SrsRtcAudioSendTrack* track = iter->second;
if ((err = track->send_rtcp_sr(now_ms)) != srs_success) {
return srs_error_wrap(err, "audiosend rtcp sr error track=%s", track->get_track_id().c_str());
}
}

return err;
}

srs_error_t SrsRtcPlayStream::send_packet(SrsRtpPacket*& pkt)
{
srs_error_t err = srs_success;
Expand Down Expand Up @@ -779,8 +802,9 @@ void SrsRtcPlayStream::set_all_tracks_status(bool status)
srs_error_t SrsRtcPlayStream::on_rtcp(SrsRtcpCommon* rtcp)
{
if(SrsRtcpType_rr == rtcp->type()) {
srs_utime_t now_ms = srs_update_system_time()/1000;
SrsRtcpRR* rr = dynamic_cast<SrsRtcpRR*>(rtcp);
return on_rtcp_rr(rr);
return on_rtcp_rr(rr, now_ms);
} else if(SrsRtcpType_rtpfb == rtcp->type()) {
//currently rtpfb of nack will be handle by player. TWCC will be handled by SrsRtcConnection
SrsRtcpNack* nack = dynamic_cast<SrsRtcpNack*>(rtcp);
Expand All @@ -799,12 +823,27 @@ srs_error_t SrsRtcPlayStream::on_rtcp(SrsRtcpCommon* rtcp)
}
}

srs_error_t SrsRtcPlayStream::on_rtcp_rr(SrsRtcpRR* rtcp)
srs_error_t SrsRtcPlayStream::on_rtcp_rr(SrsRtcpRR* rtcp, srs_utime_t now_ms)
{
srs_error_t err = srs_success;

// TODO: FIXME: Implements it.
for(std::vector<SrsRtcpRB>::iterator iter = rtcp->rr_blocks_.begin(); iter != rtcp->rr_blocks_.end(); iter++) {
SrsRtcpRB& rb = *iter;
uint32_t ssrc = rb.ssrc;

for(std::map<uint32_t, SrsRtcAudioSendTrack*>::iterator audio_iter = audio_tracks_.begin(); audio_iter != audio_tracks_.end(); audio_iter++) {
if(ssrc == audio_iter->second->track_desc_->ssrc_) {
return audio_iter->second->handle_rtcp_rr(rb, now_ms);
}
}

for(std::map<uint32_t, SrsRtcVideoSendTrack*>::iterator video_iter = video_tracks_.begin(); video_iter != video_tracks_.end(); video_iter++) {
if(ssrc == video_iter->second->track_desc_->ssrc_) {
return video_iter->second->handle_rtcp_rr(rb, now_ms);
}
}
srs_warn("rtcp rr find to find track by ssrc:%u", ssrc);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

}
return err;
}

Expand Down Expand Up @@ -928,6 +967,33 @@ srs_error_t SrsRtcPlayStream::do_request_keyframe(uint32_t ssrc, SrsContextId ci
return err;
}

SrsRtcPlayRtcpTimer::SrsRtcPlayRtcpTimer(SrsRtcPlayStream* p) : p_(p)
{
_srs_hybrid->timer1s()->subscribe(this);
}

SrsRtcPlayRtcpTimer::~SrsRtcPlayRtcpTimer()
{
_srs_hybrid->timer1s()->unsubscribe(this);
}

srs_error_t SrsRtcPlayRtcpTimer::on_timer(srs_utime_t interval)
{
srs_error_t err = srs_success;

if (!p_->is_started) {
return err;
}

srs_utime_t now_ms = srs_update_system_time() / 1000;
Copy link
Member

@winlinvip winlinvip Aug 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot divide by 1000 here, because this function returns srs_utime_t, and the variable cannot have a unit, because this type already has a unit.

It should be changed to:

srs_utime_t now = srs_update_system_time();

if ((err = p_->send_rtcp_sr(now)) != srs_success) {

Your send_rtcp_sr should not be in milliseconds or seconds, it should be srs_utime_t, because it has a unit, which is a time unit. Don't convert it to milliseconds or seconds, only convert it to milliseconds using srsu2ms when it is finally used.

TRANS_BY_GPT4

if ((err = p_->send_rtcp_sr(now_ms)) != srs_success) {
winlinvip marked this conversation as resolved.
Show resolved Hide resolved
srs_warn("RR err %s", srs_error_desc(err).c_str());
srs_freep(err);
}

return err;
}

SrsRtcPublishRtcpTimer::SrsRtcPublishRtcpTimer(SrsRtcPublishStream* p) : p_(p)
{
_srs_hybrid->timer1s()->subscribe(this);
Expand Down Expand Up @@ -1298,17 +1364,17 @@ srs_error_t SrsRtcPublishStream::send_rtcp_rr()
{
srs_error_t err = srs_success;

for (int i = 0; i < (int)video_tracks_.size(); ++i) {
SrsRtcVideoRecvTrack* track = video_tracks_.at(i);
for (std::vector<SrsRtcVideoRecvTrack*>::iterator iter = video_tracks_.begin(); iter != video_tracks_.end(); iter++) {
SrsRtcVideoRecvTrack* track = *iter;
if ((err = track->send_rtcp_rr()) != srs_success) {
return srs_error_wrap(err, "track=%s", track->get_track_id().c_str());
return srs_error_wrap(err, "send rtcp rr error, videotrack=%s", track->get_track_id().c_str());
}
}

for (int i = 0; i < (int)audio_tracks_.size(); ++i) {
SrsRtcAudioRecvTrack* track = audio_tracks_.at(i);
for (std::vector<SrsRtcAudioRecvTrack*>::iterator iter = audio_tracks_.begin(); iter != audio_tracks_.end(); iter++) {
SrsRtcAudioRecvTrack* track = *iter;
if ((err = track->send_rtcp_rr()) != srs_success) {
return srs_error_wrap(err, "track=%s", track->get_track_id().c_str());
return srs_error_wrap(err, "send rtcp rr error: audiotrack=%s", track->get_track_id().c_str());
}
}

Expand Down Expand Up @@ -2079,9 +2145,15 @@ srs_error_t SrsRtcConnection::dispatch_rtcp(SrsRtcpCommon* rtcp)
// Ignore special packet.
if (SrsRtcpType_rr == rtcp->type()) {
SrsRtcpRR* rr = dynamic_cast<SrsRtcpRR*>(rtcp);
if (rr->get_rb_ssrc() == 0) { //for native client
if (rr->rr_blocks_.empty()) { //for native client
return err;
}
for (std::vector<SrsRtcpRB>::iterator iter = rr->rr_blocks_.begin(); iter != rr->rr_blocks_.end(); iter++) {
SrsRtcpRB& rb = *iter;
if (rb.ssrc == 0) {
return err;
}
}
}

// The feedback packet for specified SSRC.
Expand All @@ -2091,7 +2163,16 @@ srs_error_t SrsRtcConnection::dispatch_rtcp(SrsRtcpCommon* rtcp)
required_publisher_ssrc = rtcp->get_ssrc();
} else if (SrsRtcpType_rr == rtcp->type()) {
SrsRtcpRR* rr = dynamic_cast<SrsRtcpRR*>(rtcp);
required_player_ssrc = rr->get_rb_ssrc();

for (std::vector<SrsRtcpRB>::iterator iter = rr->rr_blocks_.begin(); iter != rr->rr_blocks_.end(); iter++) {
SrsRtcpRB& rb = *iter;
uint32_t ssrc = rb.ssrc;
std::map<uint32_t, SrsRtcPlayStream*>::iterator it = players_ssrc_map_.find(ssrc);
if (it != players_ssrc_map_.end()) {
it->second->on_rtcp(rtcp);
break;
}
}
} else if (SrsRtcpType_rtpfb == rtcp->type()) {
if(1 == rtcp->get_rc()) {
SrsRtcpNack* nack = dynamic_cast<SrsRtcpNack*>(rtcp);
Expand Down
21 changes: 20 additions & 1 deletion trunk/src/app/srs_app_rtc_conn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class SrsRtcNetworks;
class SrsRtcUdpNetwork;
class ISrsRtcNetwork;
class SrsRtcTcpNetwork;
class SrsRtcPlayRtcpTimer;

const uint8_t kSR = 200;
const uint8_t kRR = 201;
Expand Down Expand Up @@ -210,6 +211,7 @@ class SrsRtcAsyncCallOnStop : public ISrsAsyncCallTask
class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler
, public ISrsRtcPLIWorkerHandler, public ISrsRtcSourceChangeCallback
{
friend class SrsRtcPlayRtcpTimer;
private:
SrsContextId cid_;
SrsFastCoroutine* trd_;
Expand All @@ -223,6 +225,8 @@ class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler
std::map<uint32_t, SrsRtcVideoSendTrack*> video_tracks_;
// The pithy print for special stage.
SrsErrorPithyPrint* nack_epp;
private:
SrsRtcPlayRtcpTimer* timer_rtcp_;
private:
// Fast cache for tracks.
uint32_t cache_ssrc0_;
Expand Down Expand Up @@ -259,6 +263,8 @@ class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler
virtual void stop();
public:
virtual srs_error_t cycle();
public:
srs_error_t send_rtcp_sr(srs_utime_t now_ms);
private:
srs_error_t send_packet(SrsRtpPacket*& pkt);
public:
Expand All @@ -270,7 +276,7 @@ class SrsRtcPlayStream : public ISrsCoroutineHandler, public ISrsReloadHandler
srs_error_t on_rtcp_xr(SrsRtcpXr* rtcp);
srs_error_t on_rtcp_nack(SrsRtcpNack* rtcp);
srs_error_t on_rtcp_ps_feedback(SrsRtcpFbCommon* rtcp);
srs_error_t on_rtcp_rr(SrsRtcpRR* rtcp);
srs_error_t on_rtcp_rr(SrsRtcpRR* rtcp, int64_t now_ms);
uint32_t get_video_publish_ssrc(uint32_t play_ssrc);
// Interface ISrsRtcPLIWorkerHandler
public:
Expand All @@ -290,6 +296,19 @@ class SrsRtcPublishRtcpTimer : public ISrsFastTimer
srs_error_t on_timer(srs_utime_t interval);
};

// A fast timer for play stream, for RTCP feedback.
class SrsRtcPlayRtcpTimer : public ISrsFastTimer
{
private:
SrsRtcPlayStream* p_;
public:
SrsRtcPlayRtcpTimer(SrsRtcPlayStream* p);
virtual ~SrsRtcPlayRtcpTimer();
// interface ISrsFastTimer
private:
srs_error_t on_timer(srs_utime_t interval);
};

// A fast timer for publish stream, for TWCC feedback.
class SrsRtcPublishTwccTimer : public ISrsFastTimer
{
Expand Down
Loading