mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

This is a reland of e9ae4729e0
TBR=philipel@webrtc.org,terelius@webrtc.org
Original change's description:
> Correctly handle retransmissions/padding in early loss detection.
>
> This CL makes sure we don't cull packets from the history based on
> incorrect ack mapping, just like it's predecessor:
> https://webrtc-review.googlesource.com/c/src/+/218000
>
> It also changes the logic to make sure retransmits counts towards
> history pruning - and properly ignores padding/fec.
>
> Bug: webrtc:12713
> Change-Id: I7835d10e483687e960a9cce41d4e2f1a6c3189b4
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/221863
> Reviewed-by: Björn Terelius <terelius@webrtc.org>
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> Commit-Queue: Erik Språng <sprang@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#34293}
Bug: webrtc:12713
Change-Id: Iec123d71edafea98fe289acde007b57e212681f4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/222640
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34297}
209 lines
7.9 KiB
C++
209 lines
7.9 KiB
C++
/*
|
|
* Copyright 2019 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.
|
|
*/
|
|
#include "rtc_tools/rtc_event_log_visualizer/log_simulation.h"
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
#include "logging/rtc_event_log/rtc_event_processor.h"
|
|
#include "modules/rtp_rtcp/source/time_util.h"
|
|
#include "system_wrappers/include/clock.h"
|
|
|
|
namespace webrtc {
|
|
|
|
LogBasedNetworkControllerSimulation::LogBasedNetworkControllerSimulation(
|
|
std::unique_ptr<NetworkControllerFactoryInterface> factory,
|
|
std::function<void(const NetworkControlUpdate&, Timestamp)> update_handler)
|
|
: update_handler_(update_handler), factory_(std::move(factory)) {}
|
|
|
|
LogBasedNetworkControllerSimulation::~LogBasedNetworkControllerSimulation() {}
|
|
|
|
void LogBasedNetworkControllerSimulation::HandleStateUpdate(
|
|
const NetworkControlUpdate& update) {
|
|
update_handler_(update, current_time_);
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::ProcessUntil(Timestamp to_time) {
|
|
if (last_process_.IsInfinite()) {
|
|
NetworkControllerConfig config;
|
|
config.constraints.at_time = to_time;
|
|
config.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
|
|
config.constraints.starting_rate = DataRate::KilobitsPerSec(300);
|
|
config.event_log = &null_event_log_;
|
|
controller_ = factory_->Create(config);
|
|
}
|
|
if (last_process_.IsInfinite() ||
|
|
to_time - last_process_ > TimeDelta::Seconds(1)) {
|
|
last_process_ = to_time;
|
|
current_time_ = to_time;
|
|
ProcessInterval msg;
|
|
msg.at_time = to_time;
|
|
HandleStateUpdate(controller_->OnProcessInterval(msg));
|
|
} else {
|
|
while (last_process_ + factory_->GetProcessInterval() <= to_time) {
|
|
last_process_ += factory_->GetProcessInterval();
|
|
current_time_ = last_process_;
|
|
ProcessInterval msg;
|
|
msg.at_time = current_time_;
|
|
HandleStateUpdate(controller_->OnProcessInterval(msg));
|
|
}
|
|
current_time_ = to_time;
|
|
}
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::OnProbeCreated(
|
|
const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
|
|
pending_probes_.push_back({probe_cluster, 0, 0});
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::OnPacketSent(
|
|
const LoggedPacketInfo& packet) {
|
|
ProcessUntil(packet.log_packet_time);
|
|
if (packet.has_transport_seq_no) {
|
|
PacedPacketInfo probe_info;
|
|
if (!pending_probes_.empty() &&
|
|
packet.media_type == LoggedMediaType::kVideo) {
|
|
auto& probe = pending_probes_.front();
|
|
probe_info.probe_cluster_id = probe.event.id;
|
|
probe_info.send_bitrate_bps = probe.event.bitrate_bps;
|
|
probe_info.probe_cluster_min_bytes = probe.event.min_bytes;
|
|
probe_info.probe_cluster_min_probes = probe.event.min_packets;
|
|
probe.packets_sent++;
|
|
probe.bytes_sent += packet.size + packet.overhead;
|
|
if (probe.bytes_sent >= probe.event.min_bytes &&
|
|
probe.packets_sent >= probe.event.min_packets) {
|
|
pending_probes_.pop_front();
|
|
}
|
|
}
|
|
|
|
RtpPacketSendInfo packet_info;
|
|
packet_info.media_ssrc = packet.ssrc;
|
|
packet_info.transport_sequence_number = packet.transport_seq_no;
|
|
packet_info.rtp_sequence_number = packet.stream_seq_no;
|
|
packet_info.length = packet.size;
|
|
packet_info.pacing_info = probe_info;
|
|
transport_feedback_.AddPacket(packet_info, packet.overhead,
|
|
packet.log_packet_time);
|
|
}
|
|
rtc::SentPacket sent_packet;
|
|
sent_packet.send_time_ms = packet.log_packet_time.ms();
|
|
sent_packet.info.included_in_allocation = true;
|
|
sent_packet.info.packet_size_bytes = packet.size + packet.overhead;
|
|
if (packet.has_transport_seq_no) {
|
|
sent_packet.packet_id = packet.transport_seq_no;
|
|
sent_packet.info.included_in_feedback = true;
|
|
}
|
|
auto msg = transport_feedback_.ProcessSentPacket(sent_packet);
|
|
if (msg)
|
|
HandleStateUpdate(controller_->OnSentPacket(*msg));
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::OnFeedback(
|
|
const LoggedRtcpPacketTransportFeedback& feedback) {
|
|
auto feedback_time = Timestamp::Millis(feedback.log_time_ms());
|
|
ProcessUntil(feedback_time);
|
|
auto msg = transport_feedback_.ProcessTransportFeedback(
|
|
feedback.transport_feedback, feedback_time);
|
|
if (msg)
|
|
HandleStateUpdate(controller_->OnTransportPacketsFeedback(*msg));
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::OnReceiverReport(
|
|
const LoggedRtcpPacketReceiverReport& report) {
|
|
if (report.rr.report_blocks().empty())
|
|
return;
|
|
auto report_time = Timestamp::Millis(report.log_time_ms());
|
|
ProcessUntil(report_time);
|
|
int packets_delta = 0;
|
|
int lost_delta = 0;
|
|
for (auto& block : report.rr.report_blocks()) {
|
|
auto it = last_report_blocks_.find(block.source_ssrc());
|
|
if (it != last_report_blocks_.end()) {
|
|
packets_delta +=
|
|
block.extended_high_seq_num() - it->second.extended_high_seq_num();
|
|
lost_delta += block.cumulative_lost() - it->second.cumulative_lost();
|
|
}
|
|
last_report_blocks_[block.source_ssrc()] = block;
|
|
}
|
|
if (packets_delta > lost_delta) {
|
|
TransportLossReport msg;
|
|
msg.packets_lost_delta = lost_delta;
|
|
msg.packets_received_delta = packets_delta - lost_delta;
|
|
msg.receive_time = report_time;
|
|
msg.start_time = last_report_block_time_;
|
|
msg.end_time = report_time;
|
|
last_report_block_time_ = report_time;
|
|
HandleStateUpdate(controller_->OnTransportLossReport(msg));
|
|
}
|
|
|
|
Clock* clock = Clock::GetRealTimeClock();
|
|
TimeDelta rtt = TimeDelta::PlusInfinity();
|
|
for (auto& rb : report.rr.report_blocks()) {
|
|
if (rb.last_sr()) {
|
|
Timestamp report_log_time = Timestamp::Micros(report.log_time_us());
|
|
uint32_t receive_time_ntp =
|
|
CompactNtp(clock->ConvertTimestampToNtpTime(report_log_time));
|
|
uint32_t rtt_ntp =
|
|
receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr();
|
|
rtt = std::min(rtt, TimeDelta::Millis(CompactNtpRttToMs(rtt_ntp)));
|
|
}
|
|
}
|
|
if (rtt.IsFinite()) {
|
|
RoundTripTimeUpdate msg;
|
|
msg.receive_time = report_time;
|
|
msg.round_trip_time = rtt;
|
|
HandleStateUpdate(controller_->OnRoundTripTimeUpdate(msg));
|
|
}
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::OnIceConfig(
|
|
const LoggedIceCandidatePairConfig& candidate) {
|
|
if (candidate.type == IceCandidatePairConfigType::kSelected) {
|
|
auto log_time = Timestamp::Micros(candidate.log_time_us());
|
|
ProcessUntil(log_time);
|
|
NetworkRouteChange msg;
|
|
msg.at_time = log_time;
|
|
msg.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
|
|
msg.constraints.starting_rate = DataRate::KilobitsPerSec(300);
|
|
msg.constraints.at_time = log_time;
|
|
HandleStateUpdate(controller_->OnNetworkRouteChange(msg));
|
|
}
|
|
}
|
|
|
|
void LogBasedNetworkControllerSimulation::ProcessEventsInLog(
|
|
const ParsedRtcEventLog& parsed_log_) {
|
|
auto packet_infos = parsed_log_.GetOutgoingPacketInfos();
|
|
RtcEventProcessor processor;
|
|
processor.AddEvents(
|
|
parsed_log_.bwe_probe_cluster_created_events(),
|
|
[this](const LoggedBweProbeClusterCreatedEvent& probe_cluster) {
|
|
OnProbeCreated(probe_cluster);
|
|
});
|
|
processor.AddEvents(packet_infos, [this](const LoggedPacketInfo& packet) {
|
|
OnPacketSent(packet);
|
|
});
|
|
processor.AddEvents(
|
|
parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
|
|
[this](const LoggedRtcpPacketTransportFeedback& feedback) {
|
|
OnFeedback(feedback);
|
|
});
|
|
processor.AddEvents(
|
|
parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
|
|
[this](const LoggedRtcpPacketReceiverReport& report) {
|
|
OnReceiverReport(report);
|
|
});
|
|
processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
|
|
[this](const LoggedIceCandidatePairConfig& candidate) {
|
|
OnIceConfig(candidate);
|
|
});
|
|
processor.ProcessEventsInOrder();
|
|
}
|
|
|
|
} // namespace webrtc
|