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_bitrate_estimator.h" 20#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h" 21#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 22#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" 23#include "webrtc/modules/utility/include/mock/mock_process_thread.h" 24#include "webrtc/system_wrappers/include/clock.h" 25 26using ::testing::_; 27using ::testing::Invoke; 28 29namespace webrtc { 30namespace test { 31 32class 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 // truth contains the input data for the test, and input is what will be 87 // sent to the bandwidth estimator. truth.arrival_tims_ms is used to 88 // populate the transport feedback messages. As these times may be changed 89 // (because of resolution limits in the packets, and because of the time 90 // base adjustment performed by the TransportFeedbackAdapter at the first 91 // packet, the truth[x].arrival_time and input[x].arrival_time may not be 92 // equal. However, the difference must be the same for all x. 93 int64_t arrival_time_delta = 94 truth[0].arrival_time_ms - input[0].arrival_time_ms; 95 for (size_t i = 0; i < len; ++i) { 96 EXPECT_EQ(truth[i].arrival_time_ms, 97 input[i].arrival_time_ms + arrival_time_delta); 98 EXPECT_EQ(truth[i].send_time_ms, input[i].send_time_ms); 99 EXPECT_EQ(truth[i].sequence_number, input[i].sequence_number); 100 EXPECT_EQ(truth[i].payload_size, input[i].payload_size); 101 EXPECT_EQ(truth[i].was_paced, input[i].was_paced); 102 } 103 } 104 105 // Utility method, to reset arrival_time_ms before adding send time. 106 void OnSentPacket(PacketInfo info) { 107 info.arrival_time_ms = 0; 108 adapter_->AddPacket(info.sequence_number, info.payload_size, 109 info.was_paced); 110 adapter_->OnSentPacket(info.sequence_number, info.send_time_ms); 111 } 112 113 SimulatedClock clock_; 114 MockProcessThread process_thread_; 115 MockRemoteBitrateEstimator* bitrate_estimator_; 116 rtc::scoped_ptr<TransportFeedbackAdapter> adapter_; 117 118 uint32_t receiver_estimated_bitrate_; 119}; 120 121TEST_F(TransportFeedbackAdapterTest, AdaptsFeedbackAndPopulatesSendTimes) { 122 std::vector<PacketInfo> packets; 123 packets.push_back(PacketInfo(100, 200, 0, 1500, true)); 124 packets.push_back(PacketInfo(110, 210, 1, 1500, true)); 125 packets.push_back(PacketInfo(120, 220, 2, 1500, true)); 126 packets.push_back(PacketInfo(130, 230, 3, 1500, true)); 127 packets.push_back(PacketInfo(140, 240, 4, 1500, true)); 128 129 for (const PacketInfo& packet : packets) 130 OnSentPacket(packet); 131 132 rtcp::TransportFeedback feedback; 133 feedback.WithBase(packets[0].sequence_number, 134 packets[0].arrival_time_ms * 1000); 135 136 for (const PacketInfo& packet : packets) { 137 EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, 138 packet.arrival_time_ms * 1000)); 139 } 140 141 feedback.Build(); 142 143 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) 144 .Times(1) 145 .WillOnce(Invoke( 146 [packets, this](const std::vector<PacketInfo>& feedback_vector) { 147 ComparePacketVectors(packets, feedback_vector); 148 })); 149 adapter_->OnTransportFeedback(feedback); 150} 151 152TEST_F(TransportFeedbackAdapterTest, HandlesDroppedPackets) { 153 std::vector<PacketInfo> packets; 154 packets.push_back(PacketInfo(100, 200, 0, 1500, true)); 155 packets.push_back(PacketInfo(110, 210, 1, 1500, true)); 156 packets.push_back(PacketInfo(120, 220, 2, 1500, true)); 157 packets.push_back(PacketInfo(130, 230, 3, 1500, true)); 158 packets.push_back(PacketInfo(140, 240, 4, 1500, true)); 159 160 const uint16_t kSendSideDropBefore = 1; 161 const uint16_t kReceiveSideDropAfter = 3; 162 163 for (const PacketInfo& packet : packets) { 164 if (packet.sequence_number >= kSendSideDropBefore) 165 OnSentPacket(packet); 166 } 167 168 rtcp::TransportFeedback feedback; 169 feedback.WithBase(packets[0].sequence_number, 170 packets[0].arrival_time_ms * 1000); 171 172 for (const PacketInfo& packet : packets) { 173 if (packet.sequence_number <= kReceiveSideDropAfter) { 174 EXPECT_TRUE(feedback.WithReceivedPacket(packet.sequence_number, 175 packet.arrival_time_ms * 1000)); 176 } 177 } 178 179 feedback.Build(); 180 181 std::vector<PacketInfo> expected_packets( 182 packets.begin() + kSendSideDropBefore, 183 packets.begin() + kReceiveSideDropAfter + 1); 184 185 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) 186 .Times(1) 187 .WillOnce(Invoke([expected_packets, 188 this](const std::vector<PacketInfo>& feedback_vector) { 189 ComparePacketVectors(expected_packets, feedback_vector); 190 })); 191 adapter_->OnTransportFeedback(feedback); 192} 193 194TEST_F(TransportFeedbackAdapterTest, SendTimeWrapsBothWays) { 195 int64_t kHighArrivalTimeMs = rtcp::TransportFeedback::kDeltaScaleFactor * 196 static_cast<int64_t>(1 << 8) * 197 static_cast<int64_t>((1 << 23) - 1) / 1000; 198 std::vector<PacketInfo> packets; 199 packets.push_back(PacketInfo(kHighArrivalTimeMs - 64, 200, 0, 1500, true)); 200 packets.push_back(PacketInfo(kHighArrivalTimeMs + 64, 210, 1, 1500, true)); 201 packets.push_back(PacketInfo(kHighArrivalTimeMs, 220, 2, 1500, true)); 202 203 for (const PacketInfo& packet : packets) 204 OnSentPacket(packet); 205 206 for (size_t i = 0; i < packets.size(); ++i) { 207 rtc::scoped_ptr<rtcp::TransportFeedback> feedback( 208 new rtcp::TransportFeedback()); 209 feedback->WithBase(packets[i].sequence_number, 210 packets[i].arrival_time_ms * 1000); 211 212 EXPECT_TRUE(feedback->WithReceivedPacket( 213 packets[i].sequence_number, packets[i].arrival_time_ms * 1000)); 214 215 rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build(); 216 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), 217 raw_packet->Length()); 218 219 std::vector<PacketInfo> expected_packets; 220 expected_packets.push_back(packets[i]); 221 222 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) 223 .Times(1) 224 .WillOnce(Invoke([expected_packets, this]( 225 const std::vector<PacketInfo>& feedback_vector) { 226 ComparePacketVectors(expected_packets, feedback_vector); 227 })); 228 adapter_->OnTransportFeedback(*feedback.get()); 229 } 230} 231 232TEST_F(TransportFeedbackAdapterTest, TimestampDeltas) { 233 std::vector<PacketInfo> sent_packets; 234 const int64_t kSmallDeltaUs = 235 rtcp::TransportFeedback::kDeltaScaleFactor * ((1 << 8) - 1); 236 const int64_t kLargePositiveDeltaUs = 237 rtcp::TransportFeedback::kDeltaScaleFactor * 238 std::numeric_limits<int16_t>::max(); 239 const int64_t kLargeNegativeDeltaUs = 240 rtcp::TransportFeedback::kDeltaScaleFactor * 241 std::numeric_limits<int16_t>::min(); 242 243 PacketInfo info(100, 200, 0, 1500, true); 244 sent_packets.push_back(info); 245 246 info.send_time_ms += kSmallDeltaUs / 1000; 247 info.arrival_time_ms += kSmallDeltaUs / 1000; 248 ++info.sequence_number; 249 sent_packets.push_back(info); 250 251 info.send_time_ms += kLargePositiveDeltaUs / 1000; 252 info.arrival_time_ms += kLargePositiveDeltaUs / 1000; 253 ++info.sequence_number; 254 sent_packets.push_back(info); 255 256 info.send_time_ms += kLargeNegativeDeltaUs / 1000; 257 info.arrival_time_ms += kLargeNegativeDeltaUs / 1000; 258 ++info.sequence_number; 259 sent_packets.push_back(info); 260 261 // Too large, delta - will need two feedback messages. 262 info.send_time_ms += (kLargePositiveDeltaUs + 1000) / 1000; 263 info.arrival_time_ms += (kLargePositiveDeltaUs + 1000) / 1000; 264 ++info.sequence_number; 265 266 // Packets will be added to send history. 267 for (const PacketInfo& packet : sent_packets) 268 OnSentPacket(packet); 269 OnSentPacket(info); 270 271 // Create expected feedback and send into adapter. 272 rtc::scoped_ptr<rtcp::TransportFeedback> feedback( 273 new rtcp::TransportFeedback()); 274 feedback->WithBase(sent_packets[0].sequence_number, 275 sent_packets[0].arrival_time_ms * 1000); 276 277 for (const PacketInfo& packet : sent_packets) { 278 EXPECT_TRUE(feedback->WithReceivedPacket(packet.sequence_number, 279 packet.arrival_time_ms * 1000)); 280 } 281 EXPECT_FALSE(feedback->WithReceivedPacket(info.sequence_number, 282 info.arrival_time_ms * 1000)); 283 284 rtc::scoped_ptr<rtcp::RawPacket> raw_packet = feedback->Build(); 285 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), 286 raw_packet->Length()); 287 288 std::vector<PacketInfo> received_feedback; 289 290 EXPECT_TRUE(feedback.get() != nullptr); 291 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) 292 .Times(1) 293 .WillOnce(Invoke([sent_packets, &received_feedback]( 294 const std::vector<PacketInfo>& feedback_vector) { 295 EXPECT_EQ(sent_packets.size(), feedback_vector.size()); 296 received_feedback = feedback_vector; 297 })); 298 adapter_->OnTransportFeedback(*feedback.get()); 299 300 // Create a new feedback message and add the trailing item. 301 feedback.reset(new rtcp::TransportFeedback()); 302 feedback->WithBase(info.sequence_number, info.arrival_time_ms * 1000); 303 EXPECT_TRUE(feedback->WithReceivedPacket(info.sequence_number, 304 info.arrival_time_ms * 1000)); 305 raw_packet = feedback->Build(); 306 feedback = rtcp::TransportFeedback::ParseFrom(raw_packet->Buffer(), 307 raw_packet->Length()); 308 309 EXPECT_TRUE(feedback.get() != nullptr); 310 EXPECT_CALL(*bitrate_estimator_, IncomingPacketFeedbackVector(_)) 311 .Times(1) 312 .WillOnce(Invoke( 313 [&received_feedback](const std::vector<PacketInfo>& feedback_vector) { 314 EXPECT_EQ(1u, feedback_vector.size()); 315 received_feedback.push_back(feedback_vector[0]); 316 })); 317 adapter_->OnTransportFeedback(*feedback.get()); 318 319 sent_packets.push_back(info); 320 321 ComparePacketVectors(sent_packets, received_feedback); 322} 323 324} // namespace test 325} // namespace webrtc 326