1f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org/* 2f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * 4f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * Use of this source code is governed by a BSD-style license 5f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * that can be found in the LICENSE file in the root of the source 6f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * tree. An additional intellectual property rights grant can be found 7f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * in the file PATENTS. All contributing project authors may 8f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org */ 10f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include <assert.h> 11f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 12f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include <algorithm> 13f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include <sstream> 14f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include <string> 15f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 16f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "testing/gtest/include/gtest/gtest.h" 17f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 18d54aa969545bd9c5ccc0077dd6645e742bf11418pbos@webrtc.org#include "webrtc/base/thread_annotations.h" 19f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/call.h" 2070e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" 21f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 22f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 23f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 24d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org#include "webrtc/system_wrappers/interface/rtp_to_ntp.h" 25f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h" 26eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org#include "webrtc/test/call_test.h" 27f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/direct_transport.h" 28e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org#include "webrtc/test/encoder_settings.h" 29f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/fake_audio_device.h" 30f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/fake_decoder.h" 31f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/fake_encoder.h" 32f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/frame_generator.h" 33f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/frame_generator_capturer.h" 34f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/rtp_rtcp_observer.h" 35f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/testsupport/fileutils.h" 36f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/test/testsupport/perf_test.h" 37f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/video/transport_adapter.h" 38f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/voice_engine/include/voe_base.h" 39f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/voice_engine/include/voe_codec.h" 40f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/voice_engine/include/voe_network.h" 41f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" 42f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org#include "webrtc/voice_engine/include/voe_video_sync.h" 43f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 44f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.orgnamespace webrtc { 45f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 46eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgclass CallPerfTest : public test::CallTest { 478ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org protected: 48d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org void TestAudioVideoSync(bool fec); 49d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org 503f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org void TestMinTransmitBitrate(bool pad_to_min_bitrate); 513f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 52093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 53093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org int threshold_ms, 54093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org int start_time_ms, 55093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org int run_time_ms); 56f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org}; 57f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 58f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.orgclass SyncRtcpObserver : public test::RtpRtcpObserver { 59f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org public: 60aacdb9f6eed4ceedc8db73865384e29444abcda2stefan@webrtc.org explicit SyncRtcpObserver(const FakeNetworkPipe::Config& config) 61eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs, config), 62c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org crit_(CriticalSectionWrapper::CreateCriticalSection()) {} 63f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 64f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE { 65f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org RTCPUtility::RTCPParserV2 parser(packet, length, true); 66f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_TRUE(parser.IsValid()); 67f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 68f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin(); 69f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org packet_type != RTCPUtility::kRtcpNotValidCode; 70f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org packet_type = parser.Iterate()) { 71f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (packet_type == RTCPUtility::kRtcpSrCode) { 72f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org const RTCPUtility::RTCPPacket& packet = parser.Packet(); 73d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org RtcpMeasurement ntp_rtp_pair( 74f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org packet.SR.NTPMostSignificant, 75f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org packet.SR.NTPLeastSignificant, 76f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org packet.SR.RTPTimestamp); 77f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org StoreNtpRtpPair(ntp_rtp_pair); 78f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 79f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 80f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return SEND_PACKET; 81f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 82f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 83f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t RtpTimestampToNtp(uint32_t timestamp) const { 84c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org CriticalSectionScoped lock(crit_.get()); 85f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t timestamp_in_ms = -1; 86f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (ntp_rtp_pairs_.size() == 2) { 87f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the 88f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // RTCP sender where it sends RTCP SR before any RTP packets, which leads 89f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // to a bogus NTP/RTP mapping. 90d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org RtpToNtpMs(timestamp, ntp_rtp_pairs_, ×tamp_in_ms); 91f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return timestamp_in_ms; 92f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 93f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return -1; 94f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 95f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 96f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org private: 97d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org void StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair) { 98c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org CriticalSectionScoped lock(crit_.get()); 99d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org for (RtcpList::iterator it = ntp_rtp_pairs_.begin(); 100f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org it != ntp_rtp_pairs_.end(); 101f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ++it) { 102f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (ntp_rtp_pair.ntp_secs == it->ntp_secs && 103f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ntp_rtp_pair.ntp_frac == it->ntp_frac) { 104f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // This RTCP has already been added to the list. 105f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return; 106f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 107f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 108f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // We need two RTCP SR reports to map between RTP and NTP. More than two 109f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // will not improve the mapping. 110f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (ntp_rtp_pairs_.size() == 2) { 111f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ntp_rtp_pairs_.pop_back(); 112f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 113f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ntp_rtp_pairs_.push_front(ntp_rtp_pair); 114f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 115f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 116c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org const scoped_ptr<CriticalSectionWrapper> crit_; 117d2fb259b3bc61c68f368929510215a7ee7d00fdawu@webrtc.org RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_); 118f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org}; 119f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 120f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.orgclass VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer { 121f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org static const int kInSyncThresholdMs = 50; 122f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org static const int kStartupTimeMs = 2000; 123f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org static const int kMinRunTimeMs = 30000; 124f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 125f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org public: 126f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VideoRtcpAndSyncObserver(Clock* clock, 127f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int voe_channel, 128f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoEVideoSync* voe_sync, 1296cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org SyncRtcpObserver* audio_observer) 130aacdb9f6eed4ceedc8db73865384e29444abcda2stefan@webrtc.org : SyncRtcpObserver(FakeNetworkPipe::Config()), 131f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org clock_(clock), 132f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_channel_(voe_channel), 133f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_sync_(voe_sync), 134f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org audio_observer_(audio_observer), 135f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org creation_time_ms_(clock_->TimeInMilliseconds()), 1366cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org first_time_in_sync_(-1) {} 137f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 138f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org virtual void RenderFrame(const I420VideoFrame& video_frame, 139f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int time_to_render_ms) OVERRIDE { 140f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t now_ms = clock_->TimeInMilliseconds(); 141f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org uint32_t playout_timestamp = 0; 142f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0) 143f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return; 144f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t latest_audio_ntp = 145f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org audio_observer_->RtpTimestampToNtp(playout_timestamp); 146f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp()); 147f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (latest_audio_ntp < 0 || latest_video_ntp < 0) 148f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return; 149f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int time_until_render_ms = 150f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms)); 151f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org latest_video_ntp += time_until_render_ms; 152f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t stream_offset = latest_audio_ntp - latest_video_ntp; 153f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org std::stringstream ss; 154f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ss << stream_offset; 15570e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org webrtc::test::PrintResult("stream_offset", 1566cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org "", 15770e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org "synchronization", 15870e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org ss.str(), 15970e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org "ms", 16070e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org false); 161f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t time_since_creation = now_ms - creation_time_ms_; 162f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // During the first couple of seconds audio and video can falsely be 163f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org // estimated as being synchronized. We don't want to trigger on those. 164f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (time_since_creation < kStartupTimeMs) 165f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org return; 1662a25b6c685c7d6323a8fdaf514a7b36f4f2d827dpbos@webrtc.org if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) { 167f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (first_time_in_sync_ == -1) { 168f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org first_time_in_sync_ = now_ms; 169f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org webrtc::test::PrintResult("sync_convergence_time", 1706cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org "", 171f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org "synchronization", 172f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org time_since_creation, 173f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org "ms", 174f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org false); 175f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 176f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org if (time_since_creation > kMinRunTimeMs) 177f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org observation_complete_->Set(); 178f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 179f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org } 180f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 181f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org private: 182c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org Clock* const clock_; 183f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int voe_channel_; 184f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoEVideoSync* voe_sync_; 185f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org SyncRtcpObserver* audio_observer_; 186f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t creation_time_ms_; 187f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org int64_t first_time_in_sync_; 188f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org}; 189f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 190d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.orgvoid CallPerfTest::TestAudioVideoSync(bool fec) { 191eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org class AudioPacketReceiver : public PacketReceiver { 192eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org public: 193eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org AudioPacketReceiver(int channel, VoENetwork* voe_network) 194eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org : channel_(channel), 195eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org voe_network_(voe_network), 196eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org parser_(RtpHeaderParser::Create()) {} 197eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual DeliveryStatus DeliverPacket(const uint8_t* packet, 198eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org size_t length) OVERRIDE { 199eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int ret; 200eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (parser_->IsRtcp(packet, static_cast<int>(length))) { 201eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org ret = voe_network_->ReceivedRTCPPacket( 202eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org channel_, packet, static_cast<unsigned int>(length)); 203eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } else { 204eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org ret = voe_network_->ReceivedRTPPacket( 205eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org channel_, packet, static_cast<unsigned int>(length), PacketTime()); 206eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 207eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR; 208eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 209eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 210eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org private: 211eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int channel_; 212eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org VoENetwork* voe_network_; 213eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org scoped_ptr<RtpHeaderParser> parser_; 214eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org }; 215eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 216f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoiceEngine* voice_engine = VoiceEngine::Create(); 217f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoEBase* voe_base = VoEBase::GetInterface(voice_engine); 218f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoECodec* voe_codec = VoECodec::GetInterface(voice_engine); 219f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine); 220f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine); 221f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org const std::string audio_filename = 222f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org test::ResourcePath("voice_engine/audio_long16", "pcm"); 223f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org ASSERT_STRNE("", audio_filename.c_str()); 224f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(), 225f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org audio_filename); 226f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL)); 2276cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org int channel = voe_base->CreateChannel(); 228f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 229aacdb9f6eed4ceedc8db73865384e29444abcda2stefan@webrtc.org FakeNetworkPipe::Config net_config; 230aacdb9f6eed4ceedc8db73865384e29444abcda2stefan@webrtc.org net_config.queue_delay_ms = 500; 231d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org net_config.loss_percent = 5; 232aacdb9f6eed4ceedc8db73865384e29444abcda2stefan@webrtc.org SyncRtcpObserver audio_observer(net_config); 23370e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), 23470e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org channel, 23570e2ce90d527388f9829a7d084dfa3b2a525bb49henrik.lundin@webrtc.org voe_sync, 2366cee2bafdd7b97c6b3893d67690ed2e37ada6ef1henrik.lundin@webrtc.org &audio_observer); 237f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 238f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org Call::Config receiver_config(observer.ReceiveTransport()); 239f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org receiver_config.voice_engine = voice_engine; 240eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CreateCalls(Call::Config(observer.SendTransport()), receiver_config); 241eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 242f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000}; 243f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac)); 244f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 245eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org AudioPacketReceiver voe_packet_receiver(channel, voe_network); 246f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver); 247f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 248f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org internal::TransportAdapter transport_adapter(audio_observer.SendTransport()); 2490a298154b3a4781f0294d3877f77feb58e33eeb7sprang@webrtc.org transport_adapter.Enable(); 250f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, 251f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_network->RegisterExternalTransport(channel, transport_adapter)); 252f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 253eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver()); 254f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 255f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org test::FakeDecoder fake_decoder; 256f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 257eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CreateSendConfig(1); 258eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CreateMatchingReceiveConfigs(); 259eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 260d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; 261d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org if (fec) { 262d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org send_config_.rtp.fec.red_payload_type = kRedPayloadType; 263d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; 264d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org receive_configs_[0].rtp.fec.red_payload_type = kRedPayloadType; 265d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org receive_configs_[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; 266d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org } 267d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org receive_configs_[0].rtp.nack.rtp_history_ms = 1000; 26888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org receive_configs_[0].renderer = &observer; 26988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org receive_configs_[0].audio_channel_id = channel; 270eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 271eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CreateStreams(); 272eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 273eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CreateFrameGeneratorCapturer(); 274eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 275eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org Start(); 276f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 277f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org fake_audio_device.Start(); 278f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StartPlayout(channel)); 279f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StartReceive(channel)); 280f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StartSend(channel)); 281f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 282f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(kEventSignaled, observer.Wait()) 283f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org << "Timed out while waiting for audio and video to be synchronized."; 284f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 285f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StopSend(channel)); 286f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StopReceive(channel)); 287f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org EXPECT_EQ(0, voe_base->StopPlayout(channel)); 288f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org fake_audio_device.Stop(); 289f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 290eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org Stop(); 291f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org observer.StopSending(); 292f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org audio_observer.StopSending(); 293f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org 294f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_base->DeleteChannel(channel); 295f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_base->Release(); 296f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_codec->Release(); 297f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_network->Release(); 298f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org voe_sync->Release(); 2998ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org 300eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org DestroyStreams(); 301093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 302eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org VoiceEngine::Delete(voice_engine); 303eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org} 304093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 305d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.orgTEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) { 306d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org TestAudioVideoSync(false); 307d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org} 308d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org 309d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.orgTEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithFec) { 310d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org TestAudioVideoSync(true); 311d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org} 312d01c49138f5c9c49c86251094f72759ee2c4705fstefan@webrtc.org 313eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgvoid CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 314eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int threshold_ms, 315eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int start_time_ms, 316eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int run_time_ms) { 317eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org class CaptureNtpTimeObserver : public test::EndToEndTest, 318eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org public VideoRenderer { 319eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org public: 320eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org CaptureNtpTimeObserver(const FakeNetworkPipe::Config& config, 321eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int threshold_ms, 322eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int start_time_ms, 323eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int run_time_ms) 324eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org : EndToEndTest(kLongTimeoutMs, config), 325eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org clock_(Clock::GetRealTimeClock()), 326eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org threshold_ms_(threshold_ms), 327eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org start_time_ms_(start_time_ms), 328eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org run_time_ms_(run_time_ms), 329eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org creation_time_ms_(clock_->TimeInMilliseconds()), 330eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org capturer_(NULL), 331eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org rtp_start_timestamp_set_(false), 332eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org rtp_start_timestamp_(0) {} 333093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 334eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org private: 335eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void RenderFrame(const I420VideoFrame& video_frame, 336eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int time_to_render_ms) OVERRIDE { 337eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (video_frame.ntp_time_ms() <= 0) { 338eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // Haven't got enough RTCP SR in order to calculate the capture ntp 339eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // time. 340eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org return; 341eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 342093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 343eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int64_t now_ms = clock_->TimeInMilliseconds(); 344eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int64_t time_since_creation = now_ms - creation_time_ms_; 345eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (time_since_creation < start_time_ms_) { 346eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // Wait for |start_time_ms_| before start measuring. 347eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org return; 348eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 349093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 350eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (time_since_creation > run_time_ms_) { 351eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org observation_complete_->Set(); 352eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 353093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 354eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org FrameCaptureTimeList::iterator iter = 355eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org capture_time_list_.find(video_frame.timestamp()); 356eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org EXPECT_TRUE(iter != capture_time_list_.end()); 357eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 358eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // The real capture time has been wrapped to uint32_t before converted 359eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // to rtp timestamp in the sender side. So here we convert the estimated 360eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // capture time to a uint32_t 90k timestamp also for comparing. 361eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org uint32_t estimated_capture_timestamp = 362eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); 363eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org uint32_t real_capture_timestamp = iter->second; 364eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; 365eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org time_offset_ms = time_offset_ms / 90; 366eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org std::stringstream ss; 367eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org ss << time_offset_ms; 368eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 369eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org webrtc::test::PrintResult( 370eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true); 371eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); 372093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org } 373093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 374eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual Action OnSendRtp(const uint8_t* packet, size_t length) { 375eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org RTPHeader header; 3766aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org EXPECT_TRUE(parser_->Parse(packet, length, &header)); 377eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 378eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (!rtp_start_timestamp_set_) { 379eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // Calculate the rtp timestamp offset in order to calculate the real 380eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // capture time. 381eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org uint32_t first_capture_timestamp = 382eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time()); 383eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org rtp_start_timestamp_ = header.timestamp - first_capture_timestamp; 384eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org rtp_start_timestamp_set_ = true; 385eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 386093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 387eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_; 388eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org capture_time_list_.insert( 389eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org capture_time_list_.end(), 390eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org std::make_pair(header.timestamp, capture_timestamp)); 391eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org return SEND_PACKET; 392eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 393093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 394eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void OnFrameGeneratorCapturerCreated( 395eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org test::FrameGeneratorCapturer* frame_generator_capturer) OVERRIDE { 396eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org capturer_ = frame_generator_capturer; 397eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 398093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 399eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void ModifyConfigs( 400eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org VideoSendStream::Config* send_config, 40188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org std::vector<VideoReceiveStream::Config>* receive_configs, 40258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org VideoEncoderConfig* encoder_config) OVERRIDE { 40388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org (*receive_configs)[0].renderer = this; 404eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org // Enable the receiver side rtt calculation. 40588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; 406eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 407093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 408eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void PerformTest() OVERRIDE { 409eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for " 410eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org "estimated capture NTP time to be " 411eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org "within bounds."; 412eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 413093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 414eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org Clock* clock_; 415eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int threshold_ms_; 416eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int start_time_ms_; 417eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int run_time_ms_; 418eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org int64_t creation_time_ms_; 419eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org test::FrameGeneratorCapturer* capturer_; 420eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org bool rtp_start_timestamp_set_; 421eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org uint32_t rtp_start_timestamp_; 422eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; 423eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org FrameCaptureTimeList capture_time_list_; 424eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } test(net_config, threshold_ms, start_time_ms, run_time_ms); 425eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 426eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org RunBaseTest(&test); 427093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org} 428093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 4291ef9cee4e53d42bec5761fdae0d963b163ba17aawu@webrtc.orgTEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { 430093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org FakeNetworkPipe::Config net_config; 431093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org net_config.queue_delay_ms = 100; 432093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org // TODO(wu): lower the threshold as the calculation/estimatation becomes more 433093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org // accurate. 4341ef9cee4e53d42bec5761fdae0d963b163ba17aawu@webrtc.org const int kThresholdMs = 100; 435093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org const int kStartTimeMs = 10000; 436093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org const int kRunTimeMs = 20000; 437093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 438093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org} 439093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 4401cbc360c03fcad0ebed910d371530f48cb11951fwu@webrtc.orgTEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) { 441093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org FakeNetworkPipe::Config net_config; 4421cbc360c03fcad0ebed910d371530f48cb11951fwu@webrtc.org net_config.queue_delay_ms = 100; 443093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org net_config.delay_standard_deviation_ms = 10; 444093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org // TODO(wu): lower the threshold as the calculation/estimatation becomes more 445093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org // accurate. 4461cbc360c03fcad0ebed910d371530f48cb11951fwu@webrtc.org const int kThresholdMs = 100; 447093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org const int kStartTimeMs = 10000; 448093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org const int kRunTimeMs = 20000; 449093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 450093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org} 451093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org 4528ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.orgTEST_F(CallPerfTest, RegisterCpuOveruseObserver) { 4538ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org // Verifies that either a normal or overuse callback is triggered. 454eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org class OveruseCallbackObserver : public test::SendTest, 4558ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org public webrtc::OveruseCallback { 4568ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org public: 457eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org OveruseCallbackObserver() : SendTest(kLongTimeoutMs) {} 4588ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org 4598ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org virtual void OnOveruse() OVERRIDE { 4608ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org observation_complete_->Set(); 4618ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org } 462eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 4638ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org virtual void OnNormalUse() OVERRIDE { 4648ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org observation_complete_->Set(); 4658ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org } 4668ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org 467eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual Call::Config GetSenderCallConfig() OVERRIDE { 468eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org Call::Config config(SendTransport()); 469eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org config.overuse_callback = this; 470eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org return config; 471eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 472eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 473eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void PerformTest() OVERRIDE { 474eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org EXPECT_EQ(kEventSignaled, Wait()) 475eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org << "Timed out before receiving an overuse callback."; 476eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 477eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } test; 4788ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org 479eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org RunBaseTest(&test); 4808ef65486bf136f11d8dc9c637f94d7c08b687120asapersson@webrtc.org} 4813f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 4823f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.orgvoid CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { 4833f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org static const int kMaxEncodeBitrateKbps = 30; 4841d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org static const int kMinTransmitBitrateBps = 150000; 4853f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org static const int kMinAcceptableTransmitBitrate = 130; 4863f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org static const int kMaxAcceptableTransmitBitrate = 170; 4873f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org static const int kNumBitrateObservationsInRange = 100; 488eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org class BitrateObserver : public test::EndToEndTest, public PacketReceiver { 4893f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org public: 4903f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org explicit BitrateObserver(bool using_min_transmit_bitrate) 491eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org : EndToEndTest(kLongTimeoutMs), 4923f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org send_stream_(NULL), 4933f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org send_transport_receiver_(NULL), 494eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org pad_to_min_bitrate_(using_min_transmit_bitrate), 4953f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org num_bitrate_observations_in_range_(0) {} 4963f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 497eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org private: 4983f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org virtual void SetReceivers(PacketReceiver* send_transport_receiver, 4993f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org PacketReceiver* receive_transport_receiver) 5003f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org OVERRIDE { 5013f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org send_transport_receiver_ = send_transport_receiver; 5023f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver); 5033f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5043f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 505bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org virtual DeliveryStatus DeliverPacket(const uint8_t* packet, 506bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org size_t length) OVERRIDE { 5073f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org VideoSendStream::Stats stats = send_stream_->GetStats(); 5083f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org if (stats.substreams.size() > 0) { 5093f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org assert(stats.substreams.size() == 1); 5103f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org int bitrate_kbps = stats.substreams.begin()->second.bitrate_bps / 1000; 5113f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org if (bitrate_kbps > 0) { 5123f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org test::PrintResult( 5133f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org "bitrate_stats_", 514eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org (pad_to_min_bitrate_ ? "min_transmit_bitrate" 515eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org : "without_min_transmit_bitrate"), 5163f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org "bitrate_kbps", 5173f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org static_cast<size_t>(bitrate_kbps), 5183f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org "kbps", 5193f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org false); 520eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (pad_to_min_bitrate_) { 5213f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org if (bitrate_kbps > kMinAcceptableTransmitBitrate && 5223f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org bitrate_kbps < kMaxAcceptableTransmitBitrate) { 5233f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org ++num_bitrate_observations_in_range_; 5243f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5253f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } else { 5263f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org // Expect bitrate stats to roughly match the max encode bitrate. 5273f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org if (bitrate_kbps > kMaxEncodeBitrateKbps - 5 && 5283f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org bitrate_kbps < kMaxEncodeBitrateKbps + 5) { 5293f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org ++num_bitrate_observations_in_range_; 5303f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5313f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5323f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org if (num_bitrate_observations_in_range_ == 5333f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org kNumBitrateObservationsInRange) 5343f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org observation_complete_->Set(); 5353f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5363f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5373f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org return send_transport_receiver_->DeliverPacket(packet, length); 5383f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org } 5393f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 54088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org virtual void OnStreamsCreated( 54188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org VideoSendStream* send_stream, 54288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE { 543eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org send_stream_ = send_stream; 544eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 545eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 546eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void ModifyConfigs( 547eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org VideoSendStream::Config* send_config, 54888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org std::vector<VideoReceiveStream::Config>* receive_configs, 54958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org VideoEncoderConfig* encoder_config) OVERRIDE { 550eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org if (pad_to_min_bitrate_) { 551eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps; 552eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } else { 553eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org assert(send_config->rtp.min_transmit_bitrate_bps == 0); 554eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 555eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 556eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 557eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org virtual void PerformTest() OVERRIDE { 558eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org EXPECT_EQ(kEventSignaled, Wait()) 559eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org << "Timeout while waiting for send-bitrate stats."; 560eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } 561eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org 5623f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org VideoSendStream* send_stream_; 5633f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org PacketReceiver* send_transport_receiver_; 564eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org const bool pad_to_min_bitrate_; 5653f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org int num_bitrate_observations_in_range_; 566eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org } test(pad_to_min_bitrate); 5673f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 5683f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); 569eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org RunBaseTest(&test); 5703f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org} 5713f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 5723f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.orgTEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } 5733f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 5743f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.orgTEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { 5753f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org TestMinTransmitBitrate(false); 5763f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org} 5773f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org 578f94ccd41be08c937f523b2749544f07011203905pbos@webrtc.org} // namespace webrtc 579