Home | History | Annotate | Download | only in video
      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 
     29 namespace webrtc {
     30 namespace {
     31 // Note: consider to write tests that don't depend on the trace system instead
     32 // of re-using this class.
     33 class 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 
    116 static const int kTOFExtensionId = 4;
    117 static const int kASTExtensionId = 5;
    118 
    119 class 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 
    258 TEST_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 
    269 TEST_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 
    283 TEST_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 
    302 TEST_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