blob: 75086fef9c552a1040a665d6927df16e0ab1cd20 [file] [log] [blame]
nisseeed52bf2017-05-19 06:15:19 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "call/rtx_receive_stream.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#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"
nisseeed52bf2017-05-19 06:15:19 -070019
20namespace webrtc {
21
22namespace {
23
24using ::testing::_;
Per Kjellandere19a3752019-12-03 14:41:59 +010025using ::testing::Property;
nisseeed52bf2017-05-19 06:15:19 -070026using ::testing::StrictMock;
27
nisseeed52bf2017-05-19 06:15:19 -070028constexpr int kMediaPayloadType = 100;
29constexpr int kRtxPayloadType = 98;
nisse38644992017-08-30 04:16:40 -070030constexpr int kUnknownPayloadType = 90;
nisseeed52bf2017-05-19 06:15:19 -070031constexpr uint32_t kMediaSSRC = 0x3333333;
32constexpr uint16_t kMediaSeqno = 0x5657;
33
34constexpr uint8_t kRtxPacket[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +020035 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.
nisseeed52bf2017-05-19 06:15:19 -070047 // RTX header.
Jonas Olssona4d87372019-07-05 19:08:33 +020048 0x56,
49 0x57, // Orig seqno.
nisseeed52bf2017-05-19 06:15:19 -070050 // Payload.
51 0xee,
52};
53
Niels Möller28214cd2019-10-09 17:44:40 +020054constexpr 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
nisseeed52bf2017-05-19 06:15:19 -070074constexpr uint8_t kRtxPacketWithCVO[] = {
Jonas Olssona4d87372019-07-05 19:08:33 +020075 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.
nisseeed52bf2017-05-19 06:15:19 -070095 // RTX header.
Jonas Olssona4d87372019-07-05 19:08:33 +020096 0x56,
97 0x57, // Orig seqno.
nisseeed52bf2017-05-19 06:15:19 -070098 // Payload.
99 0xee,
100};
101
102std::map<int, int> PayloadTypeMapping() {
nisse38644992017-08-30 04:16:40 -0700103 const std::map<int, int> m = {{kRtxPayloadType, kMediaPayloadType}};
nisseeed52bf2017-05-19 06:15:19 -0700104 return m;
105}
106
107template <typename T>
108rtc::ArrayView<T> Truncate(rtc::ArrayView<T> a, size_t drop) {
109 return a.subview(0, a.size() - drop);
110}
111
112} // namespace
113
114TEST(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
Niels Möller28214cd2019-10-09 17:44:40 +0200120 EXPECT_CALL(media_sink, OnRtpPacket)
121 .WillOnce([](const RtpPacketReceived& packet) {
nisseeed52bf2017-05-19 06:15:19 -0700122 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
123 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
124 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200125 EXPECT_THAT(packet.payload(), ::testing::ElementsAre(0xee));
Niels Möller28214cd2019-10-09 17:44:40 +0200126 });
nisseeed52bf2017-05-19 06:15:19 -0700127
128 rtx_sink.OnRtpPacket(rtx_packet);
129}
130
nisse38644992017-08-30 04:16:40 -0700131TEST(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());
Niels Möller28214cd2019-10-09 17:44:40 +0200137 EXPECT_CALL(media_sink, OnRtpPacket)
138 .WillOnce([](const RtpPacketReceived& packet) {
nisse38644992017-08-30 04:16:40 -0700139 EXPECT_TRUE(packet.recovered());
Niels Möller28214cd2019-10-09 17:44:40 +0200140 });
nisse38644992017-08-30 04:16:40 -0700141
142 rtx_sink.OnRtpPacket(rtx_packet);
143}
144
nisseeed52bf2017-05-19 06:15:19 -0700145TEST(RtxReceiveStreamTest, IgnoresUnknownPayloadType) {
146 StrictMock<MockRtpPacketSink> media_sink;
nisse38644992017-08-30 04:16:40 -0700147 const std::map<int, int> payload_type_mapping = {
148 {kUnknownPayloadType, kMediaPayloadType}};
149
150 RtxReceiveStream rtx_sink(&media_sink, payload_type_mapping, kMediaSSRC);
nisseeed52bf2017-05-19 06:15:19 -0700151 RtpPacketReceived rtx_packet;
152 EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
153 rtx_sink.OnRtpPacket(rtx_packet);
154}
155
156TEST(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
165TEST(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);
Yves Gerey665174f2018-06-19 15:03:05 +0200171 EXPECT_TRUE(
172 rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacketWithCVO)));
nisseeed52bf2017-05-19 06:15:19 -0700173
174 VideoRotation rotation = kVideoRotation_0;
175 EXPECT_TRUE(rtx_packet.GetExtension<VideoOrientation>(&rotation));
176 EXPECT_EQ(kVideoRotation_90, rotation);
177
Niels Möller28214cd2019-10-09 17:44:40 +0200178 EXPECT_CALL(media_sink, OnRtpPacket)
179 .WillOnce([](const RtpPacketReceived& packet) {
nisseeed52bf2017-05-19 06:15:19 -0700180 EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
181 EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
182 EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200183 EXPECT_THAT(packet.payload(), ::testing::ElementsAre(0xee));
nisseeed52bf2017-05-19 06:15:19 -0700184 VideoRotation rotation = kVideoRotation_0;
185 EXPECT_TRUE(packet.GetExtension<VideoOrientation>(&rotation));
186 EXPECT_EQ(rotation, kVideoRotation_90);
Niels Möller28214cd2019-10-09 17:44:40 +0200187 });
188
189 rtx_sink.OnRtpPacket(rtx_packet);
190}
191
Per Kjellandere19a3752019-12-03 14:41:59 +0100192TEST(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_ms(123);
198 EXPECT_CALL(media_sink,
199 OnRtpPacket(Property(&RtpPacketReceived::arrival_time_ms, 123)));
200 rtx_sink.OnRtpPacket(rtx_packet);
201}
202
Niels Möller28214cd2019-10-09 17:44:40 +0200203TEST(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
232TEST(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 });
nisseeed52bf2017-05-19 06:15:19 -0700267
268 rtx_sink.OnRtpPacket(rtx_packet);
269}
270
271} // namespace webrtc