Index: webrtc/video/end_to_end_tests.cc |
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc |
index 21a6654a833a88398fe886aafcafba737b3b9b3a..1f4ed77ffa35e3b945f1231e9dec74d30c88b8cf 100644 |
--- a/webrtc/video/end_to_end_tests.cc |
+++ b/webrtc/video/end_to_end_tests.cc |
@@ -25,6 +25,7 @@ |
#include "webrtc/modules/include/module_common_types.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" |
#include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h" |
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" |
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" |
@@ -111,7 +112,7 @@ class EndToEndTest : public test::CallTest { |
void RespectsRtcpMode(RtcpMode rtcp_mode); |
void TestXrReceiverReferenceTimeReport(bool enable_rrtr); |
void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first); |
- void TestRtpStatePreservation(bool use_rtx); |
+ void TestRtpStatePreservation(bool use_rtx, bool provoke_rtcpsr_before_rtp); |
void VerifyHistogramStats(bool use_rtx, bool use_red, bool screenshare); |
void VerifyNewVideoSendStreamsRespectNetworkState( |
MediaType network_to_bring_down, |
@@ -2965,7 +2966,8 @@ TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { |
RunBaseTest(&test); |
} |
-void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
+void EndToEndTest::TestRtpStatePreservation(bool use_rtx, |
+ bool provoke_rtcpsr_before_rtp) { |
class RtpSequenceObserver : public test::RtpRtcpObserver { |
public: |
explicit RtpSequenceObserver(bool use_rtx) |
@@ -2985,6 +2987,28 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
} |
private: |
+ void ValidateTimestampGap(uint32_t ssrc, |
+ uint32_t timestamp, |
+ bool only_padding) |
+ EXCLUSIVE_LOCKS_REQUIRED(crit_) { |
+ static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90; |
+ auto timestamp_it = last_observed_timestamp_.find(ssrc); |
+ if (timestamp_it == last_observed_timestamp_.end()) { |
+ EXPECT_FALSE(only_padding); |
+ last_observed_timestamp_[ssrc] = timestamp; |
+ } else { |
+ // Verify timestamps are reasonably close. |
+ uint32_t latest_observed = timestamp_it->second; |
+ // Wraparound handling is unnecessary here as long as an int variable |
+ // is used to store the result. |
+ int32_t timestamp_gap = timestamp - latest_observed; |
+ EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap) |
+ << "Gap in timestamps (" << latest_observed << " -> " << timestamp |
+ << ") too large for SSRC: " << ssrc << "."; |
+ timestamp_it->second = timestamp; |
+ } |
+ } |
+ |
Action OnSendRtp(const uint8_t* packet, size_t length) override { |
RTPHeader header; |
EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
@@ -3021,24 +3045,9 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
} |
} |
- static const int32_t kMaxTimestampGap = kDefaultTimeoutMs * 90; |
- auto timestamp_it = last_observed_timestamp_.find(ssrc); |
- if (timestamp_it == last_observed_timestamp_.end()) { |
- EXPECT_FALSE(only_padding); |
- last_observed_timestamp_[ssrc] = timestamp; |
- } else { |
- // Verify timestamps are reasonably close. |
- uint32_t latest_observed = timestamp_it->second; |
- // Wraparound handling is unnecessary here as long as an int variable |
- // is used to store the result. |
- int32_t timestamp_gap = timestamp - latest_observed; |
- EXPECT_LE(std::abs(timestamp_gap), kMaxTimestampGap) |
- << "Gap in timestamps (" << latest_observed << " -> " |
- << timestamp << ") too large for SSRC: " << ssrc << "."; |
- timestamp_it->second = timestamp; |
- } |
- |
rtc::CritScope lock(&crit_); |
+ ValidateTimestampGap(ssrc, timestamp, only_padding); |
+ |
// Wait for media packets on all ssrcs. |
if (!ssrc_observed_[ssrc] && !only_padding) { |
ssrc_observed_[ssrc] = true; |
@@ -3049,6 +3058,19 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
return SEND_PACKET; |
} |
+ Action OnSendRtcp(const uint8_t* packet, size_t length) override { |
+ test::RtcpPacketParser rtcp_parser; |
+ rtcp_parser.Parse(packet, length); |
+ if (rtcp_parser.sender_report()->num_packets() > 0) { |
+ uint32_t ssrc = rtcp_parser.sender_report()->Ssrc(); |
+ uint32_t rtcp_timestamp = rtcp_parser.sender_report()->RtpTimestamp(); |
+ |
+ rtc::CritScope lock(&crit_); |
+ ValidateTimestampGap(ssrc, rtcp_timestamp, false); |
+ } |
+ return SEND_PACKET; |
+ } |
+ |
SequenceNumberUnwrapper seq_numbers_unwrapper_; |
std::map<uint32_t, std::list<int64_t>> last_observed_seq_numbers_; |
std::map<uint32_t, uint32_t> last_observed_timestamp_; |
@@ -3118,6 +3140,15 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
video_send_stream_ = |
sender_call_->CreateVideoSendStream(video_send_config_, one_stream); |
video_send_stream_->Start(); |
+ if (provoke_rtcpsr_before_rtp) { |
+ // Rapid Resync Request forces sending RTCP Sender Report back. |
+ // Using this request speeds up this test because then there is no need |
+ // to wait for a second for periodic Sender Report. |
+ rtcp::RapidResyncRequest force_send_sr_back_request; |
+ rtc::Buffer packet = force_send_sr_back_request.Build(); |
+ static_cast<webrtc::test::DirectTransport&>(receive_transport) |
+ .SendRtcp(packet.data(), packet.size()); |
+ } |
CreateFrameGeneratorCapturer(); |
frame_generator_capturer_->Start(); |
@@ -3150,13 +3181,18 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) { |
} |
TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) { |
- TestRtpStatePreservation(false); |
+ TestRtpStatePreservation(false, false); |
} |
-// This test is flaky. See: |
+// These tests are flaky. See: |
// https://bugs.chromium.org/p/webrtc/issues/detail?id=4332 |
TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpStatesWithRtx) { |
- TestRtpStatePreservation(true); |
+ TestRtpStatePreservation(true, false); |
+} |
+ |
+TEST_F(EndToEndTest, |
+ DISABLED_RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) { |
+ TestRtpStatePreservation(true, true); |
} |
TEST_F(EndToEndTest, RespectsNetworkState) { |