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

Directly use RtpPacketToSend instead of RtpPacketSendInfo For RFC8888 we will need to match SSRC and RTP sequence number with the transport sequence number that only exist on the sending side. For retransmitted packets, RTX, RtpPacketSendInfo contain original SSRC and original sequence number. Bug: webrtc:42225697 Change-Id: Iafa5d851ca5c51c85e4607ed4c1919d96da6084a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366000 Auto-Submit: Per Kjellander <perkj@webrtc.org> Commit-Queue: Björn Terelius <terelius@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43264}
228 lines
8.8 KiB
C++
228 lines
8.8 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 <cstddef>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "api/environment/environment_factory.h"
|
|
#include "api/transport/network_control.h"
|
|
#include "api/transport/network_types.h"
|
|
#include "api/units/data_rate.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_ice_candidate_pair_config.h"
|
|
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
|
|
#include "logging/rtc_event_log/rtc_event_log_parser.h"
|
|
#include "logging/rtc_event_log/rtc_event_processor.h"
|
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
|
#include "modules/rtp_rtcp/source/ntp_time_util.h"
|
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
|
#include "rtc_base/network/sent_packet.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(CreateEnvironment(&null_event_log_));
|
|
config.constraints.at_time = to_time;
|
|
config.constraints.min_data_rate = DataRate::KilobitsPerSec(30);
|
|
config.constraints.starting_rate = DataRate::KilobitsPerSec(300);
|
|
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 = DataRate::BitsPerSec(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();
|
|
}
|
|
}
|
|
|
|
RtpPacketToSend send_packet(/*extensions=*/nullptr);
|
|
send_packet.set_transport_sequence_number(packet.transport_seq_no);
|
|
send_packet.SetSsrc(packet.ssrc);
|
|
send_packet.SetSequenceNumber(packet.transport_seq_no);
|
|
send_packet.SetPayloadSize(packet.size - send_packet.headers_size());
|
|
RTC_DCHECK_EQ(send_packet.size(), packet.size);
|
|
transport_feedback_.AddPacket(send_packet, probe_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, CompactNtpRttToTimeDelta(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); },
|
|
PacketDirection::kOutgoingPacket);
|
|
processor.AddEvents(
|
|
parsed_log_.transport_feedbacks(PacketDirection::kIncomingPacket),
|
|
[this](const LoggedRtcpPacketTransportFeedback& feedback) {
|
|
OnFeedback(feedback);
|
|
},
|
|
PacketDirection::kIncomingPacket);
|
|
processor.AddEvents(
|
|
parsed_log_.receiver_reports(PacketDirection::kIncomingPacket),
|
|
[this](const LoggedRtcpPacketReceiverReport& report) {
|
|
OnReceiverReport(report);
|
|
},
|
|
PacketDirection::kIncomingPacket);
|
|
processor.AddEvents(parsed_log_.ice_candidate_pair_configs(),
|
|
[this](const LoggedIceCandidatePairConfig& candidate) {
|
|
OnIceConfig(candidate);
|
|
});
|
|
processor.ProcessEventsInOrder();
|
|
}
|
|
|
|
} // namespace webrtc
|