1 /*
2 * Copyright (c) 2017 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 "call/rtx_receive_stream.h"
12
13 #include "call/test/mock_rtp_packet_sink_interface.h"
14 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
15 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
16 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19
20 namespace webrtc {
21
22 namespace {
23
24 using ::testing::_;
25 using ::testing::Property;
26 using ::testing::StrictMock;
27
28 constexpr int kMediaPayloadType = 100;
29 constexpr int kRtxPayloadType = 98;
30 constexpr int kUnknownPayloadType = 90;
31 constexpr uint32_t kMediaSSRC = 0x3333333;
32 constexpr uint16_t kMediaSeqno = 0x5657;
33
34 constexpr uint8_t kRtxPacket[] = {
35 0x80, // Version 2.
36 98, // Payload type.
37 0x12,
38 0x34, // Seqno.
39 0x11,
40 0x11,
41 0x11,
42 0x11, // Timestamp.
43 0x22,
44 0x22,
45 0x22,
46 0x22, // SSRC.
47 // RTX header.
48 0x56,
49 0x57, // Orig seqno.
50 // Payload.
51 0xee,
52 };
53
54 constexpr uint8_t kRtxPacketWithPadding[] = {
55 0xa0, // Version 2, P set
56 98, // Payload type.
57 0x12,
58 0x34, // Seqno.
59 0x11,
60 0x11,
61 0x11,
62 0x11, // Timestamp.
63 0x22,
64 0x22,
65 0x22,
66 0x22, // SSRC.
67 // RTX header.
68 0x56,
69 0x57, // Orig seqno.
70 // Padding
71 0x1,
72 };
73
74 constexpr uint8_t kRtxPacketWithCVO[] = {
75 0x90, // Version 2, X set.
76 98, // Payload type.
77 0x12,
78 0x34, // Seqno.
79 0x11,
80 0x11,
81 0x11,
82 0x11, // Timestamp.
83 0x22,
84 0x22,
85 0x22,
86 0x22, // SSRC.
87 0xbe,
88 0xde,
89 0x00,
90 0x01, // Extension header.
91 0x30,
92 0x01,
93 0x00,
94 0x00, // 90 degree rotation.
95 // RTX header.
96 0x56,
97 0x57, // Orig seqno.
98 // Payload.
99 0xee,
100 };
101
PayloadTypeMapping()102 std::map<int, int> PayloadTypeMapping() {
103 const std::map<int, int> m = {{kRtxPayloadType, kMediaPayloadType}};
104 return m;
105 }
106
107 template <typename T>
Truncate(rtc::ArrayView<T> a,size_t drop)108 rtc::ArrayView<T> Truncate(rtc::ArrayView<T> a, size_t drop) {
109 return a.subview(0, a.size() - drop);
110 }
111
112 } // namespace
113
TEST(RtxReceiveStreamTest,RestoresPacketPayload)114 TEST(RtxReceiveStreamTest, RestoresPacketPayload) {
115 StrictMock<MockRtpPacketSink> media_sink;
116 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
117 RtpPacketReceived rtx_packet;
118 EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
119
120 EXPECT_CALL(media_sink, OnRtpPacket)
121 .WillOnce([](const RtpPacketReceived& packet) {
122 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
123 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
124 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
125 EXPECT_THAT(packet.payload(), ::testing::ElementsAre(0xee));
126 });
127
128 rtx_sink.OnRtpPacket(rtx_packet);
129 }
130
TEST(RtxReceiveStreamTest,SetsRecoveredFlag)131 TEST(RtxReceiveStreamTest, SetsRecoveredFlag) {
132 StrictMock<MockRtpPacketSink> media_sink;
133 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
134 RtpPacketReceived rtx_packet;
135 EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
136 EXPECT_FALSE(rtx_packet.recovered());
137 EXPECT_CALL(media_sink, OnRtpPacket)
138 .WillOnce([](const RtpPacketReceived& packet) {
139 EXPECT_TRUE(packet.recovered());
140 });
141
142 rtx_sink.OnRtpPacket(rtx_packet);
143 }
144
TEST(RtxReceiveStreamTest,IgnoresUnknownPayloadType)145 TEST(RtxReceiveStreamTest, IgnoresUnknownPayloadType) {
146 StrictMock<MockRtpPacketSink> media_sink;
147 const std::map<int, int> payload_type_mapping = {
148 {kUnknownPayloadType, kMediaPayloadType}};
149
150 RtxReceiveStream rtx_sink(&media_sink, payload_type_mapping, kMediaSSRC);
151 RtpPacketReceived rtx_packet;
152 EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
153 rtx_sink.OnRtpPacket(rtx_packet);
154 }
155
TEST(RtxReceiveStreamTest,IgnoresTruncatedPacket)156 TEST(RtxReceiveStreamTest, IgnoresTruncatedPacket) {
157 StrictMock<MockRtpPacketSink> media_sink;
158 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
159 RtpPacketReceived rtx_packet;
160 EXPECT_TRUE(
161 rtx_packet.Parse(Truncate(rtc::ArrayView<const uint8_t>(kRtxPacket), 2)));
162 rtx_sink.OnRtpPacket(rtx_packet);
163 }
164
TEST(RtxReceiveStreamTest,CopiesRtpHeaderExtensions)165 TEST(RtxReceiveStreamTest, CopiesRtpHeaderExtensions) {
166 StrictMock<MockRtpPacketSink> media_sink;
167 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
168 RtpHeaderExtensionMap extension_map;
169 extension_map.RegisterByType(3, kRtpExtensionVideoRotation);
170 RtpPacketReceived rtx_packet(&extension_map);
171 EXPECT_TRUE(
172 rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacketWithCVO)));
173
174 VideoRotation rotation = kVideoRotation_0;
175 EXPECT_TRUE(rtx_packet.GetExtension<VideoOrientation>(&rotation));
176 EXPECT_EQ(kVideoRotation_90, rotation);
177
178 EXPECT_CALL(media_sink, OnRtpPacket)
179 .WillOnce([](const RtpPacketReceived& packet) {
180 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
181 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
182 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
183 EXPECT_THAT(packet.payload(), ::testing::ElementsAre(0xee));
184 VideoRotation rotation = kVideoRotation_0;
185 EXPECT_TRUE(packet.GetExtension<VideoOrientation>(&rotation));
186 EXPECT_EQ(rotation, kVideoRotation_90);
187 });
188
189 rtx_sink.OnRtpPacket(rtx_packet);
190 }
191
TEST(RtxReceiveStreamTest,PropagatesArrivalTime)192 TEST(RtxReceiveStreamTest, PropagatesArrivalTime) {
193 StrictMock<MockRtpPacketSink> media_sink;
194 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
195 RtpPacketReceived rtx_packet(nullptr);
196 EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
197 rtx_packet.set_arrival_time(Timestamp::Millis(123));
198 EXPECT_CALL(media_sink, OnRtpPacket(Property(&RtpPacketReceived::arrival_time,
199 Timestamp::Millis(123))));
200 rtx_sink.OnRtpPacket(rtx_packet);
201 }
202
TEST(RtxReceiveStreamTest,SupportsLargePacket)203 TEST(RtxReceiveStreamTest, SupportsLargePacket) {
204 StrictMock<MockRtpPacketSink> media_sink;
205 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
206 RtpPacketReceived rtx_packet;
207 constexpr int kRtxPacketSize = 2000;
208 constexpr int kRtxPayloadOffset = 14;
209 uint8_t large_rtx_packet[kRtxPacketSize];
210 memcpy(large_rtx_packet, kRtxPacket, sizeof(kRtxPacket));
211 rtc::ArrayView<uint8_t> payload(large_rtx_packet + kRtxPayloadOffset,
212 kRtxPacketSize - kRtxPayloadOffset);
213
214 // Fill payload.
215 for (size_t i = 0; i < payload.size(); i++) {
216 payload[i] = i;
217 }
218 EXPECT_TRUE(
219 rtx_packet.Parse(rtc::ArrayView<const uint8_t>(large_rtx_packet)));
220
221 EXPECT_CALL(media_sink, OnRtpPacket)
222 .WillOnce([&](const RtpPacketReceived& packet) {
223 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
224 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
225 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
226 EXPECT_THAT(packet.payload(), ::testing::ElementsAreArray(payload));
227 });
228
229 rtx_sink.OnRtpPacket(rtx_packet);
230 }
231
TEST(RtxReceiveStreamTest,SupportsLargePacketWithPadding)232 TEST(RtxReceiveStreamTest, SupportsLargePacketWithPadding) {
233 StrictMock<MockRtpPacketSink> media_sink;
234 RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
235 RtpPacketReceived rtx_packet;
236 constexpr int kRtxPacketSize = 2000;
237 constexpr int kRtxPayloadOffset = 14;
238 constexpr int kRtxPaddingSize = 50;
239 uint8_t large_rtx_packet[kRtxPacketSize];
240 memcpy(large_rtx_packet, kRtxPacketWithPadding,
241 sizeof(kRtxPacketWithPadding));
242 rtc::ArrayView<uint8_t> payload(
243 large_rtx_packet + kRtxPayloadOffset,
244 kRtxPacketSize - kRtxPayloadOffset - kRtxPaddingSize);
245 rtc::ArrayView<uint8_t> padding(
246 large_rtx_packet + kRtxPacketSize - kRtxPaddingSize, kRtxPaddingSize);
247
248 // Fill payload.
249 for (size_t i = 0; i < payload.size(); i++) {
250 payload[i] = i;
251 }
252 // Fill padding. Only value of last padding byte matters.
253 for (size_t i = 0; i < padding.size(); i++) {
254 padding[i] = kRtxPaddingSize;
255 }
256
257 EXPECT_TRUE(
258 rtx_packet.Parse(rtc::ArrayView<const uint8_t>(large_rtx_packet)));
259
260 EXPECT_CALL(media_sink, OnRtpPacket)
261 .WillOnce([&](const RtpPacketReceived& packet) {
262 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
263 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
264 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
265 EXPECT_THAT(packet.payload(), ::testing::ElementsAreArray(payload));
266 });
267
268 rtx_sink.OnRtpPacket(rtx_packet);
269 }
270
271 } // namespace webrtc
272