1/*
2 *  Copyright (c) 2011 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#ifndef SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_
12#define SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_
13
14#include <deque>
15
16#include "webrtc/base/platform_thread.h"
17#include "webrtc/base/scoped_ptr.h"
18#include "webrtc/common_types.h"
19#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
20#include "webrtc/system_wrappers/include/atomic32.h"
21#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
22#include "webrtc/system_wrappers/include/event_wrapper.h"
23#include "webrtc/system_wrappers/include/sleep.h"
24#include "webrtc/voice_engine/test/auto_test/fixtures/before_initialization_fixture.h"
25
26class TestErrorObserver;
27
28class LoopBackTransport : public webrtc::Transport {
29 public:
30  LoopBackTransport(webrtc::VoENetwork* voe_network, int channel)
31      : crit_(webrtc::CriticalSectionWrapper::CreateCriticalSection()),
32        packet_event_(webrtc::EventWrapper::Create()),
33        thread_(NetworkProcess, this, "LoopBackTransport"),
34        channel_(channel),
35        voe_network_(voe_network),
36        transmitted_packets_(0) {
37    thread_.Start();
38  }
39
40  ~LoopBackTransport() { thread_.Stop(); }
41
42  bool SendRtp(const uint8_t* data,
43               size_t len,
44               const webrtc::PacketOptions& options) override {
45    StorePacket(Packet::Rtp, data, len);
46    return true;
47  }
48
49  bool SendRtcp(const uint8_t* data, size_t len) override {
50    StorePacket(Packet::Rtcp, data, len);
51    return true;
52  }
53
54  void WaitForTransmittedPackets(int32_t packet_count) {
55    enum {
56      kSleepIntervalMs = 10
57    };
58    int32_t limit = transmitted_packets_.Value() + packet_count;
59    while (transmitted_packets_.Value() < limit) {
60      webrtc::SleepMs(kSleepIntervalMs);
61    }
62  }
63
64  void AddChannel(uint32_t ssrc, int channel) {
65    webrtc::CriticalSectionScoped lock(crit_.get());
66    channels_[ssrc] = channel;
67  }
68
69 private:
70  struct Packet {
71    enum Type { Rtp, Rtcp, } type;
72
73    Packet() : len(0) {}
74    Packet(Type type, const void* data, size_t len)
75        : type(type), len(len) {
76      assert(len <= 1500);
77      memcpy(this->data, data, len);
78    }
79
80    uint8_t data[1500];
81    size_t len;
82  };
83
84  void StorePacket(Packet::Type type,
85                   const void* data,
86                   size_t len) {
87    {
88      webrtc::CriticalSectionScoped lock(crit_.get());
89      packet_queue_.push_back(Packet(type, data, len));
90    }
91    packet_event_->Set();
92  }
93
94  static bool NetworkProcess(void* transport) {
95    return static_cast<LoopBackTransport*>(transport)->SendPackets();
96  }
97
98  bool SendPackets() {
99    switch (packet_event_->Wait(10)) {
100      case webrtc::kEventSignaled:
101        break;
102      case webrtc::kEventTimeout:
103        break;
104      case webrtc::kEventError:
105        // TODO(pbos): Log a warning here?
106        return true;
107    }
108
109    while (true) {
110      Packet p;
111      int channel = channel_;
112      {
113        webrtc::CriticalSectionScoped lock(crit_.get());
114        if (packet_queue_.empty())
115          break;
116        p = packet_queue_.front();
117        packet_queue_.pop_front();
118
119        if (p.type == Packet::Rtp) {
120          uint32_t ssrc =
121              webrtc::ByteReader<uint32_t>::ReadBigEndian(&p.data[8]);
122          if (channels_[ssrc] != 0)
123            channel = channels_[ssrc];
124        }
125        // TODO(pbos): Add RTCP SSRC muxing/demuxing if anything requires it.
126      }
127
128      // Minimum RTP header size.
129      if (p.len < 12)
130        continue;
131
132      switch (p.type) {
133        case Packet::Rtp:
134          voe_network_->ReceivedRTPPacket(channel, p.data, p.len,
135                                          webrtc::PacketTime());
136          break;
137        case Packet::Rtcp:
138          voe_network_->ReceivedRTCPPacket(channel, p.data, p.len);
139          break;
140      }
141      ++transmitted_packets_;
142    }
143    return true;
144  }
145
146  const rtc::scoped_ptr<webrtc::CriticalSectionWrapper> crit_;
147  const rtc::scoped_ptr<webrtc::EventWrapper> packet_event_;
148  rtc::PlatformThread thread_;
149  std::deque<Packet> packet_queue_ GUARDED_BY(crit_.get());
150  const int channel_;
151  std::map<uint32_t, int> channels_ GUARDED_BY(crit_.get());
152  webrtc::VoENetwork* const voe_network_;
153  webrtc::Atomic32 transmitted_packets_;
154};
155
156// This fixture initializes the voice engine in addition to the work
157// done by the before-initialization fixture. It also registers an error
158// observer which will fail tests on error callbacks. This fixture is
159// useful to tests that want to run before we have started any form of
160// streaming through the voice engine.
161class AfterInitializationFixture : public BeforeInitializationFixture {
162 public:
163  AfterInitializationFixture();
164  virtual ~AfterInitializationFixture();
165
166 protected:
167  rtc::scoped_ptr<TestErrorObserver> error_observer_;
168};
169
170#endif  // SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_
171