packet_sequencer.cc (5847B)
1 /* 2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/rtp_rtcp/source/packet_sequencer.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <optional> 16 17 #include "api/units/time_delta.h" 18 #include "api/units/timestamp.h" 19 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 20 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" 21 #include "rtc_base/checks.h" 22 #include "rtc_base/random.h" 23 #include "system_wrappers/include/clock.h" 24 25 namespace webrtc { 26 27 namespace { 28 // RED header is first byte of payload, if present. 29 constexpr size_t kRedForFecHeaderLength = 1; 30 31 // Timestamps use a 90kHz clock. 32 constexpr uint32_t kTimestampTicksPerMs = 90; 33 } // namespace 34 35 PacketSequencer::PacketSequencer(uint32_t media_ssrc, 36 std::optional<uint32_t> rtx_ssrc, 37 bool require_marker_before_media_padding, 38 Clock* clock) 39 : media_ssrc_(media_ssrc), 40 rtx_ssrc_(rtx_ssrc), 41 require_marker_before_media_padding_(require_marker_before_media_padding), 42 clock_(clock), 43 media_sequence_number_(0), 44 rtx_sequence_number_(0), 45 last_payload_type_(-1), 46 last_rtp_timestamp_(0), 47 last_packet_marker_bit_(false) { 48 Random random(clock_->TimeInMicroseconds()); 49 // Random start, 16 bits. Upper half of range is avoided in order to prevent 50 // SRTP wraparound issues during startup. See this unit test for details: 51 // SrtpSessionTest.ProtectUnprotectWrapAroundRocMismatch 52 // Sequence number 0 is avoided for historical reasons, presumably to avoid 53 // debugability or test usage conflicts. 54 constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff; // 2^15 - 1. 55 media_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); 56 rtx_sequence_number_ = random.Rand(1, kMaxInitRtpSeqNumber); 57 } 58 59 void PacketSequencer::Sequence(RtpPacketToSend& packet) { 60 if (packet.Ssrc() == media_ssrc_) { 61 if (packet.packet_type() == RtpPacketMediaType::kRetransmission) { 62 // Retransmission of an already sequenced packet, ignore. 63 return; 64 } else if (packet.packet_type() == RtpPacketMediaType::kPadding) { 65 PopulatePaddingFields(packet); 66 } 67 packet.SetSequenceNumber(media_sequence_number_++); 68 if (packet.packet_type() != RtpPacketMediaType::kPadding) { 69 UpdateLastPacketState(packet); 70 } 71 } else if (packet.Ssrc() == rtx_ssrc_) { 72 if (packet.packet_type() == RtpPacketMediaType::kPadding) { 73 PopulatePaddingFields(packet); 74 } 75 packet.SetSequenceNumber(rtx_sequence_number_++); 76 } else { 77 RTC_DCHECK_NOTREACHED() << "Unexpected ssrc " << packet.Ssrc(); 78 } 79 } 80 81 void PacketSequencer::SetRtpState(const RtpState& state) { 82 media_sequence_number_ = state.sequence_number; 83 last_rtp_timestamp_ = state.timestamp; 84 last_capture_time_ = state.capture_time; 85 last_timestamp_time_ = state.last_timestamp_time; 86 } 87 88 void PacketSequencer::PopulateRtpState(RtpState& state) const { 89 state.sequence_number = media_sequence_number_; 90 state.timestamp = last_rtp_timestamp_; 91 state.capture_time = last_capture_time_; 92 state.last_timestamp_time = last_timestamp_time_; 93 } 94 95 void PacketSequencer::UpdateLastPacketState(const RtpPacketToSend& packet) { 96 // Remember marker bit to determine if padding can be inserted with 97 // sequence number following `packet`. 98 last_packet_marker_bit_ = packet.Marker(); 99 // Remember media payload type to use in the padding packet if rtx is 100 // disabled. 101 if (packet.is_red()) { 102 RTC_DCHECK_GE(packet.payload_size(), kRedForFecHeaderLength); 103 last_payload_type_ = packet.PayloadBuffer()[0]; 104 } else { 105 last_payload_type_ = packet.PayloadType(); 106 } 107 // Save timestamps to generate timestamp field and extensions for the padding. 108 last_rtp_timestamp_ = packet.Timestamp(); 109 last_timestamp_time_ = clock_->CurrentTime(); 110 last_capture_time_ = packet.capture_time(); 111 } 112 113 void PacketSequencer::PopulatePaddingFields(RtpPacketToSend& packet) { 114 if (packet.Ssrc() == media_ssrc_) { 115 RTC_DCHECK(CanSendPaddingOnMediaSsrc()); 116 117 packet.SetTimestamp(last_rtp_timestamp_); 118 packet.set_capture_time(last_capture_time_); 119 packet.SetPayloadType(last_payload_type_); 120 return; 121 } 122 123 RTC_DCHECK(packet.Ssrc() == rtx_ssrc_); 124 if (packet.payload_size() > 0) { 125 // This is payload padding packet, don't update timestamp fields. 126 return; 127 } 128 129 packet.SetTimestamp(last_rtp_timestamp_); 130 packet.set_capture_time(last_capture_time_); 131 132 // Only change the timestamp of padding packets sent over RTX. 133 // Padding only packets over RTP has to be sent as part of a media 134 // frame (and therefore the same timestamp). 135 if (last_timestamp_time_ > Timestamp::Zero()) { 136 TimeDelta since_last_media = clock_->CurrentTime() - last_timestamp_time_; 137 packet.SetTimestamp(packet.Timestamp() + 138 since_last_media.ms() * kTimestampTicksPerMs); 139 if (packet.capture_time() > Timestamp::Zero()) { 140 packet.set_capture_time(packet.capture_time() + since_last_media); 141 } 142 } 143 } 144 145 bool PacketSequencer::CanSendPaddingOnMediaSsrc() const { 146 if (last_payload_type_ == -1) { 147 return false; 148 } 149 150 // Without RTX we can't send padding in the middle of frames. 151 // For audio marker bits doesn't mark the end of a frame and frames 152 // are usually a single packet, so for now we don't apply this rule 153 // for audio. 154 if (require_marker_before_media_padding_ && !last_packet_marker_bit_) { 155 return false; 156 } 157 158 return true; 159 } 160 161 } // namespace webrtc