blob: 491149c7e21701615a0217cff6e0b616ba49d95f [file] [log] [blame]
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00009 */
henrike@webrtc.org28e20752013-07-10 00:45:36 +000010
kjellandera96e2d72016-02-04 23:52:28 -080011#ifndef WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ // NOLINT
12#define WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013
kwiberg686a8ef2016-02-26 03:00:35 -080014#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000015#include <string>
16#include <vector>
17
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000018#include "webrtc/base/bytebuffer.h"
19#include "webrtc/base/gunit.h"
20#include "webrtc/base/timeutils.h"
Fredrik Solenberg709ed672015-09-15 12:26:33 +020021#include "webrtc/call.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/media/base/fakenetworkinterface.h"
23#include "webrtc/media/base/fakevideocapturer.h"
24#include "webrtc/media/base/fakevideorenderer.h"
25#include "webrtc/media/base/mediachannel.h"
26#include "webrtc/media/base/streamparams.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010027#include "webrtc/media/engine/fakewebrtccall.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029#define EXPECT_FRAME_WAIT(c, w, h, t) \
30 EXPECT_EQ_WAIT((c), renderer_.num_rendered_frames(), (t)); \
31 EXPECT_EQ((w), renderer_.width()); \
32 EXPECT_EQ((h), renderer_.height()); \
33 EXPECT_EQ(0, renderer_.errors()); \
34
35#define EXPECT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
36 EXPECT_EQ_WAIT((c), (r).num_rendered_frames(), (t)); \
37 EXPECT_EQ((w), (r).width()); \
38 EXPECT_EQ((h), (r).height()); \
39 EXPECT_EQ(0, (r).errors()); \
40
wu@webrtc.org9caf2762013-12-11 18:25:07 +000041#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
42 EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
43 (w) == (r).width() && \
44 (h) == (r).height(), (t)); \
Peter Boström0c4e06b2015-10-07 12:23:21 +020045 EXPECT_EQ(0, (r).errors());
wu@webrtc.org9caf2762013-12-11 18:25:07 +000046
Peter Boström0c4e06b2015-10-07 12:23:21 +020047static const uint32_t kTimeout = 5000U;
48static const uint32_t kDefaultReceiveSsrc = 0;
49static const uint32_t kSsrc = 1234u;
50static const uint32_t kRtxSsrc = 4321u;
51static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052
53inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
54 return a.width == w && a.height == h && a.framerate == fps;
55}
56
57inline bool IsEqualCodec(const cricket::VideoCodec& a,
58 const cricket::VideoCodec& b) {
59 return a.id == b.id && a.name == b.name &&
60 IsEqualRes(a, b.width, b.height, b.framerate);
61}
62
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000063namespace std {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
65 s << "{" << c.name << "(" << c.id << "), "
66 << c.width << "x" << c.height << "x" << c.framerate << "}";
67 return s;
68}
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +000069} // namespace std
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070
71inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000072 return static_cast<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073 cricket::VideoFormat::FpsToInterval(codec.framerate) /
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074 rtc::kNumNanosecsPerMillisec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075}
76
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077template<class E, class C>
78class VideoMediaChannelTest : public testing::Test,
79 public sigslot::has_slots<> {
80 protected:
Fredrik Solenberg709ed672015-09-15 12:26:33 +020081 VideoMediaChannelTest<E, C>()
82 : call_(webrtc::Call::Create(webrtc::Call::Config())) {}
83
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084 virtual cricket::VideoCodec DefaultCodec() = 0;
85
86 virtual cricket::StreamParams DefaultSendStreamParams() {
87 return cricket::StreamParams::CreateLegacy(kSsrc);
88 }
89
90 virtual void SetUp() {
Fredrik Solenberg9a416bd2015-05-22 09:04:09 +020091 engine_.Init();
nisse51542be2016-02-12 02:27:06 -080092 channel_.reset(engine_.CreateChannel(call_.get(), cricket::MediaConfig(),
93 cricket::VideoOptions()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 EXPECT_TRUE(channel_.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095 network_interface_.SetDestination(channel_.get());
96 channel_->SetInterface(&network_interface_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
Fredrik Solenbergb071a192015-09-17 16:42:56 +020098 cricket::VideoRecvParameters parameters;
99 parameters.codecs = engine_.codecs();
100 channel_->SetRecvParameters(parameters);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101 EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000102 video_capturer_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000103 cricket::VideoFormat format(640, 480,
104 cricket::VideoFormat::FpsToInterval(30),
105 cricket::FOURCC_I420);
106 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
nisse2ded9b12016-04-08 02:23:55 -0700107 channel_->SetSource(kSsrc, video_capturer_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 }
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000109
110 virtual cricket::FakeVideoCapturer* CreateFakeVideoCapturer() {
111 return new cricket::FakeVideoCapturer();
112 }
113
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000114 // Utility method to setup an additional stream to send and receive video.
115 // Used to test send and recv between two streams.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116 void SetUpSecondStream() {
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000117 SetUpSecondStreamWithNoRecv();
118 // Setup recv for second stream.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 EXPECT_TRUE(channel_->AddRecvStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000120 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000121 // Make the second renderer available for use by a new stream.
nisse08582ff2016-02-04 01:24:52 -0800122 EXPECT_TRUE(channel_->SetSink(kSsrc + 2, &renderer2_));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000123 }
124 // Setup an additional stream just to send video. Defer add recv stream.
125 // This is required if you want to test unsignalled recv of video rtp packets.
126 void SetUpSecondStreamWithNoRecv() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127 // SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000128 EXPECT_TRUE(channel_->AddRecvStream(
129 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800130 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 EXPECT_FALSE(channel_->AddSendStream(
132 cricket::StreamParams::CreateLegacy(kSsrc)));
133 EXPECT_TRUE(channel_->AddSendStream(
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000134 cricket::StreamParams::CreateLegacy(kSsrc + 2)));
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000135 // We dont add recv for the second stream.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000136
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000137 // Setup the receive and renderer for second stream after send.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000138 video_capturer_2_.reset(CreateFakeVideoCapturer());
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000139 cricket::VideoFormat format(640, 480,
140 cricket::VideoFormat::FpsToInterval(30),
141 cricket::FOURCC_I420);
142 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
143
nisse2ded9b12016-04-08 02:23:55 -0700144 channel_->SetSource(kSsrc + 2, video_capturer_2_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145 }
146 virtual void TearDown() {
147 channel_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149 bool SetDefaultCodec() {
150 return SetOneCodec(DefaultCodec());
151 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152
153 bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
154 return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
155 }
156 bool SetOneCodec(const cricket::VideoCodec& codec) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000157 cricket::VideoFormat capture_format(codec.width, codec.height,
158 cricket::VideoFormat::FpsToInterval(codec.framerate),
159 cricket::FOURCC_I420);
160
161 if (video_capturer_) {
162 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
163 }
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000164 if (video_capturer_2_) {
165 EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
166 }
167
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168 bool sending = channel_->sending();
169 bool success = SetSend(false);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200170 if (success) {
171 cricket::VideoSendParameters parameters;
172 parameters.codecs.push_back(codec);
173 success = channel_->SetSendParameters(parameters);
174 }
175 if (success) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000176 success = SetSend(sending);
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200177 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178 return success;
179 }
180 bool SetSend(bool send) {
181 return channel_->SetSend(send);
182 }
183 int DrainOutgoingPackets() {
184 int packets = 0;
185 do {
186 packets = NumRtpPackets();
187 // 100 ms should be long enough.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000188 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 } while (NumRtpPackets() > packets);
190 return NumRtpPackets();
191 }
192 bool SendFrame() {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000193 if (video_capturer_2_) {
194 video_capturer_2_->CaptureFrame();
195 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000196 return video_capturer_.get() &&
197 video_capturer_->CaptureFrame();
198 }
199 bool WaitAndSendFrame(int wait_ms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000200 bool ret = rtc::Thread::Current()->ProcessMessages(wait_ms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201 ret &= SendFrame();
202 return ret;
203 }
204 // Sends frames and waits for the decoder to be fully initialized.
205 // Returns the number of frames that were sent.
206 int WaitForDecoder() {
207#if defined(HAVE_OPENMAX)
208 // Send enough frames for the OpenMAX decoder to continue processing, and
209 // return the number of frames sent.
210 // Send frames for a full kTimeout's worth of 15fps video.
211 int frame_count = 0;
212 while (frame_count < static_cast<int>(kTimeout) / 66) {
213 EXPECT_TRUE(WaitAndSendFrame(66));
214 ++frame_count;
215 }
216 return frame_count;
217#else
218 return 0;
219#endif
220 }
221 bool SendCustomVideoFrame(int w, int h) {
222 if (!video_capturer_.get()) return false;
223 return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
224 }
225 int NumRtpBytes() {
226 return network_interface_.NumRtpBytes();
227 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200228 int NumRtpBytes(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229 return network_interface_.NumRtpBytes(ssrc);
230 }
231 int NumRtpPackets() {
232 return network_interface_.NumRtpPackets();
233 }
Peter Boström0c4e06b2015-10-07 12:23:21 +0200234 int NumRtpPackets(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235 return network_interface_.NumRtpPackets(ssrc);
236 }
237 int NumSentSsrcs() {
238 return network_interface_.NumSentSsrcs();
239 }
jbaucheec21bd2016-03-20 06:15:43 -0700240 const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241 return network_interface_.GetRtpPacket(index);
242 }
243 int NumRtcpPackets() {
244 return network_interface_.NumRtcpPackets();
245 }
jbaucheec21bd2016-03-20 06:15:43 -0700246 const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000247 return network_interface_.GetRtcpPacket(index);
248 }
jbaucheec21bd2016-03-20 06:15:43 -0700249 static int GetPayloadType(const rtc::CopyOnWriteBuffer* p) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250 int pt = -1;
251 ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
252 return pt;
253 }
jbaucheec21bd2016-03-20 06:15:43 -0700254 static bool ParseRtpPacket(const rtc::CopyOnWriteBuffer* p,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200255 bool* x,
256 int* pt,
257 int* seqnum,
258 uint32_t* tstamp,
259 uint32_t* ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000260 std::string* payload) {
jbauchf1f87202016-03-30 06:43:37 -0700261 rtc::ByteBufferReader buf(p->data<char>(), p->size());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200262 uint8_t u08 = 0;
263 uint16_t u16 = 0;
264 uint32_t u32 = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265
266 // Read X and CC fields.
267 if (!buf.ReadUInt8(&u08)) return false;
268 bool extension = ((u08 & 0x10) != 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200269 uint8_t cc = (u08 & 0x0F);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000270 if (x) *x = extension;
271
272 // Read PT field.
273 if (!buf.ReadUInt8(&u08)) return false;
274 if (pt) *pt = (u08 & 0x7F);
275
276 // Read Sequence Number field.
277 if (!buf.ReadUInt16(&u16)) return false;
278 if (seqnum) *seqnum = u16;
279
280 // Read Timestamp field.
281 if (!buf.ReadUInt32(&u32)) return false;
282 if (tstamp) *tstamp = u32;
283
284 // Read SSRC field.
285 if (!buf.ReadUInt32(&u32)) return false;
286 if (ssrc) *ssrc = u32;
287
288 // Skip CSRCs.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200289 for (uint8_t i = 0; i < cc; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 if (!buf.ReadUInt32(&u32)) return false;
291 }
292
293 // Skip extension header.
294 if (extension) {
295 // Read Profile-specific extension header ID
296 if (!buf.ReadUInt16(&u16)) return false;
297
298 // Read Extension header length
299 if (!buf.ReadUInt16(&u16)) return false;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200300 uint16_t ext_header_len = u16;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301
302 // Read Extension header
Peter Boström0c4e06b2015-10-07 12:23:21 +0200303 for (uint16_t i = 0; i < ext_header_len; ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 if (!buf.ReadUInt32(&u32)) return false;
305 }
306 }
307
308 if (payload) {
309 return buf.ReadString(payload, buf.Length());
310 }
311 return true;
312 }
313
314 // Parse all RTCP packet, from start_index to stop_index, and count how many
315 // FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
316 // and return true.
317 bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
318 int count = 0;
319 for (int i = start_index; i < stop_index; ++i) {
jbaucheec21bd2016-03-20 06:15:43 -0700320 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtcpPacket(i));
jbauchf1f87202016-03-30 06:43:37 -0700321 rtc::ByteBufferReader buf(p->data<char>(), p->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322 size_t total_len = 0;
323 // The packet may be a compound RTCP packet.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000324 while (total_len < p->size()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 // Read FMT, type and length.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200326 uint8_t fmt = 0;
327 uint8_t type = 0;
328 uint16_t length = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000329 if (!buf.ReadUInt8(&fmt)) return false;
330 fmt &= 0x1F;
331 if (!buf.ReadUInt8(&type)) return false;
332 if (!buf.ReadUInt16(&length)) return false;
333 buf.Consume(length * 4); // Skip RTCP data.
334 total_len += (length + 1) * 4;
335 if ((192 == type) || ((206 == type) && (4 == fmt))) {
336 ++count;
337 }
338 }
339 }
340
341 if (fir_count) {
342 *fir_count = count;
343 }
344 return true;
345 }
346
Peter Boström0c4e06b2015-10-07 12:23:21 +0200347 void OnVideoChannelError(uint32_t ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000348 cricket::VideoMediaChannel::Error error) {
349 media_error_ = error;
350 }
351
352 // Test that SetSend works.
353 void SetSend() {
354 EXPECT_FALSE(channel_->sending());
nisse2ded9b12016-04-08 02:23:55 -0700355 channel_->SetSource(kSsrc, video_capturer_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
357 EXPECT_FALSE(channel_->sending());
358 EXPECT_TRUE(SetSend(true));
359 EXPECT_TRUE(channel_->sending());
360 EXPECT_TRUE(SendFrame());
361 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
362 EXPECT_TRUE(SetSend(false));
363 EXPECT_FALSE(channel_->sending());
364 }
365 // Test that SetSend fails without codecs being set.
366 void SetSendWithoutCodecs() {
367 EXPECT_FALSE(channel_->sending());
368 EXPECT_FALSE(SetSend(true));
369 EXPECT_FALSE(channel_->sending());
370 }
371 // Test that we properly set the send and recv buffer sizes by the time
372 // SetSend is called.
373 void SetSendSetsTransportBufferSizes() {
374 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
375 EXPECT_TRUE(SetSend(true));
buildbot@webrtc.orgae694ef2014-10-28 17:37:17 +0000376 EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000377 EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
378 }
379 // Tests that we can send frames and the right payload type is used.
380 void Send(const cricket::VideoCodec& codec) {
381 EXPECT_TRUE(SetOneCodec(codec));
382 EXPECT_TRUE(SetSend(true));
383 EXPECT_TRUE(SendFrame());
384 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -0700385 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
387 }
388 // Tests that we can send and receive frames.
389 void SendAndReceive(const cricket::VideoCodec& codec) {
390 EXPECT_TRUE(SetOneCodec(codec));
391 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800392 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393 EXPECT_EQ(0, renderer_.num_rendered_frames());
394 EXPECT_TRUE(SendFrame());
395 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -0700396 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000397 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
398 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000399 void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
400 int duration_sec, int fps) {
401 EXPECT_TRUE(SetOneCodec(codec));
402 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800403 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000404 EXPECT_EQ(0, renderer_.num_rendered_frames());
405 for (int i = 0; i < duration_sec; ++i) {
406 for (int frame = 1; frame <= fps; ++frame) {
407 EXPECT_TRUE(WaitAndSendFrame(1000 / fps));
408 EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
409 }
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000410 }
jbaucheec21bd2016-03-20 06:15:43 -0700411 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000412 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
413 }
414
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 // Test that stats work properly for a 1-1 call.
416 void GetStats() {
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000417 const int kDurationSec = 3;
418 const int kFps = 10;
419 SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
420
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000422 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000423
424 ASSERT_EQ(1U, info.senders.size());
425 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000426 // For webrtc, bytes_sent does not include the RTP header length.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000427 EXPECT_GT(info.senders[0].bytes_sent, 0);
428 EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
429 EXPECT_EQ(0.0, info.senders[0].fraction_lost);
430 EXPECT_EQ(0, info.senders[0].firs_rcvd);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000431 EXPECT_EQ(0, info.senders[0].plis_rcvd);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 EXPECT_EQ(0, info.senders[0].nacks_rcvd);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000433 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
434 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 EXPECT_GT(info.senders[0].framerate_input, 0);
436 EXPECT_GT(info.senders[0].framerate_sent, 0);
437
438 ASSERT_EQ(1U, info.receivers.size());
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000439 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
440 EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
441 EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
443 EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
444 EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
445 EXPECT_EQ(0, info.receivers[0].packets_lost);
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000446 // TODO(asapersson): Not set for webrtc. Handle missing stats.
447 // EXPECT_EQ(0, info.receivers[0].packets_concealed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 EXPECT_EQ(0, info.receivers[0].firs_sent);
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000449 EXPECT_EQ(0, info.receivers[0].plis_sent);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000450 EXPECT_EQ(0, info.receivers[0].nacks_sent);
451 EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
452 EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
453 EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
454 EXPECT_GT(info.receivers[0].framerate_decoded, 0);
455 EXPECT_GT(info.receivers[0].framerate_output, 0);
456 }
Stefan Holmer586b19b2015-09-18 11:14:31 +0200457
458 cricket::VideoSenderInfo GetSenderStats(size_t i) {
459 cricket::VideoMediaInfo info;
460 EXPECT_TRUE(channel_->GetStats(&info));
461 return info.senders[i];
462 }
463
464 cricket::VideoReceiverInfo GetReceiverStats(size_t i) {
465 cricket::VideoMediaInfo info;
466 EXPECT_TRUE(channel_->GetStats(&info));
467 return info.receivers[i];
468 }
469
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000470 // Test that stats work properly for a conf call with multiple recv streams.
471 void GetStatsMultipleRecvStreams() {
472 cricket::FakeVideoRenderer renderer1, renderer2;
473 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200474 cricket::VideoSendParameters parameters;
475 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800476 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200477 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478 EXPECT_TRUE(SetSend(true));
479 EXPECT_TRUE(channel_->AddRecvStream(
480 cricket::StreamParams::CreateLegacy(1)));
481 EXPECT_TRUE(channel_->AddRecvStream(
482 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800483 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
484 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000485 EXPECT_EQ(0, renderer1.num_rendered_frames());
486 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200487 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 ssrcs.push_back(1);
489 ssrcs.push_back(2);
490 network_interface_.SetConferenceMode(true, ssrcs);
491 EXPECT_TRUE(SendFrame());
492 EXPECT_FRAME_ON_RENDERER_WAIT(
493 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
494 EXPECT_FRAME_ON_RENDERER_WAIT(
495 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200496
497 EXPECT_TRUE(channel_->SetSend(false));
498
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 cricket::VideoMediaInfo info;
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000500 EXPECT_TRUE(channel_->GetStats(&info));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000501 ASSERT_EQ(1U, info.senders.size());
502 // TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
buildbot@webrtc.org3eb2c2f2014-06-10 09:39:06 +0000503 // For webrtc, bytes_sent does not include the RTP header length.
Stefan Holmer586b19b2015-09-18 11:14:31 +0200504 EXPECT_GT(GetSenderStats(0).bytes_sent, 0);
505 EXPECT_EQ_WAIT(NumRtpPackets(), GetSenderStats(0).packets_sent, kTimeout);
506 EXPECT_EQ(DefaultCodec().width, GetSenderStats(0).send_frame_width);
507 EXPECT_EQ(DefaultCodec().height, GetSenderStats(0).send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508
509 ASSERT_EQ(2U, info.receivers.size());
510 for (size_t i = 0; i < info.receivers.size(); ++i) {
Stefan Holmer586b19b2015-09-18 11:14:31 +0200511 EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size());
512 EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]);
513 EXPECT_EQ_WAIT(NumRtpBytes(), GetReceiverStats(i).bytes_rcvd, kTimeout);
514 EXPECT_EQ_WAIT(NumRtpPackets(), GetReceiverStats(i).packets_rcvd,
515 kTimeout);
516 EXPECT_EQ(DefaultCodec().width, GetReceiverStats(i).frame_width);
517 EXPECT_EQ(DefaultCodec().height, GetReceiverStats(i).frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 }
519 }
520 // Test that stats work properly for a conf call with multiple send streams.
521 void GetStatsMultipleSendStreams() {
522 // Normal setup; note that we set the SSRC explicitly to ensure that
523 // it will come first in the senders map.
524 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200525 cricket::VideoSendParameters parameters;
526 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800527 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200528 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000529 EXPECT_TRUE(channel_->AddRecvStream(
buildbot@webrtc.org99f63082014-07-18 23:31:30 +0000530 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800531 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000532 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 EXPECT_TRUE(SendFrame());
534 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
535 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
536
537 // Add an additional capturer, and hook up a renderer to receive it.
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000538 cricket::FakeVideoRenderer renderer2;
kwiberg686a8ef2016-02-26 03:00:35 -0800539 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000540 CreateFakeVideoCapturer());
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000541 const int kTestWidth = 160;
542 const int kTestHeight = 120;
543 cricket::VideoFormat format(kTestWidth, kTestHeight,
544 cricket::VideoFormat::FpsToInterval(5),
545 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
547 EXPECT_TRUE(channel_->AddSendStream(
548 cricket::StreamParams::CreateLegacy(5678)));
nisse2ded9b12016-04-08 02:23:55 -0700549 channel_->SetSource(5678, capturer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550 EXPECT_TRUE(channel_->AddRecvStream(
551 cricket::StreamParams::CreateLegacy(5678)));
nisse08582ff2016-02-04 01:24:52 -0800552 EXPECT_TRUE(channel_->SetSink(5678, &renderer2));
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000553 EXPECT_TRUE(capturer->CaptureCustomFrame(
554 kTestWidth, kTestHeight, cricket::FOURCC_I420));
555 EXPECT_FRAME_ON_RENDERER_WAIT(
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000556 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000558 // Get stats, and make sure they are correct for two senders. We wait until
559 // the number of expected packets have been sent to avoid races where we
560 // check stats before it has been updated.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000561 cricket::VideoMediaInfo info;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200562 for (uint32_t i = 0; i < kTimeout; ++i) {
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000563 rtc::Thread::Current()->ProcessMessages(1);
pbos@webrtc.org058b1f12015-03-04 08:54:32 +0000564 EXPECT_TRUE(channel_->GetStats(&info));
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000565 ASSERT_EQ(2U, info.senders.size());
566 if (info.senders[0].packets_sent + info.senders[1].packets_sent ==
567 NumRtpPackets()) {
568 // Stats have been updated for both sent frames, expectations can be
569 // checked now.
570 break;
571 }
572 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000573 EXPECT_EQ(NumRtpPackets(),
pbos@webrtc.orgec45e3b2015-02-20 10:24:53 +0000574 info.senders[0].packets_sent + info.senders[1].packets_sent)
575 << "Timed out while waiting for packet counts for all sent packets.";
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000576 EXPECT_EQ(1U, info.senders[0].ssrcs().size());
577 EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000578 EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
579 EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000580 EXPECT_EQ(1U, info.senders[1].ssrcs().size());
581 EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
wu@webrtc.org987f2c92014-03-28 16:22:19 +0000582 EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width);
583 EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584 // The capturer must be unregistered here as it runs out of it's scope next.
nisse2ded9b12016-04-08 02:23:55 -0700585 channel_->SetSource(5678, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 }
587
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000588 // Test that we can set the bandwidth.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 void SetSendBandwidth() {
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200590 cricket::VideoSendParameters parameters;
591 parameters.codecs.push_back(DefaultCodec());
592 parameters.max_bandwidth_bps = -1; // <= 0 means unlimited.
593 EXPECT_TRUE(channel_->SetSendParameters(parameters));
594 parameters.max_bandwidth_bps = 128 * 1024;
595 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000596 }
597 // Test that we can set the SSRC for the default send source.
598 void SetSendSsrc() {
599 EXPECT_TRUE(SetDefaultCodec());
600 EXPECT_TRUE(SetSend(true));
601 EXPECT_TRUE(SendFrame());
602 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200603 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -0700604 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
606 EXPECT_EQ(kSsrc, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000607 // Packets are being paced out, so these can mismatch between the first and
608 // second call to NumRtpPackets until pending packets are paced out.
609 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
610 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 EXPECT_EQ(1, NumSentSsrcs());
612 EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
613 EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
614 }
615 // Test that we can set the SSRC even after codecs are set.
616 void SetSendSsrcAfterSetCodecs() {
617 // Remove stream added in Setup.
618 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
619 EXPECT_TRUE(SetDefaultCodec());
620 EXPECT_TRUE(channel_->AddSendStream(
621 cricket::StreamParams::CreateLegacy(999)));
nisse2ded9b12016-04-08 02:23:55 -0700622 channel_->SetSource(999u, video_capturer_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000623 EXPECT_TRUE(SetSend(true));
624 EXPECT_TRUE(WaitAndSendFrame(0));
625 EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200626 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -0700627 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
629 EXPECT_EQ(999u, ssrc);
Peter Boström718b6c72015-11-11 16:19:33 +0000630 // Packets are being paced out, so these can mismatch between the first and
631 // second call to NumRtpPackets until pending packets are paced out.
632 EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
633 EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 EXPECT_EQ(1, NumSentSsrcs());
635 EXPECT_EQ(0, NumRtpPackets(kSsrc));
636 EXPECT_EQ(0, NumRtpBytes(kSsrc));
637 }
638 // Test that we can set the default video renderer before and after
639 // media is received.
nisse08582ff2016-02-04 01:24:52 -0800640 void SetSink() {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200641 uint8_t data1[] = {
642 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643
jbaucheec21bd2016-03-20 06:15:43 -0700644 rtc::CopyOnWriteBuffer packet1(data1, sizeof(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000645 rtc::SetBE32(packet1.data() + 8, kSsrc);
nisse08582ff2016-02-04 01:24:52 -0800646 channel_->SetSink(kDefaultReceiveSsrc, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 EXPECT_TRUE(SetDefaultCodec());
648 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000650 channel_->OnPacketReceived(&packet1, rtc::PacketTime());
nisse08582ff2016-02-04 01:24:52 -0800651 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 EXPECT_TRUE(SendFrame());
653 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
654 }
655
656 // Tests empty StreamParams is rejected.
657 void RejectEmptyStreamParams() {
658 // Remove the send stream that was added during Setup.
659 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
660
661 cricket::StreamParams empty;
662 EXPECT_FALSE(channel_->AddSendStream(empty));
663 EXPECT_TRUE(channel_->AddSendStream(
664 cricket::StreamParams::CreateLegacy(789u)));
665 }
666
667 // Tests setting up and configuring a send stream.
668 void AddRemoveSendStreams() {
669 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
670 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800671 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 EXPECT_TRUE(SendFrame());
673 EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +0200674 EXPECT_GT(NumRtpPackets(), 0);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200675 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676 size_t last_packet = NumRtpPackets() - 1;
jbaucheec21bd2016-03-20 06:15:43 -0700677 std::unique_ptr<const rtc::CopyOnWriteBuffer>
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000678 p(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
680 EXPECT_EQ(kSsrc, ssrc);
681
682 // Remove the send stream that was added during Setup.
683 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
684 int rtp_packets = NumRtpPackets();
685
686 EXPECT_TRUE(channel_->AddSendStream(
687 cricket::StreamParams::CreateLegacy(789u)));
nisse2ded9b12016-04-08 02:23:55 -0700688 channel_->SetSource(789u, video_capturer_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 EXPECT_EQ(rtp_packets, NumRtpPackets());
690 // Wait 30ms to guarantee the engine does not drop the frame.
691 EXPECT_TRUE(WaitAndSendFrame(30));
692 EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
693
694 last_packet = NumRtpPackets() - 1;
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000695 p.reset(GetRtpPacket(static_cast<int>(last_packet)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000696 ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
697 EXPECT_EQ(789u, ssrc);
698 }
699
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 // Tests the behavior of incoming streams in a conference scenario.
701 void SimulateConference() {
702 cricket::FakeVideoRenderer renderer1, renderer2;
703 EXPECT_TRUE(SetDefaultCodec());
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200704 cricket::VideoSendParameters parameters;
705 parameters.codecs.push_back(DefaultCodec());
nisse4b4dc862016-02-17 05:25:36 -0800706 parameters.conference_mode = true;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200707 EXPECT_TRUE(channel_->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709 EXPECT_TRUE(channel_->AddRecvStream(
710 cricket::StreamParams::CreateLegacy(1)));
711 EXPECT_TRUE(channel_->AddRecvStream(
712 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800713 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
714 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 EXPECT_EQ(0, renderer1.num_rendered_frames());
716 EXPECT_EQ(0, renderer2.num_rendered_frames());
Peter Boström0c4e06b2015-10-07 12:23:21 +0200717 std::vector<uint32_t> ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 ssrcs.push_back(1);
719 ssrcs.push_back(2);
720 network_interface_.SetConferenceMode(true, ssrcs);
721 EXPECT_TRUE(SendFrame());
722 EXPECT_FRAME_ON_RENDERER_WAIT(
723 renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
724 EXPECT_FRAME_ON_RENDERER_WAIT(
725 renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
726
jbaucheec21bd2016-03-20 06:15:43 -0700727 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
729 EXPECT_EQ(DefaultCodec().width, renderer1.width());
730 EXPECT_EQ(DefaultCodec().height, renderer1.height());
731 EXPECT_EQ(DefaultCodec().width, renderer2.width());
732 EXPECT_EQ(DefaultCodec().height, renderer2.height());
733 EXPECT_TRUE(channel_->RemoveRecvStream(2));
734 EXPECT_TRUE(channel_->RemoveRecvStream(1));
735 }
736
737 // Tests that we can add and remove capturers and frames are sent out properly
738 void AddRemoveCapturer() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000739 cricket::VideoCodec codec = DefaultCodec();
740 codec.width = 320;
741 codec.height = 240;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742 const int time_between_send = TimeBetweenSend(codec);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000743 EXPECT_TRUE(SetOneCodec(codec));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000744 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800745 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 EXPECT_EQ(0, renderer_.num_rendered_frames());
747 EXPECT_TRUE(SendFrame());
748 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
kwiberg686a8ef2016-02-26 03:00:35 -0800749 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000750 CreateFakeVideoCapturer());
Niels Möller60653ba2016-03-02 11:41:36 +0100751
752 // TODO(nisse): This testcase fails if we don't configure
753 // screencast. It's unclear why, I see nothing obvious in this
754 // test which is related to screencast logic.
755 cricket::VideoOptions video_options;
756 video_options.is_screencast = rtc::Optional<bool>(true);
757 channel_->SetVideoSend(kSsrc, true, &video_options);
758
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000759 cricket::VideoFormat format(480, 360,
760 cricket::VideoFormat::FpsToInterval(30),
761 cricket::FOURCC_I420);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000762 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
763 // All capturers start generating frames with the same timestamp. ViE does
764 // not allow the same timestamp to be used. Capture one frame before
765 // associating the capturer with the channel.
766 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
767 cricket::FOURCC_I420));
768
769 int captured_frames = 1;
770 for (int iterations = 0; iterations < 2; ++iterations) {
nisse2ded9b12016-04-08 02:23:55 -0700771 channel_->SetSource(kSsrc, capturer.get());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000772 rtc::Thread::Current()->ProcessMessages(time_between_send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
774 cricket::FOURCC_I420));
775 ++captured_frames;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000776 // Wait until frame of right size is captured.
777 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
778 format.width == renderer_.width() &&
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000779 format.height == renderer_.height() &&
780 !renderer_.black_frame(), kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000781 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
782 EXPECT_EQ(format.width, renderer_.width());
783 EXPECT_EQ(format.height, renderer_.height());
784 captured_frames = renderer_.num_rendered_frames() + 1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000785 EXPECT_FALSE(renderer_.black_frame());
nisse2ded9b12016-04-08 02:23:55 -0700786 channel_->SetSource(kSsrc, NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000787 // Make sure a black frame is generated within the specified timeout.
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000788 // The black frame should be the resolution of the previous frame to
789 // prevent expensive encoder reconfigurations.
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000790 EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000791 format.width == renderer_.width() &&
792 format.height == renderer_.height() &&
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000793 renderer_.black_frame(), kTimeout);
794 EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
pbos@webrtc.orgb4987bf2015-02-18 10:13:09 +0000795 EXPECT_EQ(format.width, renderer_.width());
796 EXPECT_EQ(format.height, renderer_.height());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000797 EXPECT_TRUE(renderer_.black_frame());
798
799 // The black frame has the same timestamp as the next frame since it's
800 // timestamp is set to the last frame's timestamp + interval. WebRTC will
801 // not render a frame with the same timestamp so capture another frame
802 // with the frame capturer to increment the next frame's timestamp.
803 EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
804 cricket::FOURCC_I420));
805 }
806 }
807
808 // Tests that if RemoveCapturer is called without a capturer ever being
809 // added, the plugin shouldn't crash (and no black frame should be sent).
810 void RemoveCapturerWithoutAdd() {
811 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
812 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800813 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000814 EXPECT_EQ(0, renderer_.num_rendered_frames());
815 EXPECT_TRUE(SendFrame());
816 EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000817 // Wait for one frame so they don't get dropped because we send frames too
818 // tightly.
819 rtc::Thread::Current()->ProcessMessages(30);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000820 // Remove the capturer.
nisse2ded9b12016-04-08 02:23:55 -0700821 channel_->SetSource(kSsrc, NULL);
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000822 // Wait for one black frame for removing the capturer.
823 EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
824
nisse2ded9b12016-04-08 02:23:55 -0700825 // No capturer was added, so this SetSource should be a NOP.
826 channel_->SetSource(kSsrc, NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000827 rtc::Thread::Current()->ProcessMessages(300);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000828 // Verify no more frames were sent.
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000829 EXPECT_EQ(2, renderer_.num_rendered_frames());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000830 }
831
832 // Tests that we can add and remove capturer as unique sources.
833 void AddRemoveCapturerMultipleSources() {
834 // WebRTC implementation will drop frames if pushed to quickly. Wait the
835 // interval time to avoid that.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000836 // WebRTC implementation will drop frames if pushed to quickly. Wait the
837 // interval time to avoid that.
838 // Set up the stream associated with the engine.
839 EXPECT_TRUE(channel_->AddRecvStream(
840 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800841 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000842 cricket::VideoFormat capture_format; // default format
843 capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
844 // Set up additional stream 1.
845 cricket::FakeVideoRenderer renderer1;
nisse08582ff2016-02-04 01:24:52 -0800846 EXPECT_FALSE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000847 EXPECT_TRUE(channel_->AddRecvStream(
848 cricket::StreamParams::CreateLegacy(1)));
nisse08582ff2016-02-04 01:24:52 -0800849 EXPECT_TRUE(channel_->SetSink(1, &renderer1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000850 EXPECT_TRUE(channel_->AddSendStream(
851 cricket::StreamParams::CreateLegacy(1)));
kwiberg686a8ef2016-02-26 03:00:35 -0800852 std::unique_ptr<cricket::FakeVideoCapturer> capturer1(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000853 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000854 EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
855 // Set up additional stream 2.
856 cricket::FakeVideoRenderer renderer2;
nisse08582ff2016-02-04 01:24:52 -0800857 EXPECT_FALSE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000858 EXPECT_TRUE(channel_->AddRecvStream(
859 cricket::StreamParams::CreateLegacy(2)));
nisse08582ff2016-02-04 01:24:52 -0800860 EXPECT_TRUE(channel_->SetSink(2, &renderer2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 EXPECT_TRUE(channel_->AddSendStream(
862 cricket::StreamParams::CreateLegacy(2)));
kwiberg686a8ef2016-02-26 03:00:35 -0800863 std::unique_ptr<cricket::FakeVideoCapturer> capturer2(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000864 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000865 EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
866 // State for all the streams.
867 EXPECT_TRUE(SetOneCodec(DefaultCodec()));
nisse2ded9b12016-04-08 02:23:55 -0700868 // A limitation in the lmi implementation requires that SetSource() is
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000869 // called after SetOneCodec().
870 // TODO(hellner): this seems like an unnecessary constraint, fix it.
nisse2ded9b12016-04-08 02:23:55 -0700871 channel_->SetSource(1, capturer1.get());
872 channel_->SetSource(2, capturer2.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000873 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000874 // Test capturer associated with engine.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000875 const int kTestWidth = 160;
876 const int kTestHeight = 120;
877 EXPECT_TRUE(capturer1->CaptureCustomFrame(
878 kTestWidth, kTestHeight, cricket::FOURCC_I420));
879 EXPECT_FRAME_ON_RENDERER_WAIT(
880 renderer1, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000881 // Capture a frame with additional capturer2, frames should be received
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000882 EXPECT_TRUE(capturer2->CaptureCustomFrame(
883 kTestWidth, kTestHeight, cricket::FOURCC_I420));
884 EXPECT_FRAME_ON_RENDERER_WAIT(
885 renderer2, 1, kTestWidth, kTestHeight, kTimeout);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000886 // Successfully remove the capturer.
nisse2ded9b12016-04-08 02:23:55 -0700887 channel_->SetSource(kSsrc, NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000888 // Fail to re-remove the capturer.
nisse2ded9b12016-04-08 02:23:55 -0700889 channel_->SetSource(kSsrc, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000890 // The capturers must be unregistered here as it runs out of it's scope
891 // next.
nisse2ded9b12016-04-08 02:23:55 -0700892 channel_->SetSource(1, NULL);
893 channel_->SetSource(2, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 }
895
896 void HighAspectHighHeightCapturer() {
897 const int kWidth = 80;
898 const int kHeight = 10000;
899 const int kScaledWidth = 20;
900 const int kScaledHeight = 2500;
901
902 cricket::VideoCodec codec(DefaultCodec());
903 EXPECT_TRUE(SetOneCodec(codec));
904 EXPECT_TRUE(SetSend(true));
905
906 cricket::FakeVideoRenderer renderer;
907 EXPECT_TRUE(channel_->AddRecvStream(
908 cricket::StreamParams::CreateLegacy(kSsrc)));
nisse08582ff2016-02-04 01:24:52 -0800909 EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910 EXPECT_EQ(0, renderer.num_rendered_frames());
911
912 EXPECT_TRUE(SendFrame());
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000913 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
914 renderer, 1, codec.width, codec.height, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915
916 // Registering an external capturer is currently the same as screen casting
917 // (update the test when this changes).
kwiberg686a8ef2016-02-26 03:00:35 -0800918 std::unique_ptr<cricket::FakeVideoCapturer> capturer(
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000919 CreateFakeVideoCapturer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920 const std::vector<cricket::VideoFormat>* formats =
921 capturer->GetSupportedFormats();
922 cricket::VideoFormat capture_format = (*formats)[0];
923 EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
924 // Capture frame to not get same frame timestamps as previous capturer.
925 capturer->CaptureFrame();
nisse2ded9b12016-04-08 02:23:55 -0700926 channel_->SetSource(kSsrc, capturer.get());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000927 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928 EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
929 cricket::FOURCC_ARGB));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000930 EXPECT_GT_FRAME_ON_RENDERER_WAIT(
931 renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
nisse2ded9b12016-04-08 02:23:55 -0700932 channel_->SetSource(kSsrc, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 }
934
935 // Tests that we can adapt video resolution with 16:10 aspect ratio properly.
936 void AdaptResolution16x10() {
nisse08582ff2016-02-04 01:24:52 -0800937 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000938 cricket::VideoCodec codec(DefaultCodec());
939 codec.width = 640;
940 codec.height = 400;
941 SendAndReceive(codec);
942 codec.width /= 2;
943 codec.height /= 2;
944 // Adapt the resolution.
945 EXPECT_TRUE(SetOneCodec(codec));
946 EXPECT_TRUE(WaitAndSendFrame(30));
947 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
948 }
949 // Tests that we can adapt video resolution with 4:3 aspect ratio properly.
950 void AdaptResolution4x3() {
nisse08582ff2016-02-04 01:24:52 -0800951 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000952 cricket::VideoCodec codec(DefaultCodec());
953 codec.width = 640;
954 codec.height = 400;
955 SendAndReceive(codec);
956 codec.width /= 2;
957 codec.height /= 2;
958 // Adapt the resolution.
959 EXPECT_TRUE(SetOneCodec(codec));
960 EXPECT_TRUE(WaitAndSendFrame(30));
961 EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
962 }
963 // Tests that we can drop all frames properly.
964 void AdaptDropAllFrames() {
965 // Set the channel codec's resolution to 0, which will require the adapter
966 // to drop all frames.
967 cricket::VideoCodec codec(DefaultCodec());
968 codec.width = codec.height = codec.framerate = 0;
969 EXPECT_TRUE(SetOneCodec(codec));
970 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -0800971 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972 EXPECT_EQ(0, renderer_.num_rendered_frames());
973 EXPECT_TRUE(SendFrame());
974 EXPECT_TRUE(SendFrame());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000975 rtc::Thread::Current()->ProcessMessages(500);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000976 EXPECT_EQ(0, renderer_.num_rendered_frames());
977 }
978 // Tests that we can reduce the frame rate on demand properly.
979 // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable
980 void AdaptFramerate() {
981 cricket::VideoCodec codec(DefaultCodec());
982 int frame_count = 0;
983 // The capturer runs at 30 fps. The channel requires 30 fps.
984 EXPECT_TRUE(SetOneCodec(codec));
985 EXPECT_TRUE(SetSend(true));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
987 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
988 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
989 frame_count += 2;
990 EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
jbaucheec21bd2016-03-20 06:15:43 -0700991 std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 EXPECT_EQ(codec.id, GetPayloadType(p.get()));
993
994 // The channel requires 15 fps.
995 codec.framerate = 15;
996 EXPECT_TRUE(SetOneCodec(codec));
997 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
998 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
999 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1000 frame_count += 2;
1001 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1002
1003 // The channel requires 10 fps.
1004 codec.framerate = 10;
1005 EXPECT_TRUE(SetOneCodec(codec));
1006 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1007 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1008 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1009 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1010 frame_count += 2;
1011 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1012
1013 // The channel requires 8 fps. The adapter adapts to 10 fps, which is the
1014 // closest factor of 30.
1015 codec.framerate = 8;
1016 EXPECT_TRUE(SetOneCodec(codec));
1017 EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
1018 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1019 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
1020 EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
1021 frame_count += 2;
1022 EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
1023 }
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001024 // Tests that adapted frames won't be upscaled to a higher resolution.
1025 void SendsLowerResolutionOnSmallerFrames() {
1026 cricket::VideoCodec codec = DefaultCodec();
1027 codec.width = 320;
1028 codec.height = 240;
1029 EXPECT_TRUE(SetOneCodec(codec));
1030 EXPECT_TRUE(SetSend(true));
nisse08582ff2016-02-04 01:24:52 -08001031 EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001032 EXPECT_EQ(0, renderer_.num_rendered_frames());
1033 EXPECT_TRUE(SendFrame());
1034 EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
1035
1036 // Check that we send smaller frames at the new resolution.
pbos@webrtc.orgebee4012014-09-03 15:52:02 +00001037 EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(33));
pbos@webrtc.orgc4175b92014-09-03 15:25:49 +00001038 EXPECT_TRUE(video_capturer_->CaptureCustomFrame(
1039 codec.width / 2, codec.height / 2, cricket::FOURCC_I420));
1040 EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout);
1041 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001042
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 // Test that multiple send streams can be created and deleted properly.
1044 void MultipleSendStreams() {
1045 // Remove stream added in Setup. I.e. remove stream corresponding to default
1046 // channel.
1047 EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
1048 const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
1049 for (unsigned int i = 0; i < kSsrcsSize; ++i) {
1050 EXPECT_TRUE(channel_->AddSendStream(
1051 cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
1052 }
1053 // Delete one of the non default channel streams, let the destructor delete
1054 // the remaining ones.
1055 EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1056 // Stream should already be deleted.
1057 EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
1058 }
1059
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 // Two streams one channel tests.
1061
1062 // Tests that we can send and receive frames.
1063 void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
1064 SetUpSecondStream();
1065 // Test sending and receiving on first stream.
1066 SendAndReceive(codec);
1067 // Test sending and receiving on second stream.
1068 EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
Stefan Holmer586b19b2015-09-18 11:14:31 +02001069 EXPECT_GT(NumRtpPackets(), 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001070 EXPECT_EQ(1, renderer2_.num_rendered_frames());
1071 }
1072
kwiberg686a8ef2016-02-26 03:00:35 -08001073 const std::unique_ptr<webrtc::Call> call_;
nisse2ded9b12016-04-08 02:23:55 -07001074 E engine_;
kwiberg686a8ef2016-02-26 03:00:35 -08001075 std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_;
1076 std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
1077 std::unique_ptr<C> channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001078 cricket::FakeNetworkInterface network_interface_;
1079 cricket::FakeVideoRenderer renderer_;
1080 cricket::VideoMediaChannel::Error media_error_;
1081
1082 // Used by test cases where 2 streams are run on the same channel.
1083 cricket::FakeVideoRenderer renderer2_;
1084};
1085
kjellandera96e2d72016-02-04 23:52:28 -08001086#endif // WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT