| /* | |
| * 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 <cstdint> | |
| #include <map> | |
| #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<int, int> BuildNoopPtToAptMap() { | |
| // Build a noop mapping from the allowed range of PTs (see pc/g3doc/rtp.md). | |
| std::map<int, int> 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 |