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 "api/units/timestamp.h"
14 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
15 #include "system_wrappers/include/clock.h"
16 #include "test/gmock.h"
17 #include "test/gtest.h"
18
19 namespace webrtc {
20 namespace {
21 constexpr Timestamp kStartTime = Timestamp::Millis(98765);
22 constexpr uint32_t kMediaSsrc = 123456;
23 constexpr uint32_t kRtxSsrc = 123457;
24 constexpr uint8_t kMediaPayloadType = 42;
25 constexpr uint16_t kMediaStartSequenceNumber = 123;
26 constexpr uint16_t kRtxStartSequenceNumber = 234;
27 constexpr uint16_t kDefaultSequenceNumber = 0x1234;
28 constexpr uint32_t kStartRtpTimestamp = 798;
29
30 class PacketSequencerTest : public ::testing::Test {
31 public:
PacketSequencerTest()32 PacketSequencerTest()
33 : clock_(kStartTime),
34 sequencer_(kMediaSsrc,
35 kRtxSsrc,
36 /*require_marker_before_media_padding=*/true,
37 &clock_) {}
38
CreatePacket(RtpPacketMediaType type,uint32_t ssrc)39 RtpPacketToSend CreatePacket(RtpPacketMediaType type, uint32_t ssrc) {
40 RtpPacketToSend packet(/*extension_manager=*/nullptr);
41 packet.set_packet_type(type);
42 packet.SetSsrc(ssrc);
43 packet.SetSequenceNumber(kDefaultSequenceNumber);
44 packet.set_capture_time(clock_.CurrentTime());
45 packet.SetTimestamp(
46 kStartRtpTimestamp +
47 static_cast<uint32_t>(packet.capture_time().ms() - kStartTime.ms()));
48 return packet;
49 }
50
51 protected:
52 SimulatedClock clock_;
53 PacketSequencer sequencer_;
54 };
55
TEST_F(PacketSequencerTest,IgnoresMediaSsrcRetransmissions)56 TEST_F(PacketSequencerTest, IgnoresMediaSsrcRetransmissions) {
57 RtpPacketToSend packet =
58 CreatePacket(RtpPacketMediaType::kRetransmission, kMediaSsrc);
59 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
60 sequencer_.Sequence(packet);
61 EXPECT_EQ(packet.SequenceNumber(), kDefaultSequenceNumber);
62 EXPECT_EQ(sequencer_.media_sequence_number(), kMediaStartSequenceNumber);
63 }
64
TEST_F(PacketSequencerTest,SequencesAudio)65 TEST_F(PacketSequencerTest, SequencesAudio) {
66 RtpPacketToSend packet = CreatePacket(RtpPacketMediaType::kAudio, kMediaSsrc);
67 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
68 sequencer_.Sequence(packet);
69 EXPECT_EQ(packet.SequenceNumber(), kMediaStartSequenceNumber);
70 EXPECT_EQ(sequencer_.media_sequence_number(), kMediaStartSequenceNumber + 1);
71 }
72
TEST_F(PacketSequencerTest,SequencesVideo)73 TEST_F(PacketSequencerTest, SequencesVideo) {
74 RtpPacketToSend packet = CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
75 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
76 sequencer_.Sequence(packet);
77 EXPECT_EQ(packet.SequenceNumber(), kMediaStartSequenceNumber);
78 EXPECT_EQ(sequencer_.media_sequence_number(), kMediaStartSequenceNumber + 1);
79 }
80
TEST_F(PacketSequencerTest,SequencesUlpFec)81 TEST_F(PacketSequencerTest, SequencesUlpFec) {
82 RtpPacketToSend packet =
83 CreatePacket(RtpPacketMediaType::kForwardErrorCorrection, kMediaSsrc);
84 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
85 sequencer_.Sequence(packet);
86 EXPECT_EQ(packet.SequenceNumber(), kMediaStartSequenceNumber);
87 EXPECT_EQ(sequencer_.media_sequence_number(), kMediaStartSequenceNumber + 1);
88 }
89
TEST_F(PacketSequencerTest,SequencesRtxRetransmissions)90 TEST_F(PacketSequencerTest, SequencesRtxRetransmissions) {
91 RtpPacketToSend packet =
92 CreatePacket(RtpPacketMediaType::kRetransmission, kRtxSsrc);
93 sequencer_.set_rtx_sequence_number(kRtxStartSequenceNumber);
94 sequencer_.Sequence(packet);
95 EXPECT_EQ(packet.SequenceNumber(), kRtxStartSequenceNumber);
96 EXPECT_EQ(sequencer_.rtx_sequence_number(), kRtxStartSequenceNumber + 1);
97 }
98
TEST_F(PacketSequencerTest,ProhibitsPaddingWithinVideoFrame)99 TEST_F(PacketSequencerTest, ProhibitsPaddingWithinVideoFrame) {
100 // Send a video packet with the marker bit set to false (indicating it is not
101 // the last packet of a frame).
102 RtpPacketToSend media_packet =
103 CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
104 media_packet.SetPayloadType(kMediaPayloadType);
105 media_packet.SetMarker(false);
106 sequencer_.Sequence(media_packet);
107
108 // Sending padding on the media SSRC should not be allowed at this point.
109 EXPECT_FALSE(sequencer_.CanSendPaddingOnMediaSsrc());
110
111 // Send a video packet with marker set to true, padding should be allowed
112 // again.
113 media_packet.SetMarker(true);
114 sequencer_.Sequence(media_packet);
115 EXPECT_TRUE(sequencer_.CanSendPaddingOnMediaSsrc());
116 }
117
TEST_F(PacketSequencerTest,AllowsPaddingAtAnyTimeIfSoConfigured)118 TEST_F(PacketSequencerTest, AllowsPaddingAtAnyTimeIfSoConfigured) {
119 PacketSequencer packet_sequencer(
120 kMediaSsrc, kRtxSsrc,
121 /*require_marker_before_media_padding=*/false, &clock_);
122
123 // Send an audio packet with the marker bit set to false.
124 RtpPacketToSend media_packet =
125 CreatePacket(RtpPacketMediaType::kAudio, kMediaSsrc);
126 media_packet.SetPayloadType(kMediaPayloadType);
127 media_packet.SetMarker(false);
128 packet_sequencer.Sequence(media_packet);
129
130 // Sending padding on the media SSRC should be allowed despite no marker bit.
131 EXPECT_TRUE(packet_sequencer.CanSendPaddingOnMediaSsrc());
132 }
133
TEST_F(PacketSequencerTest,UpdatesPaddingBasedOnLastMediaPacket)134 TEST_F(PacketSequencerTest, UpdatesPaddingBasedOnLastMediaPacket) {
135 // First send a media packet.
136 RtpPacketToSend media_packet =
137 CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
138 media_packet.SetPayloadType(kMediaPayloadType);
139 media_packet.SetMarker(true);
140 // Advance time so current time doesn't exactly match timestamp.
141 clock_.AdvanceTime(TimeDelta::Millis(5));
142 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
143 sequencer_.Sequence(media_packet);
144
145 // Next send a padding packet and verify the media packet's timestamps and
146 // payload type is transferred to the padding packet.
147 RtpPacketToSend padding_packet =
148 CreatePacket(RtpPacketMediaType::kPadding, kMediaSsrc);
149 padding_packet.SetPadding(/*padding_size=*/100);
150 sequencer_.Sequence(padding_packet);
151
152 EXPECT_EQ(padding_packet.SequenceNumber(), kMediaStartSequenceNumber + 1);
153 EXPECT_EQ(padding_packet.PayloadType(), kMediaPayloadType);
154 EXPECT_EQ(padding_packet.Timestamp(), media_packet.Timestamp());
155 EXPECT_EQ(padding_packet.capture_time(), media_packet.capture_time());
156 }
157
TEST_F(PacketSequencerTest,UpdatesPaddingBasedOnLastRedPacket)158 TEST_F(PacketSequencerTest, UpdatesPaddingBasedOnLastRedPacket) {
159 // First send a media packet.
160 RtpPacketToSend media_packet =
161 CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
162 media_packet.SetPayloadType(kMediaPayloadType);
163 // Simulate a packet with RED encapsulation;
164 media_packet.set_is_red(true);
165 uint8_t* payload_buffer = media_packet.SetPayloadSize(1);
166 payload_buffer[0] = kMediaPayloadType + 1;
167
168 media_packet.SetMarker(true);
169 // Advance time so current time doesn't exactly match timestamp.
170 clock_.AdvanceTime(TimeDelta::Millis(5));
171 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
172 sequencer_.Sequence(media_packet);
173
174 // Next send a padding packet and verify the media packet's timestamps and
175 // payload type is transferred to the padding packet.
176 RtpPacketToSend padding_packet =
177 CreatePacket(RtpPacketMediaType::kPadding, kMediaSsrc);
178 padding_packet.SetPadding(100);
179 sequencer_.Sequence(padding_packet);
180
181 EXPECT_EQ(padding_packet.SequenceNumber(), kMediaStartSequenceNumber + 1);
182 EXPECT_EQ(padding_packet.PayloadType(), kMediaPayloadType + 1);
183 EXPECT_EQ(padding_packet.Timestamp(), media_packet.Timestamp());
184 EXPECT_EQ(padding_packet.capture_time(), media_packet.capture_time());
185 }
186
TEST_F(PacketSequencerTest,DoesNotUpdateFieldsOnPayloadPadding)187 TEST_F(PacketSequencerTest, DoesNotUpdateFieldsOnPayloadPadding) {
188 // First send a media packet.
189 RtpPacketToSend media_packet =
190 CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
191 media_packet.SetPayloadType(kMediaPayloadType);
192 media_packet.SetMarker(true);
193 // Advance time so current time doesn't exactly match timestamp.
194 clock_.AdvanceTime(TimeDelta::Millis(5));
195 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
196 sequencer_.Sequence(media_packet);
197
198 // Simulate a payload padding packet on the RTX SSRC.
199 RtpPacketToSend padding_packet =
200 CreatePacket(RtpPacketMediaType::kPadding, kRtxSsrc);
201 padding_packet.SetPayloadSize(100);
202 padding_packet.SetPayloadType(kMediaPayloadType + 1);
203 padding_packet.SetTimestamp(kStartRtpTimestamp + 1);
204 padding_packet.set_capture_time(kStartTime + TimeDelta::Millis(1));
205 sequencer_.set_rtx_sequence_number(kRtxStartSequenceNumber);
206 sequencer_.Sequence(padding_packet);
207
208 // The sequence number should be updated, but timestamps kept.
209 EXPECT_EQ(padding_packet.SequenceNumber(), kRtxStartSequenceNumber);
210 EXPECT_EQ(padding_packet.PayloadType(), kMediaPayloadType + 1);
211 EXPECT_EQ(padding_packet.Timestamp(), kStartRtpTimestamp + 1);
212 EXPECT_EQ(padding_packet.capture_time(), kStartTime + TimeDelta::Millis(1));
213 }
214
TEST_F(PacketSequencerTest,UpdatesRtxPaddingBasedOnLastMediaPacket)215 TEST_F(PacketSequencerTest, UpdatesRtxPaddingBasedOnLastMediaPacket) {
216 constexpr uint32_t kTimestampTicksPerMs = 90;
217
218 // First send a media packet.
219 RtpPacketToSend media_packet =
220 CreatePacket(RtpPacketMediaType::kVideo, kMediaSsrc);
221 media_packet.SetPayloadType(kMediaPayloadType);
222 media_packet.SetMarker(true);
223 sequencer_.set_media_sequence_number(kMediaStartSequenceNumber);
224 sequencer_.Sequence(media_packet);
225
226 // Advance time, this time delta will be used to interpolate padding
227 // timestamps.
228 constexpr TimeDelta kTimeDelta = TimeDelta::Millis(10);
229 clock_.AdvanceTime(kTimeDelta);
230
231 RtpPacketToSend padding_packet =
232 CreatePacket(RtpPacketMediaType::kPadding, kRtxSsrc);
233 padding_packet.SetPadding(100);
234 padding_packet.SetPayloadType(kMediaPayloadType + 1);
235 sequencer_.set_rtx_sequence_number(kRtxStartSequenceNumber);
236 sequencer_.Sequence(padding_packet);
237
238 // Assigned RTX sequence number, but payload type unchanged in this case.
239 EXPECT_EQ(padding_packet.SequenceNumber(), kRtxStartSequenceNumber);
240 EXPECT_EQ(padding_packet.PayloadType(), kMediaPayloadType + 1);
241 // Timestamps are offset realtive to last media packet.
242 EXPECT_EQ(
243 padding_packet.Timestamp(),
244 media_packet.Timestamp() + (kTimeDelta.ms() * kTimestampTicksPerMs));
245 EXPECT_EQ(padding_packet.capture_time(),
246 media_packet.capture_time() + kTimeDelta);
247 }
248
249 } // namespace
250 } // namespace webrtc
251