diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc')
-rw-r--r-- | third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc new file mode 100644 index 0000000000..5f2f69f830 --- /dev/null +++ b/third_party/libwebrtc/modules/rtp_rtcp/source/packet_sequencer.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021 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 "modules/rtp_rtcp/source/packet_sequencer.h" + +#include "rtc_base/checks.h" +#include "rtc_base/random.h" + +namespace webrtc { + +namespace { +// RED header is first byte of payload, if present. +constexpr size_t kRedForFecHeaderLength = 1; + +// Timestamps use a 90kHz clock. +constexpr uint32_t kTimestampTicksPerMs = 90; +} // namespace + +PacketSequencer::PacketSequencer(uint32_t media_ssrc, + absl::optional<uint32_t> rtx_ssrc, + bool require_marker_before_media_padding, + Clock* clock) + : media_ssrc_(media_ssrc), + rtx_ssrc_(rtx_ssrc), + require_marker_before_media_padding_(require_marker_before_media_padding), + clock_(clock), + media_sequence_number_(0), + rtx_sequence_number_(0), + last_payload_type_(-1), + last_rtp_timestamp_(0), + last_packet_marker_bit_(false) { + Random random(clock_->TimeInMicroseconds()); + // Random start, 16 bits. Upper half of range is avoided in order to prevent + // wraparound issues during startup. Sequence number 0 is avoided for + // historical reasons, presumably to avoid debugability or test usage + // conflicts. + constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff; // 2^15 - 1. + media_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); + rtx_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); +} + +void PacketSequencer::Sequence(RtpPacketToSend& packet) { + if (packet.Ssrc() == media_ssrc_) { + if (packet.packet_type() == RtpPacketMediaType::kRetransmission) { + // Retransmission of an already sequenced packet, ignore. + return; + } else if (packet.packet_type() == RtpPacketMediaType::kPadding) { + PopulatePaddingFields(packet); + } + packet.SetSequenceNumber(media_sequence_number_++); + if (packet.packet_type() != RtpPacketMediaType::kPadding) { + UpdateLastPacketState(packet); + } + } else if (packet.Ssrc() == rtx_ssrc_) { + if (packet.packet_type() == RtpPacketMediaType::kPadding) { + PopulatePaddingFields(packet); + } + packet.SetSequenceNumber(rtx_sequence_number_++); + } else { + RTC_DCHECK_NOTREACHED() << "Unexpected ssrc " << packet.Ssrc(); + } +} + +void PacketSequencer::SetRtpState(const RtpState& state) { + media_sequence_number_ = state.sequence_number; + last_rtp_timestamp_ = state.timestamp; + last_capture_time_ = state.capture_time; + last_timestamp_time_ = state.last_timestamp_time; +} + +void PacketSequencer::PopulateRtpState(RtpState& state) const { + state.sequence_number = media_sequence_number_; + state.timestamp = last_rtp_timestamp_; + state.capture_time = last_capture_time_; + state.last_timestamp_time = last_timestamp_time_; +} + +void PacketSequencer::UpdateLastPacketState(const RtpPacketToSend& packet) { + // Remember marker bit to determine if padding can be inserted with + // sequence number following `packet`. + last_packet_marker_bit_ = packet.Marker(); + // Remember media payload type to use in the padding packet if rtx is + // disabled. + if (packet.is_red()) { + RTC_DCHECK_GE(packet.payload_size(), kRedForFecHeaderLength); + last_payload_type_ = packet.PayloadBuffer()[0]; + } else { + last_payload_type_ = packet.PayloadType(); + } + // Save timestamps to generate timestamp field and extensions for the padding. + last_rtp_timestamp_ = packet.Timestamp(); + last_timestamp_time_ = clock_->CurrentTime(); + last_capture_time_ = packet.capture_time(); +} + +void PacketSequencer::PopulatePaddingFields(RtpPacketToSend& packet) { + if (packet.Ssrc() == media_ssrc_) { + RTC_DCHECK(CanSendPaddingOnMediaSsrc()); + + packet.SetTimestamp(last_rtp_timestamp_); + packet.set_capture_time(last_capture_time_); + packet.SetPayloadType(last_payload_type_); + return; + } + + RTC_DCHECK(packet.Ssrc() == rtx_ssrc_); + if (packet.payload_size() > 0) { + // This is payload padding packet, don't update timestamp fields. + return; + } + + packet.SetTimestamp(last_rtp_timestamp_); + packet.set_capture_time(last_capture_time_); + + // Only change the timestamp of padding packets sent over RTX. + // Padding only packets over RTP has to be sent as part of a media + // frame (and therefore the same timestamp). + if (last_timestamp_time_ > Timestamp::Zero()) { + TimeDelta since_last_media = clock_->CurrentTime() - last_timestamp_time_; + packet.SetTimestamp(packet.Timestamp() + + since_last_media.ms() * kTimestampTicksPerMs); + if (packet.capture_time() > Timestamp::Zero()) { + packet.set_capture_time(packet.capture_time() + since_last_media); + } + } +} + +bool PacketSequencer::CanSendPaddingOnMediaSsrc() const { + if (last_payload_type_ == -1) { + return false; + } + + // Without RTX we can't send padding in the middle of frames. + // For audio marker bits doesn't mark the end of a frame and frames + // are usually a single packet, so for now we don't apply this rule + // for audio. + if (require_marker_before_media_padding_ && !last_packet_marker_bit_) { + return false; + } + + return true; +} + +} // namespace webrtc |