blob: 773886d77ee9f0731ca9c330bd351713dd9c720a [file] [log] [blame]
pbos@webrtc.orgce851092013-08-05 12:01:36 +00001/*
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 */
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000010#include <assert.h>
11
stefan@webrtc.orge0284102013-11-18 11:45:11 +000012#include <algorithm>
pbos@webrtc.orgce851092013-08-05 12:01:36 +000013#include <map>
stefan@webrtc.orge0284102013-11-18 11:45:11 +000014#include <sstream>
15#include <string>
pbos@webrtc.orgce851092013-08-05 12:01:36 +000016
17#include "testing/gtest/include/gtest/gtest.h"
18
pbos@webrtc.org24e20892013-10-28 16:32:01 +000019#include "webrtc/call.h"
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +000020#include "webrtc/common_video/test/frame_generator.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000021#include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
pbos@webrtc.orgce851092013-08-05 12:01:36 +000022#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.orgce851092013-08-05 12:01:36 +000025#include "webrtc/system_wrappers/interface/event_wrapper.h"
pbos@webrtc.orgfa996f22013-09-10 09:26:25 +000026#include "webrtc/system_wrappers/interface/scoped_ptr.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000027#include "webrtc/video/transport_adapter.h"
28#include "webrtc/voice_engine/include/voe_base.h"
29#include "webrtc/voice_engine/include/voe_codec.h"
30#include "webrtc/voice_engine/include/voe_network.h"
31#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
32#include "webrtc/voice_engine/include/voe_video_sync.h"
33#include "webrtc/voice_engine/test/auto_test/resource_manager.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000034#include "webrtc/test/direct_transport.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000035#include "webrtc/test/fake_audio_device.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000036#include "webrtc/test/fake_decoder.h"
37#include "webrtc/test/fake_encoder.h"
38#include "webrtc/test/frame_generator_capturer.h"
39#include "webrtc/test/generate_ssrcs.h"
40#include "webrtc/test/rtp_rtcp_observer.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000041#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.orgce851092013-08-05 12:01:36 +000042
43namespace webrtc {
44
pbos@webrtc.org51e01012013-10-17 14:14:42 +000045static unsigned int kDefaultTimeoutMs = 30 * 1000;
46static unsigned int kLongTimeoutMs = 120 * 1000;
stefan@webrtc.org4985c7b2013-11-15 12:32:15 +000047static const uint8_t kSendPayloadType = 125;
pbos@webrtc.org51e01012013-10-17 14:14:42 +000048
pbos@webrtc.org362e3e52013-09-27 10:54:10 +000049class CallTest : public ::testing::Test {
pbos@webrtc.orgce851092013-08-05 12:01:36 +000050 public:
pbos@webrtc.org28a11662013-09-19 14:22:12 +000051 CallTest()
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000052 : send_stream_(NULL),
53 receive_stream_(NULL),
54 fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.orgce851092013-08-05 12:01:36 +000055
pbos@webrtc.org28a11662013-09-19 14:22:12 +000056 ~CallTest() {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000057 EXPECT_EQ(NULL, send_stream_);
58 EXPECT_EQ(NULL, receive_stream_);
59 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000060
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000061 protected:
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +000062 void CreateCalls(const Call::Config& sender_config,
63 const Call::Config& receiver_config) {
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +000064 sender_call_.reset(Call::Create(sender_config));
65 receiver_call_.reset(Call::Create(receiver_config));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000066 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000067
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000068 void CreateTestConfigs() {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000069 send_config_ = sender_call_->GetDefaultSendConfig();
70 receive_config_ = receiver_call_->GetDefaultReceiveConfig();
pbos@webrtc.orgce851092013-08-05 12:01:36 +000071
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000072 test::GenerateRandomSsrcs(&send_config_, &reserved_ssrcs_);
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000073 send_config_.encoder = &fake_encoder_;
74 send_config_.internal_source = false;
75 test::FakeEncoder::SetCodecSettings(&send_config_.codec, 1);
stefan@webrtc.org4985c7b2013-11-15 12:32:15 +000076 send_config_.codec.plType = kSendPayloadType;
pbos@webrtc.orgce851092013-08-05 12:01:36 +000077
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000078 receive_config_.codecs.clear();
79 receive_config_.codecs.push_back(send_config_.codec);
80 ExternalVideoDecoder decoder;
81 decoder.decoder = &fake_decoder_;
82 decoder.payload_type = send_config_.codec.plType;
83 receive_config_.external_decoders.push_back(decoder);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000084 receive_config_.rtp.ssrc = send_config_.rtp.ssrcs[0];
85 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000086
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000087 void CreateStreams() {
88 assert(send_stream_ == NULL);
89 assert(receive_stream_ == NULL);
pbos@webrtc.orgce851092013-08-05 12:01:36 +000090
pbos@webrtc.org964d78e2013-11-20 10:40:25 +000091 send_stream_ = sender_call_->CreateVideoSendStream(send_config_);
92 receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000093 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000094
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000095 void CreateFrameGenerator() {
andresp@webrtc.org28631e72013-09-19 12:14:03 +000096 frame_generator_capturer_.reset(
97 test::FrameGeneratorCapturer::Create(send_stream_->Input(),
98 send_config_.codec.width,
99 send_config_.codec.height,
100 30,
101 Clock::GetRealTimeClock()));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000102 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000103
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000104 void StartSending() {
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000105 receive_stream_->StartReceiving();
106 send_stream_->StartSending();
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000107 if (frame_generator_capturer_.get() != NULL)
108 frame_generator_capturer_->Start();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000109 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000110
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000111 void StopSending() {
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000112 if (frame_generator_capturer_.get() != NULL)
113 frame_generator_capturer_->Stop();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000114 if (send_stream_ != NULL)
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000115 send_stream_->StopSending();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000116 if (receive_stream_ != NULL)
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000117 receive_stream_->StopReceiving();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000118 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000119
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000120 void DestroyStreams() {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000121 if (send_stream_ != NULL)
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000122 sender_call_->DestroyVideoSendStream(send_stream_);
pbos@webrtc.org00208582013-09-05 12:38:54 +0000123 if (receive_stream_ != NULL)
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000124 receiver_call_->DestroyVideoReceiveStream(receive_stream_);
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000125 send_stream_ = NULL;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000126 receive_stream_ = NULL;
127 }
128
129 void ReceivesPliAndRecovers(int rtp_history_ms);
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000130 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
stefan@webrtc.orge0284102013-11-18 11:45:11 +0000131 void PlaysOutAudioAndVideoInSync();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000132
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000133 scoped_ptr<Call> sender_call_;
134 scoped_ptr<Call> receiver_call_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000135
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000136 VideoSendStream::Config send_config_;
137 VideoReceiveStream::Config receive_config_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000138
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000139 VideoSendStream* send_stream_;
140 VideoReceiveStream* receive_stream_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000141
142 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
143
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000144 test::FakeEncoder fake_encoder_;
145 test::FakeDecoder fake_decoder_;
146
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000147 std::map<uint32_t, bool> reserved_ssrcs_;
148};
149
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000150class NackObserver : public test::RtpRtcpObserver {
151 static const int kNumberOfNacksToObserve = 4;
152 static const int kInverseProbabilityToStartLossBurst = 20;
153 static const int kMaxLossBurst = 10;
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000154
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000155 public:
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000156 NackObserver()
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000157 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000158 rtp_parser_(RtpHeaderParser::Create()),
159 drop_burst_count_(0),
160 sent_rtp_packets_(0),
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000161 nacks_left_(kNumberOfNacksToObserve) {}
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000162
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000163 private:
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000164 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000165 EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)));
166
167 RTPHeader header;
168 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
169
170 // Never drop retransmitted packets.
171 if (dropped_packets_.find(header.sequenceNumber) !=
172 dropped_packets_.end()) {
173 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000174 return SEND_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000175 }
176
177 // Enough NACKs received, stop dropping packets.
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000178 if (nacks_left_ == 0) {
179 ++sent_rtp_packets_;
180 return SEND_PACKET;
181 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000182
183 // Still dropping packets.
184 if (drop_burst_count_ > 0) {
185 --drop_burst_count_;
186 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000187 return DROP_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000188 }
189
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000190 // Should we start dropping packets?
191 if (sent_rtp_packets_ > 0 &&
192 rand() % kInverseProbabilityToStartLossBurst == 0) {
193 drop_burst_count_ = rand() % kMaxLossBurst;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000194 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000195 return DROP_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000196 }
197
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000198 ++sent_rtp_packets_;
199 return SEND_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000200 }
201
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000202 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
203 RTCPUtility::RTCPParserV2 parser(packet, length, true);
204 EXPECT_TRUE(parser.IsValid());
205
206 bool received_nack = false;
207 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
208 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
209 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode)
210 received_nack = true;
211
212 packet_type = parser.Iterate();
213 }
214
215 if (received_nack) {
216 ReceivedNack();
217 } else {
218 RtcpWithoutNack();
219 }
220 return SEND_PACKET;
221 }
222
223 private:
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000224 void ReceivedNack() {
225 if (nacks_left_ > 0)
226 --nacks_left_;
227 rtcp_without_nack_count_ = 0;
228 }
229
230 void RtcpWithoutNack() {
231 if (nacks_left_ > 0)
232 return;
233 ++rtcp_without_nack_count_;
234
235 // All packets retransmitted and no recent NACKs.
236 if (dropped_packets_.size() == retransmitted_packets_.size() &&
237 rtcp_without_nack_count_ >= kRequiredRtcpsWithoutNack) {
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000238 observation_complete_->Set();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000239 }
240 }
241
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000242 scoped_ptr<RtpHeaderParser> rtp_parser_;
243 std::set<uint16_t> dropped_packets_;
244 std::set<uint16_t> retransmitted_packets_;
245 int drop_burst_count_;
246 uint64_t sent_rtp_packets_;
247 int nacks_left_;
248 int rtcp_without_nack_count_;
249 static const int kRequiredRtcpsWithoutNack = 2;
250};
251
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000252TEST_F(CallTest, UsesTraceCallback) {
253 const unsigned int kSenderTraceFilter = kTraceDebug;
254 const unsigned int kReceiverTraceFilter = kTraceDefault & (~kTraceDebug);
pbos@webrtc.org63301bd2013-10-21 10:34:43 +0000255 class TraceObserver : public TraceCallback {
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000256 public:
257 TraceObserver(unsigned int filter)
258 : filter_(filter), messages_left_(50), done_(EventWrapper::Create()) {}
259
260 virtual void Print(TraceLevel level,
261 const char* message,
262 int length) OVERRIDE {
263 EXPECT_EQ(0u, level & (~filter_));
264 if (--messages_left_ == 0)
265 done_->Set();
266 }
267
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000268 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000269
270 private:
271 unsigned int filter_;
272 unsigned int messages_left_;
273 scoped_ptr<EventWrapper> done_;
274 } sender_trace(kSenderTraceFilter), receiver_trace(kReceiverTraceFilter);
275
276 test::DirectTransport send_transport, receive_transport;
277 Call::Config sender_call_config(&send_transport);
278 sender_call_config.trace_callback = &sender_trace;
279 sender_call_config.trace_filter = kSenderTraceFilter;
280 Call::Config receiver_call_config(&receive_transport);
281 receiver_call_config.trace_callback = &receiver_trace;
282 receiver_call_config.trace_filter = kReceiverTraceFilter;
283 CreateCalls(sender_call_config, receiver_call_config);
284 send_transport.SetReceiver(receiver_call_->Receiver());
285 receive_transport.SetReceiver(sender_call_->Receiver());
286
287 CreateTestConfigs();
288
289 CreateStreams();
290 CreateFrameGenerator();
291 StartSending();
292
293 // Wait() waits for a couple of trace callbacks to occur.
294 EXPECT_EQ(kEventSignaled, sender_trace.Wait());
295 EXPECT_EQ(kEventSignaled, receiver_trace.Wait());
296
297 StopSending();
298 send_transport.StopSending();
299 receive_transport.StopSending();
300 DestroyStreams();
301
302 // The TraceCallback instance MUST outlive Calls, destroy Calls explicitly.
303 sender_call_.reset();
304 receiver_call_.reset();
305}
306
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000307TEST_F(CallTest, TransmitsFirstFrame) {
308 class Renderer : public VideoRenderer {
309 public:
310 Renderer() : event_(EventWrapper::Create()) {}
311
312 virtual void RenderFrame(const I420VideoFrame& video_frame,
313 int /*time_to_render_ms*/) OVERRIDE {
314 event_->Set();
315 }
316
317 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
318
319 scoped_ptr<EventWrapper> event_;
320 } renderer;
321
322 test::DirectTransport sender_transport, receiver_transport;
323
324 CreateCalls(Call::Config(&sender_transport),
325 Call::Config(&receiver_transport));
326
327 sender_transport.SetReceiver(receiver_call_->Receiver());
328 receiver_transport.SetReceiver(sender_call_->Receiver());
329
330 CreateTestConfigs();
331 receive_config_.renderer = &renderer;
332
333 CreateStreams();
334 StartSending();
335
336 scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
337 send_config_.codec.width, send_config_.codec.height));
338 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
339
340 EXPECT_EQ(kEventSignaled, renderer.Wait())
341 << "Timed out while waiting for the frame to render.";
342
343 StopSending();
344
345 sender_transport.StopSending();
346 receiver_transport.StopSending();
347
348 DestroyStreams();
349}
350
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000351TEST_F(CallTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000352 NackObserver observer;
353
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000354 CreateCalls(Call::Config(observer.SendTransport()),
355 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000356
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000357 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000358
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000359 CreateTestConfigs();
360 int rtp_history_ms = 1000;
361 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
362 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000363
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000364 CreateStreams();
365 CreateFrameGenerator();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000366 StartSending();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000367
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000368 // Wait() waits for an event triggered when NACKs have been received, NACKed
369 // packets retransmitted and frames rendered again.
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000370 EXPECT_EQ(kEventSignaled, observer.Wait());
371
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000372 StopSending();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000373
pbos@webrtc.orgfe881f62013-08-12 12:59:04 +0000374 observer.StopSending();
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000375
376 DestroyStreams();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000377}
378
pbos@webrtc.org63301bd2013-10-21 10:34:43 +0000379TEST_F(CallTest, UsesFrameCallbacks) {
380 static const int kWidth = 320;
381 static const int kHeight = 240;
382
383 class Renderer : public VideoRenderer {
384 public:
385 Renderer() : event_(EventWrapper::Create()) {}
386
387 virtual void RenderFrame(const I420VideoFrame& video_frame,
388 int /*time_to_render_ms*/) OVERRIDE {
389 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
390 << "Rendered frame should have zero luma which is applied by the "
391 "pre-render callback.";
392 event_->Set();
393 }
394
395 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
396 scoped_ptr<EventWrapper> event_;
397 } renderer;
398
399 class TestFrameCallback : public I420FrameCallback {
400 public:
401 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
402 : event_(EventWrapper::Create()),
403 expected_luma_byte_(expected_luma_byte),
404 next_luma_byte_(next_luma_byte) {}
405
406 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
407
408 private:
409 virtual void FrameCallback(I420VideoFrame* frame) {
410 EXPECT_EQ(kWidth, frame->width())
411 << "Width not as expected, callback done before resize?";
412 EXPECT_EQ(kHeight, frame->height())
413 << "Height not as expected, callback done before resize?";
414
415 // Previous luma specified, observed luma should be fairly close.
416 if (expected_luma_byte_ != -1) {
417 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
418 }
419
420 memset(frame->buffer(kYPlane),
421 next_luma_byte_,
422 frame->allocated_size(kYPlane));
423
424 event_->Set();
425 }
426
427 scoped_ptr<EventWrapper> event_;
428 int expected_luma_byte_;
429 int next_luma_byte_;
430 };
431
432 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
433 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
434
435 test::DirectTransport sender_transport, receiver_transport;
436
437 CreateCalls(Call::Config(&sender_transport),
438 Call::Config(&receiver_transport));
439
440 sender_transport.SetReceiver(receiver_call_->Receiver());
441 receiver_transport.SetReceiver(sender_call_->Receiver());
442
443 CreateTestConfigs();
444 send_config_.encoder = NULL;
445 send_config_.codec = sender_call_->GetVideoCodecs()[0];
446 send_config_.codec.width = kWidth;
447 send_config_.codec.height = kHeight;
448 send_config_.pre_encode_callback = &pre_encode_callback;
449 receive_config_.pre_render_callback = &pre_render_callback;
450 receive_config_.renderer = &renderer;
451
452 CreateStreams();
453 StartSending();
454
455 // Create frames that are smaller than the send width/height, this is done to
456 // check that the callbacks are done after processing video.
457 scoped_ptr<test::FrameGenerator> frame_generator(
458 test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
459 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
460
461 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
462 << "Timed out while waiting for pre-encode callback.";
463 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
464 << "Timed out while waiting for pre-render callback.";
465 EXPECT_EQ(kEventSignaled, renderer.Wait())
466 << "Timed out while waiting for the frame to render.";
467
468 StopSending();
469
470 sender_transport.StopSending();
471 receiver_transport.StopSending();
472
473 DestroyStreams();
474}
475
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000476class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000477 static const int kInverseDropProbability = 16;
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000478
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000479 public:
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000480 explicit PliObserver(bool nack_enabled)
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000481 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000482 rtp_header_parser_(RtpHeaderParser::Create()),
483 nack_enabled_(nack_enabled),
484 first_retransmitted_timestamp_(0),
485 last_send_timestamp_(0),
486 rendered_frame_(false),
487 received_pli_(false) {}
488
489 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
490 RTPHeader header;
pbos@webrtc.org96ff6ab2013-08-19 16:35:36 +0000491 EXPECT_TRUE(
492 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000493
494 // Drop all NACK retransmissions. This is to force transmission of a PLI.
495 if (header.timestamp < last_send_timestamp_)
496 return DROP_PACKET;
497
498 if (received_pli_) {
499 if (first_retransmitted_timestamp_ == 0) {
500 first_retransmitted_timestamp_ = header.timestamp;
501 }
502 } else if (rendered_frame_ && rand() % kInverseDropProbability == 0) {
503 return DROP_PACKET;
504 }
505
506 last_send_timestamp_ = header.timestamp;
507 return SEND_PACKET;
508 }
509
510 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
511 RTCPUtility::RTCPParserV2 parser(packet, length, true);
512 EXPECT_TRUE(parser.IsValid());
513
514 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
515 packet_type != RTCPUtility::kRtcpNotValidCode;
516 packet_type = parser.Iterate()) {
517 if (!nack_enabled_)
518 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
519
520 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
521 received_pli_ = true;
522 break;
523 }
524 }
525 return SEND_PACKET;
526 }
527
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000528 virtual void RenderFrame(const I420VideoFrame& video_frame,
529 int time_to_render_ms) OVERRIDE {
530 CriticalSectionScoped crit_(lock_.get());
531 if (first_retransmitted_timestamp_ != 0 &&
532 video_frame.timestamp() > first_retransmitted_timestamp_) {
533 EXPECT_TRUE(received_pli_);
534 observation_complete_->Set();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000535 }
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000536 rendered_frame_ = true;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000537 }
538
539 private:
540 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
541 bool nack_enabled_;
542
543 uint32_t first_retransmitted_timestamp_;
544 uint32_t last_send_timestamp_;
545
546 bool rendered_frame_;
547 bool received_pli_;
548};
549
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000550void CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000551 PliObserver observer(rtp_history_ms > 0);
552
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000553 CreateCalls(Call::Config(observer.SendTransport()),
554 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000555
556 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
557
558 CreateTestConfigs();
559 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
560 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000561 receive_config_.renderer = &observer;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000562
563 CreateStreams();
564 CreateFrameGenerator();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000565 StartSending();
566
567 // Wait() waits for an event triggered when Pli has been received and frames
568 // have been rendered afterwards.
569 EXPECT_EQ(kEventSignaled, observer.Wait());
570
571 StopSending();
572
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000573 observer.StopSending();
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000574
575 DestroyStreams();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000576}
577
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000578TEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000579 ReceivesPliAndRecovers(1000);
580}
581
582// TODO(pbos): Enable this when 2250 is resolved.
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000583TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000584 ReceivesPliAndRecovers(0);
585}
586
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000587TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000588 class PacketInputObserver : public PacketReceiver {
589 public:
590 explicit PacketInputObserver(PacketReceiver* receiver)
591 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
592
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000593 EventTypeWrapper Wait() {
594 return delivered_packet_->Wait(kDefaultTimeoutMs);
595 }
pbos@webrtc.org00208582013-09-05 12:38:54 +0000596
597 private:
598 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
599 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
600 return receiver_->DeliverPacket(packet, length);
601 } else {
602 EXPECT_FALSE(receiver_->DeliverPacket(packet, length));
603 delivered_packet_->Set();
604 return false;
605 }
606 }
607
608 PacketReceiver* receiver_;
609 scoped_ptr<EventWrapper> delivered_packet_;
610 };
611
612 test::DirectTransport send_transport, receive_transport;
613
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000614 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
pbos@webrtc.org00208582013-09-05 12:38:54 +0000615 PacketInputObserver input_observer(receiver_call_->Receiver());
616
617 send_transport.SetReceiver(&input_observer);
618 receive_transport.SetReceiver(sender_call_->Receiver());
619
620 CreateTestConfigs();
621
622 CreateStreams();
623 CreateFrameGenerator();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000624 StartSending();
625
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000626 receiver_call_->DestroyVideoReceiveStream(receive_stream_);
pbos@webrtc.org00208582013-09-05 12:38:54 +0000627 receive_stream_ = NULL;
628
629 // Wait() waits for a received packet.
630 EXPECT_EQ(kEventSignaled, input_observer.Wait());
631
632 StopSending();
633
634 DestroyStreams();
635
636 send_transport.StopSending();
637 receive_transport.StopSending();
638}
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000639
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000640void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
641 static const int kRtpHistoryMs = 1000;
642 static const int kNumCompoundRtcpPacketsToObserve = 10;
643 class RtcpModeObserver : public test::RtpRtcpObserver {
644 public:
645 RtcpModeObserver(newapi::RtcpMode rtcp_mode)
646 : test::RtpRtcpObserver(kDefaultTimeoutMs),
647 rtcp_mode_(rtcp_mode),
648 sent_rtp_(0),
649 sent_rtcp_(0) {}
650
651 private:
652 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
653 if (++sent_rtp_ % 3 == 0)
654 return DROP_PACKET;
655
656 return SEND_PACKET;
657 }
658
659 virtual Action OnReceiveRtcp(const uint8_t* packet,
660 size_t length) OVERRIDE {
661 ++sent_rtcp_;
662 RTCPUtility::RTCPParserV2 parser(packet, length, true);
663 EXPECT_TRUE(parser.IsValid());
664
665 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
666 bool has_report_block = false;
667 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
668 EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
669 if (packet_type == RTCPUtility::kRtcpRrCode) {
670 has_report_block = true;
671 break;
672 }
673 packet_type = parser.Iterate();
674 }
675
676 switch (rtcp_mode_) {
677 case newapi::kRtcpCompound:
678 if (!has_report_block) {
679 ADD_FAILURE() << "Received RTCP packet without receiver report for "
680 "kRtcpCompound.";
681 observation_complete_->Set();
682 }
683
684 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
685 observation_complete_->Set();
686
687 break;
688 case newapi::kRtcpReducedSize:
689 if (!has_report_block)
690 observation_complete_->Set();
691 break;
692 }
693
694 return SEND_PACKET;
695 }
696
697 newapi::RtcpMode rtcp_mode_;
698 int sent_rtp_;
699 int sent_rtcp_;
700 } observer(rtcp_mode);
701
702 CreateCalls(Call::Config(observer.SendTransport()),
703 Call::Config(observer.ReceiveTransport()));
704
705 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
706
707 CreateTestConfigs();
708 send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
709 receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
710 receive_config_.rtp.rtcp_mode = rtcp_mode;
711
712 CreateStreams();
713 CreateFrameGenerator();
714 StartSending();
715
716 EXPECT_EQ(kEventSignaled, observer.Wait())
717 << (rtcp_mode == newapi::kRtcpCompound
718 ? "Timed out before observing enough compound packets."
719 : "Timed out before receiving a non-compound RTCP packet.");
720
721 StopSending();
722 observer.StopSending();
723 DestroyStreams();
724}
725
726TEST_F(CallTest, UsesRtcpCompoundMode) {
727 RespectsRtcpMode(newapi::kRtcpCompound);
728}
729
730TEST_F(CallTest, UsesRtcpReducedSizeMode) {
731 RespectsRtcpMode(newapi::kRtcpReducedSize);
732}
733
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000734// Test sets up a Call multiple senders with different resolutions and SSRCs.
735// Another is set up to receive all three of these with different renderers.
736// Each renderer verifies that it receives the expected resolution, and as soon
737// as every renderer has received a frame, the test finishes.
738TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
739 static const size_t kNumStreams = 3;
740
741 class VideoOutputObserver : public VideoRenderer {
742 public:
743 VideoOutputObserver(int width, int height)
744 : width_(width), height_(height), done_(EventWrapper::Create()) {}
745
746 virtual void RenderFrame(const I420VideoFrame& video_frame,
747 int time_to_render_ms) OVERRIDE {
748 EXPECT_EQ(width_, video_frame.width());
749 EXPECT_EQ(height_, video_frame.height());
750 done_->Set();
751 }
752
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000753 void Wait() { done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000754
755 private:
756 int width_;
757 int height_;
758 scoped_ptr<EventWrapper> done_;
759 };
760
761 struct {
762 uint32_t ssrc;
763 int width;
764 int height;
765 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
766
767 test::DirectTransport sender_transport, receiver_transport;
768 scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
769 scoped_ptr<Call> receiver_call(
770 Call::Create(Call::Config(&receiver_transport)));
771 sender_transport.SetReceiver(receiver_call->Receiver());
772 receiver_transport.SetReceiver(sender_call->Receiver());
773
774 VideoSendStream* send_streams[kNumStreams];
775 VideoReceiveStream* receive_streams[kNumStreams];
776
777 VideoOutputObserver* observers[kNumStreams];
778 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
779
780 for (size_t i = 0; i < kNumStreams; ++i) {
781 uint32_t ssrc = codec_settings[i].ssrc;
782 int width = codec_settings[i].width;
783 int height = codec_settings[i].height;
784 observers[i] = new VideoOutputObserver(width, height);
785
786 VideoReceiveStream::Config receive_config =
787 receiver_call->GetDefaultReceiveConfig();
788 receive_config.renderer = observers[i];
789 receive_config.rtp.ssrc = ssrc;
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000790 receive_streams[i] =
791 receiver_call->CreateVideoReceiveStream(receive_config);
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000792 receive_streams[i]->StartReceiving();
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000793
794 VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
795 send_config.rtp.ssrcs.push_back(ssrc);
796 send_config.codec.width = width;
797 send_config.codec.height = height;
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000798 send_streams[i] = sender_call->CreateVideoSendStream(send_config);
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000799 send_streams[i]->StartSending();
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000800
801 frame_generators[i] = test::FrameGeneratorCapturer::Create(
802 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
803 frame_generators[i]->Start();
804 }
805
806 for (size_t i = 0; i < kNumStreams; ++i) {
807 observers[i]->Wait();
808 }
809
810 for (size_t i = 0; i < kNumStreams; ++i) {
811 frame_generators[i]->Stop();
812 delete frame_generators[i];
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000813 sender_call->DestroyVideoSendStream(send_streams[i]);
814 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000815 delete observers[i];
816 }
817
818 sender_transport.StopSending();
819 receiver_transport.StopSending();
820}
stefan@webrtc.orge0284102013-11-18 11:45:11 +0000821
822class SyncRtcpObserver : public test::RtpRtcpObserver {
823 public:
824 SyncRtcpObserver(int delay_ms)
825 : test::RtpRtcpObserver(kLongTimeoutMs, delay_ms),
826 critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
827
828 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
829 RTCPUtility::RTCPParserV2 parser(packet, length, true);
830 EXPECT_TRUE(parser.IsValid());
831
832 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
833 packet_type != RTCPUtility::kRtcpNotValidCode;
834 packet_type = parser.Iterate()) {
835 if (packet_type == RTCPUtility::kRtcpSrCode) {
836 const RTCPUtility::RTCPPacket& packet = parser.Packet();
837 synchronization::RtcpMeasurement ntp_rtp_pair(
838 packet.SR.NTPMostSignificant,
839 packet.SR.NTPLeastSignificant,
840 packet.SR.RTPTimestamp);
841 StoreNtpRtpPair(ntp_rtp_pair);
842 }
843 }
844 return SEND_PACKET;
845 }
846
847 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
848 CriticalSectionScoped cs(critical_section_.get());
849 int64_t timestamp_in_ms = -1;
850 if (ntp_rtp_pairs_.size() == 2) {
851 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
852 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
853 // to a bogus NTP/RTP mapping.
854 synchronization::RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
855 return timestamp_in_ms;
856 }
857 return -1;
858 }
859
860 private:
861 void StoreNtpRtpPair(synchronization::RtcpMeasurement ntp_rtp_pair) {
862 CriticalSectionScoped cs(critical_section_.get());
863 for (synchronization::RtcpList::iterator it = ntp_rtp_pairs_.begin();
864 it != ntp_rtp_pairs_.end();
865 ++it) {
866 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
867 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
868 // This RTCP has already been added to the list.
869 return;
870 }
871 }
872 // We need two RTCP SR reports to map between RTP and NTP. More than two
873 // will not improve the mapping.
874 if (ntp_rtp_pairs_.size() == 2) {
875 ntp_rtp_pairs_.pop_back();
876 }
877 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
878 }
879
880 scoped_ptr<CriticalSectionWrapper> critical_section_;
881 synchronization::RtcpList ntp_rtp_pairs_;
882};
883
884class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
885 static const int kInSyncThresholdMs = 50;
886 static const int kStartupTimeMs = 2000;
887 static const int kMinRunTimeMs = 30000;
888
889 public:
890 VideoRtcpAndSyncObserver(Clock* clock,
891 int voe_channel,
892 VoEVideoSync* voe_sync,
893 SyncRtcpObserver* audio_observer)
894 : SyncRtcpObserver(0),
895 clock_(clock),
896 voe_channel_(voe_channel),
897 voe_sync_(voe_sync),
898 audio_observer_(audio_observer),
899 creation_time_ms_(clock_->TimeInMilliseconds()),
900 first_time_in_sync_(-1) {}
901
902 virtual void RenderFrame(const I420VideoFrame& video_frame,
903 int time_to_render_ms) OVERRIDE {
904 int64_t now_ms = clock_->TimeInMilliseconds();
905 uint32_t playout_timestamp = 0;
906 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
907 return;
908 int64_t latest_audio_ntp =
909 audio_observer_->RtpTimestampToNtp(playout_timestamp);
910 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
911 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
912 return;
913 int time_until_render_ms =
914 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
915 latest_video_ntp += time_until_render_ms;
916 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
917 std::stringstream ss;
918 ss << stream_offset;
919 webrtc::test::PrintResult(
920 "stream_offset", "", "synchronization", ss.str(), "ms", false);
921 int64_t time_since_creation = now_ms - creation_time_ms_;
922 // During the first couple of seconds audio and video can falsely be
923 // estimated as being synchronized. We don't want to trigger on those.
924 if (time_since_creation < kStartupTimeMs)
925 return;
926 if (abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
927 if (first_time_in_sync_ == -1) {
928 first_time_in_sync_ = now_ms;
929 webrtc::test::PrintResult("sync_convergence_time",
930 "",
931 "synchronization",
932 time_since_creation,
933 "ms",
934 false);
935 }
936 if (time_since_creation > kMinRunTimeMs)
937 observation_complete_->Set();
938 }
939 }
940
941 private:
942 Clock* clock_;
943 int voe_channel_;
944 VoEVideoSync* voe_sync_;
945 SyncRtcpObserver* audio_observer_;
946 int64_t creation_time_ms_;
947 int64_t first_time_in_sync_;
948};
949
950TEST_F(CallTest, PlaysOutAudioAndVideoInSync) {
951 VoiceEngine* voice_engine = VoiceEngine::Create();
952 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
953 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
954 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
955 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
956 ResourceManager resource_manager;
957 const std::string audio_filename = resource_manager.long_audio_file_path();
958 ASSERT_STRNE("", audio_filename.c_str());
959 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
960 audio_filename);
961 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
962 int channel = voe_base->CreateChannel();
963
964 const int kVoiceDelayMs = 500;
965 SyncRtcpObserver audio_observer(kVoiceDelayMs);
966 VideoRtcpAndSyncObserver observer(
967 Clock::GetRealTimeClock(), channel, voe_sync, &audio_observer);
968
969 Call::Config receiver_config(observer.ReceiveTransport());
970 receiver_config.voice_engine = voice_engine;
971 CreateCalls(Call::Config(observer.SendTransport()), receiver_config);
972 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
973 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
974
975 class VoicePacketReceiver : public PacketReceiver {
976 public:
977 VoicePacketReceiver(int channel, VoENetwork* voe_network)
978 : channel_(channel),
979 voe_network_(voe_network),
980 parser_(RtpHeaderParser::Create()) {}
981 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
982 int ret;
983 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
984 ret = voe_network_->ReceivedRTCPPacket(
985 channel_, packet, static_cast<unsigned int>(length));
986 } else {
987 ret = voe_network_->ReceivedRTPPacket(
988 channel_, packet, static_cast<unsigned int>(length));
989 }
990 return ret == 0;
991 }
992
993 private:
994 int channel_;
995 VoENetwork* voe_network_;
996 scoped_ptr<RtpHeaderParser> parser_;
997 } voe_packet_receiver(channel, voe_network);
998
999 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
1000
1001 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
1002 EXPECT_EQ(0,
1003 voe_network->RegisterExternalTransport(channel, transport_adapter));
1004
1005 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
1006
1007 CreateTestConfigs();
1008 send_config_.rtp.nack.rtp_history_ms = 1000;
1009 receive_config_.rtp.nack.rtp_history_ms = 1000;
1010 receive_config_.renderer = &observer;
1011 receive_config_.audio_channel_id = channel;
1012
1013 CreateStreams();
1014 CreateFrameGenerator();
1015 StartSending();
1016
1017 fake_audio_device.Start();
1018 EXPECT_EQ(0, voe_base->StartPlayout(channel));
1019 EXPECT_EQ(0, voe_base->StartReceive(channel));
1020 EXPECT_EQ(0, voe_base->StartSend(channel));
1021
1022 EXPECT_EQ(kEventSignaled, observer.Wait())
1023 << "Timed out while waiting for audio and video to be synchronized.";
1024
1025 EXPECT_EQ(0, voe_base->StopSend(channel));
1026 EXPECT_EQ(0, voe_base->StopReceive(channel));
1027 EXPECT_EQ(0, voe_base->StopPlayout(channel));
1028 fake_audio_device.Stop();
1029
1030 StopSending();
1031 observer.StopSending();
1032 audio_observer.StopSending();
1033
1034 voe_base->DeleteChannel(channel);
1035 voe_base->Release();
1036 voe_codec->Release();
1037 voe_network->Release();
1038 voe_sync->Release();
1039 DestroyStreams();
1040 VoiceEngine::Delete(voice_engine);
1041}
1042
pbos@webrtc.orgce851092013-08-05 12:01:36 +00001043} // namespace webrtc