1 /*
2 * Copyright 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "rtc_tools/rtc_event_log_visualizer/log_simulation.h"
11
12 #include <algorithm>
13 #include <utility>
14
15 #include "logging/rtc_event_log/rtc_event_processor.h"
16 #include "modules/rtp_rtcp/source/time_util.h"
17
18 namespace webrtc {
19
LogBasedNetworkControllerSimulation(std::unique_ptr<NetworkControllerFactoryInterface> factory,std::function<void (const NetworkControlUpdate &,Timestamp)> update_handler)20 LogBasedNetworkControllerSimulation::LogBasedNetworkControllerSimulation(
21 std::unique_ptr<NetworkControllerFactoryInterface> factory,
22 std::function<void(const NetworkControlUpdate&, Timestamp)> update_handler)
23 : update_handler_(update_handler), factory_(std::move(factory)) {}
24
~LogBasedNetworkControllerSimulation()25 LogBasedNetworkControllerSimulation::~LogBasedNetworkControllerSimulation() {}
26
HandleStateUpdate(const NetworkControlUpdate & update)27 void LogBasedNetworkControllerSimulation::HandleStateUpdate(
28 const NetworkControlUpdate& update) {
29 update_handler_(update, current_time_);
30 }
31
ProcessUntil(Timestamp to_time)32 void LogBasedNetworkControllerSimulation::ProcessUntil(Timestamp to_time) {
33 if (last_process_.IsInfinite()) {
34 NetworkControllerConfig config;
35 config.constraints.at_time = to_time;
36 config.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
37 config.constraints.starting_rate = DataRate::KilobitsPerSec(300);
38 config.event_log = &null_event_log_;
39 controller_ = factory_->Create(config);
40 }
41 if (last_process_.IsInfinite() ||
42 to_time - last_process_ > TimeDelta::Seconds(1)) {
43 last_process_ = to_time;
44 current_time_ = to_time;
45 ProcessInterval msg;
46 msg.at_time = to_time;
47 HandleStateUpdate(controller_->OnProcessInterval(msg));
48 } else {
49 while (last_process_ + factory_->GetProcessInterval() <= to_time) {
50 last_process_ += factory_->GetProcessInterval();
51 current_time_ = last_process_;
52 ProcessInterval msg;
53 msg.at_time = current_time_;
54 HandleStateUpdate(controller_->OnProcessInterval(msg));
55 }
56 current_time_ = to_time;
57 }
58 }
59
OnProbeCreated(const LoggedBweProbeClusterCreatedEvent & probe_cluster)60 void LogBasedNetworkControllerSimulation::OnProbeCreated(
61 const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
62 pending_probes_.push_back({probe_cluster, 0, 0});
63 }
64
OnPacketSent(const LoggedPacketInfo & packet)65 void LogBasedNetworkControllerSimulation::OnPacketSent(
66 const LoggedPacketInfo& packet) {
67 ProcessUntil(packet.log_packet_time);
68 if (packet.has_transport_seq_no) {
69 PacedPacketInfo probe_info;
70 if (!pending_probes_.empty() &&
71 packet.media_type == LoggedMediaType::kVideo) {
72 auto& probe = pending_probes_.front();
73 probe_info.probe_cluster_id = probe.event.id;
74 probe_info.send_bitrate_bps = probe.event.bitrate_bps;
75 probe_info.probe_cluster_min_bytes = probe.event.min_bytes;
76 probe_info.probe_cluster_min_probes = probe.event.min_packets;
77 probe.packets_sent++;
78 probe.bytes_sent += packet.size + packet.overhead;
79 if (probe.bytes_sent >= probe.event.min_bytes &&
80 probe.packets_sent >= probe.event.min_packets) {
81 pending_probes_.pop_front();
82 }
83 }
84
85 RtpPacketSendInfo packet_info;
86 packet_info.ssrc = packet.ssrc;
87 packet_info.transport_sequence_number = packet.transport_seq_no;
88 packet_info.rtp_sequence_number = packet.stream_seq_no;
89 packet_info.length = packet.size;
90 packet_info.pacing_info = probe_info;
91 transport_feedback_.AddPacket(packet_info, packet.overhead,
92 packet.log_packet_time);
93 }
94 rtc::SentPacket sent_packet;
95 sent_packet.send_time_ms = packet.log_packet_time.ms();
96 sent_packet.info.included_in_allocation = true;
97 sent_packet.info.packet_size_bytes = packet.size + packet.overhead;
98 if (packet.has_transport_seq_no) {
99 sent_packet.packet_id = packet.transport_seq_no;
100 sent_packet.info.included_in_feedback = true;
101 }
102 auto msg = transport_feedback_.ProcessSentPacket(sent_packet);
103 if (msg)
104 HandleStateUpdate(controller_->OnSentPacket(*msg));
105 }
106
OnFeedback(const LoggedRtcpPacketTransportFeedback & feedback)107 void LogBasedNetworkControllerSimulation::OnFeedback(
108 const LoggedRtcpPacketTransportFeedback& feedback) {
109 auto feedback_time = Timestamp::Millis(feedback.log_time_ms());
110 ProcessUntil(feedback_time);
111 auto msg = transport_feedback_.ProcessTransportFeedback(
112 feedback.transport_feedback, feedback_time);
113 if (msg)
114 HandleStateUpdate(controller_->OnTransportPacketsFeedback(*msg));
115 }
116
OnReceiverReport(const LoggedRtcpPacketReceiverReport & report)117 void LogBasedNetworkControllerSimulation::OnReceiverReport(
118 const LoggedRtcpPacketReceiverReport& report) {
119 if (report.rr.report_blocks().empty())
120 return;
121 auto report_time = Timestamp::Millis(report.log_time_ms());
122 ProcessUntil(report_time);
123 int packets_delta = 0;
124 int lost_delta = 0;
125 for (auto& block : report.rr.report_blocks()) {
126 auto it = last_report_blocks_.find(block.source_ssrc());
127 if (it != last_report_blocks_.end()) {
128 packets_delta +=
129 block.extended_high_seq_num() - it->second.extended_high_seq_num();
130 lost_delta += block.cumulative_lost() - it->second.cumulative_lost();
131 }
132 last_report_blocks_[block.source_ssrc()] = block;
133 }
134 if (packets_delta > lost_delta) {
135 TransportLossReport msg;
136 msg.packets_lost_delta = lost_delta;
137 msg.packets_received_delta = packets_delta - lost_delta;
138 msg.receive_time = report_time;
139 msg.start_time = last_report_block_time_;
140 msg.end_time = report_time;
141 last_report_block_time_ = report_time;
142 HandleStateUpdate(controller_->OnTransportLossReport(msg));
143 }
144
145 TimeDelta rtt = TimeDelta::PlusInfinity();
146 for (auto& rb : report.rr.report_blocks()) {
147 if (rb.last_sr()) {
148 uint32_t receive_time_ntp =
149 CompactNtp(TimeMicrosToNtp(report.log_time_us()));
150 uint32_t rtt_ntp =
151 receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr();
152 rtt = std::min(rtt, TimeDelta::Millis(CompactNtpRttToMs(rtt_ntp)));
153 }
154 }
155 if (rtt.IsFinite()) {
156 RoundTripTimeUpdate msg;
157 msg.receive_time = report_time;
158 msg.round_trip_time = rtt;
159 HandleStateUpdate(controller_->OnRoundTripTimeUpdate(msg));
160 }
161 }
162
OnIceConfig(const LoggedIceCandidatePairConfig & candidate)163 void LogBasedNetworkControllerSimulation::OnIceConfig(
164 const LoggedIceCandidatePairConfig& candidate) {
165 if (candidate.type == IceCandidatePairConfigType::kSelected) {
166 auto log_time = Timestamp::Micros(candidate.log_time_us());
167 ProcessUntil(log_time);
168 NetworkRouteChange msg;
169 msg.at_time = log_time;
170 msg.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
171 msg.constraints.starting_rate = DataRate::KilobitsPerSec(300);
172 msg.constraints.at_time = log_time;
173 HandleStateUpdate(controller_->OnNetworkRouteChange(msg));
174 }
175 }
176
ProcessEventsInLog(const ParsedRtcEventLog & parsed_log_)177 void LogBasedNetworkControllerSimulation::ProcessEventsInLog(
178 const ParsedRtcEventLog& parsed_log_) {
179 auto packet_infos = parsed_log_.GetOutgoingPacketInfos();
180 RtcEventProcessor processor;
181 processor.AddEvents(
182 parsed_log_.bwe_probe_cluster_created_events(),
183 [this](const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
184 OnProbeCreated(probe_cluster);
185 });
186 processor.AddEvents(packet_infos, [this](const LoggedPacketInfo& packet) {
187 OnPacketSent(packet);
188 });
189 processor.AddEvents(
190 parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
191 [this](const LoggedRtcpPacketTransportFeedback& feedback) {
192 OnFeedback(feedback);
193 });
194 processor.AddEvents(
195 parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
196 [this](const LoggedRtcpPacketReceiverReport& report) {
197 OnReceiverReport(report);
198 });
199 processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
200 [this](const LoggedIceCandidatePairConfig& candidate) {
201 OnIceConfig(candidate);
202 });
203 processor.ProcessEventsInOrder();
204 }
205
206 } // namespace webrtc
207