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#include <functional>
11#include <list>
12#include <string>
13
14#include "testing/gtest/include/gtest/gtest.h"
15
16#include "webrtc/base/thread_annotations.h"
17#include "webrtc/call.h"
18#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/interface/event_wrapper.h"
20#include "webrtc/system_wrappers/interface/scoped_ptr.h"
21#include "webrtc/system_wrappers/interface/trace.h"
22#include "webrtc/test/call_test.h"
23#include "webrtc/test/direct_transport.h"
24#include "webrtc/test/encoder_settings.h"
25#include "webrtc/test/fake_decoder.h"
26#include "webrtc/test/fake_encoder.h"
27#include "webrtc/test/frame_generator_capturer.h"
28
29namespace webrtc {
30namespace {
31// Note: consider to write tests that don't depend on the trace system instead
32// of re-using this class.
33class TraceObserver {
34 public:
35  TraceObserver() {
36    Trace::set_level_filter(kTraceTerseInfo);
37
38    Trace::CreateTrace();
39    Trace::SetTraceCallback(&callback_);
40
41    // Call webrtc trace to initialize the tracer that would otherwise trigger a
42    // data-race if left to be initialized by multiple threads (i.e. threads
43    // spawned by test::DirectTransport members in BitrateEstimatorTest).
44    WEBRTC_TRACE(kTraceStateInfo,
45                 kTraceUtility,
46                 -1,
47                 "Instantiate without data races.");
48  }
49
50  ~TraceObserver() {
51    Trace::SetTraceCallback(NULL);
52    Trace::ReturnTrace();
53  }
54
55  void PushExpectedLogLine(const std::string& expected_log_line) {
56    callback_.PushExpectedLogLine(expected_log_line);
57  }
58
59  EventTypeWrapper Wait() {
60    return callback_.Wait();
61  }
62
63 private:
64  class Callback : public TraceCallback {
65   public:
66    Callback()
67        : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
68          done_(EventWrapper::Create()) {}
69
70    virtual void Print(TraceLevel level,
71                       const char* message,
72                       int length) OVERRIDE {
73      CriticalSectionScoped lock(crit_sect_.get());
74      std::string msg(message);
75      if (msg.find("BitrateEstimator") != std::string::npos) {
76        received_log_lines_.push_back(msg);
77      }
78      int num_popped = 0;
79      while (!received_log_lines_.empty() && !expected_log_lines_.empty()) {
80        std::string a = received_log_lines_.front();
81        std::string b = expected_log_lines_.front();
82        received_log_lines_.pop_front();
83        expected_log_lines_.pop_front();
84        num_popped++;
85        EXPECT_TRUE(a.find(b) != std::string::npos);
86      }
87      if (expected_log_lines_.size() <= 0) {
88        if (num_popped > 0) {
89          done_->Set();
90        }
91        return;
92      }
93    }
94
95    EventTypeWrapper Wait() {
96      return done_->Wait(test::CallTest::kDefaultTimeoutMs);
97    }
98
99    void PushExpectedLogLine(const std::string& expected_log_line) {
100      CriticalSectionScoped lock(crit_sect_.get());
101      expected_log_lines_.push_back(expected_log_line);
102    }
103
104   private:
105    typedef std::list<std::string> Strings;
106    const scoped_ptr<CriticalSectionWrapper> crit_sect_;
107    Strings received_log_lines_ GUARDED_BY(crit_sect_);
108    Strings expected_log_lines_ GUARDED_BY(crit_sect_);
109    scoped_ptr<EventWrapper> done_;
110  };
111
112  Callback callback_;
113};
114}  // namespace
115
116static const int kTOFExtensionId = 4;
117static const int kASTExtensionId = 5;
118
119class BitrateEstimatorTest : public test::CallTest {
120 public:
121  BitrateEstimatorTest()
122      : receiver_trace_(),
123        send_transport_(),
124        receive_transport_(),
125        sender_call_(),
126        receiver_call_(),
127        receive_config_(),
128        streams_() {
129  }
130
131  virtual ~BitrateEstimatorTest() {
132    EXPECT_TRUE(streams_.empty());
133  }
134
135  virtual void SetUp() {
136    Call::Config receiver_call_config(&receive_transport_);
137    receiver_call_.reset(Call::Create(receiver_call_config));
138
139    Call::Config sender_call_config(&send_transport_);
140    sender_call_.reset(Call::Create(sender_call_config));
141
142    send_transport_.SetReceiver(receiver_call_->Receiver());
143    receive_transport_.SetReceiver(sender_call_->Receiver());
144
145    send_config_ = VideoSendStream::Config();
146    send_config_.rtp.ssrcs.push_back(kSendSsrcs[0]);
147    // Encoders will be set separately per stream.
148    send_config_.encoder_settings.encoder = NULL;
149    send_config_.encoder_settings.payload_name = "FAKE";
150    send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
151    encoder_config_.streams = test::CreateVideoStreams(1);
152
153    receive_config_ = VideoReceiveStream::Config();
154    assert(receive_config_.codecs.empty());
155    VideoCodec codec =
156        test::CreateDecoderVideoCodec(send_config_.encoder_settings);
157    receive_config_.codecs.push_back(codec);
158    // receive_config_.external_decoders will be set by every stream separately.
159    receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
160    receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
161    receive_config_.rtp.extensions.push_back(
162        RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
163    receive_config_.rtp.extensions.push_back(
164        RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
165  }
166
167  virtual void TearDown() {
168    std::for_each(streams_.begin(), streams_.end(),
169        std::mem_fun(&Stream::StopSending));
170
171    send_transport_.StopSending();
172    receive_transport_.StopSending();
173
174    while (!streams_.empty()) {
175      delete streams_.back();
176      streams_.pop_back();
177    }
178
179    receiver_call_.reset();
180  }
181
182 protected:
183  friend class Stream;
184
185  class Stream {
186   public:
187    explicit Stream(BitrateEstimatorTest* test)
188        : test_(test),
189          is_sending_receiving_(false),
190          send_stream_(NULL),
191          receive_stream_(NULL),
192          frame_generator_capturer_(),
193          fake_encoder_(Clock::GetRealTimeClock()),
194          fake_decoder_() {
195      test_->send_config_.rtp.ssrcs[0]++;
196      test_->send_config_.encoder_settings.encoder = &fake_encoder_;
197      send_stream_ = test_->sender_call_->CreateVideoSendStream(
198          test_->send_config_, test_->encoder_config_);
199      assert(test_->encoder_config_.streams.size() == 1);
200      frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
201          send_stream_->Input(),
202          test_->encoder_config_.streams[0].width,
203          test_->encoder_config_.streams[0].height,
204          30,
205          Clock::GetRealTimeClock()));
206      send_stream_->Start();
207      frame_generator_capturer_->Start();
208
209      ExternalVideoDecoder decoder;
210      decoder.decoder = &fake_decoder_;
211      decoder.payload_type = test_->send_config_.encoder_settings.payload_type;
212      test_->receive_config_.rtp.remote_ssrc = test_->send_config_.rtp.ssrcs[0];
213      test_->receive_config_.rtp.local_ssrc++;
214      test_->receive_config_.external_decoders.push_back(decoder);
215      receive_stream_ = test_->receiver_call_->CreateVideoReceiveStream(
216          test_->receive_config_);
217      receive_stream_->Start();
218
219      is_sending_receiving_ = true;
220    }
221
222    ~Stream() {
223      frame_generator_capturer_.reset(NULL);
224      test_->sender_call_->DestroyVideoSendStream(send_stream_);
225      send_stream_ = NULL;
226      test_->receiver_call_->DestroyVideoReceiveStream(receive_stream_);
227      receive_stream_ = NULL;
228    }
229
230    void StopSending() {
231      if (is_sending_receiving_) {
232        frame_generator_capturer_->Stop();
233        send_stream_->Stop();
234        receive_stream_->Stop();
235        is_sending_receiving_ = false;
236      }
237    }
238
239   private:
240    BitrateEstimatorTest* test_;
241    bool is_sending_receiving_;
242    VideoSendStream* send_stream_;
243    VideoReceiveStream* receive_stream_;
244    scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
245    test::FakeEncoder fake_encoder_;
246    test::FakeDecoder fake_decoder_;
247  };
248
249  TraceObserver receiver_trace_;
250  test::DirectTransport send_transport_;
251  test::DirectTransport receive_transport_;
252  scoped_ptr<Call> sender_call_;
253  scoped_ptr<Call> receiver_call_;
254  VideoReceiveStream::Config receive_config_;
255  std::vector<Stream*> streams_;
256};
257
258TEST_F(BitrateEstimatorTest, InstantiatesTOFPerDefault) {
259  send_config_.rtp.extensions.push_back(
260      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
261  receiver_trace_.PushExpectedLogLine(
262      "RemoteBitrateEstimatorFactory: Instantiating.");
263  receiver_trace_.PushExpectedLogLine(
264      "RemoteBitrateEstimatorFactory: Instantiating.");
265  streams_.push_back(new Stream(this));
266  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
267}
268
269TEST_F(BitrateEstimatorTest, ImmediatelySwitchToAST) {
270  send_config_.rtp.extensions.push_back(
271      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId));
272  receiver_trace_.PushExpectedLogLine(
273      "RemoteBitrateEstimatorFactory: Instantiating.");
274  receiver_trace_.PushExpectedLogLine(
275      "RemoteBitrateEstimatorFactory: Instantiating.");
276  receiver_trace_.PushExpectedLogLine("Switching to absolute send time RBE.");
277  receiver_trace_.PushExpectedLogLine(
278      "AbsoluteSendTimeRemoteBitrateEstimatorFactory: Instantiating.");
279  streams_.push_back(new Stream(this));
280  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
281}
282
283TEST_F(BitrateEstimatorTest, SwitchesToAST) {
284  send_config_.rtp.extensions.push_back(
285      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
286  receiver_trace_.PushExpectedLogLine(
287      "RemoteBitrateEstimatorFactory: Instantiating.");
288  receiver_trace_.PushExpectedLogLine(
289      "RemoteBitrateEstimatorFactory: Instantiating.");
290  streams_.push_back(new Stream(this));
291  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
292
293  send_config_.rtp.extensions[0] =
294      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
295  receiver_trace_.PushExpectedLogLine("Switching to absolute send time RBE.");
296  receiver_trace_.PushExpectedLogLine(
297      "AbsoluteSendTimeRemoteBitrateEstimatorFactory: Instantiating.");
298  streams_.push_back(new Stream(this));
299  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
300}
301
302TEST_F(BitrateEstimatorTest, SwitchesToASTThenBackToTOF) {
303  send_config_.rtp.extensions.push_back(
304      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId));
305  receiver_trace_.PushExpectedLogLine(
306      "RemoteBitrateEstimatorFactory: Instantiating.");
307  receiver_trace_.PushExpectedLogLine(
308      "RemoteBitrateEstimatorFactory: Instantiating.");
309  streams_.push_back(new Stream(this));
310  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
311
312  send_config_.rtp.extensions[0] =
313      RtpExtension(RtpExtension::kAbsSendTime, kASTExtensionId);
314  receiver_trace_.PushExpectedLogLine("Switching to absolute send time RBE.");
315  receiver_trace_.PushExpectedLogLine(
316      "AbsoluteSendTimeRemoteBitrateEstimatorFactory: Instantiating.");
317  streams_.push_back(new Stream(this));
318  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
319
320  send_config_.rtp.extensions[0] =
321      RtpExtension(RtpExtension::kTOffset, kTOFExtensionId);
322  receiver_trace_.PushExpectedLogLine(
323      "WrappingBitrateEstimator: Switching to transmission time offset RBE.");
324  receiver_trace_.PushExpectedLogLine(
325      "RemoteBitrateEstimatorFactory: Instantiating.");
326  streams_.push_back(new Stream(this));
327  streams_[0]->StopSending();
328  streams_[1]->StopSending();
329  EXPECT_EQ(kEventSignaled, receiver_trace_.Wait());
330}
331}  // namespace webrtc
332