blob: 67e01131a359ba6eb06c10e68a41700fa9e63b0f [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"
sprang@webrtc.org2e98d452013-11-26 11:41:59 +000021#include "webrtc/frame_callback.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000022#include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
pbos@webrtc.orgce851092013-08-05 12:01:36 +000023#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
24#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
25#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.orgce851092013-08-05 12:01:36 +000026#include "webrtc/system_wrappers/interface/event_wrapper.h"
pbos@webrtc.orgfa996f22013-09-10 09:26:25 +000027#include "webrtc/system_wrappers/interface/scoped_ptr.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000028#include "webrtc/video/transport_adapter.h"
29#include "webrtc/voice_engine/include/voe_base.h"
30#include "webrtc/voice_engine/include/voe_codec.h"
31#include "webrtc/voice_engine/include/voe_network.h"
32#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
33#include "webrtc/voice_engine/include/voe_video_sync.h"
34#include "webrtc/voice_engine/test/auto_test/resource_manager.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000035#include "webrtc/test/direct_transport.h"
stefan@webrtc.orge0284102013-11-18 11:45:11 +000036#include "webrtc/test/fake_audio_device.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000037#include "webrtc/test/fake_decoder.h"
38#include "webrtc/test/fake_encoder.h"
39#include "webrtc/test/frame_generator_capturer.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000040#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;
pbos@webrtc.org4b50db12013-12-03 10:13:04 +000047static const uint32_t kSendSsrc = 0x654321;
48static const uint32_t kReceiverLocalSsrc = 0x123456;
stefan@webrtc.org4985c7b2013-11-15 12:32:15 +000049static const uint8_t kSendPayloadType = 125;
pbos@webrtc.org51e01012013-10-17 14:14:42 +000050
pbos@webrtc.org362e3e52013-09-27 10:54:10 +000051class CallTest : public ::testing::Test {
pbos@webrtc.orgce851092013-08-05 12:01:36 +000052 public:
pbos@webrtc.org28a11662013-09-19 14:22:12 +000053 CallTest()
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000054 : send_stream_(NULL),
55 receive_stream_(NULL),
56 fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.orgce851092013-08-05 12:01:36 +000057
pbos@webrtc.org28a11662013-09-19 14:22:12 +000058 ~CallTest() {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000059 EXPECT_EQ(NULL, send_stream_);
60 EXPECT_EQ(NULL, receive_stream_);
61 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000062
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000063 protected:
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +000064 void CreateCalls(const Call::Config& sender_config,
65 const Call::Config& receiver_config) {
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +000066 sender_call_.reset(Call::Create(sender_config));
67 receiver_call_.reset(Call::Create(receiver_config));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000068 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000069
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000070 void CreateTestConfigs() {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000071 send_config_ = sender_call_->GetDefaultSendConfig();
72 receive_config_ = receiver_call_->GetDefaultReceiveConfig();
pbos@webrtc.orgce851092013-08-05 12:01:36 +000073
pbos@webrtc.org4b50db12013-12-03 10:13:04 +000074 send_config_.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000075 send_config_.encoder = &fake_encoder_;
76 send_config_.internal_source = false;
77 test::FakeEncoder::SetCodecSettings(&send_config_.codec, 1);
stefan@webrtc.org4985c7b2013-11-15 12:32:15 +000078 send_config_.codec.plType = kSendPayloadType;
pbos@webrtc.orgce851092013-08-05 12:01:36 +000079
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +000080 receive_config_.codecs.clear();
81 receive_config_.codecs.push_back(send_config_.codec);
82 ExternalVideoDecoder decoder;
83 decoder.decoder = &fake_decoder_;
84 decoder.payload_type = send_config_.codec.plType;
85 receive_config_.external_decoders.push_back(decoder);
pbos@webrtc.org4b50db12013-12-03 10:13:04 +000086 receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
87 receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000088 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000089
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000090 void CreateStreams() {
91 assert(send_stream_ == NULL);
92 assert(receive_stream_ == NULL);
pbos@webrtc.orgce851092013-08-05 12:01:36 +000093
pbos@webrtc.org964d78e2013-11-20 10:40:25 +000094 send_stream_ = sender_call_->CreateVideoSendStream(send_config_);
95 receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000096 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +000097
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +000098 void CreateFrameGenerator() {
andresp@webrtc.org28631e72013-09-19 12:14:03 +000099 frame_generator_capturer_.reset(
100 test::FrameGeneratorCapturer::Create(send_stream_->Input(),
101 send_config_.codec.width,
102 send_config_.codec.height,
103 30,
104 Clock::GetRealTimeClock()));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000105 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000106
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000107 void StartSending() {
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000108 receive_stream_->StartReceiving();
109 send_stream_->StartSending();
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000110 if (frame_generator_capturer_.get() != NULL)
111 frame_generator_capturer_->Start();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000112 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000113
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000114 void StopSending() {
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000115 if (frame_generator_capturer_.get() != NULL)
116 frame_generator_capturer_->Stop();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000117 if (send_stream_ != NULL)
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000118 send_stream_->StopSending();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000119 if (receive_stream_ != NULL)
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000120 receive_stream_->StopReceiving();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000121 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000122
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000123 void DestroyStreams() {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000124 if (send_stream_ != NULL)
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000125 sender_call_->DestroyVideoSendStream(send_stream_);
pbos@webrtc.org00208582013-09-05 12:38:54 +0000126 if (receive_stream_ != NULL)
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000127 receiver_call_->DestroyVideoReceiveStream(receive_stream_);
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000128 send_stream_ = NULL;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000129 receive_stream_ = NULL;
130 }
131
132 void ReceivesPliAndRecovers(int rtp_history_ms);
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000133 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
stefan@webrtc.orge0284102013-11-18 11:45:11 +0000134 void PlaysOutAudioAndVideoInSync();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000135
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000136 scoped_ptr<Call> sender_call_;
137 scoped_ptr<Call> receiver_call_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000138
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000139 VideoSendStream::Config send_config_;
140 VideoReceiveStream::Config receive_config_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000141
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000142 VideoSendStream* send_stream_;
143 VideoReceiveStream* receive_stream_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000144
145 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
146
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000147 test::FakeEncoder fake_encoder_;
148 test::FakeDecoder fake_decoder_;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000149};
150
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000151class NackObserver : public test::RtpRtcpObserver {
152 static const int kNumberOfNacksToObserve = 4;
153 static const int kInverseProbabilityToStartLossBurst = 20;
154 static const int kMaxLossBurst = 10;
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000155
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000156 public:
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000157 NackObserver()
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000158 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000159 rtp_parser_(RtpHeaderParser::Create()),
160 drop_burst_count_(0),
161 sent_rtp_packets_(0),
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000162 nacks_left_(kNumberOfNacksToObserve) {}
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000163
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000164 private:
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000165 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000166 EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)));
167
168 RTPHeader header;
169 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
170
171 // Never drop retransmitted packets.
172 if (dropped_packets_.find(header.sequenceNumber) !=
173 dropped_packets_.end()) {
174 retransmitted_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000175 return SEND_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000176 }
177
178 // Enough NACKs received, stop dropping packets.
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000179 if (nacks_left_ == 0) {
180 ++sent_rtp_packets_;
181 return SEND_PACKET;
182 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000183
184 // Still dropping packets.
185 if (drop_burst_count_ > 0) {
186 --drop_burst_count_;
187 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000188 return DROP_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000189 }
190
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000191 // Should we start dropping packets?
192 if (sent_rtp_packets_ > 0 &&
193 rand() % kInverseProbabilityToStartLossBurst == 0) {
194 drop_burst_count_ = rand() % kMaxLossBurst;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000195 dropped_packets_.insert(header.sequenceNumber);
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000196 return DROP_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000197 }
198
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000199 ++sent_rtp_packets_;
200 return SEND_PACKET;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000201 }
202
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000203 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
204 RTCPUtility::RTCPParserV2 parser(packet, length, true);
205 EXPECT_TRUE(parser.IsValid());
206
207 bool received_nack = false;
208 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
209 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
210 if (packet_type == RTCPUtility::kRtcpRtpfbNackCode)
211 received_nack = true;
212
213 packet_type = parser.Iterate();
214 }
215
216 if (received_nack) {
217 ReceivedNack();
218 } else {
219 RtcpWithoutNack();
220 }
221 return SEND_PACKET;
222 }
223
224 private:
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000225 void ReceivedNack() {
226 if (nacks_left_ > 0)
227 --nacks_left_;
228 rtcp_without_nack_count_ = 0;
229 }
230
231 void RtcpWithoutNack() {
232 if (nacks_left_ > 0)
233 return;
234 ++rtcp_without_nack_count_;
235
236 // All packets retransmitted and no recent NACKs.
237 if (dropped_packets_.size() == retransmitted_packets_.size() &&
238 rtcp_without_nack_count_ >= kRequiredRtcpsWithoutNack) {
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000239 observation_complete_->Set();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000240 }
241 }
242
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000243 scoped_ptr<RtpHeaderParser> rtp_parser_;
244 std::set<uint16_t> dropped_packets_;
245 std::set<uint16_t> retransmitted_packets_;
246 int drop_burst_count_;
247 uint64_t sent_rtp_packets_;
248 int nacks_left_;
249 int rtcp_without_nack_count_;
250 static const int kRequiredRtcpsWithoutNack = 2;
251};
252
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000253TEST_F(CallTest, UsesTraceCallback) {
254 const unsigned int kSenderTraceFilter = kTraceDebug;
255 const unsigned int kReceiverTraceFilter = kTraceDefault & (~kTraceDebug);
pbos@webrtc.org63301bd2013-10-21 10:34:43 +0000256 class TraceObserver : public TraceCallback {
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000257 public:
pbos@webrtc.orgd05597a2013-12-05 12:11:47 +0000258 explicit TraceObserver(unsigned int filter)
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000259 : filter_(filter), messages_left_(50), done_(EventWrapper::Create()) {}
260
261 virtual void Print(TraceLevel level,
262 const char* message,
263 int length) OVERRIDE {
264 EXPECT_EQ(0u, level & (~filter_));
265 if (--messages_left_ == 0)
266 done_->Set();
267 }
268
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000269 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000270
271 private:
272 unsigned int filter_;
273 unsigned int messages_left_;
274 scoped_ptr<EventWrapper> done_;
275 } sender_trace(kSenderTraceFilter), receiver_trace(kReceiverTraceFilter);
276
277 test::DirectTransport send_transport, receive_transport;
278 Call::Config sender_call_config(&send_transport);
279 sender_call_config.trace_callback = &sender_trace;
280 sender_call_config.trace_filter = kSenderTraceFilter;
281 Call::Config receiver_call_config(&receive_transport);
282 receiver_call_config.trace_callback = &receiver_trace;
283 receiver_call_config.trace_filter = kReceiverTraceFilter;
284 CreateCalls(sender_call_config, receiver_call_config);
285 send_transport.SetReceiver(receiver_call_->Receiver());
286 receive_transport.SetReceiver(sender_call_->Receiver());
287
288 CreateTestConfigs();
289
290 CreateStreams();
291 CreateFrameGenerator();
292 StartSending();
293
294 // Wait() waits for a couple of trace callbacks to occur.
295 EXPECT_EQ(kEventSignaled, sender_trace.Wait());
296 EXPECT_EQ(kEventSignaled, receiver_trace.Wait());
297
298 StopSending();
299 send_transport.StopSending();
300 receive_transport.StopSending();
301 DestroyStreams();
302
303 // The TraceCallback instance MUST outlive Calls, destroy Calls explicitly.
304 sender_call_.reset();
305 receiver_call_.reset();
306}
307
pbos@webrtc.orgc5b5ad12013-10-21 09:02:30 +0000308TEST_F(CallTest, TransmitsFirstFrame) {
309 class Renderer : public VideoRenderer {
310 public:
311 Renderer() : event_(EventWrapper::Create()) {}
312
313 virtual void RenderFrame(const I420VideoFrame& video_frame,
314 int /*time_to_render_ms*/) OVERRIDE {
315 event_->Set();
316 }
317
318 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
319
320 scoped_ptr<EventWrapper> event_;
321 } renderer;
322
323 test::DirectTransport sender_transport, receiver_transport;
324
325 CreateCalls(Call::Config(&sender_transport),
326 Call::Config(&receiver_transport));
327
328 sender_transport.SetReceiver(receiver_call_->Receiver());
329 receiver_transport.SetReceiver(sender_call_->Receiver());
330
331 CreateTestConfigs();
332 receive_config_.renderer = &renderer;
333
334 CreateStreams();
335 StartSending();
336
337 scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
338 send_config_.codec.width, send_config_.codec.height));
339 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
340
341 EXPECT_EQ(kEventSignaled, renderer.Wait())
342 << "Timed out while waiting for the frame to render.";
343
344 StopSending();
345
346 sender_transport.StopSending();
347 receiver_transport.StopSending();
348
349 DestroyStreams();
350}
351
pbos@webrtc.org4b50db12013-12-03 10:13:04 +0000352TEST_F(CallTest, ReceiverUsesLocalSsrc) {
353 class SyncRtcpObserver : public test::RtpRtcpObserver {
354 public:
355 SyncRtcpObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
356
357 virtual Action OnReceiveRtcp(const uint8_t* packet,
358 size_t length) OVERRIDE {
359 RTCPUtility::RTCPParserV2 parser(packet, length, true);
360 EXPECT_TRUE(parser.IsValid());
361 uint32_t ssrc = 0;
362 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
363 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
364 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
365 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
366 EXPECT_EQ(kReceiverLocalSsrc, ssrc);
367 observation_complete_->Set();
368
369 return SEND_PACKET;
370 }
371 } observer;
372
373 CreateCalls(Call::Config(observer.SendTransport()),
374 Call::Config(observer.ReceiveTransport()));
375
376 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
377
378 CreateTestConfigs();
379
380 CreateStreams();
381 CreateFrameGenerator();
382 StartSending();
383
384 EXPECT_EQ(kEventSignaled, observer.Wait())
385 << "Timed out while waiting for a receiver RTCP packet to be sent.";
386
387 StopSending();
388
389 observer.StopSending();
390
391 DestroyStreams();
392}
393
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000394TEST_F(CallTest, ReceivesAndRetransmitsNack) {
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000395 NackObserver observer;
396
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000397 CreateCalls(Call::Config(observer.SendTransport()),
398 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000399
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000400 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000401
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000402 CreateTestConfigs();
403 int rtp_history_ms = 1000;
404 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
405 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000406
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000407 CreateStreams();
408 CreateFrameGenerator();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000409 StartSending();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000410
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000411 // Wait() waits for an event triggered when NACKs have been received, NACKed
412 // packets retransmitted and frames rendered again.
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000413 EXPECT_EQ(kEventSignaled, observer.Wait());
414
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000415 StopSending();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000416
pbos@webrtc.orgfe881f62013-08-12 12:59:04 +0000417 observer.StopSending();
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000418
419 DestroyStreams();
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000420}
421
pbos@webrtc.org63301bd2013-10-21 10:34:43 +0000422TEST_F(CallTest, UsesFrameCallbacks) {
423 static const int kWidth = 320;
424 static const int kHeight = 240;
425
426 class Renderer : public VideoRenderer {
427 public:
428 Renderer() : event_(EventWrapper::Create()) {}
429
430 virtual void RenderFrame(const I420VideoFrame& video_frame,
431 int /*time_to_render_ms*/) OVERRIDE {
432 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
433 << "Rendered frame should have zero luma which is applied by the "
434 "pre-render callback.";
435 event_->Set();
436 }
437
438 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
439 scoped_ptr<EventWrapper> event_;
440 } renderer;
441
442 class TestFrameCallback : public I420FrameCallback {
443 public:
444 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
445 : event_(EventWrapper::Create()),
446 expected_luma_byte_(expected_luma_byte),
447 next_luma_byte_(next_luma_byte) {}
448
449 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
450
451 private:
452 virtual void FrameCallback(I420VideoFrame* frame) {
453 EXPECT_EQ(kWidth, frame->width())
454 << "Width not as expected, callback done before resize?";
455 EXPECT_EQ(kHeight, frame->height())
456 << "Height not as expected, callback done before resize?";
457
458 // Previous luma specified, observed luma should be fairly close.
459 if (expected_luma_byte_ != -1) {
460 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
461 }
462
463 memset(frame->buffer(kYPlane),
464 next_luma_byte_,
465 frame->allocated_size(kYPlane));
466
467 event_->Set();
468 }
469
470 scoped_ptr<EventWrapper> event_;
471 int expected_luma_byte_;
472 int next_luma_byte_;
473 };
474
475 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
476 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
477
478 test::DirectTransport sender_transport, receiver_transport;
479
480 CreateCalls(Call::Config(&sender_transport),
481 Call::Config(&receiver_transport));
482
483 sender_transport.SetReceiver(receiver_call_->Receiver());
484 receiver_transport.SetReceiver(sender_call_->Receiver());
485
486 CreateTestConfigs();
487 send_config_.encoder = NULL;
488 send_config_.codec = sender_call_->GetVideoCodecs()[0];
489 send_config_.codec.width = kWidth;
490 send_config_.codec.height = kHeight;
491 send_config_.pre_encode_callback = &pre_encode_callback;
492 receive_config_.pre_render_callback = &pre_render_callback;
493 receive_config_.renderer = &renderer;
494
495 CreateStreams();
496 StartSending();
497
498 // Create frames that are smaller than the send width/height, this is done to
499 // check that the callbacks are done after processing video.
500 scoped_ptr<test::FrameGenerator> frame_generator(
501 test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
502 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
503
504 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
505 << "Timed out while waiting for pre-encode callback.";
506 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
507 << "Timed out while waiting for pre-render callback.";
508 EXPECT_EQ(kEventSignaled, renderer.Wait())
509 << "Timed out while waiting for the frame to render.";
510
511 StopSending();
512
513 sender_transport.StopSending();
514 receiver_transport.StopSending();
515
516 DestroyStreams();
517}
518
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000519class PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000520 static const int kInverseDropProbability = 16;
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000521
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000522 public:
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000523 explicit PliObserver(bool nack_enabled)
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000524 : test::RtpRtcpObserver(kLongTimeoutMs),
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000525 rtp_header_parser_(RtpHeaderParser::Create()),
526 nack_enabled_(nack_enabled),
527 first_retransmitted_timestamp_(0),
528 last_send_timestamp_(0),
529 rendered_frame_(false),
530 received_pli_(false) {}
531
532 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
533 RTPHeader header;
pbos@webrtc.org96ff6ab2013-08-19 16:35:36 +0000534 EXPECT_TRUE(
535 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000536
537 // Drop all NACK retransmissions. This is to force transmission of a PLI.
538 if (header.timestamp < last_send_timestamp_)
539 return DROP_PACKET;
540
541 if (received_pli_) {
542 if (first_retransmitted_timestamp_ == 0) {
543 first_retransmitted_timestamp_ = header.timestamp;
544 }
545 } else if (rendered_frame_ && rand() % kInverseDropProbability == 0) {
546 return DROP_PACKET;
547 }
548
549 last_send_timestamp_ = header.timestamp;
550 return SEND_PACKET;
551 }
552
553 virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
554 RTCPUtility::RTCPParserV2 parser(packet, length, true);
555 EXPECT_TRUE(parser.IsValid());
556
557 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
558 packet_type != RTCPUtility::kRtcpNotValidCode;
559 packet_type = parser.Iterate()) {
560 if (!nack_enabled_)
561 EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
562
563 if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
564 received_pli_ = true;
565 break;
566 }
567 }
568 return SEND_PACKET;
569 }
570
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000571 virtual void RenderFrame(const I420VideoFrame& video_frame,
572 int time_to_render_ms) OVERRIDE {
573 CriticalSectionScoped crit_(lock_.get());
574 if (first_retransmitted_timestamp_ != 0 &&
575 video_frame.timestamp() > first_retransmitted_timestamp_) {
576 EXPECT_TRUE(received_pli_);
577 observation_complete_->Set();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000578 }
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000579 rendered_frame_ = true;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000580 }
581
582 private:
583 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
584 bool nack_enabled_;
585
586 uint32_t first_retransmitted_timestamp_;
587 uint32_t last_send_timestamp_;
588
589 bool rendered_frame_;
590 bool received_pli_;
591};
592
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000593void CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000594 PliObserver observer(rtp_history_ms > 0);
595
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000596 CreateCalls(Call::Config(observer.SendTransport()),
597 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000598
599 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
600
601 CreateTestConfigs();
602 send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
603 receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org28a11662013-09-19 14:22:12 +0000604 receive_config_.renderer = &observer;
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000605
606 CreateStreams();
607 CreateFrameGenerator();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000608 StartSending();
609
610 // Wait() waits for an event triggered when Pli has been received and frames
611 // have been rendered afterwards.
612 EXPECT_EQ(kEventSignaled, observer.Wait());
613
614 StopSending();
615
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000616 observer.StopSending();
pbos@webrtc.org618a0ec2013-09-09 08:26:30 +0000617
618 DestroyStreams();
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000619}
620
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000621TEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000622 ReceivesPliAndRecovers(1000);
623}
624
625// TODO(pbos): Enable this when 2250 is resolved.
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000626TEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
pbos@webrtc.org8ce445e2013-08-19 16:09:34 +0000627 ReceivesPliAndRecovers(0);
628}
629
pbos@webrtc.org362e3e52013-09-27 10:54:10 +0000630TEST_F(CallTest, SurvivesIncomingRtpPacketsToDestroyedReceiveStream) {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000631 class PacketInputObserver : public PacketReceiver {
632 public:
633 explicit PacketInputObserver(PacketReceiver* receiver)
634 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
635
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000636 EventTypeWrapper Wait() {
637 return delivered_packet_->Wait(kDefaultTimeoutMs);
638 }
pbos@webrtc.org00208582013-09-05 12:38:54 +0000639
640 private:
641 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
642 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
643 return receiver_->DeliverPacket(packet, length);
644 } else {
645 EXPECT_FALSE(receiver_->DeliverPacket(packet, length));
646 delivered_packet_->Set();
647 return false;
648 }
649 }
650
651 PacketReceiver* receiver_;
652 scoped_ptr<EventWrapper> delivered_packet_;
653 };
654
655 test::DirectTransport send_transport, receive_transport;
656
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000657 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
pbos@webrtc.org00208582013-09-05 12:38:54 +0000658 PacketInputObserver input_observer(receiver_call_->Receiver());
659
660 send_transport.SetReceiver(&input_observer);
661 receive_transport.SetReceiver(sender_call_->Receiver());
662
663 CreateTestConfigs();
664
665 CreateStreams();
666 CreateFrameGenerator();
pbos@webrtc.org00208582013-09-05 12:38:54 +0000667 StartSending();
668
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000669 receiver_call_->DestroyVideoReceiveStream(receive_stream_);
pbos@webrtc.org00208582013-09-05 12:38:54 +0000670 receive_stream_ = NULL;
671
672 // Wait() waits for a received packet.
673 EXPECT_EQ(kEventSignaled, input_observer.Wait());
674
675 StopSending();
676
677 DestroyStreams();
678
679 send_transport.StopSending();
680 receive_transport.StopSending();
681}
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000682
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000683void CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
684 static const int kRtpHistoryMs = 1000;
685 static const int kNumCompoundRtcpPacketsToObserve = 10;
686 class RtcpModeObserver : public test::RtpRtcpObserver {
687 public:
pbos@webrtc.orgd05597a2013-12-05 12:11:47 +0000688 explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000689 : test::RtpRtcpObserver(kDefaultTimeoutMs),
690 rtcp_mode_(rtcp_mode),
691 sent_rtp_(0),
692 sent_rtcp_(0) {}
693
694 private:
695 virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
696 if (++sent_rtp_ % 3 == 0)
697 return DROP_PACKET;
698
699 return SEND_PACKET;
700 }
701
702 virtual Action OnReceiveRtcp(const uint8_t* packet,
703 size_t length) OVERRIDE {
704 ++sent_rtcp_;
705 RTCPUtility::RTCPParserV2 parser(packet, length, true);
706 EXPECT_TRUE(parser.IsValid());
707
708 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
709 bool has_report_block = false;
710 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
711 EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
712 if (packet_type == RTCPUtility::kRtcpRrCode) {
713 has_report_block = true;
714 break;
715 }
716 packet_type = parser.Iterate();
717 }
718
719 switch (rtcp_mode_) {
720 case newapi::kRtcpCompound:
721 if (!has_report_block) {
722 ADD_FAILURE() << "Received RTCP packet without receiver report for "
723 "kRtcpCompound.";
724 observation_complete_->Set();
725 }
726
727 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
728 observation_complete_->Set();
729
730 break;
731 case newapi::kRtcpReducedSize:
732 if (!has_report_block)
733 observation_complete_->Set();
734 break;
735 }
736
737 return SEND_PACKET;
738 }
739
740 newapi::RtcpMode rtcp_mode_;
741 int sent_rtp_;
742 int sent_rtcp_;
743 } observer(rtcp_mode);
744
745 CreateCalls(Call::Config(observer.SendTransport()),
746 Call::Config(observer.ReceiveTransport()));
747
748 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
749
750 CreateTestConfigs();
751 send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
752 receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
753 receive_config_.rtp.rtcp_mode = rtcp_mode;
754
755 CreateStreams();
756 CreateFrameGenerator();
757 StartSending();
758
759 EXPECT_EQ(kEventSignaled, observer.Wait())
760 << (rtcp_mode == newapi::kRtcpCompound
761 ? "Timed out before observing enough compound packets."
762 : "Timed out before receiving a non-compound RTCP packet.");
763
764 StopSending();
765 observer.StopSending();
766 DestroyStreams();
767}
768
769TEST_F(CallTest, UsesRtcpCompoundMode) {
770 RespectsRtcpMode(newapi::kRtcpCompound);
771}
772
773TEST_F(CallTest, UsesRtcpReducedSizeMode) {
774 RespectsRtcpMode(newapi::kRtcpReducedSize);
775}
776
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000777// Test sets up a Call multiple senders with different resolutions and SSRCs.
778// Another is set up to receive all three of these with different renderers.
779// Each renderer verifies that it receives the expected resolution, and as soon
780// as every renderer has received a frame, the test finishes.
781TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
782 static const size_t kNumStreams = 3;
783
784 class VideoOutputObserver : public VideoRenderer {
785 public:
786 VideoOutputObserver(int width, int height)
787 : width_(width), height_(height), done_(EventWrapper::Create()) {}
788
789 virtual void RenderFrame(const I420VideoFrame& video_frame,
790 int time_to_render_ms) OVERRIDE {
791 EXPECT_EQ(width_, video_frame.width());
792 EXPECT_EQ(height_, video_frame.height());
793 done_->Set();
794 }
795
pbos@webrtc.org51e01012013-10-17 14:14:42 +0000796 void Wait() { done_->Wait(kDefaultTimeoutMs); }
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000797
798 private:
799 int width_;
800 int height_;
801 scoped_ptr<EventWrapper> done_;
802 };
803
804 struct {
805 uint32_t ssrc;
806 int width;
807 int height;
808 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
809
810 test::DirectTransport sender_transport, receiver_transport;
811 scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
812 scoped_ptr<Call> receiver_call(
813 Call::Create(Call::Config(&receiver_transport)));
814 sender_transport.SetReceiver(receiver_call->Receiver());
815 receiver_transport.SetReceiver(sender_call->Receiver());
816
817 VideoSendStream* send_streams[kNumStreams];
818 VideoReceiveStream* receive_streams[kNumStreams];
819
820 VideoOutputObserver* observers[kNumStreams];
821 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
822
823 for (size_t i = 0; i < kNumStreams; ++i) {
824 uint32_t ssrc = codec_settings[i].ssrc;
825 int width = codec_settings[i].width;
826 int height = codec_settings[i].height;
827 observers[i] = new VideoOutputObserver(width, height);
828
829 VideoReceiveStream::Config receive_config =
830 receiver_call->GetDefaultReceiveConfig();
831 receive_config.renderer = observers[i];
pbos@webrtc.org4b50db12013-12-03 10:13:04 +0000832 receive_config.rtp.remote_ssrc = ssrc;
833 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000834 receive_streams[i] =
835 receiver_call->CreateVideoReceiveStream(receive_config);
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000836 receive_streams[i]->StartReceiving();
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000837
838 VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
839 send_config.rtp.ssrcs.push_back(ssrc);
840 send_config.codec.width = width;
841 send_config.codec.height = height;
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000842 send_streams[i] = sender_call->CreateVideoSendStream(send_config);
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000843 send_streams[i]->StartSending();
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000844
845 frame_generators[i] = test::FrameGeneratorCapturer::Create(
846 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
847 frame_generators[i]->Start();
848 }
849
850 for (size_t i = 0; i < kNumStreams; ++i) {
851 observers[i]->Wait();
852 }
853
854 for (size_t i = 0; i < kNumStreams; ++i) {
855 frame_generators[i]->Stop();
856 delete frame_generators[i];
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000857 sender_call->DestroyVideoSendStream(send_streams[i]);
858 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
pbos@webrtc.orgc5080a92013-10-01 11:33:24 +0000859 delete observers[i];
860 }
861
862 sender_transport.StopSending();
863 receiver_transport.StopSending();
864}
stefan@webrtc.orge0284102013-11-18 11:45:11 +0000865
866class SyncRtcpObserver : public test::RtpRtcpObserver {
867 public:
pbos@webrtc.orgd05597a2013-12-05 12:11:47 +0000868 explicit SyncRtcpObserver(int delay_ms)
stefan@webrtc.orge0284102013-11-18 11:45:11 +0000869 : test::RtpRtcpObserver(kLongTimeoutMs, delay_ms),
870 critical_section_(CriticalSectionWrapper::CreateCriticalSection()) {}
871
872 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
873 RTCPUtility::RTCPParserV2 parser(packet, length, true);
874 EXPECT_TRUE(parser.IsValid());
875
876 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
877 packet_type != RTCPUtility::kRtcpNotValidCode;
878 packet_type = parser.Iterate()) {
879 if (packet_type == RTCPUtility::kRtcpSrCode) {
880 const RTCPUtility::RTCPPacket& packet = parser.Packet();
881 synchronization::RtcpMeasurement ntp_rtp_pair(
882 packet.SR.NTPMostSignificant,
883 packet.SR.NTPLeastSignificant,
884 packet.SR.RTPTimestamp);
885 StoreNtpRtpPair(ntp_rtp_pair);
886 }
887 }
888 return SEND_PACKET;
889 }
890
891 int64_t RtpTimestampToNtp(uint32_t timestamp) const {
892 CriticalSectionScoped cs(critical_section_.get());
893 int64_t timestamp_in_ms = -1;
894 if (ntp_rtp_pairs_.size() == 2) {
895 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the
896 // RTCP sender where it sends RTCP SR before any RTP packets, which leads
897 // to a bogus NTP/RTP mapping.
898 synchronization::RtpToNtpMs(timestamp, ntp_rtp_pairs_, &timestamp_in_ms);
899 return timestamp_in_ms;
900 }
901 return -1;
902 }
903
904 private:
905 void StoreNtpRtpPair(synchronization::RtcpMeasurement ntp_rtp_pair) {
906 CriticalSectionScoped cs(critical_section_.get());
907 for (synchronization::RtcpList::iterator it = ntp_rtp_pairs_.begin();
908 it != ntp_rtp_pairs_.end();
909 ++it) {
910 if (ntp_rtp_pair.ntp_secs == it->ntp_secs &&
911 ntp_rtp_pair.ntp_frac == it->ntp_frac) {
912 // This RTCP has already been added to the list.
913 return;
914 }
915 }
916 // We need two RTCP SR reports to map between RTP and NTP. More than two
917 // will not improve the mapping.
918 if (ntp_rtp_pairs_.size() == 2) {
919 ntp_rtp_pairs_.pop_back();
920 }
921 ntp_rtp_pairs_.push_front(ntp_rtp_pair);
922 }
923
924 scoped_ptr<CriticalSectionWrapper> critical_section_;
925 synchronization::RtcpList ntp_rtp_pairs_;
926};
927
928class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer {
929 static const int kInSyncThresholdMs = 50;
930 static const int kStartupTimeMs = 2000;
931 static const int kMinRunTimeMs = 30000;
932
933 public:
934 VideoRtcpAndSyncObserver(Clock* clock,
935 int voe_channel,
936 VoEVideoSync* voe_sync,
937 SyncRtcpObserver* audio_observer)
938 : SyncRtcpObserver(0),
939 clock_(clock),
940 voe_channel_(voe_channel),
941 voe_sync_(voe_sync),
942 audio_observer_(audio_observer),
943 creation_time_ms_(clock_->TimeInMilliseconds()),
944 first_time_in_sync_(-1) {}
945
946 virtual void RenderFrame(const I420VideoFrame& video_frame,
947 int time_to_render_ms) OVERRIDE {
948 int64_t now_ms = clock_->TimeInMilliseconds();
949 uint32_t playout_timestamp = 0;
950 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0)
951 return;
952 int64_t latest_audio_ntp =
953 audio_observer_->RtpTimestampToNtp(playout_timestamp);
954 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp());
955 if (latest_audio_ntp < 0 || latest_video_ntp < 0)
956 return;
957 int time_until_render_ms =
958 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms));
959 latest_video_ntp += time_until_render_ms;
960 int64_t stream_offset = latest_audio_ntp - latest_video_ntp;
961 std::stringstream ss;
962 ss << stream_offset;
963 webrtc::test::PrintResult(
964 "stream_offset", "", "synchronization", ss.str(), "ms", false);
965 int64_t time_since_creation = now_ms - creation_time_ms_;
966 // During the first couple of seconds audio and video can falsely be
967 // estimated as being synchronized. We don't want to trigger on those.
968 if (time_since_creation < kStartupTimeMs)
969 return;
970 if (abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) {
971 if (first_time_in_sync_ == -1) {
972 first_time_in_sync_ = now_ms;
973 webrtc::test::PrintResult("sync_convergence_time",
974 "",
975 "synchronization",
976 time_since_creation,
977 "ms",
978 false);
979 }
980 if (time_since_creation > kMinRunTimeMs)
981 observation_complete_->Set();
982 }
983 }
984
985 private:
986 Clock* clock_;
987 int voe_channel_;
988 VoEVideoSync* voe_sync_;
989 SyncRtcpObserver* audio_observer_;
990 int64_t creation_time_ms_;
991 int64_t first_time_in_sync_;
992};
993
994TEST_F(CallTest, PlaysOutAudioAndVideoInSync) {
995 VoiceEngine* voice_engine = VoiceEngine::Create();
996 VoEBase* voe_base = VoEBase::GetInterface(voice_engine);
997 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine);
998 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine);
999 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine);
1000 ResourceManager resource_manager;
1001 const std::string audio_filename = resource_manager.long_audio_file_path();
1002 ASSERT_STRNE("", audio_filename.c_str());
1003 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(),
1004 audio_filename);
1005 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, NULL));
1006 int channel = voe_base->CreateChannel();
1007
1008 const int kVoiceDelayMs = 500;
1009 SyncRtcpObserver audio_observer(kVoiceDelayMs);
1010 VideoRtcpAndSyncObserver observer(
1011 Clock::GetRealTimeClock(), channel, voe_sync, &audio_observer);
1012
1013 Call::Config receiver_config(observer.ReceiveTransport());
1014 receiver_config.voice_engine = voice_engine;
1015 CreateCalls(Call::Config(observer.SendTransport()), receiver_config);
1016 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000};
1017 EXPECT_EQ(0, voe_codec->SetSendCodec(channel, isac));
1018
1019 class VoicePacketReceiver : public PacketReceiver {
1020 public:
1021 VoicePacketReceiver(int channel, VoENetwork* voe_network)
1022 : channel_(channel),
1023 voe_network_(voe_network),
1024 parser_(RtpHeaderParser::Create()) {}
1025 virtual bool DeliverPacket(const uint8_t* packet, size_t length) {
1026 int ret;
1027 if (parser_->IsRtcp(packet, static_cast<int>(length))) {
1028 ret = voe_network_->ReceivedRTCPPacket(
1029 channel_, packet, static_cast<unsigned int>(length));
1030 } else {
1031 ret = voe_network_->ReceivedRTPPacket(
1032 channel_, packet, static_cast<unsigned int>(length));
1033 }
1034 return ret == 0;
1035 }
1036
1037 private:
1038 int channel_;
1039 VoENetwork* voe_network_;
1040 scoped_ptr<RtpHeaderParser> parser_;
1041 } voe_packet_receiver(channel, voe_network);
1042
1043 audio_observer.SetReceivers(&voe_packet_receiver, &voe_packet_receiver);
1044
1045 internal::TransportAdapter transport_adapter(audio_observer.SendTransport());
1046 EXPECT_EQ(0,
1047 voe_network->RegisterExternalTransport(channel, transport_adapter));
1048
1049 observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
1050
1051 CreateTestConfigs();
1052 send_config_.rtp.nack.rtp_history_ms = 1000;
1053 receive_config_.rtp.nack.rtp_history_ms = 1000;
1054 receive_config_.renderer = &observer;
1055 receive_config_.audio_channel_id = channel;
1056
1057 CreateStreams();
1058 CreateFrameGenerator();
1059 StartSending();
1060
1061 fake_audio_device.Start();
1062 EXPECT_EQ(0, voe_base->StartPlayout(channel));
1063 EXPECT_EQ(0, voe_base->StartReceive(channel));
1064 EXPECT_EQ(0, voe_base->StartSend(channel));
1065
1066 EXPECT_EQ(kEventSignaled, observer.Wait())
1067 << "Timed out while waiting for audio and video to be synchronized.";
1068
1069 EXPECT_EQ(0, voe_base->StopSend(channel));
1070 EXPECT_EQ(0, voe_base->StopReceive(channel));
1071 EXPECT_EQ(0, voe_base->StopPlayout(channel));
1072 fake_audio_device.Stop();
1073
1074 StopSending();
1075 observer.StopSending();
1076 audio_observer.StopSending();
1077
1078 voe_base->DeleteChannel(channel);
1079 voe_base->Release();
1080 voe_codec->Release();
1081 voe_network->Release();
1082 voe_sync->Release();
1083 DestroyStreams();
1084 VoiceEngine::Delete(voice_engine);
1085}
1086
sprang@webrtc.org2e98d452013-11-26 11:41:59 +00001087TEST_F(CallTest, ObserversEncodedFrames) {
1088 class EncodedFrameTestObserver : public EncodedFrameObserver {
1089 public:
1090 EncodedFrameTestObserver() : length_(0),
1091 frame_type_(kFrameEmpty),
1092 called_(EventWrapper::Create()) {}
1093 virtual ~EncodedFrameTestObserver() {}
1094
1095 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1096 frame_type_ = encoded_frame.frame_type_;
1097 length_ = encoded_frame.length_;
1098 buffer_.reset(new uint8_t[length_]);
1099 memcpy(buffer_.get(), encoded_frame.data_, length_);
1100 called_->Set();
1101 }
1102
1103 EventTypeWrapper Wait() {
1104 return called_->Wait(kDefaultTimeoutMs);
1105 }
1106
1107 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1108 ASSERT_EQ(length_, observer.length_)
1109 << "Observed frames are of different lengths.";
1110 EXPECT_EQ(frame_type_, observer.frame_type_)
1111 << "Observed frames have different frame types.";
1112 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1113 << "Observed encoded frames have different content.";
1114 }
1115
1116 private:
1117 scoped_ptr<uint8_t[]> buffer_;
1118 size_t length_;
1119 FrameType frame_type_;
1120 scoped_ptr<EventWrapper> called_;
1121 };
1122
1123 EncodedFrameTestObserver post_encode_observer;
1124 EncodedFrameTestObserver pre_decode_observer;
1125
1126 test::DirectTransport sender_transport, receiver_transport;
1127
1128 CreateCalls(Call::Config(&sender_transport),
1129 Call::Config(&receiver_transport));
1130
1131 sender_transport.SetReceiver(receiver_call_->Receiver());
1132 receiver_transport.SetReceiver(sender_call_->Receiver());
1133
1134 CreateTestConfigs();
1135 send_config_.post_encode_callback = &post_encode_observer;
1136 receive_config_.pre_decode_callback = &pre_decode_observer;
1137
1138 CreateStreams();
1139 StartSending();
1140
1141 scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
1142 send_config_.codec.width, send_config_.codec.height));
1143 send_stream_->Input()->PutFrame(frame_generator->NextFrame(), 0);
1144
1145 EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
1146 << "Timed out while waiting for send-side encoded-frame callback.";
1147
1148 EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
1149 << "Timed out while waiting for pre-decode encoded-frame callback.";
1150
1151 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1152
1153 StopSending();
1154
1155 sender_transport.StopSending();
1156 receiver_transport.StopSending();
1157
1158 DestroyStreams();
1159}
pbos@webrtc.orgce851092013-08-05 12:01:36 +00001160} // namespace webrtc