/* * Copyright (c) 2026 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 "video/timing/simulator/receiver.h" #include #include #include "absl/base/nullability.h" #include "api/environment/environment.h" #include "api/sequence_checker.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "video/timing/simulator/rtp_packet_simulator.h" namespace webrtc::video_timing_simulator { namespace { // The RtcEventLog currently does not encode the RTX pt<->apt mapping. That is // a problem for RTX->RTP decapsulation, but it is not a real problem for our // "decoding", since the latter is just fake anyways. So in order to satisfy the // `RtxReceiveStream` runtime requirements, we provide a noop pt<->apt mapping. std::map BuildNoopPtToAptMap() { // Build a noop mapping from the allowed range of PTs (see pc/g3doc/rtp.md). std::map pt_to_apt; for (int pt = 35; pt <= 63; ++pt) { pt_to_apt[pt] = pt; } for (int pt = 96; pt <= 127; ++pt) { pt_to_apt[pt] = pt; } return pt_to_apt; } } // namespace Receiver::Receiver(const Environment& env, uint32_t ssrc, uint32_t rtx_ssrc, ReceivedRtpPacketCallback* absl_nonnull received_rtp_packet_cb) : env_(env), ssrc_(ssrc), rtx_ssrc_(rtx_ssrc), adapter_(received_rtp_packet_cb), rtx_receive_stream_(env_, &adapter_, BuildNoopPtToAptMap(), ssrc) { RTC_DCHECK_NE(ssrc_, rtx_ssrc_); } Receiver::~Receiver() = default; void Receiver::InsertSimulatedPacket( const RtpPacketSimulator::SimulatedPacket& simulated_packet) { uint32_t packet_ssrc = simulated_packet.rtp_packet.Ssrc(); bool is_video = (packet_ssrc == ssrc_); bool is_rtx = (packet_ssrc == rtx_ssrc_); if (!is_video && !is_rtx) { RTC_LOG(LS_WARNING) << "Received packet with ssrc=" << packet_ssrc << " that was neither video [ssrc=" << ssrc_ << "] nor RTX [rtx_ssrc=" << rtx_ssrc_ << "]. " << "Discarding it. (simulated_ts=" << env_.clock().CurrentTime() << ")"; return; } if (is_rtx) { if (!simulated_packet.has_rtx_osn) { RTC_LOG(LS_INFO) << "RTX packet without RTX OSN received. Discarding it."; return; } InsertRtxPacket(simulated_packet.rtp_packet); return; } InsertVideoPacket(simulated_packet.rtp_packet); } void Receiver::InsertVideoPacket(const RtpPacketReceived& rtp_packet) { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_EQ(rtp_packet.Ssrc(), ssrc_); adapter_.OnRtpPacket(rtp_packet); } void Receiver::InsertRtxPacket(const RtpPacketReceived& rtp_packet) { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_EQ(rtp_packet.Ssrc(), rtx_ssrc_); rtx_receive_stream_.OnRtpPacket(rtp_packet); } } // namespace webrtc::video_timing_simulator