OLD | NEW |
---|---|
(Empty) | |
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 <memory> | |
12 | |
13 #include "webrtc/common_types.h" | |
14 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | |
15 #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" | |
16 #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" | |
17 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | |
18 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h" | |
19 #include "webrtc/test/gtest.h" | |
20 | |
21 namespace webrtc { | |
22 | |
23 const uint32_t kTestRate = 64000u; | |
24 const uint8_t kTestPayload[] = {'t', 'e', 's', 't'}; | |
25 const uint8_t kPcmuPayloadType = 96; | |
26 const int64_t kGetSourcesTimeoutMs = 10000; | |
27 const int kSourceListsSize = 20; | |
28 | |
29 class RtpReceiverTest : public ::testing::Test { | |
30 protected: | |
31 RtpReceiverTest() | |
32 : fake_clock_(123456), | |
33 rtp_receiver_( | |
34 RtpReceiver::CreateAudioReceiver(&fake_clock_, | |
35 nullptr, | |
36 nullptr, | |
37 &rtp_payload_registry_)) { | |
38 CodecInst voice_codec = {}; | |
39 voice_codec.pltype = kPcmuPayloadType; | |
40 voice_codec.plfreq = 8000; | |
41 voice_codec.rate = kTestRate; | |
42 memcpy(voice_codec.plname, "PCMU", 5); | |
43 rtp_receiver_->RegisterReceivePayload(voice_codec); | |
44 } | |
45 ~RtpReceiverTest() {} | |
46 | |
47 bool FindSourceByIdAndType(const std::vector<RtpSource>& sources, | |
48 uint32_t source_id, | |
49 RtpSourceType type, | |
50 RtpSource* source) { | |
51 for (size_t i = 0; i < sources.size(); ++i) { | |
52 if (sources[i].source_id() == source_id && | |
53 sources[i].source_type() == type) { | |
54 (*source) = sources[i]; | |
55 return true; | |
56 } | |
57 } | |
58 return false; | |
59 } | |
60 | |
61 SimulatedClock fake_clock_; | |
62 RTPPayloadRegistry rtp_payload_registry_; | |
63 std::unique_ptr<RtpReceiver> rtp_receiver_; | |
64 }; | |
65 | |
66 TEST_F(RtpReceiverTest, GetSources) { | |
67 int64_t timestamp = fake_clock_.TimeInMilliseconds(); | |
hbos
2017/04/06 08:17:16
nit/optionally: I'd just remove timestamp and call
Zhi Huang
2017/04/06 22:30:25
Done.
| |
68 RTPHeader header; | |
69 header.payloadType = kPcmuPayloadType; | |
70 header.ssrc = 1; | |
71 header.timestamp = timestamp; | |
72 header.numCSRCs = 2; | |
73 header.arrOfCSRCs[0] = 111; | |
74 header.arrOfCSRCs[1] = 222; | |
75 PayloadUnion payload_specific = {AudioPayload()}; | |
76 bool in_order = false; | |
77 RtpSource source(0, 0, RtpSourceType::SSRC); | |
78 | |
79 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
80 payload_specific, in_order)); | |
81 auto sources = rtp_receiver_->GetSources(); | |
82 // One SSRC source and two CSRC sources. | |
83 ASSERT_EQ(3u, sources.size()); | |
84 ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source)); | |
85 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
86 ASSERT_TRUE( | |
87 FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source)); | |
88 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
89 ASSERT_TRUE( | |
90 FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source)); | |
91 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
92 | |
93 // Advance the fake clock and the method is expected to return the | |
94 // contributing source object with same source id and updated timestamp. | |
95 fake_clock_.AdvanceTimeMilliseconds(1); | |
96 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
97 payload_specific, in_order)); | |
98 sources = rtp_receiver_->GetSources(); | |
99 ASSERT_EQ(3u, sources.size()); | |
100 ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source)); | |
101 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
102 ASSERT_TRUE( | |
103 FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source)); | |
104 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
105 ASSERT_TRUE( | |
106 FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source)); | |
107 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
108 | |
109 fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs); | |
hbos
2017/04/06 08:17:17
This should have the "// Time out."
You have alrea
Zhi Huang
2017/04/06 22:30:25
Not exactly.
After clock is advanced by 1ms (line
hbos
2017/04/07 08:22:21
Acknowledged.
| |
110 ASSERT_EQ(3u, sources.size()); | |
hbos
2017/04/06 08:17:17
These asserts/expects are doing the same thing as
Zhi Huang
2017/04/06 22:30:25
Oh I meant to test that the sources are still ther
| |
111 ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source)); | |
112 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
113 ASSERT_TRUE( | |
114 FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source)); | |
115 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
116 ASSERT_TRUE( | |
117 FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source)); | |
118 EXPECT_EQ(timestamp + 1, source.timestamp_ms()); | |
119 | |
120 // Time out. | |
121 fake_clock_.AdvanceTimeMilliseconds(1); | |
122 sources = rtp_receiver_->GetSources(); | |
hbos
2017/04/06 08:17:16
Move this and the next line to after AdvanceTimeMi
Zhi Huang
2017/04/06 22:30:25
Please see the explanation above.
| |
123 // All the sources should be out of date. | |
124 ASSERT_EQ(0u, sources.size()); | |
125 } | |
126 | |
127 // Test the case that the SSRC is changed. | |
128 TEST_F(RtpReceiverTest, GetSourcesChangeSSRC) { | |
129 int64_t prev_time = -1; | |
130 int64_t cur_time = fake_clock_.TimeInMilliseconds(); | |
131 RTPHeader header; | |
132 header.payloadType = kPcmuPayloadType; | |
133 header.ssrc = 1; | |
134 header.timestamp = cur_time; | |
135 PayloadUnion payload_specific = {AudioPayload()}; | |
136 bool in_order = false; | |
137 RtpSource source(0, 0, RtpSourceType::SSRC); | |
138 | |
139 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
140 payload_specific, in_order)); | |
141 auto sources = rtp_receiver_->GetSources(); | |
142 ASSERT_EQ(1u, sources.size()); | |
143 EXPECT_EQ(1u, sources[0].source_id()); | |
144 EXPECT_EQ(cur_time, sources[0].timestamp_ms()); | |
145 | |
146 // The SSRC is changed and the old SSRC is expected to be returned. | |
147 fake_clock_.AdvanceTimeMilliseconds(100); | |
148 prev_time = cur_time; | |
149 cur_time = fake_clock_.TimeInMilliseconds(); | |
150 header.ssrc = 2; | |
151 header.timestamp = cur_time; | |
152 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
153 payload_specific, in_order)); | |
154 sources = rtp_receiver_->GetSources(); | |
155 ASSERT_EQ(2u, sources.size()); | |
156 ASSERT_TRUE(FindSourceByIdAndType(sources, 2u, RtpSourceType::SSRC, &source)); | |
157 EXPECT_EQ(cur_time, source.timestamp_ms()); | |
158 ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source)); | |
159 EXPECT_EQ(prev_time, source.timestamp_ms()); | |
160 | |
161 // The SSRC is changed again and happen to be changed back to 1. No | |
162 // duplication is expected. | |
163 fake_clock_.AdvanceTimeMilliseconds(100); | |
164 header.ssrc = 1; | |
165 header.timestamp = cur_time; | |
166 prev_time = cur_time; | |
167 cur_time = fake_clock_.TimeInMilliseconds(); | |
168 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
169 payload_specific, in_order)); | |
170 sources = rtp_receiver_->GetSources(); | |
171 ASSERT_EQ(2u, sources.size()); | |
172 ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source)); | |
173 EXPECT_EQ(cur_time, source.timestamp_ms()); | |
174 ASSERT_TRUE(FindSourceByIdAndType(sources, 2u, RtpSourceType::SSRC, &source)); | |
175 EXPECT_EQ(prev_time, source.timestamp_ms()); | |
176 | |
177 // Old SSRC source timeout. | |
178 fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs); | |
179 cur_time = fake_clock_.TimeInMilliseconds(); | |
180 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
181 payload_specific, in_order)); | |
182 sources = rtp_receiver_->GetSources(); | |
183 ASSERT_EQ(1u, sources.size()); | |
184 EXPECT_EQ(1u, sources[0].source_id()); | |
185 EXPECT_EQ(cur_time, sources[0].timestamp_ms()); | |
186 EXPECT_EQ(RtpSourceType::SSRC, sources[0].source_type()); | |
187 } | |
188 | |
189 TEST_F(RtpReceiverTest, GetSourcesRemoveOutdatedSource) { | |
190 int64_t timestamp = fake_clock_.TimeInMilliseconds(); | |
191 bool in_order = false; | |
192 RTPHeader header; | |
193 header.payloadType = kPcmuPayloadType; | |
194 header.timestamp = timestamp; | |
195 PayloadUnion payload_specific = {AudioPayload()}; | |
196 header.numCSRCs = 1; | |
197 RtpSource source(0, 0, RtpSourceType::SSRC); | |
198 | |
199 for (size_t i = 0; i < kSourceListsSize; ++i) { | |
200 header.ssrc = i; | |
201 header.arrOfCSRCs[0] = (i + 1); | |
202 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
203 payload_specific, in_order)); | |
204 } | |
205 | |
206 auto sources = rtp_receiver_->GetSources(); | |
207 // Expect |kSourceListsSize| SSRC sources and |kSourceListsSize| CSRC sources. | |
208 ASSERT_TRUE(sources.size() == 2 * kSourceListsSize); | |
209 for (size_t i = 0; i < kSourceListsSize; ++i) { | |
210 // The SSRC source IDs are expected to be 19, 18, 17 ... 0 | |
211 ASSERT_TRUE( | |
212 FindSourceByIdAndType(sources, i, RtpSourceType::SSRC, &source)); | |
213 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
214 | |
215 // The CSRC source IDs are expected to be 20, 19, 18 ... 1 | |
216 ASSERT_TRUE( | |
217 FindSourceByIdAndType(sources, (i + 1), RtpSourceType::CSRC, &source)); | |
218 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
219 } | |
220 | |
221 fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs); | |
222 for (size_t i = 0; i < kSourceListsSize; ++i) { | |
223 // The SSRC source IDs are expected to be 19, 18, 17 ... 0 | |
224 ASSERT_TRUE( | |
225 FindSourceByIdAndType(sources, i, RtpSourceType::SSRC, &source)); | |
226 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
227 | |
228 // The CSRC source IDs are expected to be 20, 19, 18 ... 1 | |
229 ASSERT_TRUE( | |
230 FindSourceByIdAndType(sources, (i + 1), RtpSourceType::CSRC, &source)); | |
231 EXPECT_EQ(timestamp, source.timestamp_ms()); | |
232 } | |
233 | |
234 // Timeout. All the existing objects are out of date and are expected to be | |
235 // removed. | |
236 fake_clock_.AdvanceTimeMilliseconds(1); | |
237 header.ssrc = 111; | |
238 header.arrOfCSRCs[0] = 222; | |
239 EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4, | |
240 payload_specific, in_order)); | |
241 auto rtp_receiver_impl = static_cast<RtpReceiverImpl*>(rtp_receiver_.get()); | |
242 auto ssrc_sources = rtp_receiver_impl->ssrc_sources(); | |
243 ASSERT_EQ(1u, ssrc_sources.size()); | |
244 EXPECT_EQ(111u, ssrc_sources.begin()->source_id()); | |
245 EXPECT_EQ(RtpSourceType::SSRC, ssrc_sources.begin()->source_type()); | |
246 EXPECT_EQ(fake_clock_.TimeInMilliseconds(), | |
247 ssrc_sources.begin()->timestamp_ms()); | |
248 | |
249 auto csrc_sources = rtp_receiver_impl->csrc_sources(); | |
250 ASSERT_EQ(1u, csrc_sources.size()); | |
251 EXPECT_EQ(222u, csrc_sources.begin()->source_id()); | |
252 EXPECT_EQ(RtpSourceType::CSRC, csrc_sources.begin()->source_type()); | |
253 EXPECT_EQ(fake_clock_.TimeInMilliseconds(), | |
254 csrc_sources.begin()->timestamp_ms()); | |
255 } | |
256 | |
257 } // namespace webrtc | |
OLD | NEW |