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