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