Add hack to RtcpTransceiver to mitigate bug in RtcpReceiver of remote endpoint.
Bug: webrtc:8805 Change-Id: I540ff1d2503ba43723e82800b0bebd322f1af351 Reviewed-on: https://webrtc-review.googlesource.com/44481 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21802}
This commit is contained in:
parent
f120cba82d
commit
49456a5b33
@ -93,6 +93,11 @@ struct RtcpTransceiverConfig {
|
||||
// Estimate RTT as non-sender as described in
|
||||
// https://tools.ietf.org/html/rfc3611#section-4.4 and #section-4.5
|
||||
bool non_sender_rtt_measurement = false;
|
||||
// Copies LastSR/DelaySinceLastSR for previous report block to avoid
|
||||
// triggering bug in older version of RtcpReceiver.
|
||||
// TODO(bugs.webrtc.org/8805): Change to false by default then remove when
|
||||
// all major webrtc clients updated with the fix in RtcpReceiver.
|
||||
bool avoid_zero_last_sr_in_last_report_block = true;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -402,15 +402,27 @@ std::vector<rtcp::ReportBlock> RtcpTransceiverImpl::CreateReportBlocks(
|
||||
std::vector<rtcp::ReportBlock> report_blocks =
|
||||
config_.receive_statistics->RtcpReportBlocks(
|
||||
rtcp::ReceiverReport::kMaxNumberOfReportBlocks);
|
||||
uint32_t last_sr = 0;
|
||||
uint32_t last_delay = 0;
|
||||
for (rtcp::ReportBlock& report_block : report_blocks) {
|
||||
auto it = remote_senders_.find(report_block.source_ssrc());
|
||||
if (it == remote_senders_.end() || !it->second.last_received_sender_report)
|
||||
if (it == remote_senders_.end() ||
|
||||
!it->second.last_received_sender_report) {
|
||||
if (config_.avoid_zero_last_sr_in_last_report_block && last_sr != 0) {
|
||||
// Simulate behaviour of the RtcpSender to avoid hitting bug in
|
||||
// RtcpReceiver.
|
||||
report_block.SetLastSr(last_sr);
|
||||
report_block.SetDelayLastSr(last_delay);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const SenderReportTimes& last_sender_report =
|
||||
*it->second.last_received_sender_report;
|
||||
report_block.SetLastSr(CompactNtp(last_sender_report.remote_sent_time));
|
||||
report_block.SetDelayLastSr(SaturatedUsToCompactNtp(
|
||||
now_us - last_sender_report.local_received_time_us));
|
||||
last_sr = CompactNtp(last_sender_report.remote_sent_time);
|
||||
last_delay = SaturatedUsToCompactNtp(
|
||||
now_us - last_sender_report.local_received_time_us);
|
||||
report_block.SetLastSr(last_sr);
|
||||
report_block.SetDelayLastSr(last_delay);
|
||||
}
|
||||
return report_blocks;
|
||||
}
|
||||
|
||||
@ -569,6 +569,7 @@ TEST(RtcpTransceiverImplTest,
|
||||
|
||||
RtcpTransceiverConfig config;
|
||||
config.schedule_periodic_compound_packets = false;
|
||||
config.avoid_zero_last_sr_in_last_report_block = false;
|
||||
RtcpPacketParser rtcp_parser;
|
||||
RtcpParserTransport transport(&rtcp_parser);
|
||||
config.outgoing_transport = &transport;
|
||||
@ -576,9 +577,9 @@ TEST(RtcpTransceiverImplTest,
|
||||
RtcpTransceiverImpl rtcp_transceiver(config);
|
||||
|
||||
const NtpTime kRemoteNtp(0x9876543211);
|
||||
// Receive SenderReport for RemoteSsrc2, but no report for RemoteSsrc1.
|
||||
// Receive SenderReport for RemoteSsrc1, but no report for RemoteSsrc2.
|
||||
SenderReport sr;
|
||||
sr.SetSenderSsrc(kRemoteSsrc2);
|
||||
sr.SetSenderSsrc(kRemoteSsrc1);
|
||||
sr.SetNtp(kRemoteNtp);
|
||||
auto raw_packet = sr.Build();
|
||||
rtcp_transceiver.ReceivePacket(raw_packet, /*now_us=*/0);
|
||||
@ -593,11 +594,57 @@ TEST(RtcpTransceiverImplTest,
|
||||
// match result of ReceiveStatisticsProvider::RtcpReportBlocks callback,
|
||||
// but for simplicity of the test asume it is the same.
|
||||
ASSERT_EQ(report_blocks[0].source_ssrc(), kRemoteSsrc1);
|
||||
// No matching Sender Report for kRemoteSsrc1, LastSR fields has to be 0.
|
||||
EXPECT_EQ(report_blocks[0].last_sr(), 0u);
|
||||
EXPECT_EQ(report_blocks[0].last_sr(), CompactNtp(kRemoteNtp));
|
||||
|
||||
ASSERT_EQ(report_blocks[1].source_ssrc(), kRemoteSsrc2);
|
||||
EXPECT_EQ(report_blocks[1].last_sr(), CompactNtp(kRemoteNtp));
|
||||
// No matching Sender Report for kRemoteSsrc2, LastSR fields has to be 0.
|
||||
EXPECT_EQ(report_blocks[1].last_sr(), 0u);
|
||||
}
|
||||
|
||||
TEST(RtcpTransceiverImplTest, AvoidLastReportBlockToHaveZeroLastSrField) {
|
||||
const uint32_t kRemoteSsrc1 = 54321;
|
||||
const uint32_t kRemoteSsrc2 = 54323;
|
||||
MockReceiveStatisticsProvider receive_statistics;
|
||||
std::vector<ReportBlock> statistics_report_blocks(2);
|
||||
statistics_report_blocks[0].SetMediaSsrc(kRemoteSsrc1);
|
||||
statistics_report_blocks[1].SetMediaSsrc(kRemoteSsrc2);
|
||||
ON_CALL(receive_statistics, RtcpReportBlocks(_))
|
||||
.WillByDefault(Return(statistics_report_blocks));
|
||||
|
||||
RtcpTransceiverConfig config;
|
||||
config.schedule_periodic_compound_packets = false;
|
||||
config.avoid_zero_last_sr_in_last_report_block = true;
|
||||
RtcpPacketParser rtcp_parser;
|
||||
RtcpParserTransport transport(&rtcp_parser);
|
||||
config.outgoing_transport = &transport;
|
||||
config.receive_statistics = &receive_statistics;
|
||||
RtcpTransceiverImpl rtcp_transceiver(config);
|
||||
|
||||
const NtpTime kRemoteNtp(0x9876543211);
|
||||
// Receive SenderReport for RemoteSsrc1, but no report for RemoteSsrc2.
|
||||
SenderReport sr;
|
||||
sr.SetSenderSsrc(kRemoteSsrc1);
|
||||
sr.SetNtp(kRemoteNtp);
|
||||
auto raw_packet = sr.Build();
|
||||
rtcp_transceiver.ReceivePacket(raw_packet, /*now_us=*/0);
|
||||
|
||||
// Trigger sending ReceiverReport.
|
||||
rtcp_transceiver.SendCompoundPacket();
|
||||
|
||||
EXPECT_GT(rtcp_parser.receiver_report()->num_packets(), 0);
|
||||
const auto& report_blocks = rtcp_parser.receiver_report()->report_blocks();
|
||||
ASSERT_EQ(report_blocks.size(), 2u);
|
||||
// RtcpTransceiverImpl doesn't guarantee order of the report blocks
|
||||
// match result of ReceiveStatisticsProvider::RtcpReportBlocks callback,
|
||||
// but for simplicity of the test asume it is the same.
|
||||
ASSERT_EQ(report_blocks[0].source_ssrc(), kRemoteSsrc1);
|
||||
EXPECT_NE(report_blocks[0].last_sr(), 0u);
|
||||
|
||||
ASSERT_EQ(report_blocks[1].source_ssrc(), kRemoteSsrc2);
|
||||
// No Sender Report for kRemoteSsrc2, use same LastSR as for kRemoteSsrc1
|
||||
EXPECT_EQ(report_blocks[1].last_sr(), report_blocks[0].last_sr());
|
||||
EXPECT_EQ(report_blocks[1].delay_since_last_sr(),
|
||||
report_blocks[0].delay_since_last_sr());
|
||||
}
|
||||
|
||||
TEST(RtcpTransceiverImplTest,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user