| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_ |
| #define SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_ |
| |
| #include <deque> |
| #include <memory> |
| |
| #include "webrtc/common_types.h" |
| #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| #include "webrtc/rtc_base/criticalsection.h" |
| #include "webrtc/rtc_base/platform_thread.h" |
| #include "webrtc/system_wrappers/include/atomic32.h" |
| #include "webrtc/system_wrappers/include/event_wrapper.h" |
| #include "webrtc/system_wrappers/include/sleep.h" |
| #include "webrtc/voice_engine/test/auto_test/fixtures/before_initialization_fixture.h" |
| |
| class TestErrorObserver; |
| |
| class LoopBackTransport : public webrtc::Transport { |
| public: |
| LoopBackTransport(webrtc::VoENetwork* voe_network, int channel) |
| : packet_event_(webrtc::EventWrapper::Create()), |
| thread_(NetworkProcess, this, "LoopBackTransport"), |
| channel_(channel), |
| voe_network_(voe_network), |
| transmitted_packets_(0) { |
| thread_.Start(); |
| } |
| |
| ~LoopBackTransport() { thread_.Stop(); } |
| |
| bool SendRtp(const uint8_t* data, |
| size_t len, |
| const webrtc::PacketOptions& options) override { |
| StorePacket(Packet::Rtp, data, len); |
| return true; |
| } |
| |
| bool SendRtcp(const uint8_t* data, size_t len) override { |
| StorePacket(Packet::Rtcp, data, len); |
| return true; |
| } |
| |
| void WaitForTransmittedPackets(int32_t packet_count) { |
| enum { |
| kSleepIntervalMs = 10 |
| }; |
| int32_t limit = transmitted_packets_.Value() + packet_count; |
| while (transmitted_packets_.Value() < limit) { |
| webrtc::SleepMs(kSleepIntervalMs); |
| } |
| } |
| |
| void AddChannel(uint32_t ssrc, int channel) { |
| rtc::CritScope lock(&crit_); |
| channels_[ssrc] = channel; |
| } |
| |
| private: |
| struct Packet { |
| enum Type { Rtp, Rtcp, } type; |
| |
| Packet() : len(0) {} |
| Packet(Type type, const void* data, size_t len) |
| : type(type), len(len) { |
| assert(len <= 1500); |
| memcpy(this->data, data, len); |
| } |
| |
| uint8_t data[1500]; |
| size_t len; |
| }; |
| |
| void StorePacket(Packet::Type type, |
| const void* data, |
| size_t len) { |
| { |
| rtc::CritScope lock(&crit_); |
| packet_queue_.push_back(Packet(type, data, len)); |
| } |
| packet_event_->Set(); |
| } |
| |
| static bool NetworkProcess(void* transport) { |
| return static_cast<LoopBackTransport*>(transport)->SendPackets(); |
| } |
| |
| bool SendPackets() { |
| switch (packet_event_->Wait(10)) { |
| case webrtc::kEventSignaled: |
| break; |
| case webrtc::kEventTimeout: |
| break; |
| case webrtc::kEventError: |
| // TODO(pbos): Log a warning here? |
| return true; |
| } |
| |
| while (true) { |
| Packet p; |
| int channel = channel_; |
| { |
| rtc::CritScope lock(&crit_); |
| if (packet_queue_.empty()) |
| break; |
| p = packet_queue_.front(); |
| packet_queue_.pop_front(); |
| |
| if (p.type == Packet::Rtp) { |
| uint32_t ssrc = |
| webrtc::ByteReader<uint32_t>::ReadBigEndian(&p.data[8]); |
| if (channels_[ssrc] != 0) |
| channel = channels_[ssrc]; |
| } |
| // TODO(pbos): Add RTCP SSRC muxing/demuxing if anything requires it. |
| } |
| |
| // Minimum RTP header size. |
| if (p.len < 12) |
| continue; |
| |
| switch (p.type) { |
| case Packet::Rtp: |
| voe_network_->ReceivedRTPPacket(channel, p.data, p.len, |
| webrtc::PacketTime()); |
| break; |
| case Packet::Rtcp: |
| voe_network_->ReceivedRTCPPacket(channel, p.data, p.len); |
| break; |
| } |
| ++transmitted_packets_; |
| } |
| return true; |
| } |
| |
| rtc::CriticalSection crit_; |
| const std::unique_ptr<webrtc::EventWrapper> packet_event_; |
| rtc::PlatformThread thread_; |
| std::deque<Packet> packet_queue_ GUARDED_BY(crit_); |
| const int channel_; |
| std::map<uint32_t, int> channels_ GUARDED_BY(crit_); |
| webrtc::VoENetwork* const voe_network_; |
| webrtc::Atomic32 transmitted_packets_; |
| }; |
| |
| // This fixture initializes the voice engine in addition to the work |
| // done by the before-initialization fixture. It also registers an error |
| // observer which will fail tests on error callbacks. This fixture is |
| // useful to tests that want to run before we have started any form of |
| // streaming through the voice engine. |
| class AfterInitializationFixture : public BeforeInitializationFixture { |
| public: |
| AfterInitializationFixture(); |
| virtual ~AfterInitializationFixture(); |
| |
| protected: |
| std::unique_ptr<TestErrorObserver> error_observer_; |
| }; |
| |
| #endif // SRC_VOICE_ENGINE_MAIN_TEST_AUTO_TEST_STANDARD_TEST_BASE_AFTER_INIT_H_ |