OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 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 <limits> | |
12 #include <vector> | |
13 | |
14 #include "testing/gmock/include/gmock/gmock.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 #include "webrtc/base/checks.h" | |
18 #include "webrtc/base/scoped_ptr.h" | |
19 #include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitra te_estimator.h" | |
20 #include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h" | |
21 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" | |
22 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" | |
23 #include "webrtc/modules/utility/interface/mock/mock_process_thread.h" | |
24 #include "webrtc/system_wrappers/interface/clock.h" | |
25 | |
26 using ::testing::_; | |
27 using ::testing::Invoke; | |
28 | |
29 namespace webrtc { | |
30 namespace test { | |
31 | |
32 class TransportFeedbackAdapterTest : public ::testing::Test { | |
33 public: | |
34 TransportFeedbackAdapterTest() | |
35 : clock_(0), | |
36 bitrate_estimator_(nullptr), | |
37 receiver_estimated_bitrate_(0) {} | |
38 | |
39 virtual ~TransportFeedbackAdapterTest() {} | |
40 | |
41 virtual void SetUp() { | |
42 adapter_.reset(new TransportFeedbackAdapter( | |
43 new RtcpBandwidthObserverAdapter(this), &clock_, &process_thread_)); | |
44 | |
45 bitrate_estimator_ = new MockRemoteBitrateEstimator(); | |
46 EXPECT_CALL(process_thread_, RegisterModule(bitrate_estimator_)).Times(1); | |
47 adapter_->SetBitrateEstimator(bitrate_estimator_); | |
48 } | |
49 | |
50 virtual void TearDown() { | |
51 EXPECT_CALL(process_thread_, DeRegisterModule(bitrate_estimator_)).Times(1); | |
52 adapter_.reset(); | |
53 } | |
54 | |
55 protected: | |
56 // Proxy class used since TransportFeedbackAdapter will own the instance | |
57 // passed at construction. | |
58 class RtcpBandwidthObserverAdapter : public RtcpBandwidthObserver { | |
59 public: | |
60 explicit RtcpBandwidthObserverAdapter(TransportFeedbackAdapterTest* owner) | |
61 : owner_(owner) {} | |
62 | |
63 void OnReceivedEstimatedBitrate(uint32_t bitrate) override { | |
64 owner_->receiver_estimated_bitrate_ = bitrate; | |
65 } | |
66 | |
67 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, | |
68 int64_t rtt, | |
69 int64_t now_ms) override { | |
70 RTC_NOTREACHED(); | |
71 } | |
72 | |
73 TransportFeedbackAdapterTest* const owner_; | |
74 }; | |
75 | |
76 void OnReceivedEstimatedBitrate(uint32_t bitrate) {} | |
77 | |
78 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, | |
79 int64_t rtt, | |
80 int64_t now_ms) {} | |
81 | |
82 void ComparePacketVectors(const std::vector<PacketInfo>& truth, | |
83 const std::vector<PacketInfo>& input) { | |
84 ASSERT_EQ(truth.size(), input.size()); | |
85 size_t len = truth.size(); | |
86 // Arrival timestamps will have a different time base, so subtract that | |
87 // difference when comparing. | |
stefan-webrtc
2015/09/14 08:48:50
This is still a bit weird to me. Both seem to be a
sprang_webrtc
2015/09/14 09:03:01
truth[i].arrival_time_ms is the timestamp given as
stefan-webrtc
2015/09/14 09:18:54
Ah, ok. Maybe you can just comment on that it's co
sprang_webrtc
2015/09/14 13:26:03
Done.
| |
88 int64_t arrival_time_delta = | |
89 truth[0].arrival_time_ms - input[0].arrival_time_ms; | |
90 for (size_t i = 0; i < len; ++i) { | |
91 EXPECT_EQ(truth[i].arrival_time_ms, | |
92 input[i].arrival_time_ms + arrival_time_delta); | |
93 EXPECT_EQ(truth[i].send_time_ms, input[i].send_time_ms); | |
94 EXPECT_EQ(truth[i].sequence_number, input[i].sequence_number); | |
95 EXPECT_EQ(truth[i].payload_size, input[i].payload_size); | |
96 EXPECT_EQ(truth[i].was_paced, input[i].was_paced); | |
97 } | |
98 } | |
99 | |
100 // Utility method, to reset arrival_time_ms before adding send time. | |
101 void OnPacketSent(PacketInfo info) { | |
102 info.arrival_time_ms = 0; | |
103 adapter_->OnPacketSent(info); | |
104 } | |
105 | |
106 SimulatedClock clock_; | |
107 MockProcessThread process_thread_; | |
108 MockRemoteBitrateEstimator* bitrate_estimator_; | |
109 rtc::scoped_ptr<TransportFeedbackAdapter> adapter_; | |
110 | |
111 uint32_t receiver_estimated_bitrate_; | |
112 }; | |
113 | |
114 TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) { | |
115 std::vector<PacketInfo> packets; | |
116 packets.push_back(PacketInfo(100, 200, 0, 1500, true)); | |
117 packets.push_back(PacketInfo(110, 210, 1, 1500, true)); | |
118 packets.push_back(PacketInfo(120, 220, 2, 1500, true)); | |
119 packets.push_back(PacketInfo(130, 230, 3, 1500, true)); | |
120 packets.push_back(PacketInfo(140, 240, 4, 1500, true)); | |
121 | |
122 for (const PacketInfo& packet : packets) | |
123 OnPacketSent(packet); | |
124 | |
125 rtcp::TransportFeedback feedback; | |
126 feedback.WithBase(packets[0].sequence_number, | |
127 packets[0].arrival_time_ms * 1000); | |
128 | |
129 for (const PacketInfo& packet : packets) { | |
130 EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, | |
131 packet.arrival_time_ms * 1000)); | |
132 } | |
133 | |
134 feedback.Build(); | |
135 | |
136 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) | |
137 .Times(1) | |
138 .WillOnce(Invoke( | |
139 [packets, this](const std::vector<PacketInfo>& feedback_vector) { | |
140 ComparePacketVectors(packets, feedback_vector); | |
141 })); | |
142 adapter_->OnTransportFeedback(feedback); | |
143 } | |
144 | |
145 TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) { | |
146 std::vector<PacketInfo> packets; | |
147 packets.push_back(PacketInfo(100, 200, 0, 1500, true)); | |
148 packets.push_back(PacketInfo(110, 210, 1, 1500, true)); | |
149 packets.push_back(PacketInfo(120, 220, 2, 1500, true)); | |
150 packets.push_back(PacketInfo(130, 230, 3, 1500, true)); | |
151 packets.push_back(PacketInfo(140, 240, 4, 1500, true)); | |
152 | |
153 const uint16_t kSendSideDropBefore = 1; | |
154 const uint16_t kReceiveSideDropAfter = 3; | |
155 | |
156 for (const PacketInfo& packet : packets) { | |
157 if (packet.sequence_number >= kSendSideDropBefore) | |
158 OnPacketSent(packet); | |
159 } | |
160 | |
161 rtcp::TransportFeedback feedback; | |
162 feedback.WithBase(packets[0].sequence_number, | |
163 packets[0].arrival_time_ms * 1000); | |
164 | |
165 for (const PacketInfo& packet : packets) { | |
166 if (packet.sequence_number <= kReceiveSideDropAfter) { | |
167 EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, | |
168 packet.arrival_time_ms * 1000)); | |
169 } | |
170 } | |
171 | |
172 feedback.Build(); | |
173 | |
174 std::vector<PacketInfo> expected_packets( | |
175 packets.begin() + kSendSideDropBefore, | |
176 packets.begin() + kReceiveSideDropAfter + 1); | |
177 | |
178 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) | |
179 .Times(1) | |
180 .WillOnce(Invoke([expected_packets, | |
181 this](const std::vector<PacketInfo>& feedback_vector) { | |
182 ComparePacketVectors(expected_packets, feedback_vector); | |
183 })); | |
184 adapter_->OnTransportFeedback(feedback); | |
185 } | |
186 | |
187 TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) { | |
188 int64_t kHighArrivalTimeMs = rtcp::TransportFeedback::kDeltaScaleFactor * | |
189 (1L << 8) * ((1L << 23) - 1) / 1000; | |
190 std::vector<PacketInfo> packets; | |
191 packets.push_back(PacketInfo(kHighArrivalTimeMs - 64, 200, 0, 1500, true)); | |
192 packets.push_back(PacketInfo(kHighArrivalTimeMs + 64, 210, 1, 1500, true)); | |
193 packets.push_back(PacketInfo(kHighArrivalTimeMs, 220, 2, 1500, true)); | |
194 | |
195 for (const PacketInfo& packet : packets) | |
196 OnPacketSent(packet); | |
197 | |
198 for (size_t i = 0; i < packets.size(); ++i) { | |
199 rtc::scoped_ptr<rtcp::TransportFeedback> feedback( | |
200 new rtcp::TransportFeedback()); | |
201 feedback->WithBase(packets[i].sequence_number, | |
202 packets[i].arrival_time_ms * 1000); | |
203 | |
204 EXPECT_TRUE(feedback->WithReceivedPacket( | |
205 packets[i].sequence_number, packets[i].arrival_time_ms * 1000)); | |
206 | |
207 rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build(); | |
208 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), | |
209 raw_packet->Length()); | |
210 | |
211 std::vector<PacketInfo> expected_packets; | |
212 expected_packets.push_back(packets[i]); | |
213 | |
214 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) | |
215 .Times(1) | |
216 .WillOnce(Invoke([expected_packets, this]( | |
217 const std::vector<PacketInfo>& feedback_vector) { | |
218 ComparePacketVectors(expected_packets, feedback_vector); | |
219 })); | |
220 adapter_->OnTransportFeedback(*feedback.get()); | |
221 } | |
222 } | |
223 | |
224 TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) { | |
225 std::vector<PacketInfo> sent_packets; | |
226 const int64_t kSmallDeltaUs = | |
227 rtcp::TransportFeedback::kDeltaScaleFactor * ((1 << 8) - 1); | |
228 const int64_t kLargePositiveDeltaUs = | |
229 rtcp::TransportFeedback::kDeltaScaleFactor * | |
230 std::numeric_limits<int16_t>::max(); | |
231 const int64_t kLargeNegativeDeltaUs = | |
232 rtcp::TransportFeedback::kDeltaScaleFactor * | |
233 std::numeric_limits<int16_t>::min(); | |
234 | |
235 PacketInfo info(100, 200, 0, 1500, true); | |
236 sent_packets.push_back(info); | |
237 | |
238 info.send_time_ms += kSmallDeltaUs / 1000; | |
239 info.arrival_time_ms += kSmallDeltaUs / 1000; | |
240 ++info.sequence_number; | |
241 sent_packets.push_back(info); | |
242 | |
243 info.send_time_ms += kLargePositiveDeltaUs / 1000; | |
244 info.arrival_time_ms += kLargePositiveDeltaUs / 1000; | |
245 ++info.sequence_number; | |
246 sent_packets.push_back(info); | |
247 | |
248 info.send_time_ms += kLargeNegativeDeltaUs / 1000; | |
249 info.arrival_time_ms += kLargeNegativeDeltaUs / 1000; | |
250 ++info.sequence_number; | |
251 sent_packets.push_back(info); | |
252 | |
253 // Too large, delta - will need two feedback messages. | |
254 info.send_time_ms += (kLargePositiveDeltaUs + 1000) / 1000; | |
255 info.arrival_time_ms += (kLargePositiveDeltaUs + 1000) / 1000; | |
256 ++info.sequence_number; | |
257 | |
258 // Packets will be added to send history. | |
259 for (const PacketInfo& packet : sent_packets) | |
260 OnPacketSent(packet); | |
261 OnPacketSent(info); | |
262 | |
263 // Create expected feedback and send into adapter. | |
264 rtc::scoped_ptr<rtcp::TransportFeedback> feedback( | |
265 new rtcp::TransportFeedback()); | |
266 feedback->WithBase(sent_packets[0].sequence_number, | |
267 sent_packets[0].arrival_time_ms * 1000); | |
268 | |
269 for (const PacketInfo& packet : sent_packets) { | |
270 EXPECT_TRUE(feedback->WithReceivedPacket(packet.sequence_number, | |
271 packet.arrival_time_ms * 1000)); | |
272 } | |
273 EXPECT_FALSE(feedback->WithReceivedPacket(info.sequence_number, | |
274 info.arrival_time_ms * 1000)); | |
275 | |
276 rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build(); | |
277 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), | |
278 raw_packet->Length()); | |
279 | |
280 std::vector<PacketInfo> received_feedback; | |
281 | |
282 EXPECT_TRUE(feedback.get() != nullptr); | |
283 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) | |
284 .Times(1) | |
285 .WillOnce(Invoke([sent_packets, &received_feedback]( | |
286 const std::vector<PacketInfo>& feedback_vector) { | |
287 EXPECT_EQ(sent_packets.size(), feedback_vector.size()); | |
288 received_feedback = feedback_vector; | |
289 })); | |
290 adapter_->OnTransportFeedback(*feedback.get()); | |
291 | |
292 // Create a new feedback message and add the trailing item. | |
293 feedback.reset(new rtcp::TransportFeedback()); | |
294 feedback->WithBase(info.sequence_number, info.arrival_time_ms * 1000); | |
295 EXPECT_TRUE(feedback->WithReceivedPacket(info.sequence_number, | |
296 info.arrival_time_ms * 1000)); | |
297 raw_packet = feedback->Build(); | |
298 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), | |
299 raw_packet->Length()); | |
300 | |
301 EXPECT_TRUE(feedback.get() != nullptr); | |
302 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) | |
303 .Times(1) | |
304 .WillOnce(Invoke( | |
305 [&received_feedback](const std::vector<PacketInfo>& feedback_vector) { | |
306 EXPECT_EQ(1u, feedback_vector.size()); | |
307 received_feedback.push_back(feedback_vector[0]); | |
308 })); | |
309 adapter_->OnTransportFeedback(*feedback.get()); | |
310 | |
311 sent_packets.push_back(info); | |
312 | |
313 ComparePacketVectors(sent_packets, received_feedback); | |
314 } | |
315 | |
316 } // namespace test | |
317 } // namespace webrtc | |
OLD | NEW |