blob: f4e07e0495705fea0355932d86166e9e4680a2cf [file] [log] [blame]
pbos@webrtc.orgaf8d5af2013-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.orgaf8d5af2013-07-09 08:02:33 +000015#include "gflags/gflags.h"
pbos@webrtc.org69215d82013-07-10 15:02:02 +000016#include "testing/gtest/include/gtest/gtest.h"
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000017
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000018#include "webrtc/call.h"
pbos@webrtc.orgaf8d5af2013-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"
21#include "webrtc/system_wrappers/interface/clock.h"
22#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
23#include "webrtc/system_wrappers/interface/event_wrapper.h"
24#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org94015242013-10-16 11:05:37 +000025#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000026#include "webrtc/test/testsupport/fileutils.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000027#include "webrtc/test/direct_transport.h"
28#include "webrtc/test/frame_generator_capturer.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000029#include "webrtc/test/statistics.h"
30#include "webrtc/test/video_renderer.h"
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000031#include "webrtc/typedefs.h"
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000032
33DEFINE_int32(seconds, 10, "Seconds to run each clip.");
34
35namespace webrtc {
36
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +000037static const uint32_t kSendSsrc = 0x654321;
38
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000039struct FullStackTestParams {
40 const char* test_label;
41 struct {
42 const char* name;
pbos@webrtc.orgf3f13582013-07-09 14:04:46 +000043 size_t width, height;
44 int fps;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000045 } clip;
pbos@webrtc.orgf3f13582013-07-09 14:04:46 +000046 unsigned int bitrate;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000047 double avg_psnr_threshold;
48 double avg_ssim_threshold;
49};
50
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000051FullStackTestParams paris_qcif = {
52 "net_delay_0_0_plr_0", {"paris_qcif", 176, 144, 30}, 300, 36.0, 0.96};
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000053
54// TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000055FullStackTestParams foreman_cif = {
56 "foreman_cif_net_delay_0_0_plr_0",
57 {"foreman_cif", 352, 288, 30},
58 700,
59 0.0,
60 0.0};
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000061
62class FullStackTest : public ::testing::TestWithParam<FullStackTestParams> {
63 protected:
64 std::map<uint32_t, bool> reserved_ssrcs_;
65};
66
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000067class VideoAnalyzer : public PacketReceiver,
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000068 public newapi::Transport,
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000069 public VideoRenderer,
70 public VideoSendStreamInput {
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000071 public:
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000072 VideoAnalyzer(VideoSendStreamInput* input,
73 Transport* transport,
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000074 const char* test_label,
75 double avg_psnr_threshold,
76 double avg_ssim_threshold,
pbos@webrtc.org94015242013-10-16 11:05:37 +000077 int duration_frames)
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000078 : input_(input),
79 transport_(transport),
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000080 receiver_(NULL),
81 test_label_(test_label),
pbos@webrtc.org94015242013-10-16 11:05:37 +000082 dropped_frames_(0),
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000083 rtp_timestamp_delta_(0),
84 first_send_frame_(NULL),
85 last_render_time_(0),
86 avg_psnr_threshold_(avg_psnr_threshold),
87 avg_ssim_threshold_(avg_ssim_threshold),
88 frames_left_(duration_frames),
89 crit_(CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.org94015242013-10-16 11:05:37 +000090 comparison_lock_(CriticalSectionWrapper::CreateCriticalSection()),
91 comparison_thread_(ThreadWrapper::CreateThread(&FrameComparisonThread,
92 this)),
93 trigger_(EventWrapper::Create()) {
94 unsigned int id;
95 EXPECT_TRUE(comparison_thread_->Start(id));
96 }
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +000097
98 ~VideoAnalyzer() {
pbos@webrtc.org94015242013-10-16 11:05:37 +000099 EXPECT_TRUE(comparison_thread_->Stop());
100
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000101 while (!frames_.empty()) {
102 delete frames_.back();
103 frames_.pop_back();
104 }
105 while (!frame_pool_.empty()) {
106 delete frame_pool_.back();
107 frame_pool_.pop_back();
108 }
109 }
110
pbos@webrtc.org94015242013-10-16 11:05:37 +0000111 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; }
112
pbos@webrtc.org40523702013-08-05 12:49:22 +0000113 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000114 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
115 RTPHeader header;
pbos@webrtc.org40523702013-08-05 12:49:22 +0000116 parser->Parse(packet, static_cast<int>(length), &header);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000117 {
118 CriticalSectionScoped cs(crit_.get());
119 recv_times_[header.timestamp - rtp_timestamp_delta_] =
120 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
121 }
122
123 return receiver_->DeliverPacket(packet, length);
124 }
125
126 virtual void PutFrame(const I420VideoFrame& video_frame,
127 uint32_t delta_capture_ms) OVERRIDE {
128 I420VideoFrame* copy = NULL;
129 {
130 CriticalSectionScoped cs(crit_.get());
131 if (frame_pool_.size() > 0) {
132 copy = frame_pool_.front();
133 frame_pool_.pop_front();
134 }
135 }
136 if (copy == NULL)
137 copy = new I420VideoFrame();
138
139 copy->CopyFrame(video_frame);
140 copy->set_timestamp(copy->render_time_ms() * 90);
141
142 {
143 CriticalSectionScoped cs(crit_.get());
144 if (first_send_frame_ == NULL && rtp_timestamp_delta_ == 0)
145 first_send_frame_ = copy;
146
147 frames_.push_back(copy);
148 }
149
150 input_->PutFrame(video_frame, delta_capture_ms);
151 }
152
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000153 virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000154 scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
155 RTPHeader header;
156 parser->Parse(packet, static_cast<int>(length), &header);
157
158 {
159 CriticalSectionScoped cs(crit_.get());
160 if (rtp_timestamp_delta_ == 0) {
161 rtp_timestamp_delta_ =
162 header.timestamp - first_send_frame_->timestamp();
163 first_send_frame_ = NULL;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000164 }
pbos@webrtc.org7fb9ce02013-08-05 09:29:50 +0000165 send_times_[header.timestamp - rtp_timestamp_delta_] =
166 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000167 }
168
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000169 return transport_->SendRtp(packet, length);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000170 }
171
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000172 virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
173 return transport_->SendRtcp(packet, length);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000174 }
175
176 virtual void RenderFrame(const I420VideoFrame& video_frame,
177 int time_to_render_ms) OVERRIDE {
pbos@webrtc.org94015242013-10-16 11:05:37 +0000178 int64_t render_time_ms =
179 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000180 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_;
181
182 {
183 CriticalSectionScoped cs(crit_.get());
184 while (frames_.front()->timestamp() < send_timestamp) {
pbos@webrtc.org94015242013-10-16 11:05:37 +0000185 AddFrameComparison(
186 frames_.front(), &last_rendered_frame_, true, render_time_ms);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000187 frame_pool_.push_back(frames_.front());
188 frames_.pop_front();
189 }
190
191 I420VideoFrame* reference_frame = frames_.front();
192 frames_.pop_front();
193 assert(reference_frame != NULL);
pbos@webrtc.org94015242013-10-16 11:05:37 +0000194 EXPECT_EQ(reference_frame->timestamp(), send_timestamp);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000195 assert(reference_frame->timestamp() == send_timestamp);
196
pbos@webrtc.org94015242013-10-16 11:05:37 +0000197 AddFrameComparison(reference_frame, &video_frame, false, render_time_ms);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000198 frame_pool_.push_back(reference_frame);
pbos@webrtc.org94015242013-10-16 11:05:37 +0000199 }
200
201 last_rendered_frame_.CopyFrame(video_frame);
202 }
203
204 void Wait() { trigger_->Wait(120 * 1000); }
205
206 VideoSendStreamInput* input_;
207 Transport* transport_;
208 PacketReceiver* receiver_;
209
210 private:
211 struct FrameComparison {
212 FrameComparison(const I420VideoFrame* reference,
213 const I420VideoFrame* render,
214 bool dropped,
215 int64_t send_time_ms,
216 int64_t recv_time_ms,
217 int64_t render_time_ms)
218 : dropped(dropped),
219 send_time_ms(send_time_ms),
220 recv_time_ms(recv_time_ms),
221 render_time_ms(render_time_ms) {
222 this->reference.CopyFrame(*reference);
223 this->render.CopyFrame(*render);
224 }
225
226 FrameComparison(const FrameComparison& compare)
227 : dropped(compare.dropped),
228 send_time_ms(compare.send_time_ms),
229 recv_time_ms(compare.recv_time_ms),
230 render_time_ms(compare.render_time_ms) {
231 this->reference.CopyFrame(compare.reference);
232 this->render.CopyFrame(compare.render);
233 }
234
235 ~FrameComparison() {}
236
237 I420VideoFrame reference;
238 I420VideoFrame render;
239 bool dropped;
240 int64_t send_time_ms;
241 int64_t recv_time_ms;
242 int64_t render_time_ms;
243 };
244
245 void AddFrameComparison(const I420VideoFrame* reference,
246 const I420VideoFrame* render,
247 bool dropped,
248 int64_t render_time_ms) {
249 int64_t send_time_ms = send_times_[reference->timestamp()];
250 send_times_.erase(reference->timestamp());
251 int64_t recv_time_ms = recv_times_[reference->timestamp()];
252 recv_times_.erase(reference->timestamp());
253
254 CriticalSectionScoped crit(comparison_lock_.get());
255 comparisons_.push_back(FrameComparison(reference,
256 render,
257 dropped,
258 send_time_ms,
259 recv_time_ms,
260 render_time_ms));
261 }
262
263 static bool FrameComparisonThread(void* obj) {
264 return static_cast<VideoAnalyzer*>(obj)->CompareFrames();
265 }
266
267 bool CompareFrames() {
268 assert(frames_left_ > 0);
269
270 I420VideoFrame reference;
271 I420VideoFrame render;
272 bool dropped;
273 int64_t send_time_ms;
274 int64_t recv_time_ms;
275 int64_t render_time_ms;
276
277 SleepMs(10);
278
279 while (true) {
280 {
281 CriticalSectionScoped crit(comparison_lock_.get());
282 if (comparisons_.empty())
283 return true;
284 reference.SwapFrame(&comparisons_.front().reference);
285 render.SwapFrame(&comparisons_.front().render);
286 dropped = comparisons_.front().dropped;
287 send_time_ms = comparisons_.front().send_time_ms;
288 recv_time_ms = comparisons_.front().recv_time_ms;
289 render_time_ms = comparisons_.front().render_time_ms;
290 comparisons_.pop_front();
291 }
292
293 PerformFrameComparison(&reference,
294 &render,
295 dropped,
296 send_time_ms,
297 recv_time_ms,
298 render_time_ms);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000299
300 if (--frames_left_ == 0) {
301 PrintResult("psnr", psnr_, " dB");
302 PrintResult("ssim", ssim_, "");
303 PrintResult("sender_time", sender_time_, " ms");
pbos@webrtc.org94015242013-10-16 11:05:37 +0000304 printf(
305 "RESULT dropped_frames: %s = %d\n", test_label_, dropped_frames_);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000306 PrintResult("receiver_time", receiver_time_, " ms");
307 PrintResult("total_delay_incl_network", end_to_end_, " ms");
308 PrintResult("time_between_rendered_frames", rendered_delta_, " ms");
309 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_);
310 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_);
311 trigger_->Set();
pbos@webrtc.org94015242013-10-16 11:05:37 +0000312
313 return false;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000314 }
315 }
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000316 }
317
pbos@webrtc.org94015242013-10-16 11:05:37 +0000318 void PerformFrameComparison(const I420VideoFrame* reference,
319 const I420VideoFrame* render,
320 bool dropped,
321 int64_t send_time_ms,
322 int64_t recv_time_ms,
323 int64_t render_time_ms) {
324 psnr_.AddSample(I420PSNR(reference, render));
325 ssim_.AddSample(I420SSIM(reference, render));
326 if (dropped) {
327 ++dropped_frames_;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000328 return;
pbos@webrtc.org94015242013-10-16 11:05:37 +0000329 }
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000330 if (last_render_time_ != 0)
pbos@webrtc.org94015242013-10-16 11:05:37 +0000331 rendered_delta_.AddSample(render_time_ms - last_render_time_);
332 last_render_time_ = render_time_ms;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000333
pbos@webrtc.org94015242013-10-16 11:05:37 +0000334 int64_t input_time_ms = reference->render_time_ms();
335 sender_time_.AddSample(send_time_ms - input_time_ms);
336 receiver_time_.AddSample(render_time_ms - recv_time_ms);
337 end_to_end_.AddSample(render_time_ms - input_time_ms);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000338 }
339
340 void PrintResult(const char* result_type,
341 test::Statistics stats,
342 const char* unit) {
343 printf("RESULT %s: %s = {%f, %f}%s\n",
344 result_type,
345 test_label_,
346 stats.Mean(),
347 stats.StandardDeviation(),
348 unit);
349 }
350
351 const char* test_label_;
352 test::Statistics sender_time_;
353 test::Statistics receiver_time_;
354 test::Statistics psnr_;
355 test::Statistics ssim_;
356 test::Statistics end_to_end_;
357 test::Statistics rendered_delta_;
358
pbos@webrtc.org94015242013-10-16 11:05:37 +0000359 int dropped_frames_;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000360 std::deque<I420VideoFrame*> frames_;
361 std::deque<I420VideoFrame*> frame_pool_;
362 I420VideoFrame last_rendered_frame_;
363 std::map<uint32_t, int64_t> send_times_;
364 std::map<uint32_t, int64_t> recv_times_;
365 uint32_t rtp_timestamp_delta_;
366 I420VideoFrame* first_send_frame_;
367 int64_t last_render_time_;
368 double avg_psnr_threshold_;
369 double avg_ssim_threshold_;
pbos@webrtc.org94015242013-10-16 11:05:37 +0000370 int frames_left_;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000371 scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org94015242013-10-16 11:05:37 +0000372 scoped_ptr<CriticalSectionWrapper> comparison_lock_;
373 scoped_ptr<ThreadWrapper> comparison_thread_;
374 std::deque<FrameComparison> comparisons_;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000375 scoped_ptr<EventWrapper> trigger_;
376};
377
pbos@webrtc.org94015242013-10-16 11:05:37 +0000378TEST_P(FullStackTest, NoPacketLoss) {
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +0000379 static const uint32_t kReceiverLocalSsrc = 0x123456;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000380 FullStackTestParams params = GetParam();
381
pbos@webrtc.org96684672013-08-12 12:59:04 +0000382 test::DirectTransport transport;
pbos@webrtc.org94015242013-10-16 11:05:37 +0000383 VideoAnalyzer analyzer(NULL,
384 &transport,
385 params.test_label,
386 params.avg_psnr_threshold,
387 params.avg_ssim_threshold,
388 FLAGS_seconds * params.clip.fps);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000389
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000390 Call::Config call_config(&analyzer);
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +0000391
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000392 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org94015242013-10-16 11:05:37 +0000393 analyzer.SetReceiver(call->Receiver());
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000394 transport.SetReceiver(&analyzer);
395
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000396 VideoSendStream::Config send_config = call->GetDefaultSendConfig();
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +0000397 send_config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000398
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000399 // TODO(pbos): static_cast shouldn't be required after mflodman refactors the
400 // VideoCodec struct.
401 send_config.codec.width = static_cast<uint16_t>(params.clip.width);
402 send_config.codec.height = static_cast<uint16_t>(params.clip.height);
403 send_config.codec.minBitrate = params.bitrate;
404 send_config.codec.startBitrate = params.bitrate;
405 send_config.codec.maxBitrate = params.bitrate;
406
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000407 VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000408 analyzer.input_ = send_stream->Input();
409
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000410 scoped_ptr<test::FrameGeneratorCapturer> file_capturer(
andresp@webrtc.orgab654952013-09-19 12:14:03 +0000411 test::FrameGeneratorCapturer::CreateFromYuvFile(
pbos@webrtc.org4c966012013-08-21 12:07:37 +0000412 &analyzer,
andresp@webrtc.orgab654952013-09-19 12:14:03 +0000413 test::ResourcePath(params.clip.name, "yuv").c_str(),
414 params.clip.width,
415 params.clip.height,
416 params.clip.fps,
417 Clock::GetRealTimeClock()));
pbos@webrtc.org94015242013-10-16 11:05:37 +0000418 ASSERT_TRUE(file_capturer.get() != NULL)
419 << "Could not create capturer for " << params.clip.name
420 << ".yuv. Is this resource file present?";
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000421
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000422 VideoReceiveStream::Config receive_config = call->GetDefaultReceiveConfig();
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +0000423 receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
424 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000425 receive_config.renderer = &analyzer;
426
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000427 VideoReceiveStream* receive_stream =
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000428 call->CreateVideoReceiveStream(receive_config);
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000429
pbos@webrtc.org53c85732013-11-20 11:36:47 +0000430 receive_stream->StartReceiving();
431 send_stream->StartSending();
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000432
433 file_capturer->Start();
434
435 analyzer.Wait();
436
437 file_capturer->Stop();
pbos@webrtc.org53c85732013-11-20 11:36:47 +0000438 send_stream->StopSending();
439 receive_stream->StopReceiving();
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000440
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000441 call->DestroyVideoReceiveStream(receive_stream);
442 call->DestroyVideoSendStream(send_stream);
pbos@webrtc.org96684672013-08-12 12:59:04 +0000443
444 transport.StopSending();
pbos@webrtc.orgaf8d5af2013-07-09 08:02:33 +0000445}
446
447INSTANTIATE_TEST_CASE_P(FullStack,
448 FullStackTest,
449 ::testing::Values(paris_qcif, foreman_cif));
450
451} // namespace webrtc