Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / remote_bitrate_estimator / test / bwe_test.cc
1 /*
2  *  Copyright (c) 2013 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 "webrtc/modules/remote_bitrate_estimator/test/bwe_test.h"
12
13 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h"
14 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h"
15 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
16 #include "webrtc/system_wrappers/interface/clock.h"
17 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
18
19 using std::string;
20 using std::vector;
21
22 namespace webrtc {
23 namespace testing {
24 namespace bwe {
25
26 class TestedEstimator : public RemoteBitrateObserver {
27  public:
28   static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
29   static const int kDelayPlotIntervalMs = 100;
30
31   TestedEstimator(const string& test_name,
32                   const BweTestConfig::EstimatorConfig& config)
33       : debug_name_(config.debug_name),
34         delay_log_prefix_(),
35         estimate_log_prefix_(),
36         last_delay_plot_ms_(0),
37         plot_delay_(config.plot_delay),
38         plot_estimate_(config.plot_estimate),
39         clock_(0),
40         stats_(),
41         latest_estimate_bps_(-1),
42         estimator_(config.estimator_factory->Create(
43             this, &clock_, config.control_type,
44             kRemoteBitrateEstimatorMinBitrateBps)),
45         baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
46                                                 config.update_baseline)) {
47     assert(estimator_.get());
48     assert(baseline_.get());
49     // Setup the prefix strings used when logging.
50     std::stringstream ss;
51     ss << "Delay_" << config.flow_id << "#2";
52     delay_log_prefix_ = ss.str();
53     ss.str("");
54     ss << "Estimate_" << config.flow_id << "#1";
55     estimate_log_prefix_ = ss.str();
56     // Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
57     estimator_->OnRttUpdate(50);
58   }
59
60   void EatPacket(const Packet& packet) {
61     BWE_TEST_LOGGING_CONTEXT(debug_name_);
62
63     latest_estimate_bps_ = -1;
64
65     // We're treating the send time (from previous filter) as the arrival
66     // time once packet reaches the estimator.
67     int64_t packet_time_ms = (packet.send_time_us() + 500) / 1000;
68     BWE_TEST_LOGGING_TIME(packet_time_ms);
69     if (plot_delay_) {
70       if (clock_.TimeInMilliseconds() - last_delay_plot_ms_ >
71           kDelayPlotIntervalMs) {
72         BWE_TEST_LOGGING_PLOT(delay_log_prefix_, clock_.TimeInMilliseconds(),
73                               packet_time_ms -
74                               (packet.creation_time_us() + 500) / 1000);
75         last_delay_plot_ms_ = clock_.TimeInMilliseconds();
76       }
77     }
78
79     int64_t step_ms = std::max(estimator_->TimeUntilNextProcess(), 0);
80     while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
81       clock_.AdvanceTimeMilliseconds(step_ms);
82       estimator_->Process();
83       step_ms = std::max(estimator_->TimeUntilNextProcess(), 0);
84     }
85     estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
86                                packet.header());
87     clock_.AdvanceTimeMilliseconds(packet_time_ms -
88                                    clock_.TimeInMilliseconds());
89     ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
90   }
91
92   bool CheckEstimate(PacketSender::Feedback* feedback) {
93     assert(feedback);
94     BWE_TEST_LOGGING_CONTEXT(debug_name_);
95     uint32_t estimated_bps = 0;
96     if (LatestEstimate(&estimated_bps)) {
97       feedback->estimated_bps = estimated_bps;
98       baseline_->Estimate(clock_.TimeInMilliseconds(), estimated_bps);
99
100       double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
101       stats_.Push(estimated_kbps);
102       if (plot_estimate_) {
103         BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
104                               estimated_kbps);
105       }
106       return true;
107     }
108     return false;
109   }
110
111   void LogStats() {
112     BWE_TEST_LOGGING_CONTEXT(debug_name_);
113     BWE_TEST_LOGGING_CONTEXT("Mean");
114     stats_.Log("kbps");
115   }
116
117   void VerifyOrWriteBaseline() {
118     EXPECT_TRUE(baseline_->VerifyOrWrite());
119   }
120
121   virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
122                                        unsigned int bitrate) {
123   }
124
125  private:
126   bool LatestEstimate(uint32_t* estimate_bps) {
127     if (latest_estimate_bps_ < 0) {
128       vector<unsigned int> ssrcs;
129       unsigned int bps = 0;
130       if (!estimator_->LatestEstimate(&ssrcs, &bps)) {
131         return false;
132       }
133       latest_estimate_bps_ = bps;
134     }
135     *estimate_bps = latest_estimate_bps_;
136     return true;
137   }
138
139   string debug_name_;
140   string delay_log_prefix_;
141   string estimate_log_prefix_;
142   int64_t last_delay_plot_ms_;
143   bool plot_delay_;
144   bool plot_estimate_;
145   SimulatedClock clock_;
146   Stats<double> stats_;
147   int64_t latest_estimate_bps_;
148   scoped_ptr<RemoteBitrateEstimator> estimator_;
149   scoped_ptr<BaseLineFileInterface> baseline_;
150
151   DISALLOW_IMPLICIT_CONSTRUCTORS(TestedEstimator);
152 };
153
154 class PacketProcessorRunner {
155  public:
156   explicit PacketProcessorRunner(PacketProcessor* processor)
157       : processor_(processor) {}
158
159   bool HasProcessor(const PacketProcessor* processor) const {
160     return processor == processor_;
161   }
162
163   void RunFor(int64_t time_ms, int64_t time_now_ms, Packets* in_out) {
164     Packets to_process;
165     FindPacketsToProcess(processor_->flow_ids(), in_out, &to_process);
166     processor_->RunFor(time_ms, &to_process);
167     QueuePackets(&to_process, time_now_ms * 1000);
168     if (!to_process.empty()) {
169       processor_->Plot((to_process.back().send_time_us() + 500) / 1000);
170     }
171     in_out->merge(to_process);
172   }
173
174  private:
175   void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in,
176                             Packets* out) {
177     assert(out->empty());
178     for (Packets::iterator it = in->begin(); it != in->end();) {
179       // TODO(holmer): Further optimize this by looking for consecutive flow ids
180       // in the packet list and only doing the binary search + splice once for a
181       // sequence.
182       if (std::binary_search(flow_ids.begin(), flow_ids.end(), it->flow_id())) {
183         Packets::iterator next = it;
184         ++next;
185         out->splice(out->end(), *in, it);
186         it = next;
187       } else {
188         ++it;
189       }
190     }
191   }
192
193   void QueuePackets(Packets* batch, int64_t end_of_batch_time_us) {
194     queue_.merge(*batch);
195     if (queue_.empty()) {
196       return;
197     }
198     Packets::iterator it = queue_.begin();
199     for (; it != queue_.end(); ++it) {
200       if (it->send_time_us() > end_of_batch_time_us) {
201         break;
202       }
203     }
204     Packets to_transfer;
205     to_transfer.splice(to_transfer.begin(), queue_, queue_.begin(), it);
206     batch->merge(to_transfer);
207   }
208
209   PacketProcessor* processor_;
210   Packets queue_;
211 };
212
213 BweTest::BweTest()
214     : run_time_ms_(0),
215       time_now_ms_(-1),
216       simulation_interval_ms_(-1),
217       estimators_(),
218       processors_() {
219 }
220
221 BweTest::~BweTest() {
222   BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
223   for (EstimatorMap::iterator it = estimators_.begin(); it != estimators_.end();
224       ++it) {
225     it->second->VerifyOrWriteBaseline();
226     it->second->LogStats();
227   }
228   BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
229
230   for (EstimatorMap::iterator it = estimators_.begin();
231        it != estimators_.end(); ++it) {
232     delete it->second;
233   }
234 }
235
236 void BweTest::SetupTestFromConfig(const BweTestConfig& config) {
237   const ::testing::TestInfo* const test_info =
238       ::testing::UnitTest::GetInstance()->current_test_info();
239   string test_name =
240       string(test_info->test_case_name()) + "_" + string(test_info->name());
241   BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name);
242   for (vector<BweTestConfig::EstimatorConfig>::const_iterator it =
243        config.estimator_configs.begin(); it != config.estimator_configs.end();
244        ++it) {
245     estimators_.insert(std::make_pair(it->flow_id, new TestedEstimator(
246         test_name, *it)));
247   }
248   BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
249 }
250
251 void BweTest::AddPacketProcessor(PacketProcessor* processor, bool is_sender) {
252   assert(processor);
253   processors_.push_back(PacketProcessorRunner(processor));
254   if (is_sender) {
255     senders_.push_back(static_cast<PacketSender*>(processor));
256   }
257   const FlowIds& flow_ids = processor->flow_ids();
258   for (size_t i = 0; i < flow_ids.size(); ++i) {
259     assert(estimators_.count(flow_ids[i]) == 1);
260   }
261 }
262
263 void BweTest::RemovePacketProcessor(
264     PacketProcessor* processor) {
265   for (vector<PacketProcessorRunner>::iterator it = processors_.begin();
266        it != processors_.end(); ++it) {
267     if (it->HasProcessor(processor)) {
268       processors_.erase(it);
269       return;
270     }
271   }
272   assert(false);
273 }
274
275 void BweTest::VerboseLogging(bool enable) {
276   BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
277 }
278
279 void BweTest::GiveFeedbackToAffectedSenders(int flow_id,
280                                             TestedEstimator* estimator) {
281   std::list<PacketSender*> affected_senders;
282   for (std::vector<PacketSender*>::iterator psit =
283        senders_.begin(); psit != senders_.end(); ++psit) {
284     const FlowIds& flow_ids = (*psit)->flow_ids();
285     if (std::binary_search(flow_ids.begin(), flow_ids.end(), flow_id)) {
286       affected_senders.push_back(*psit);
287     }
288   }
289   PacketSender::Feedback feedback = {0};
290   if (estimator->CheckEstimate(&feedback) && !affected_senders.empty()) {
291     // Allocate the bitrate evenly between the senders.
292     feedback.estimated_bps /= affected_senders.size();
293     for (std::list<PacketSender*>::iterator psit = affected_senders.begin();
294         psit != affected_senders.end(); ++psit) {
295       (*psit)->GiveFeedback(feedback);
296     }
297   }
298 }
299
300 void BweTest::RunFor(int64_t time_ms) {
301   // Set simulation interval from first packet sender.
302   // TODO(holmer): Support different feedback intervals for different flows.
303   if (!senders_.empty()) {
304     simulation_interval_ms_ = senders_[0]->GetFeedbackIntervalMs();
305   }
306   assert(simulation_interval_ms_ > 0);
307   if (time_now_ms_ == -1) {
308     time_now_ms_ = simulation_interval_ms_;
309   }
310   for (run_time_ms_ += time_ms;
311        time_now_ms_ <= run_time_ms_ - simulation_interval_ms_;
312        time_now_ms_ += simulation_interval_ms_) {
313     Packets packets;
314     for (vector<PacketProcessorRunner>::iterator it =
315          processors_.begin(); it != processors_.end(); ++it) {
316       it->RunFor(simulation_interval_ms_, time_now_ms_, &packets);
317     }
318
319     // Verify packets are in order between batches.
320     if (!packets.empty()) {
321       if (!previous_packets_.empty()) {
322         packets.splice(packets.begin(), previous_packets_,
323                        --previous_packets_.end());
324         ASSERT_TRUE(IsTimeSorted(packets));
325         packets.erase(packets.begin());
326       }
327       ASSERT_LE(packets.front().send_time_us(), time_now_ms_ * 1000);
328       ASSERT_LE(packets.back().send_time_us(), time_now_ms_ * 1000);
329     } else {
330       ASSERT_TRUE(IsTimeSorted(packets));
331     }
332
333     for (PacketsConstIt it = packets.begin(); it != packets.end(); ++it) {
334       EstimatorMap::iterator est_it = estimators_.find(it->flow_id());
335       ASSERT_TRUE(est_it != estimators_.end());
336       est_it->second->EatPacket(*it);
337     }
338
339     for (EstimatorMap::iterator est_it = estimators_.begin();
340          est_it != estimators_.end(); ++est_it) {
341       GiveFeedbackToAffectedSenders(est_it->first, est_it->second);
342     }
343   }
344 }
345
346 string BweTest::GetTestName() const {
347   const ::testing::TestInfo* const test_info =
348       ::testing::UnitTest::GetInstance()->current_test_info();
349   return string(test_info->name());
350 }
351 }  // namespace bwe
352 }  // namespace testing
353 }  // namespace webrtc