| /* | |
| * Copyright (c) 2025 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #ifndef VIDEO_TIMING_SIMULATOR_RTC_EVENT_LOG_DRIVER_H_ | |
| #define VIDEO_TIMING_SIMULATOR_RTC_EVENT_LOG_DRIVER_H_ | |
| #include <cstdint> | |
| #include <memory> | |
| #include <optional> | |
| #include <set> | |
| #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.h" | |
| #include "api/task_queue/task_queue_base.h" | |
| #include "api/units/time_delta.h" | |
| #include "api/units/timestamp.h" | |
| #include "logging/rtc_event_log/events/logged_rtp_rtcp.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_event_processor.h" | |
| #include "rtc_base/thread_annotations.h" | |
| #include "test/time_controller/simulated_time_task_queue_controller.h" | |
| #include "video/timing/simulator/rtp_packet_simulator.h" | |
| namespace webrtc::video_timing_simulator { | |
| // The `RtcEventLogDriver` is responsible for driving a simulation given an | |
| // RtcEventLog. It walks through the relevant events in the log in | |
| // `log_timestamp` order, and provides the events to an underlying `stream` | |
| // abstraction. This abstraction allows the `RtcEventLogDriver` to be agnostic | |
| // w.r.t. how the simulated packets are used. We will provide abstractions for | |
| // decodability tracking and simulated rendering, but in the future we could | |
| // also wrap all of `VideoReceiveStream2`, to have a "full stack simulation". | |
| // | |
| // The `RtcEventLogDriver` is responsible for the environment and the | |
| // simulated time task queues. All worker objects should be single-threaded, | |
| // running on the provided task queue(s). | |
| // | |
| // TODO: b/423646186 - Improvements: | |
| // * Handle `LogSegment`s. | |
| // * Handle stop events. | |
| // * Parse RTT updates from RTCPs. | |
| class RtcEventLogDriver { | |
| public: | |
| // Configuration for the `RtcEventLogDriver` itself. | |
| struct Config { | |
| // If true, existing streams are reused, even if a new | |
| // `LoggedVideoRecvConfig` was logged for the same stream. (This might | |
| // happen around `SetRemoteDescription`s.) | |
| bool reuse_streams = false; | |
| // If non-empty, will only simulate video streams whose main SSRCs is | |
| // contained in the set. | |
| std::set<uint32_t> ssrc_filter = {}; | |
| }; | |
| // A stream that is driven by simulated RTP packets coming from the log. | |
| class StreamInterface { | |
| public: | |
| virtual ~StreamInterface() = default; | |
| // Insert `simulated_packet` into the stream. | |
| virtual void InsertSimulatedPacket( | |
| const RtpPacketSimulator::SimulatedPacket& simulated_packet) = 0; | |
| // Notify the stream that no more packets will be inserted. | |
| virtual void Close() = 0; | |
| }; | |
| // Factory that creates a stream given the environment and the stream SSRCs. | |
| using StreamInterfaceFactory = | |
| absl::AnyInvocable<std::unique_ptr<StreamInterface>(const Environment&, | |
| /*ssrc=*/uint32_t, | |
| /*rtx_ssrc=*/uint32_t) | |
| const>; | |
| // Slack added after final event, in order to catch any straggling frames. | |
| static constexpr TimeDelta kShutdownAdvanceTimeSlack = TimeDelta::Millis(100); | |
| RtcEventLogDriver(const Config& config, | |
| const ParsedRtcEventLog* absl_nonnull parsed_log, | |
| absl::string_view field_trials_string, | |
| StreamInterfaceFactory stream_factory); | |
| ~RtcEventLogDriver(); | |
| RtcEventLogDriver(const RtcEventLogDriver&) = delete; | |
| RtcEventLogDriver& operator=(const RtcEventLogDriver&) = delete; | |
| // Perform the simulation. Should only be called once per instantiation. | |
| void Simulate(); | |
| Timestamp GetCurrentTimeForTesting() { | |
| return time_controller_.GetClock()->CurrentTime(); | |
| } | |
| private: | |
| // Simulation. | |
| // Sets the `time_controller_` simulated time to `log_timestamp`, thus | |
| // executing all relevant tasks on the `simulator_queue_`. | |
| void AdvanceTime(Timestamp log_timestamp); | |
| // Advances time according to `log_timestamp`, and handles the event through | |
| // the `handler`. | |
| void HandleEvent(Timestamp log_timestamp, | |
| absl::AnyInvocable<void() &&> handler); | |
| // RtcEventProcessor callbacks (running on main thread). | |
| void OnLoggedVideoRecvConfig(const LoggedVideoRecvConfig& config); | |
| void OnLoggedRtpPacketIncoming(const LoggedRtpPacketIncoming& packet); | |
| // Environment. | |
| const Config config_; | |
| SimulatedTimeTaskQueueController time_controller_; | |
| const Environment env_; | |
| // Input. | |
| const ParsedRtcEventLog& parsed_log_; | |
| StreamInterfaceFactory stream_factory_; | |
| // Simulator. | |
| RtcEventProcessor processor_; | |
| std::optional<Timestamp> prev_log_timestamp_; | |
| std::unique_ptr<TaskQueueBase, TaskQueueDeleter> simulator_queue_; | |
| RtpPacketSimulator packet_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_); | |
| // Streams for reception. Keyed by both `ssrc` and `rtx_ssrc`. | |
| absl::flat_hash_map<uint32_t, StreamInterface*> receiving_streams_ | |
| RTC_GUARDED_BY(simulator_queue_); | |
| // Keep track of all logged `ssrc`s for text logging purposes. | |
| absl::flat_hash_set<uint32_t> all_known_ssrcs_ | |
| RTC_GUARDED_BY(simulator_queue_); | |
| }; | |
| } // namespace webrtc::video_timing_simulator | |
| #endif // VIDEO_TIMING_SIMULATOR_RTC_EVENT_LOG_DRIVER_H_ |