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

Fix regression (crash) in transport-cc feedback generation #1339

Merged
merged 6 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### Next

- Fix regression (crash) in transport-cc feedback generation ([PR #1339](https://github.com/versatica/mediasoup/pull/1339)).

### 3.13.19

- Node: Fix `router.createWebRtcTransport()` with `listenIps` ([PR #1330](https://github.com/versatica/mediasoup/pull/1330)).
Expand Down
4 changes: 4 additions & 0 deletions worker/include/RTC/RTCP/FeedbackRtpTransport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ namespace RTC
~FeedbackRtpTransportPacket() override;

public:
bool IsBaseSet() const
{
return this->baseSet;
}
void SetBase(uint16_t sequenceNumber, uint64_t timestamp);
AddPacketResult AddPacket(uint16_t sequenceNumber, uint64_t timestamp, size_t maxRtcpPacketLen);
// Just for locally generated packets.
Expand Down
4 changes: 3 additions & 1 deletion worker/include/RTC/TransportCongestionControlServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ namespace RTC
void FillAndSendTransportCcFeedback();

private:
void SendTransportCcFeedback();
// Returns true if a feedback packet was sent.
bool SendTransportCcFeedback();
void MayDropOldPacketArrivalTimes(uint16_t seqNum, uint64_t nowMs);
void MaySendLimitationRembFeedback(uint64_t nowMs);
void UpdatePacketLoss(double packetLoss);
Expand Down Expand Up @@ -95,6 +96,7 @@ namespace RTC
// Whether any packet with transport wide sequence number was received.
bool transportWideSeqNumberReceived{ false };
uint16_t transportCcFeedbackWideSeqNumStart{ 0u };
// Map of arrival timestamp (ms) indexed by wide seq number.
std::map<uint16_t, uint64_t, RTC::SeqManager<uint16_t>::SeqLowerThan> mapPacketArrivalTimes;
};
} // namespace RTC
Expand Down
9 changes: 6 additions & 3 deletions worker/src/RTC/RTCP/FeedbackRtpTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ namespace RTC
{
MS_TRACE();

MS_ASSERT(!this->baseSet, "base already set");

this->baseSet = true;
this->baseSequenceNumber = sequenceNumber;
this->referenceTime = static_cast<int32_t>((timestamp & 0x1FFFFFC0) / 64);
Expand All @@ -297,8 +299,8 @@ namespace RTC
MS_ASSERT(this->baseSet, "base not set");
MS_ASSERT(!IsFull(), "packet is full");

// If the wide sequence number of the new packet is lower than the latest seen,
// ignore it.
// If the wide sequence number of the new packet is lower than the latest
// seen, ignore it.
// NOTE: Not very spec compliant but libwebrtc does it.
// Also ignore if the sequence number matches the latest seen.
if (!RTC::SeqManager<uint16_t>::IsSeqHigherThan(sequenceNumber, this->latestSequenceNumber))
Expand Down Expand Up @@ -340,7 +342,8 @@ namespace RTC
// Delta in 16 bits signed.
auto delta = static_cast<int16_t>(delta64);

// Check whether another chunks and corresponding delta infos could be added.
// Check whether another chunks and corresponding delta infos could be
// added.
{
// Fixed packet size.
size_t size = FeedbackRtpPacket::GetSize();
Expand Down
78 changes: 57 additions & 21 deletions worker/src/RTC/TransportCongestionControlServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ namespace RTC
// Create a feedback packet.
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(0u, 0u));

// Set initial packet count.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(this->transportCcFeedbackPacketCount);
ibc marked this conversation as resolved.
Show resolved Hide resolved

// Create the feedback send periodic timer.
this->transportCcFeedbackSendPeriodicTimer = new TimerHandle(this);

Expand Down Expand Up @@ -96,6 +93,9 @@ namespace RTC
// Create a new feedback packet.
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(0u, 0u));

// Set current packet count.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(this->transportCcFeedbackPacketCount);

break;
}

Expand Down Expand Up @@ -131,9 +131,10 @@ namespace RTC
break;
}

// We may receive packets with sequence number lower than the one in previous
// tcc feedback, these packets may have been reported as lost previously,
// therefore we need to reset the start sequence num for the next tcc feedback.
// We may receive packets with sequence number lower than the one in
// previous tcc feedback, these packets may have been reported as lost
// previously, therefore we need to reset the start sequence num for the
// next tcc feedback.
if (
!this->transportWideSeqNumberReceived ||
RTC::SeqManager<uint16_t>::IsSeqLowerThan(
Expand Down Expand Up @@ -192,13 +193,23 @@ namespace RTC
return;
}

// Set base sequence num and reference time.
this->transportCcFeedbackPacket->SetBase(this->transportCcFeedbackWideSeqNumStart, it->second);

for (; it != this->mapPacketArrivalTimes.end(); ++it)
{
auto result =
this->transportCcFeedbackPacket->AddPacket(it->first, it->second, this->maxRtcpPacketLen);
auto sequenceNumber = it->first;
auto timestamp = it->second;

// If the base is not set in this packet let's set it.
// NOTE: This maybe needed many times during this loop since the current
// feedback packet maybe a fresh new one if the previous one was full (so
// already sent) or failed to be built.
if (!this->transportCcFeedbackPacket->IsBaseSet())
jmillan marked this conversation as resolved.
Show resolved Hide resolved
{
// Set base sequence num and reference time.
this->transportCcFeedbackPacket->SetBase(this->transportCcFeedbackWideSeqNumStart, timestamp);
}

auto result = this->transportCcFeedbackPacket->AddPacket(
sequenceNumber, timestamp, this->maxRtcpPacketLen);

switch (result)
{
Expand All @@ -209,7 +220,19 @@ namespace RTC
{
MS_DEBUG_DEV("transport-cc feedback packet is full, sending feedback now");

SendTransportCcFeedback();
if (!SendTransportCcFeedback())
{
// If no feedback packet was sent then the feedback packet was
// not reset and hence it remains full so we cannot add more
// packets on it, so we have to reset it.
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(
this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc));

// Set current packet count.
// NOTE: Do not increment it since no feedback packet was sent.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(
this->transportCcFeedbackPacketCount);
}
}

break;
Expand All @@ -218,11 +241,19 @@ namespace RTC
case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::MAX_SIZE_EXCEEDED:
{
// This should not happen.
MS_WARN_DEV("transport-cc feedback packet is exceeded");
MS_WARN_TAG(rtcp, "transport-cc feedback packet is exceeded");

// Create a new feedback packet.
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(
this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc));

// Set current packet count.
// NOTE: Do not increment it since the previous ongoing feedback
// packet was not sent.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(
jmillan marked this conversation as resolved.
Show resolved Hide resolved
this->transportCcFeedbackPacketCount);

break;
}

case RTC::RTCP::FeedbackRtpTransportPacket::AddPacketResult::FATAL:
Expand All @@ -231,7 +262,7 @@ namespace RTC
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(
this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc));

// Use current packet count.
// Set current packet count.
// NOTE: Do not increment it since the previous ongoing feedback
// packet was not sent.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(
Expand All @@ -242,6 +273,8 @@ namespace RTC
}
}

// It may happen that the packet is empty (no deltas) but in that case
// SendTransportCcFeedback() won't send it so we are safe.
SendTransportCcFeedback();
}

Expand All @@ -264,15 +297,17 @@ namespace RTC
}
}

inline void TransportCongestionControlServer::SendTransportCcFeedback()
ibc marked this conversation as resolved.
Show resolved Hide resolved
bool TransportCongestionControlServer::SendTransportCcFeedback()
{
MS_TRACE();

this->transportCcFeedbackPacket->Finish();

if (!this->transportCcFeedbackPacket->IsSerializable())
{
return;
MS_WARN_DEV("couldn't send feedback packet (not serializable)");

return false;
}

auto latestWideSeqNumber = this->transportCcFeedbackPacket->GetLatestSequenceNumber();
Expand Down Expand Up @@ -305,10 +340,11 @@ namespace RTC
// Increment packet count.
this->transportCcFeedbackPacket->SetFeedbackPacketCount(++this->transportCcFeedbackPacketCount);
this->transportCcFeedbackWideSeqNumStart = latestWideSeqNumber + 1;

return true;
}

inline void TransportCongestionControlServer::MayDropOldPacketArrivalTimes(
uint16_t seqNum, uint64_t nowMs)
void TransportCongestionControlServer::MayDropOldPacketArrivalTimes(uint16_t seqNum, uint64_t nowMs)
{
MS_TRACE();

Expand All @@ -330,7 +366,7 @@ namespace RTC
}
}

inline void TransportCongestionControlServer::MaySendLimitationRembFeedback(uint64_t nowMs)
void TransportCongestionControlServer::MaySendLimitationRembFeedback(uint64_t nowMs)
{
MS_TRACE();

Expand Down Expand Up @@ -402,7 +438,7 @@ namespace RTC
this->packetLoss = totalPacketLoss / samples;
}

inline void TransportCongestionControlServer::OnRembServerAvailableBitrate(
void TransportCongestionControlServer::OnRembServerAvailableBitrate(
const webrtc::RemoteBitrateEstimator* /*rembServer*/,
const std::vector<uint32_t>& ssrcs,
uint32_t availableBitrate)
Expand Down Expand Up @@ -440,7 +476,7 @@ namespace RTC
this->listener->OnTransportCongestionControlServerSendRtcpPacket(this, &packet);
}

inline void TransportCongestionControlServer::OnTimer(TimerHandle* timer)
void TransportCongestionControlServer::OnTimer(TimerHandle* timer)
{
MS_TRACE();

Expand Down
Loading