blob: 4778cc505d4a659bf2623b81103b0bc1cb6aa258 [file] [log] [blame]
Sebastian Jansson1175ae02019-03-13 08:56:58 +01001/*
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/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
18namespace webrtc {
19
20LogBasedNetworkControllerSimulation::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
25LogBasedNetworkControllerSimulation::~LogBasedNetworkControllerSimulation() {}
26
27void LogBasedNetworkControllerSimulation::HandleStateUpdate(
28 const NetworkControlUpdate& update) {
29 update_handler_(update, current_time_);
30}
31
32void 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::kbps(30);
37 config.constraints.starting_rate = DataRate::kbps(300);
38 controller_ = factory_->Create(config);
39 }
40 if (last_process_.IsInfinite() ||
41 to_time - last_process_ > TimeDelta::seconds(1)) {
42 last_process_ = to_time;
43 current_time_ = to_time;
44 ProcessInterval msg;
45 msg.at_time = to_time;
46 HandleStateUpdate(controller_->OnProcessInterval(msg));
47 } else {
48 while (last_process_ + factory_->GetProcessInterval() <= to_time) {
49 last_process_ += factory_->GetProcessInterval();
50 current_time_ = last_process_;
51 ProcessInterval msg;
52 msg.at_time = current_time_;
53 HandleStateUpdate(controller_->OnProcessInterval(msg));
54 }
55 current_time_ = to_time;
56 }
57}
58
59void LogBasedNetworkControllerSimulation::OnProbeCreated(
60 const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
61 pending_probes_.push_back({probe_cluster, 0, 0});
62}
63
64void LogBasedNetworkControllerSimulation::OnPacketSent(
65 const LoggedPacketInfo& packet) {
66 ProcessUntil(packet.log_packet_time);
67 if (packet.has_transport_seq_no) {
68 PacedPacketInfo probe_info;
69 if (!pending_probes_.empty() &&
70 packet.media_type == LoggedMediaType::kVideo) {
71 auto& probe = pending_probes_.front();
72 probe_info.probe_cluster_id = probe.event.id;
73 probe_info.send_bitrate_bps = probe.event.bitrate_bps;
74 probe_info.probe_cluster_min_bytes = probe.event.min_bytes;
75 probe_info.probe_cluster_min_probes = probe.event.min_packets;
76 probe.packets_sent++;
77 probe.bytes_sent += packet.size + packet.overhead;
78 if (probe.bytes_sent >= probe.event.min_bytes &&
79 probe.packets_sent >= probe.event.min_packets) {
80 pending_probes_.pop_front();
81 }
82 }
83 transport_feedback_.AddPacket(packet.ssrc, packet.transport_seq_no,
84 packet.size + packet.overhead, probe_info,
85 packet.log_packet_time);
86 }
87 rtc::SentPacket sent_packet;
88 sent_packet.send_time_ms = packet.log_packet_time.ms();
89 sent_packet.info.included_in_allocation = true;
90 sent_packet.info.packet_size_bytes = packet.size + packet.overhead;
91 if (packet.has_transport_seq_no) {
92 sent_packet.packet_id = packet.transport_seq_no;
93 sent_packet.info.included_in_feedback = true;
94 }
95 auto msg = transport_feedback_.ProcessSentPacket(sent_packet);
96 if (msg)
97 HandleStateUpdate(controller_->OnSentPacket(*msg));
98}
99
100void LogBasedNetworkControllerSimulation::OnFeedback(
101 const LoggedRtcpPacketTransportFeedback& feedback) {
102 auto feedback_time = Timestamp::ms(feedback.log_time_ms());
103 ProcessUntil(feedback_time);
104 auto msg = transport_feedback_.ProcessTransportFeedback(
105 feedback.transport_feedback, feedback_time);
106 if (msg)
107 HandleStateUpdate(controller_->OnTransportPacketsFeedback(*msg));
108}
109
110void LogBasedNetworkControllerSimulation::OnReceiverReport(
111 const LoggedRtcpPacketReceiverReport& report) {
112 if (report.rr.report_blocks().empty())
113 return;
114 auto report_time = Timestamp::ms(report.log_time_ms());
115 ProcessUntil(report_time);
116 int packets_delta = 0;
117 int lost_delta = 0;
118 for (auto& block : report.rr.report_blocks()) {
119 auto it = last_report_blocks_.find(block.source_ssrc());
120 if (it != last_report_blocks_.end()) {
121 packets_delta +=
122 block.extended_high_seq_num() - it->second.extended_high_seq_num();
123 lost_delta += block.cumulative_lost() - it->second.cumulative_lost();
124 }
125 last_report_blocks_[block.source_ssrc()] = block;
126 }
127 if (packets_delta > lost_delta) {
128 TransportLossReport msg;
129 msg.packets_lost_delta = lost_delta;
130 msg.packets_received_delta = packets_delta - lost_delta;
131 msg.receive_time = report_time;
132 msg.start_time = last_report_block_time_;
133 msg.end_time = report_time;
134 last_report_block_time_ = report_time;
135 HandleStateUpdate(controller_->OnTransportLossReport(msg));
136 }
137
138 TimeDelta rtt = TimeDelta::PlusInfinity();
139 for (auto& rb : report.rr.report_blocks()) {
140 if (rb.last_sr()) {
141 uint32_t receive_time_ntp =
142 CompactNtp(TimeMicrosToNtp(report.log_time_us()));
143 uint32_t rtt_ntp =
144 receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr();
145 rtt = std::min(rtt, TimeDelta::ms(CompactNtpRttToMs(rtt_ntp)));
146 }
147 }
148 if (rtt.IsFinite()) {
149 RoundTripTimeUpdate msg;
150 msg.receive_time = report_time;
151 msg.round_trip_time = rtt;
152 HandleStateUpdate(controller_->OnRoundTripTimeUpdate(msg));
153 }
154}
155
156void LogBasedNetworkControllerSimulation::OnIceConfig(
157 const LoggedIceCandidatePairConfig& candidate) {
158 if (candidate.type == IceCandidatePairConfigType::kSelected) {
159 auto log_time = Timestamp::us(candidate.log_time_us());
160 ProcessUntil(log_time);
161 NetworkRouteChange msg;
162 msg.at_time = log_time;
163 msg.constraints.min_data_rate = DataRate::kbps(30);
164 msg.constraints.starting_rate = DataRate::kbps(300);
165 msg.constraints.at_time = log_time;
166 HandleStateUpdate(controller_->OnNetworkRouteChange(msg));
167 }
168}
169
170void LogBasedNetworkControllerSimulation::ProcessEventsInLog(
171 const ParsedRtcEventLog& parsed_log_) {
172 auto packet_infos = parsed_log_.GetOutgoingPacketInfos();
173 RtcEventProcessor processor;
174 processor.AddEvents(
175 parsed_log_.bwe_probe_cluster_created_events(),
176 [this](const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
177 OnProbeCreated(probe_cluster);
178 });
179 processor.AddEvents(packet_infos, [this](const LoggedPacketInfo& packet) {
180 OnPacketSent(packet);
181 });
182 processor.AddEvents(
183 parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
184 [this](const LoggedRtcpPacketTransportFeedback& feedback) {
185 OnFeedback(feedback);
186 });
187 processor.AddEvents(
188 parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
189 [this](const LoggedRtcpPacketReceiverReport& report) {
190 OnReceiverReport(report);
191 });
192 processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
193 [this](const LoggedIceCandidatePairConfig& candidate) {
194 OnIceConfig(candidate);
195 });
196 processor.ProcessEventsInOrder();
197}
198
199} // namespace webrtc