blob: 0d3c8ee9bd94ea49c1bfd2acb0a073934fe5187b [file] [log] [blame]
pbos@webrtc.org2f02da82013-07-09 08:02:33 +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 */
10#include <stdio.h>
11
12#include <deque>
13#include <map>
14
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000015#include "gflags/gflags.h"
pbos@webrtc.orge8350192013-07-10 15:02:02 +000016#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000017
pbos@webrtc.org24e20892013-10-28 16:32:01 +000018#include "webrtc/call.h"
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000019#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
20#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +000021#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000022#include "webrtc/system_wrappers/interface/clock.h"
23#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24#include "webrtc/system_wrappers/interface/event_wrapper.h"
25#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.orga24c3562013-10-16 11:05:37 +000026#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000027#include "webrtc/test/direct_transport.h"
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +000028#include "webrtc/test/encoder_settings.h"
29#include "webrtc/test/fake_encoder.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000030#include "webrtc/test/frame_generator_capturer.h"
pbos@webrtc.org24e20892013-10-28 16:32:01 +000031#include "webrtc/test/statistics.h"
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +000032#include "webrtc/test/testsupport/fileutils.h"
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000033#include "webrtc/typedefs.h"
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000034
35DEFINE_int32(seconds, 10, "Seconds to run each clip.");
36
37namespace webrtc {
38
pbos@webrtc.org4b50db12013-12-03 10:13:04 +000039static const uint32_t kSendSsrc = 0x654321;
40
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000041struct FullStackTestParams {
42 const char* test_label;
43 struct {
44 const char* name;
pbos@webrtc.orge9bd2992013-07-09 14:04:46 +000045 size_t width, height;
46 int fps;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000047 } clip;
pbos@webrtc.orge9bd2992013-07-09 14:04:46 +000048 unsigned int bitrate;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000049 double avg_psnr_threshold;
50 double avg_ssim_threshold;
51};
52
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +000053FullStackTestParams paris_qcif = {
54 "net_delay_0_0_plr_0", {"paris_qcif", 176, 144, 30}, 300, 36.0, 0.96};
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000055
56// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +000057FullStackTestParams foreman_cif = {
58 "foreman_cif_net_delay_0_0_plr_0",
59 {"foreman_cif", 352, 288, 30},
60 700,
61 0.0,
62 0.0};
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000063
64class FullStackTest : public ::testing::TestWithParam<FullStackTestParams> {
65 protected:
66 std::map<uint32_t, bool> reserved_ssrcs_;
67};
68
pbos@webrtc.orgc1797062013-08-23 09:19:30 +000069class VideoAnalyzer : public PacketReceiver,
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000070 public newapi::Transport,
pbos@webrtc.orgc1797062013-08-23 09:19:30 +000071 public VideoRenderer,
72 public VideoSendStreamInput {
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000073 public:
pbos@webrtc.orgc1797062013-08-23 09:19:30 +000074 VideoAnalyzer(VideoSendStreamInput* input,
75 Transport* transport,
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000076 const char* test_label,
77 double avg_psnr_threshold,
78 double avg_ssim_threshold,
pbos@webrtc.orga24c3562013-10-16 11:05:37 +000079 int duration_frames)
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000080 : input_(input),
81 transport_(transport),
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000082 receiver_(NULL),
83 test_label_(test_label),
pbos@webrtc.orga24c3562013-10-16 11:05:37 +000084 dropped_frames_(0),
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000085 rtp_timestamp_delta_(0),
86 first_send_frame_(NULL),
87 last_render_time_(0),
88 avg_psnr_threshold_(avg_psnr_threshold),
89 avg_ssim_threshold_(avg_ssim_threshold),
90 frames_left_(duration_frames),
91 crit_(CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.orga24c3562013-10-16 11:05:37 +000092 comparison_lock_(CriticalSectionWrapper::CreateCriticalSection()),
93 comparison_thread_(ThreadWrapper::CreateThread(&FrameComparisonThread,
94 this)),
95 trigger_(EventWrapper::Create()) {
96 unsigned int id;
97 EXPECT_TRUE(comparison_thread_->Start(id));
98 }
pbos@webrtc.org2f02da82013-07-09 08:02:33 +000099
100 ~VideoAnalyzer() {
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000101 EXPECT_TRUE(comparison_thread_->Stop());
102
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000103 while (!frames_.empty()) {
104 delete frames_.back();
105 frames_.pop_back();
106 }
107 while (!frame_pool_.empty()) {
108 delete frame_pool_.back();
109 frame_pool_.pop_back();
110 }
111 }
112
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000113 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; }
114
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000115 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000116 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
117 RTPHeader header;
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000118 parser->Parse(packet, static_cast<int>(length), &header);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000119 {
120 CriticalSectionScoped cs(crit_.get());
121 recv_times_[header.timestamp - rtp_timestamp_delta_] =
122 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
123 }
124
125 return receiver_->DeliverPacket(packet, length);
126 }
127
pbos@webrtc.orgc33d37c2013-12-11 16:26:16 +0000128 virtual void PutFrame(const I420VideoFrame& video_frame) OVERRIDE {
129 ADD_FAILURE() << "PutFrame() should not have been called in this test.";
130 }
131
132 virtual void SwapFrame(I420VideoFrame* video_frame) OVERRIDE {
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000133 I420VideoFrame* copy = NULL;
134 {
135 CriticalSectionScoped cs(crit_.get());
136 if (frame_pool_.size() > 0) {
137 copy = frame_pool_.front();
138 frame_pool_.pop_front();
139 }
140 }
141 if (copy == NULL)
142 copy = new I420VideoFrame();
143
pbos@webrtc.orgc33d37c2013-12-11 16:26:16 +0000144 copy->CopyFrame(*video_frame);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000145 copy->set_timestamp(copy->render_time_ms() * 90);
146
147 {
148 CriticalSectionScoped cs(crit_.get());
149 if (first_send_frame_ == NULL && rtp_timestamp_delta_ == 0)
150 first_send_frame_ = copy;
151
152 frames_.push_back(copy);
153 }
154
pbos@webrtc.orgc33d37c2013-12-11 16:26:16 +0000155 input_->SwapFrame(video_frame);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000156 }
157
pbos@webrtc.org3009c812013-11-20 12:17:04 +0000158 virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000159 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
160 RTPHeader header;
161 parser->Parse(packet, static_cast<int>(length), &header);
162
163 {
164 CriticalSectionScoped cs(crit_.get());
165 if (rtp_timestamp_delta_ == 0) {
166 rtp_timestamp_delta_ =
167 header.timestamp - first_send_frame_->timestamp();
168 first_send_frame_ = NULL;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000169 }
pbos@webrtc.org3a74d402013-08-05 09:29:50 +0000170 send_times_[header.timestamp - rtp_timestamp_delta_] =
171 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000172 }
173
pbos@webrtc.org3009c812013-11-20 12:17:04 +0000174 return transport_->SendRtp(packet, length);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000175 }
176
pbos@webrtc.org3009c812013-11-20 12:17:04 +0000177 virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
178 return transport_->SendRtcp(packet, length);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000179 }
180
181 virtual void RenderFrame(const I420VideoFrame& video_frame,
182 int time_to_render_ms) OVERRIDE {
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000183 int64_t render_time_ms =
184 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000185 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_;
186
187 {
188 CriticalSectionScoped cs(crit_.get());
189 while (frames_.front()->timestamp() < send_timestamp) {
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000190 AddFrameComparison(
191 frames_.front(), &last_rendered_frame_, true, render_time_ms);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000192 frame_pool_.push_back(frames_.front());
193 frames_.pop_front();
194 }
195
196 I420VideoFrame* reference_frame = frames_.front();
197 frames_.pop_front();
198 assert(reference_frame != NULL);
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000199 EXPECT_EQ(reference_frame->timestamp(), send_timestamp);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000200 assert(reference_frame->timestamp() == send_timestamp);
201
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000202 AddFrameComparison(reference_frame, &video_frame, false, render_time_ms);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000203 frame_pool_.push_back(reference_frame);
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000204 }
205
206 last_rendered_frame_.CopyFrame(video_frame);
207 }
208
209 void Wait() { trigger_->Wait(120 * 1000); }
210
211 VideoSendStreamInput* input_;
212 Transport* transport_;
213 PacketReceiver* receiver_;
214
215 private:
216 struct FrameComparison {
217 FrameComparison(const I420VideoFrame* reference,
218 const I420VideoFrame* render,
219 bool dropped,
220 int64_t send_time_ms,
221 int64_t recv_time_ms,
222 int64_t render_time_ms)
223 : dropped(dropped),
224 send_time_ms(send_time_ms),
225 recv_time_ms(recv_time_ms),
226 render_time_ms(render_time_ms) {
227 this->reference.CopyFrame(*reference);
228 this->render.CopyFrame(*render);
229 }
230
231 FrameComparison(const FrameComparison& compare)
232 : dropped(compare.dropped),
233 send_time_ms(compare.send_time_ms),
234 recv_time_ms(compare.recv_time_ms),
235 render_time_ms(compare.render_time_ms) {
236 this->reference.CopyFrame(compare.reference);
237 this->render.CopyFrame(compare.render);
238 }
239
240 ~FrameComparison() {}
241
242 I420VideoFrame reference;
243 I420VideoFrame render;
244 bool dropped;
245 int64_t send_time_ms;
246 int64_t recv_time_ms;
247 int64_t render_time_ms;
248 };
249
250 void AddFrameComparison(const I420VideoFrame* reference,
251 const I420VideoFrame* render,
252 bool dropped,
253 int64_t render_time_ms) {
254 int64_t send_time_ms = send_times_[reference->timestamp()];
255 send_times_.erase(reference->timestamp());
256 int64_t recv_time_ms = recv_times_[reference->timestamp()];
257 recv_times_.erase(reference->timestamp());
258
259 CriticalSectionScoped crit(comparison_lock_.get());
260 comparisons_.push_back(FrameComparison(reference,
261 render,
262 dropped,
263 send_time_ms,
264 recv_time_ms,
265 render_time_ms));
266 }
267
268 static bool FrameComparisonThread(void* obj) {
269 return static_cast<VideoAnalyzer*>(obj)->CompareFrames();
270 }
271
272 bool CompareFrames() {
273 assert(frames_left_ > 0);
274
275 I420VideoFrame reference;
276 I420VideoFrame render;
277 bool dropped;
278 int64_t send_time_ms;
279 int64_t recv_time_ms;
280 int64_t render_time_ms;
281
282 SleepMs(10);
283
284 while (true) {
285 {
286 CriticalSectionScoped crit(comparison_lock_.get());
287 if (comparisons_.empty())
288 return true;
289 reference.SwapFrame(&comparisons_.front().reference);
290 render.SwapFrame(&comparisons_.front().render);
291 dropped = comparisons_.front().dropped;
292 send_time_ms = comparisons_.front().send_time_ms;
293 recv_time_ms = comparisons_.front().recv_time_ms;
294 render_time_ms = comparisons_.front().render_time_ms;
295 comparisons_.pop_front();
296 }
297
298 PerformFrameComparison(&reference,
299 &render,
300 dropped,
301 send_time_ms,
302 recv_time_ms,
303 render_time_ms);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000304
305 if (--frames_left_ == 0) {
306 PrintResult("psnr", psnr_, " dB");
307 PrintResult("ssim", ssim_, "");
308 PrintResult("sender_time", sender_time_, " ms");
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000309 printf(
310 "RESULT dropped_frames: %s = %d\n", test_label_, dropped_frames_);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000311 PrintResult("receiver_time", receiver_time_, " ms");
312 PrintResult("total_delay_incl_network", end_to_end_, " ms");
313 PrintResult("time_between_rendered_frames", rendered_delta_, " ms");
314 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_);
315 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_);
316 trigger_->Set();
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000317
318 return false;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000319 }
320 }
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000321 }
322
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000323 void PerformFrameComparison(const I420VideoFrame* reference,
324 const I420VideoFrame* render,
325 bool dropped,
326 int64_t send_time_ms,
327 int64_t recv_time_ms,
328 int64_t render_time_ms) {
329 psnr_.AddSample(I420PSNR(reference, render));
330 ssim_.AddSample(I420SSIM(reference, render));
331 if (dropped) {
332 ++dropped_frames_;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000333 return;
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000334 }
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000335 if (last_render_time_ != 0)
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000336 rendered_delta_.AddSample(render_time_ms - last_render_time_);
337 last_render_time_ = render_time_ms;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000338
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000339 int64_t input_time_ms = reference->render_time_ms();
340 sender_time_.AddSample(send_time_ms - input_time_ms);
341 receiver_time_.AddSample(render_time_ms - recv_time_ms);
342 end_to_end_.AddSample(render_time_ms - input_time_ms);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000343 }
344
345 void PrintResult(const char* result_type,
346 test::Statistics stats,
347 const char* unit) {
348 printf("RESULT %s: %s = {%f, %f}%s\n",
349 result_type,
350 test_label_,
351 stats.Mean(),
352 stats.StandardDeviation(),
353 unit);
354 }
355
356 const char* test_label_;
357 test::Statistics sender_time_;
358 test::Statistics receiver_time_;
359 test::Statistics psnr_;
360 test::Statistics ssim_;
361 test::Statistics end_to_end_;
362 test::Statistics rendered_delta_;
363
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000364 int dropped_frames_;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000365 std::deque<I420VideoFrame*> frames_;
366 std::deque<I420VideoFrame*> frame_pool_;
367 I420VideoFrame last_rendered_frame_;
368 std::map<uint32_t, int64_t> send_times_;
369 std::map<uint32_t, int64_t> recv_times_;
370 uint32_t rtp_timestamp_delta_;
371 I420VideoFrame* first_send_frame_;
372 int64_t last_render_time_;
373 double avg_psnr_threshold_;
374 double avg_ssim_threshold_;
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000375 int frames_left_;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000376 scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000377 scoped_ptr<CriticalSectionWrapper> comparison_lock_;
378 scoped_ptr<ThreadWrapper> comparison_thread_;
379 std::deque<FrameComparison> comparisons_;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000380 scoped_ptr<EventWrapper> trigger_;
381};
382
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000383TEST_P(FullStackTest, NoPacketLoss) {
pbos@webrtc.org4b50db12013-12-03 10:13:04 +0000384 static const uint32_t kReceiverLocalSsrc = 0x123456;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000385 FullStackTestParams params = GetParam();
386
pbos@webrtc.orgfe881f62013-08-12 12:59:04 +0000387 test::DirectTransport transport;
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000388 VideoAnalyzer analyzer(NULL,
389 &transport,
390 params.test_label,
391 params.avg_psnr_threshold,
392 params.avg_ssim_threshold,
393 FLAGS_seconds * params.clip.fps);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000394
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000395 Call::Config call_config(&analyzer);
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +0000396
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000397 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000398 analyzer.SetReceiver(call->Receiver());
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000399 transport.SetReceiver(&analyzer);
400
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000401 VideoSendStream::Config send_config = call->GetDefaultSendConfig();
pbos@webrtc.org4b50db12013-12-03 10:13:04 +0000402 send_config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000403
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000404 scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
405 send_config.encoder_settings =
406 test::CreateEncoderSettings(encoder.get(), "VP8", 124, 1);
407 VideoStream* stream = &send_config.encoder_settings.streams[0];
408 stream->width = params.clip.width;
409 stream->height = params.clip.height;
410 stream->min_bitrate_bps = stream->target_bitrate_bps =
411 stream->max_bitrate_bps = params.bitrate * 1000;
412 stream->max_framerate = params.clip.fps;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000413
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000414 VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000415 analyzer.input_ = send_stream->Input();
416
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000417 scoped_ptr<test::FrameGeneratorCapturer> file_capturer(
andresp@webrtc.org28631e72013-09-19 12:14:03 +0000418 test::FrameGeneratorCapturer::CreateFromYuvFile(
pbos@webrtc.org7deb3352013-08-21 12:07:37 +0000419 &analyzer,
andresp@webrtc.org28631e72013-09-19 12:14:03 +0000420 test::ResourcePath(params.clip.name, "yuv").c_str(),
421 params.clip.width,
422 params.clip.height,
423 params.clip.fps,
424 Clock::GetRealTimeClock()));
pbos@webrtc.orga24c3562013-10-16 11:05:37 +0000425 ASSERT_TRUE(file_capturer.get() != NULL)
426 << "Could not create capturer for " << params.clip.name
427 << ".yuv. Is this resource file present?";
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000428
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000429 VideoReceiveStream::Config receive_config = call->GetDefaultReceiveConfig();
pbos@webrtc.orge2a7a772014-03-19 08:43:57 +0000430 VideoCodec codec =
431 test::CreateDecoderVideoCodec(send_config.encoder_settings);
432 receive_config.codecs.push_back(codec);
pbos@webrtc.org4b50db12013-12-03 10:13:04 +0000433 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
434 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000435 receive_config.renderer = &analyzer;
436
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000437 VideoReceiveStream* receive_stream =
pbos@webrtc.org964d78e2013-11-20 10:40:25 +0000438 call->CreateVideoReceiveStream(receive_config);
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000439
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000440 receive_stream->StartReceiving();
441 send_stream->StartSending();
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000442
443 file_capturer->Start();
444
445 analyzer.Wait();
446
447 file_capturer->Stop();
pbos@webrtc.org7f9f8402013-11-20 11:36:47 +0000448 send_stream->StopSending();
449 receive_stream->StopReceiving();
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000450
pbos@webrtc.org12a93e02013-11-21 13:49:43 +0000451 call->DestroyVideoReceiveStream(receive_stream);
452 call->DestroyVideoSendStream(send_stream);
pbos@webrtc.orgfe881f62013-08-12 12:59:04 +0000453
454 transport.StopSending();
pbos@webrtc.org2f02da82013-07-09 08:02:33 +0000455}
456
457INSTANTIATE_TEST_CASE_P(FullStack,
458 FullStackTest,
459 ::testing::Values(paris_qcif, foreman_cif));
460
461} // namespace webrtc