Integrate `RttSimulator` into video timing simulator In this change, the previously landed `RttSimulator` is integrated into the video timing simulator. The `RtcEventLogDriver` receives the smoothed session-level RTT estimates, and distributes them to the streams. The streams use the RTTs to adapt the NACK module (inside the `Assembler`) and the jitter estimator (inside the `RenderingTracker`). Bug: b/423646186 Change-Id: I792fcfea7ac7f4bf8d97a73f674a7d5ca8c25727 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/479821 Commit-Queue: Rasmus Brandt <brandtr@webrtc.org> Reviewed-by: Åsa Persson <asapersson@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47960}
diff --git a/video/timing/simulator/assembler.cc b/video/timing/simulator/assembler.cc index af881d0..93d4baa 100644 --- a/video/timing/simulator/assembler.cc +++ b/video/timing/simulator/assembler.cc
@@ -19,6 +19,7 @@ #include "api/rtp_parameters.h" #include "api/sequence_checker.h" #include "api/task_queue/task_queue_base.h" +#include "api/units/time_delta.h" #include "api/video/encoded_frame.h" #include "api/video/video_codec_type.h" #include "call/video_receive_stream.h" @@ -96,6 +97,11 @@ rtp_video_stream_receiver2_.FrameDecoded(frame_id); } +void Assembler::UpdateMaxRtt(TimeDelta max_rtt) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + rtp_video_stream_receiver2_.UpdateRtt(max_rtt.ms()); +} + void Assembler::OnCompleteFrame(std::unique_ptr<EncodedFrame> encoded_frame) { RTC_DCHECK_RUN_ON(&sequence_checker_); // We rename this callback from `OnCompleteFrame` to `OnAssembledFrame`, since
diff --git a/video/timing/simulator/assembler.h b/video/timing/simulator/assembler.h index 2e3fe11..f85c230 100644 --- a/video/timing/simulator/assembler.h +++ b/video/timing/simulator/assembler.h
@@ -20,6 +20,7 @@ #include "api/call/transport.h" #include "api/environment/environment.h" #include "api/sequence_checker.h" +#include "api/units/time_delta.h" #include "api/video/encoded_frame.h" #include "call/video_receive_stream.h" #include "modules/rtp_rtcp/include/receive_statistics.h" @@ -80,6 +81,8 @@ // so that it can be flushed from the `PacketBuffer`. void OnDecodedFrameId(int64_t frame_id) override; + void UpdateMaxRtt(TimeDelta max_rtt); + private: // Trivially implements `Transport`. // We need to implement this due to an RTC_DCHECK in rtcp_sender.cc.
diff --git a/video/timing/simulator/decodability_simulator.cc b/video/timing/simulator/decodability_simulator.cc index acabf2e..d6d8b51 100644 --- a/video/timing/simulator/decodability_simulator.cc +++ b/video/timing/simulator/decodability_simulator.cc
@@ -20,6 +20,7 @@ #include "api/environment/environment.h" #include "api/sequence_checker.h" #include "api/units/data_size.h" +#include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/video/encoded_frame.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" @@ -150,6 +151,11 @@ receiver_.InsertSimulatedPacket(simulated_packet); } + void UpdateMaxRtt(TimeDelta max_rtt) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + assembler_.UpdateMaxRtt(max_rtt); + } + void Close() override { RTC_DCHECK_RUN_ON(&sequence_checker_); DecodabilitySimulator::Stream stream = collector_.GetStream();
diff --git a/video/timing/simulator/rendering_simulator.cc b/video/timing/simulator/rendering_simulator.cc index 9bb5527..6ebe186 100644 --- a/video/timing/simulator/rendering_simulator.cc +++ b/video/timing/simulator/rendering_simulator.cc
@@ -207,6 +207,12 @@ receiver_.InsertSimulatedPacket(simulated_packet); } + void UpdateMaxRtt(TimeDelta max_rtt) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + assembler_.UpdateMaxRtt(max_rtt); + tracker_.UpdateMaxRtt(max_rtt); + } + void Close() override { RTC_DCHECK_RUN_ON(&sequence_checker_); RenderingSimulator::Stream stream = collector_.GetStream();
diff --git a/video/timing/simulator/rendering_simulator_unittest.cc b/video/timing/simulator/rendering_simulator_unittest.cc index b7e813e..eef19e1 100644 --- a/video/timing/simulator/rendering_simulator_unittest.cc +++ b/video/timing/simulator/rendering_simulator_unittest.cc
@@ -479,7 +479,7 @@ [](const auto& e) { return e.ArrivalTimestamp().IsFinite(); }), - Eq(960)); + Eq(987)); // Find the last rendered frame. EXPECT_TRUE(absl::c_is_sorted(stream.frames, @@ -511,15 +511,14 @@ .last_packet_arrival_timestamp = Timestamp::Millis(821457158), // Frame timestamps. .assembled_timestamp = Timestamp::Millis(821457158), - .render_timestamp = Timestamp::Millis(821457178), - .decoded_timestamp = Timestamp::Micros(821457168065), - .rendered_timestamp = Timestamp::Micros(821457168065), + .render_timestamp = Timestamp::Millis(821457378), + .decoded_timestamp = Timestamp::Micros(821457368242), + .rendered_timestamp = Timestamp::Micros(821457368242), // Jitter buffer information. .frames_dropped = 0, - // The value below is unreasonably low, we should fix this. - .jitter_buffer_minimum_delay = TimeDelta::Micros(13085), - .jitter_buffer_target_delay = TimeDelta::Micros(13085), - .jitter_buffer_delay = TimeDelta::Micros(21065)})); + .jitter_buffer_minimum_delay = TimeDelta::Micros(213371), + .jitter_buffer_target_delay = TimeDelta::Micros(213371), + .jitter_buffer_delay = TimeDelta::Micros(221242)})); } } // namespace
diff --git a/video/timing/simulator/rendering_tracker.cc b/video/timing/simulator/rendering_tracker.cc index 0fc6eb3..88fcbcd 100644 --- a/video/timing/simulator/rendering_tracker.cc +++ b/video/timing/simulator/rendering_tracker.cc
@@ -116,6 +116,11 @@ } } +void RenderingTracker::UpdateMaxRtt(TimeDelta max_rtt) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + video_stream_buffer_controller_.UpdateRtt(max_rtt.ms()); +} + void RenderingTracker::OnEncodedFrame( std::unique_ptr<EncodedFrame> encoded_frame) { RTC_DCHECK_RUN_ON(&sequence_checker_);
diff --git a/video/timing/simulator/rendering_tracker.h b/video/timing/simulator/rendering_tracker.h index 0e0dc75..7acaf48 100644 --- a/video/timing/simulator/rendering_tracker.h +++ b/video/timing/simulator/rendering_tracker.h
@@ -80,6 +80,8 @@ // any rendered frames to the `observer_`. void OnAssembledFrame(std::unique_ptr<EncodedFrame> assembled_frame) override; + void UpdateMaxRtt(TimeDelta max_rtt); + private: struct VideoStreamBufferControllerObserverDecodableStats { TimeDelta jitter_buffer_delay = TimeDelta::Zero();
diff --git a/video/timing/simulator/rtc_event_log_driver.cc b/video/timing/simulator/rtc_event_log_driver.cc index 3ca305a..c51a766 100644 --- a/video/timing/simulator/rtc_event_log_driver.cc +++ b/video/timing/simulator/rtc_event_log_driver.cc
@@ -13,9 +13,12 @@ #include <cstdint> #include <memory> #include <optional> +#include <set> #include <utility> #include "absl/base/nullability.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "api/environment/environment_factory.h" @@ -32,6 +35,7 @@ #include "rtc_base/logging.h" #include "test/time_controller/simulated_time_task_queue_controller.h" #include "video/timing/simulator/rtp_packet_simulator.h" +#include "video/timing/simulator/rtt_simulator.h" namespace webrtc::video_timing_simulator { @@ -52,15 +56,26 @@ simulator_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue( "simulator_queue", TaskQueueFactory::Priority::kNormal)), - packet_simulator_(env_) { + packet_simulator_(env_), + rtt_callback_adapter_(this) { RTC_DCHECK(stream_factory_) << "stream_factory must be provided"; + bool done = false; + simulator_queue_->PostTask([this, &done]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_ = std::make_unique<RttSimulator>( + env_, simulator_queue_.get(), &rtt_callback_adapter_); + done = true; + }); + time_controller_.AdvanceTime(TimeDelta::Zero()); + RTC_DCHECK(done); + // Config events. processor_.AddEvents( parsed_log_.video_recv_configs(), - [&](const auto& config) { OnLoggedVideoRecvConfig(config); }); + [this](const auto& config) { OnLoggedVideoRecvConfig(config); }); - // Video packet events (media + RTX). + // RTP video packet events (media + RTX). for (const auto& stream : parsed_log_.incoming_rtp_packets_by_ssrc()) { bool is_video = parsed_log_.GetMediaType( stream.ssrc, PacketDirection::kIncomingPacket) == @@ -68,10 +83,44 @@ if (!is_video) { continue; } - processor_.AddEvents(stream.incoming_packets, [&](const auto& packet) { + processor_.AddEvents(stream.incoming_packets, [this](const auto& packet) { OnLoggedRtpPacketIncoming(packet); }); } + + // RTCP packet events (outgoing). + processor_.AddEvents( + parsed_log_.sender_reports(PacketDirection::kOutgoingPacket), + [this](const auto& packet) { + OnLoggedRtcpPacketSenderReportOutgoing(packet); + }, + PacketDirection::kOutgoingPacket); + processor_.AddEvents( + parsed_log_.extended_reports(PacketDirection::kOutgoingPacket), + [this](const auto& packet) { + OnLoggedRtcpPacketExtendedReportsOutgoing(packet); + }, + PacketDirection::kOutgoingPacket); + + // RTCP packet events (incoming). + processor_.AddEvents( + parsed_log_.sender_reports(PacketDirection::kIncomingPacket), + [this](const auto& packet) { + OnLoggedRtcpPacketSenderReportIncoming(packet); + }, + PacketDirection::kIncomingPacket); + processor_.AddEvents( + parsed_log_.receiver_reports(PacketDirection::kIncomingPacket), + [this](const auto& packet) { + OnLoggedRtcpPacketReceiverReportIncoming(packet); + }, + PacketDirection::kIncomingPacket); + processor_.AddEvents( + parsed_log_.extended_reports(PacketDirection::kIncomingPacket), + [this](const auto& packet) { + OnLoggedRtcpPacketExtendedReportsIncoming(packet); + }, + PacketDirection::kIncomingPacket); } RtcEventLogDriver::~RtcEventLogDriver() = default; @@ -200,13 +249,62 @@ }); } +void RtcEventLogDriver::OnLoggedRtcpPacketSenderReportOutgoing( + const LoggedRtcpPacketSenderReport& packet) { + HandleEvent(packet.log_time(), [this, packet]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_->OnOutgoingSenderReport(packet); + }); +} + +void RtcEventLogDriver::OnLoggedRtcpPacketExtendedReportsOutgoing( + const LoggedRtcpPacketExtendedReports& packet) { + HandleEvent(packet.log_time(), [this, packet]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_->OnOutgoingExtendedReports(packet); + }); +} + +void RtcEventLogDriver::OnLoggedRtcpPacketSenderReportIncoming( + const LoggedRtcpPacketSenderReport& packet) { + HandleEvent(packet.log_time(), [this, packet]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_->OnIncomingSenderReport(packet); + }); +} + +void RtcEventLogDriver::OnLoggedRtcpPacketReceiverReportIncoming( + const LoggedRtcpPacketReceiverReport& packet) { + HandleEvent(packet.log_time(), [this, packet]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_->OnIncomingReceiverReport(packet); + }); +} + +void RtcEventLogDriver::OnLoggedRtcpPacketExtendedReportsIncoming( + const LoggedRtcpPacketExtendedReports& packet) { + HandleEvent(packet.log_time(), [this, packet]() { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + rtt_simulator_->OnIncomingExtendedReports(packet); + }); +} + +void RtcEventLogDriver::UpdateMaxRtt(TimeDelta max_rtt) { + RTC_DCHECK_RUN_ON(simulator_queue_.get()); + for (auto& stream : streams_) { + stream.second->UpdateMaxRtt(max_rtt); + } +} + void RtcEventLogDriver::TeardownOnQueue() { RTC_DCHECK_RUN_ON(simulator_queue_.get()); for (auto& stream : streams_) { stream.second->Close(); } + all_known_ssrcs_.clear(); receiving_streams_.clear(); streams_.clear(); + rtt_simulator_.reset(); } } // namespace webrtc::video_timing_simulator
diff --git a/video/timing/simulator/rtc_event_log_driver.h b/video/timing/simulator/rtc_event_log_driver.h index 48a8eee..ab311e9 100644 --- a/video/timing/simulator/rtc_event_log_driver.h +++ b/video/timing/simulator/rtc_event_log_driver.h
@@ -33,6 +33,7 @@ #include "rtc_base/thread_annotations.h" #include "test/time_controller/simulated_time_task_queue_controller.h" #include "video/timing/simulator/rtp_packet_simulator.h" +#include "video/timing/simulator/rtt_simulator.h" namespace webrtc::video_timing_simulator { @@ -49,9 +50,12 @@ // running on the provided task queue(s). // // TODO: b/423646186 - Improvements: +// * Consider splitting the `RtcEventLogDriver` class into two: +// - One for orchestration (queue, event processor, +// event handler registration, ...). +// - One for media simulation (RTTs, streams, ...). Running on the queue. // * Handle `LogSegment`s. // * Handle stop events. -// * Parse RTT updates from RTCPs. class RtcEventLogDriver { public: // Configuration for the `RtcEventLogDriver` itself. @@ -73,6 +77,8 @@ // Insert `simulated_packet` into the stream. virtual void InsertSimulatedPacket( const RtpPacketSimulator::SimulatedPacket& simulated_packet) = 0; + // Propagate an RTT update to the stream components. + virtual void UpdateMaxRtt(TimeDelta max_rtt) = 0; // Notify the stream that no more packets will be inserted. virtual void Close() = 0; }; @@ -104,6 +110,19 @@ } private: + class RttCallbackAdapter : public SimulatedRttCallback { + public: + explicit RttCallbackAdapter(RtcEventLogDriver* absl_nonnull driver) + : driver_(*driver) {} + ~RttCallbackAdapter() override = default; + void OnMaxRttUpdate(TimeDelta max_rtt) override { + driver_.UpdateMaxRtt(max_rtt); + } + + private: + RtcEventLogDriver& driver_; + }; + // Simulation. // Sets the `time_controller_` simulated time to `log_timestamp`, thus // executing all relevant tasks on the `simulator_queue_`. @@ -117,6 +136,18 @@ // RtcEventProcessor callbacks (running on main thread). void OnLoggedVideoRecvConfig(const LoggedVideoRecvConfig& config); void OnLoggedRtpPacketIncoming(const LoggedRtpPacketIncoming& packet); + void OnLoggedRtcpPacketSenderReportOutgoing( + const LoggedRtcpPacketSenderReport& packet); + void OnLoggedRtcpPacketExtendedReportsOutgoing( + const LoggedRtcpPacketExtendedReports& packet); + void OnLoggedRtcpPacketSenderReportIncoming( + const LoggedRtcpPacketSenderReport& packet); + void OnLoggedRtcpPacketReceiverReportIncoming( + const LoggedRtcpPacketReceiverReport& packet); + void OnLoggedRtcpPacketExtendedReportsIncoming( + const LoggedRtcpPacketExtendedReports& packet); + + void UpdateMaxRtt(TimeDelta max_rtt); // Destroy owned objects on `simulator_queue_`. void TeardownOnQueue() RTC_RUN_ON(simulator_queue_); @@ -135,6 +166,8 @@ std::optional<Timestamp> prev_log_timestamp_; std::unique_ptr<TaskQueueBase, TaskQueueDeleter> simulator_queue_; RtpPacketSimulator packet_simulator_ RTC_GUARDED_BY(simulator_queue_); + RttCallbackAdapter rtt_callback_adapter_ RTC_GUARDED_BY(simulator_queue_); + std::unique_ptr<RttSimulator> rtt_simulator_ RTC_GUARDED_BY(simulator_queue_); // Owned streams. Keyed by `ssrc`, so that they can be replaced if needed. absl::flat_hash_map<uint32_t, std::unique_ptr<StreamInterface>> streams_ RTC_GUARDED_BY(simulator_queue_);
diff --git a/video/timing/simulator/rtc_event_log_driver_unittest.cc b/video/timing/simulator/rtc_event_log_driver_unittest.cc index 50ac1f2..9922fc6 100644 --- a/video/timing/simulator/rtc_event_log_driver_unittest.cc +++ b/video/timing/simulator/rtc_event_log_driver_unittest.cc
@@ -17,8 +17,17 @@ #include "absl/strings/string_view.h" #include "api/environment/environment.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" +#include "modules/rtp_rtcp/source/ntp_time_util.h" +#include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h" +#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h" +#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" +#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h" +#include "modules/rtp_rtcp/source/rtcp_packet/rrtr.h" +#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h" #include "rtc_base/checks.h" +#include "system_wrappers/include/ntp_time.h" #include "test/gmock.h" #include "test/gtest.h" #include "video/timing/simulator/rtp_packet_simulator.h" @@ -39,12 +48,16 @@ constexpr uint16_t kRtxOsn = 823; +constexpr uint32_t kSenderSsrc = 123456; +constexpr uint32_t kReceiverSsrc = 987654; + class MockRtcEventLogDriverStream : public RtcEventLogDriver::StreamInterface { public: MOCK_METHOD(void, InsertSimulatedPacket, (const RtpPacketSimulator::SimulatedPacket& simulated_packet), (override)); + MOCK_METHOD(void, UpdateMaxRtt, (TimeDelta max_rtt), (override)); MOCK_METHOD(void, Close, (), (override)); }; @@ -272,5 +285,134 @@ driver.Simulate(); } +rtcp::SenderReport CreateSenderReport(NtpTime ntp) { + rtcp::SenderReport sr; + sr.SetSenderSsrc(kSenderSsrc); + sr.SetNtp(ntp); + return sr; +} + +rtcp::SenderReport CreateSenderReportWithReportBlock( + NtpTime ntp, + uint32_t last_sr, + uint32_t delay_since_last_sr) { + rtcp::SenderReport sr; + sr.SetSenderSsrc(kReceiverSsrc); + sr.SetNtp(ntp); + rtcp::ReportBlock block; + block.SetMediaSsrc(kSenderSsrc); + block.SetLastSr(last_sr); + block.SetDelayLastSr(delay_since_last_sr); + sr.AddReportBlock(block); + return sr; +} + +rtcp::ReceiverReport CreateReceiverReport(uint32_t last_sr, + uint32_t delay_since_last_sr) { + rtcp::ReceiverReport rr; + rr.SetSenderSsrc(kReceiverSsrc); + rtcp::ReportBlock block; + block.SetMediaSsrc(kSenderSsrc); + block.SetLastSr(last_sr); + block.SetDelayLastSr(delay_since_last_sr); + rr.AddReportBlock(block); + return rr; +} + +rtcp::ExtendedReports CreateExtendedReportsWithRrtr(NtpTime ntp) { + rtcp::ExtendedReports xr; + xr.SetSenderSsrc(kReceiverSsrc); + rtcp::Rrtr rrtr; + rrtr.SetNtp(ntp); + xr.SetRrtr(rrtr); + return xr; +} + +rtcp::ExtendedReports CreateExtendedReportsWithDlrr( + uint32_t last_rr, + uint32_t delay_since_last_rr) { + rtcp::ExtendedReports xr; + xr.SetSenderSsrc(kSenderSsrc); + rtcp::ReceiveTimeInfo dlrr_block; + dlrr_block.ssrc = kReceiverSsrc; + dlrr_block.last_rr = last_rr; + dlrr_block.delay_since_last_rr = delay_since_last_rr; + xr.AddDlrrItem(dlrr_block); + return xr; +} + +TEST_F(RtcEventLogDriverTest, SenderCalculatesRttFromIncomingRr) { + parsed_log_builder_.LogVideoRecvConfig(kSsrc1, kRtxSsrc1); + + // Outgoing SR. + NtpTime ntp = parsed_log_builder_.CurrentNtpTime(); + parsed_log_builder_.LogRtcpPacketOutgoing(CreateSenderReport(ntp)); + + // Incoming RR: 50ms delay, arrives after 150ms => RTT is 100ms. + parsed_log_builder_.AdvanceTime(TimeDelta::Millis(150)); + uint32_t last_sr = CompactNtp(ntp); + uint32_t delay_since_last_sr = SaturatedToCompactNtp(TimeDelta::Millis(50)); + parsed_log_builder_.LogRtcpPacketIncoming( + CreateReceiverReport(last_sr, delay_since_last_sr)); + + std::unique_ptr<ParsedRtcEventLog> parsed_log = parsed_log_builder_.Build(); + + EXPECT_CALL(*stream_factory_.stream1_ptr_, + UpdateMaxRtt(TimeDelta::Millis(100))); + EXPECT_CALL(*stream_factory_.stream1_ptr_, Close()); + RtcEventLogDriver driver(RtcEventLogDriver::Config(), parsed_log.get(), + kEmptyFieldTrialsString, BuildStreamFactory()); + driver.Simulate(); +} + +TEST_F(RtcEventLogDriverTest, SenderCalculatesRttFromIncomingSr) { + parsed_log_builder_.LogVideoRecvConfig(kSsrc1, kRtxSsrc1); + + // Outgoing SR. + NtpTime ntp = parsed_log_builder_.CurrentNtpTime(); + parsed_log_builder_.LogRtcpPacketOutgoing(CreateSenderReport(ntp)); + + // Incoming SR: 50ms delay, arrives after 150ms => RTT is 100ms. + parsed_log_builder_.AdvanceTime(TimeDelta::Millis(150)); + uint32_t last_sr = CompactNtp(ntp); + uint32_t delay_since_last_sr = SaturatedToCompactNtp(TimeDelta::Millis(50)); + NtpTime ntp_incoming; + parsed_log_builder_.LogRtcpPacketIncoming(CreateSenderReportWithReportBlock( + ntp_incoming, last_sr, delay_since_last_sr)); + + std::unique_ptr<ParsedRtcEventLog> parsed_log = parsed_log_builder_.Build(); + + EXPECT_CALL(*stream_factory_.stream1_ptr_, + UpdateMaxRtt(TimeDelta::Millis(100))); + EXPECT_CALL(*stream_factory_.stream1_ptr_, Close()); + RtcEventLogDriver driver(RtcEventLogDriver::Config(), parsed_log.get(), + kEmptyFieldTrialsString, BuildStreamFactory()); + driver.Simulate(); +} + +TEST_F(RtcEventLogDriverTest, ReceiverCalculatesRttFromIncomingXr) { + parsed_log_builder_.LogVideoRecvConfig(kSsrc1, kRtxSsrc1); + + // Outgoing XR with RRTR. + NtpTime ntp = parsed_log_builder_.CurrentNtpTime(); + parsed_log_builder_.LogRtcpPacketOutgoing(CreateExtendedReportsWithRrtr(ntp)); + + // Incoming XR with DLRR: 50ms delay, arrives after 150ms => RTT is 100ms. + parsed_log_builder_.AdvanceTime(TimeDelta::Millis(150)); + uint32_t last_rr = CompactNtp(ntp); + uint32_t delay_since_last_rr = SaturatedToCompactNtp(TimeDelta::Millis(50)); + parsed_log_builder_.LogRtcpPacketIncoming( + CreateExtendedReportsWithDlrr(last_rr, delay_since_last_rr)); + + std::unique_ptr<ParsedRtcEventLog> parsed_log = parsed_log_builder_.Build(); + + EXPECT_CALL(*stream_factory_.stream1_ptr_, + UpdateMaxRtt(TimeDelta::Millis(100))); + EXPECT_CALL(*stream_factory_.stream1_ptr_, Close()); + RtcEventLogDriver driver(RtcEventLogDriver::Config(), parsed_log.get(), + kEmptyFieldTrialsString, BuildStreamFactory()); + driver.Simulate(); +} + } // namespace } // namespace webrtc::video_timing_simulator
diff --git a/video/timing/simulator/rtt_simulator.h b/video/timing/simulator/rtt_simulator.h index 11ef4b7..4599fef 100644 --- a/video/timing/simulator/rtt_simulator.h +++ b/video/timing/simulator/rtt_simulator.h
@@ -68,7 +68,7 @@ // Worker objects. RtcpRttCalculator rtt_calculator_ RTC_GUARDED_BY(sequence_checker_); - webrtc::internal::CallStats call_stats_ RTC_GUARDED_BY(sequence_checker_); + internal::CallStats call_stats_ RTC_GUARDED_BY(sequence_checker_); // Outputs. SimulatedRttCallback& simulated_rtt_cb_;
diff --git a/video/timing/simulator/rtt_simulator_unittest.cc b/video/timing/simulator/rtt_simulator_unittest.cc index 31b2714..b7bfdf2 100644 --- a/video/timing/simulator/rtt_simulator_unittest.cc +++ b/video/timing/simulator/rtt_simulator_unittest.cc
@@ -163,7 +163,7 @@ Timestamp recv_timestamp = time_controller_.GetClock()->CurrentTime(); uint32_t last_sr = CompactNtp(ntp); uint32_t delay_since_last_sr = SaturatedToCompactNtp(TimeDelta::Millis(50)); - NtpTime ntp_incoming = env_.clock().ConvertTimestampToNtpTime(recv_timestamp); + NtpTime ntp_incoming; auto sr_incoming = CreateLoggedRtcpPacketSenderReportWithReportBlock( ntp_incoming, last_sr, delay_since_last_sr, recv_timestamp);
diff --git a/video/timing/simulator/test/parsed_rtc_event_log_builder.cc b/video/timing/simulator/test/parsed_rtc_event_log_builder.cc index 8f2c558..4e23453 100644 --- a/video/timing/simulator/test/parsed_rtc_event_log_builder.cc +++ b/video/timing/simulator/test/parsed_rtc_event_log_builder.cc
@@ -23,12 +23,16 @@ #include "api/rtc_event_log_output.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" +#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h" +#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h" #include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h" #include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" #include "logging/rtc_event_log/rtc_stream_config.h" +#include "modules/rtp_rtcp/source/rtcp_packet.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/checks.h" +#include "system_wrappers/include/ntp_time.h" #include "test/create_test_environment.h" namespace webrtc::video_timing_simulator { @@ -82,6 +86,10 @@ return log_clock_.CurrentTime(); } +NtpTime ParsedRtcEventLogBuilder::CurrentNtpTime() { + return log_clock_.ConvertTimestampToNtpTime(log_clock_.CurrentTime()); +} + void ParsedRtcEventLogBuilder::AdvanceTime(TimeDelta duration) { log_clock_.AdvanceTime(duration); } @@ -103,6 +111,16 @@ rtp_packet, rtx_original_sequence_number)); } +void ParsedRtcEventLogBuilder::LogRtcpPacketOutgoing( + const rtcp::RtcpPacket& rtcp_packet) { + Log(std::make_unique<RtcEventRtcpPacketOutgoing>(rtcp_packet.Build())); +} + +void ParsedRtcEventLogBuilder::LogRtcpPacketIncoming( + const rtcp::RtcpPacket& rtcp_packet) { + Log(std::make_unique<RtcEventRtcpPacketIncoming>(rtcp_packet.Build())); +} + void ParsedRtcEventLogBuilder::Log(std::unique_ptr<RtcEvent> event) { RTC_DCHECK(log_); log_->Log(std::move(event));
diff --git a/video/timing/simulator/test/parsed_rtc_event_log_builder.h b/video/timing/simulator/test/parsed_rtc_event_log_builder.h index 815e775..b54a1de 100644 --- a/video/timing/simulator/test/parsed_rtc_event_log_builder.h +++ b/video/timing/simulator/test/parsed_rtc_event_log_builder.h
@@ -21,7 +21,9 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "logging/rtc_event_log/rtc_event_log_parser.h" +#include "modules/rtp_rtcp/source/rtcp_packet.h" #include "system_wrappers/include/clock.h" +#include "system_wrappers/include/ntp_time.h" namespace webrtc::video_timing_simulator { @@ -37,6 +39,7 @@ // Interactions with the `log_clock_`. // Note that this clock is different from the simulation clock! Timestamp CurrentTime(); + NtpTime CurrentNtpTime(); void AdvanceTime(TimeDelta duration); // Log specific events to the log. @@ -45,6 +48,8 @@ void LogRtpPacketIncoming( uint32_t ssrc, std::optional<uint16_t> rtx_original_sequence_number = std::nullopt); + void LogRtcpPacketOutgoing(const rtcp::RtcpPacket& rtcp_packet); + void LogRtcpPacketIncoming(const rtcp::RtcpPacket& rtcp_packet); // Returns the parsed log. Should only be called once. std::unique_ptr<ParsedRtcEventLog> Build();