1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdint.h>
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "media/base/video_frame.h"
13 #include "media/cast/cast_environment.h"
14 #include "media/cast/logging/simple_event_subscriber.h"
15 #include "media/cast/test/fake_single_thread_task_runner.h"
16 #include "media/cast/test/fake_video_encode_accelerator.h"
17 #include "media/cast/test/utility/default_config.h"
18 #include "media/cast/test/utility/video_utility.h"
19 #include "media/cast/transport/cast_transport_config.h"
20 #include "media/cast/transport/cast_transport_sender_impl.h"
21 #include "media/cast/transport/pacing/paced_sender.h"
22 #include "media/cast/video_sender/video_sender.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace media {
27 namespace cast {
28
29 namespace {
30 static const uint8 kPixelValue = 123;
31 static const int kWidth = 320;
32 static const int kHeight = 240;
33
34 using testing::_;
35 using testing::AtLeast;
36
CreateVideoEncodeAccelerator(const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,scoped_ptr<VideoEncodeAccelerator> fake_vea,const ReceiveVideoEncodeAcceleratorCallback & callback)37 void CreateVideoEncodeAccelerator(
38 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
39 scoped_ptr<VideoEncodeAccelerator> fake_vea,
40 const ReceiveVideoEncodeAcceleratorCallback& callback) {
41 callback.Run(task_runner, fake_vea.Pass());
42 }
43
CreateSharedMemory(size_t size,const ReceiveVideoEncodeMemoryCallback & callback)44 void CreateSharedMemory(
45 size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
46 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
47 if (!shm->CreateAndMapAnonymous(size)) {
48 NOTREACHED();
49 return;
50 }
51 callback.Run(shm.Pass());
52 }
53
54 class TestPacketSender : public transport::PacketSender {
55 public:
TestPacketSender()56 TestPacketSender()
57 : number_of_rtp_packets_(0),
58 number_of_rtcp_packets_(0),
59 paused_(false) {}
60
61 // A singular packet implies a RTCP packet.
SendPacket(transport::PacketRef packet,const base::Closure & cb)62 virtual bool SendPacket(transport::PacketRef packet,
63 const base::Closure& cb) OVERRIDE {
64 if (paused_) {
65 stored_packet_ = packet;
66 callback_ = cb;
67 return false;
68 }
69 if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
70 ++number_of_rtcp_packets_;
71 } else {
72 // Check that at least one RTCP packet was sent before the first RTP
73 // packet. This confirms that the receiver will have the necessary lip
74 // sync info before it has to calculate the playout time of the first
75 // frame.
76 if (number_of_rtp_packets_ == 0)
77 EXPECT_LE(1, number_of_rtcp_packets_);
78 ++number_of_rtp_packets_;
79 }
80 return true;
81 }
82
number_of_rtp_packets() const83 int number_of_rtp_packets() const { return number_of_rtp_packets_; }
84
number_of_rtcp_packets() const85 int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
86
SetPause(bool paused)87 void SetPause(bool paused) {
88 paused_ = paused;
89 if (!paused && stored_packet_) {
90 SendPacket(stored_packet_, callback_);
91 callback_.Run();
92 }
93 }
94
95 private:
96 int number_of_rtp_packets_;
97 int number_of_rtcp_packets_;
98 bool paused_;
99 base::Closure callback_;
100 transport::PacketRef stored_packet_;
101
102 DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
103 };
104
105 class PeerVideoSender : public VideoSender {
106 public:
PeerVideoSender(scoped_refptr<CastEnvironment> cast_environment,const VideoSenderConfig & video_config,const CreateVideoEncodeAcceleratorCallback & create_vea_cb,const CreateVideoEncodeMemoryCallback & create_video_encode_mem_cb,transport::CastTransportSender * const transport_sender)107 PeerVideoSender(
108 scoped_refptr<CastEnvironment> cast_environment,
109 const VideoSenderConfig& video_config,
110 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
111 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
112 transport::CastTransportSender* const transport_sender)
113 : VideoSender(cast_environment,
114 video_config,
115 create_vea_cb,
116 create_video_encode_mem_cb,
117 transport_sender) {}
118 using VideoSender::OnReceivedCastFeedback;
119 };
120 } // namespace
121
122 class VideoSenderTest : public ::testing::Test {
123 protected:
VideoSenderTest()124 VideoSenderTest() {
125 testing_clock_ = new base::SimpleTestTickClock();
126 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
127 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
128 cast_environment_ =
129 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
130 task_runner_,
131 task_runner_,
132 task_runner_);
133 last_pixel_value_ = kPixelValue;
134 net::IPEndPoint dummy_endpoint;
135 transport_sender_.reset(new transport::CastTransportSenderImpl(
136 NULL,
137 testing_clock_,
138 dummy_endpoint,
139 base::Bind(&UpdateCastTransportStatus),
140 transport::BulkRawEventsCallback(),
141 base::TimeDelta(),
142 task_runner_,
143 &transport_));
144 }
145
~VideoSenderTest()146 virtual ~VideoSenderTest() {}
147
TearDown()148 virtual void TearDown() OVERRIDE {
149 video_sender_.reset();
150 task_runner_->RunTasks();
151 }
152
UpdateCastTransportStatus(transport::CastTransportStatus status)153 static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
154 EXPECT_EQ(transport::TRANSPORT_VIDEO_INITIALIZED, status);
155 }
156
InitEncoder(bool external)157 void InitEncoder(bool external) {
158 VideoSenderConfig video_config;
159 video_config.rtp_config.ssrc = 1;
160 video_config.incoming_feedback_ssrc = 2;
161 video_config.rtcp_c_name = "video_test@10.1.1.1";
162 video_config.rtp_config.payload_type = 127;
163 video_config.use_external_encoder = external;
164 video_config.width = kWidth;
165 video_config.height = kHeight;
166 video_config.max_bitrate = 5000000;
167 video_config.min_bitrate = 1000000;
168 video_config.start_bitrate = 1000000;
169 video_config.max_qp = 56;
170 video_config.min_qp = 0;
171 video_config.max_frame_rate = 30;
172 video_config.max_number_of_video_buffers_used = 1;
173 video_config.codec = transport::kVp8;
174
175 if (external) {
176 scoped_ptr<VideoEncodeAccelerator> fake_vea(
177 new test::FakeVideoEncodeAccelerator(task_runner_));
178 video_sender_.reset(
179 new PeerVideoSender(cast_environment_,
180 video_config,
181 base::Bind(&CreateVideoEncodeAccelerator,
182 task_runner_,
183 base::Passed(&fake_vea)),
184 base::Bind(&CreateSharedMemory),
185 transport_sender_.get()));
186 } else {
187 video_sender_.reset(
188 new PeerVideoSender(cast_environment_,
189 video_config,
190 CreateDefaultVideoEncodeAcceleratorCallback(),
191 CreateDefaultVideoEncodeMemoryCallback(),
192 transport_sender_.get()));
193 }
194 ASSERT_EQ(STATUS_VIDEO_INITIALIZED, video_sender_->InitializationResult());
195 }
196
GetNewVideoFrame()197 scoped_refptr<media::VideoFrame> GetNewVideoFrame() {
198 gfx::Size size(kWidth, kHeight);
199 scoped_refptr<media::VideoFrame> video_frame =
200 media::VideoFrame::CreateFrame(
201 VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
202 PopulateVideoFrame(video_frame, last_pixel_value_++);
203 return video_frame;
204 }
205
GetLargeNewVideoFrame()206 scoped_refptr<media::VideoFrame> GetLargeNewVideoFrame() {
207 gfx::Size size(kWidth, kHeight);
208 scoped_refptr<media::VideoFrame> video_frame =
209 media::VideoFrame::CreateFrame(
210 VideoFrame::I420, size, gfx::Rect(size), size, base::TimeDelta());
211 PopulateVideoFrameWithNoise(video_frame);
212 return video_frame;
213 }
214
RunTasks(int during_ms)215 void RunTasks(int during_ms) {
216 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(during_ms));
217 }
218
219 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
220 TestPacketSender transport_;
221 scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
222 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
223 scoped_ptr<PeerVideoSender> video_sender_;
224 scoped_refptr<CastEnvironment> cast_environment_;
225 int last_pixel_value_;
226
227 DISALLOW_COPY_AND_ASSIGN(VideoSenderTest);
228 };
229
TEST_F(VideoSenderTest,BuiltInEncoder)230 TEST_F(VideoSenderTest, BuiltInEncoder) {
231 InitEncoder(false);
232 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
233
234 const base::TimeTicks capture_time = testing_clock_->NowTicks();
235 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
236
237 task_runner_->RunTasks();
238 EXPECT_LE(1, transport_.number_of_rtp_packets());
239 EXPECT_LE(1, transport_.number_of_rtcp_packets());
240 }
241
TEST_F(VideoSenderTest,ExternalEncoder)242 TEST_F(VideoSenderTest, ExternalEncoder) {
243 InitEncoder(true);
244 task_runner_->RunTasks();
245
246 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
247
248 const base::TimeTicks capture_time = testing_clock_->NowTicks();
249 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
250
251 task_runner_->RunTasks();
252
253 // We need to run the task to cleanup the GPU instance.
254 video_sender_.reset(NULL);
255 task_runner_->RunTasks();
256 }
257
TEST_F(VideoSenderTest,RtcpTimer)258 TEST_F(VideoSenderTest, RtcpTimer) {
259 InitEncoder(false);
260
261 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
262
263 const base::TimeTicks capture_time = testing_clock_->NowTicks();
264 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
265
266 // Make sure that we send at least one RTCP packet.
267 base::TimeDelta max_rtcp_timeout =
268 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
269
270 RunTasks(max_rtcp_timeout.InMilliseconds());
271 EXPECT_LE(1, transport_.number_of_rtp_packets());
272 EXPECT_LE(1, transport_.number_of_rtcp_packets());
273 // Build Cast msg and expect RTCP packet.
274 RtcpCastMessage cast_feedback(1);
275 cast_feedback.media_ssrc_ = 2;
276 cast_feedback.ack_frame_id_ = 0;
277 video_sender_->OnReceivedCastFeedback(cast_feedback);
278 RunTasks(max_rtcp_timeout.InMilliseconds());
279 EXPECT_LE(1, transport_.number_of_rtcp_packets());
280 }
281
TEST_F(VideoSenderTest,ResendTimer)282 TEST_F(VideoSenderTest, ResendTimer) {
283 InitEncoder(false);
284
285 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
286
287 const base::TimeTicks capture_time = testing_clock_->NowTicks();
288 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
289
290 // ACK the key frame.
291 RtcpCastMessage cast_feedback(1);
292 cast_feedback.media_ssrc_ = 2;
293 cast_feedback.ack_frame_id_ = 0;
294 video_sender_->OnReceivedCastFeedback(cast_feedback);
295
296 video_frame = GetNewVideoFrame();
297 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
298
299 base::TimeDelta max_resend_timeout =
300 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs);
301
302 // Make sure that we do a re-send.
303 RunTasks(max_resend_timeout.InMilliseconds());
304 // Should have sent at least 3 packets.
305 EXPECT_LE(
306 3,
307 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
308 }
309
TEST_F(VideoSenderTest,LogAckReceivedEvent)310 TEST_F(VideoSenderTest, LogAckReceivedEvent) {
311 InitEncoder(false);
312 SimpleEventSubscriber event_subscriber;
313 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
314
315 int num_frames = 10;
316 for (int i = 0; i < num_frames; i++) {
317 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
318
319 const base::TimeTicks capture_time = testing_clock_->NowTicks();
320 video_sender_->InsertRawVideoFrame(video_frame, capture_time);
321 RunTasks(33);
322 }
323
324 task_runner_->RunTasks();
325
326 RtcpCastMessage cast_feedback(1);
327 cast_feedback.ack_frame_id_ = num_frames - 1;
328
329 video_sender_->OnReceivedCastFeedback(cast_feedback);
330
331 std::vector<FrameEvent> frame_events;
332 event_subscriber.GetFrameEventsAndReset(&frame_events);
333
334 ASSERT_TRUE(!frame_events.empty());
335 EXPECT_EQ(FRAME_ACK_RECEIVED, frame_events.rbegin()->type);
336 EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type);
337 EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id);
338
339 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
340 }
341
TEST_F(VideoSenderTest,StopSendingInTheAbsenceOfAck)342 TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
343 InitEncoder(false);
344 // Send a stream of frames and don't ACK; by default we shouldn't have more
345 // than 4 frames in flight.
346 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
347 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
348 RunTasks(33);
349
350 // Send 3 more frames and record the number of packets sent.
351 for (int i = 0; i < 3; ++i) {
352 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
353 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
354 RunTasks(33);
355 }
356 const int number_of_packets_sent = transport_.number_of_rtp_packets();
357
358 // Send 3 more frames - they should not be encoded, as we have not received
359 // any acks.
360 for (int i = 0; i < 3; ++i) {
361 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
362 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
363 RunTasks(33);
364 }
365
366 // We expect a frame to be retransmitted because of duplicated ACKs.
367 // Only one packet of the frame is re-transmitted.
368 EXPECT_EQ(number_of_packets_sent + 1,
369 transport_.number_of_rtp_packets());
370
371 // Start acking and make sure we're back to steady-state.
372 RtcpCastMessage cast_feedback(1);
373 cast_feedback.media_ssrc_ = 2;
374 cast_feedback.ack_frame_id_ = 0;
375 video_sender_->OnReceivedCastFeedback(cast_feedback);
376 EXPECT_LE(
377 4,
378 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
379
380 // Empty the pipeline.
381 RunTasks(100);
382 // Should have sent at least 7 packets.
383 EXPECT_LE(
384 7,
385 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
386 }
387
TEST_F(VideoSenderTest,DuplicateAckRetransmit)388 TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
389 InitEncoder(false);
390 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
391 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
392 RunTasks(33);
393 RtcpCastMessage cast_feedback(1);
394 cast_feedback.media_ssrc_ = 2;
395 cast_feedback.ack_frame_id_ = 0;
396
397 // Send 3 more frames but don't ACK.
398 for (int i = 0; i < 3; ++i) {
399 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
400 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
401 RunTasks(33);
402 }
403 const int number_of_packets_sent = transport_.number_of_rtp_packets();
404
405 // Send duplicated ACKs and mix some invalid NACKs.
406 for (int i = 0; i < 10; ++i) {
407 RtcpCastMessage ack_feedback(1);
408 ack_feedback.media_ssrc_ = 2;
409 ack_feedback.ack_frame_id_ = 0;
410 RtcpCastMessage nack_feedback(1);
411 nack_feedback.media_ssrc_ = 2;
412 nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
413 video_sender_->OnReceivedCastFeedback(ack_feedback);
414 video_sender_->OnReceivedCastFeedback(nack_feedback);
415 }
416 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
417
418 // Re-transmit one packet because of duplicated ACKs.
419 for (int i = 0; i < 3; ++i) {
420 RtcpCastMessage ack_feedback(1);
421 ack_feedback.media_ssrc_ = 2;
422 ack_feedback.ack_frame_id_ = 0;
423 video_sender_->OnReceivedCastFeedback(ack_feedback);
424 }
425 EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
426 }
427
TEST_F(VideoSenderTest,DuplicateAckRetransmitDoesNotCancelRetransmits)428 TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
429 InitEncoder(false);
430 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
431 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
432 RunTasks(33);
433 RtcpCastMessage cast_feedback(1);
434 cast_feedback.media_ssrc_ = 2;
435 cast_feedback.ack_frame_id_ = 0;
436
437 // Send 2 more frames but don't ACK.
438 for (int i = 0; i < 2; ++i) {
439 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
440 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
441 RunTasks(33);
442 }
443 // Pause the transport
444 transport_.SetPause(true);
445
446 // Insert one more video frame.
447 video_frame = GetLargeNewVideoFrame();
448 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
449 RunTasks(33);
450
451 const int number_of_packets_sent = transport_.number_of_rtp_packets();
452
453 // Send duplicated ACKs and mix some invalid NACKs.
454 for (int i = 0; i < 10; ++i) {
455 RtcpCastMessage ack_feedback(1);
456 ack_feedback.media_ssrc_ = 2;
457 ack_feedback.ack_frame_id_ = 0;
458 RtcpCastMessage nack_feedback(1);
459 nack_feedback.media_ssrc_ = 2;
460 nack_feedback.missing_frames_and_packets_[255] = PacketIdSet();
461 video_sender_->OnReceivedCastFeedback(ack_feedback);
462 video_sender_->OnReceivedCastFeedback(nack_feedback);
463 }
464 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
465
466 // Re-transmit one packet because of duplicated ACKs.
467 for (int i = 0; i < 3; ++i) {
468 RtcpCastMessage ack_feedback(1);
469 ack_feedback.media_ssrc_ = 2;
470 ack_feedback.ack_frame_id_ = 0;
471 video_sender_->OnReceivedCastFeedback(ack_feedback);
472 }
473
474 transport_.SetPause(false);
475 RunTasks(100);
476 EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
477 }
478
TEST_F(VideoSenderTest,AcksCancelRetransmits)479 TEST_F(VideoSenderTest, AcksCancelRetransmits) {
480 InitEncoder(false);
481 transport_.SetPause(true);
482 scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
483 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
484 RunTasks(33);
485
486 // Frame should be in buffer, waiting. Now let's ack it.
487 RtcpCastMessage cast_feedback(1);
488 cast_feedback.media_ssrc_ = 2;
489 cast_feedback.ack_frame_id_ = 0;
490 video_sender_->OnReceivedCastFeedback(cast_feedback);
491
492 transport_.SetPause(false);
493 RunTasks(33);
494 EXPECT_EQ(0, transport_.number_of_rtp_packets());
495 }
496
TEST_F(VideoSenderTest,NAcksCancelRetransmits)497 TEST_F(VideoSenderTest, NAcksCancelRetransmits) {
498 InitEncoder(false);
499 transport_.SetPause(true);
500 // Send two video frames.
501 scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
502 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
503 RunTasks(33);
504 video_frame = GetLargeNewVideoFrame();
505 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
506 RunTasks(33);
507
508 // Frames should be in buffer, waiting. Now let's ack the first one and nack
509 // one packet in the second one.
510 RtcpCastMessage cast_feedback(1);
511 cast_feedback.media_ssrc_ = 2;
512 cast_feedback.ack_frame_id_ = 0;
513 PacketIdSet missing_packets;
514 missing_packets.insert(0);
515 cast_feedback.missing_frames_and_packets_[1] = missing_packets;
516 video_sender_->OnReceivedCastFeedback(cast_feedback);
517
518 transport_.SetPause(false);
519 RunTasks(33);
520 // Only one packet should be retransmitted.
521 EXPECT_EQ(1, transport_.number_of_rtp_packets());
522 }
523
524 } // namespace cast
525 } // namespace media
526