blob: 138ba1ca7acc234c920deee25a02dbd35f915730 [file] [log] [blame]
/*
* 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