1 // Copyright 2014 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.
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/net/cast_transport_config.h"
16 #include "media/cast/net/cast_transport_sender_impl.h"
17 #include "media/cast/net/pacing/paced_sender.h"
18 #include "media/cast/sender/video_sender.h"
19 #include "media/cast/test/fake_single_thread_task_runner.h"
20 #include "media/cast/test/fake_video_encode_accelerator.h"
21 #include "media/cast/test/utility/default_config.h"
22 #include "media/cast/test/utility/video_utility.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
30 static const uint8 kPixelValue = 123;
31 static const int kWidth = 320;
32 static const int kHeight = 240;
35 using testing::AtLeast;
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());
44 void CreateSharedMemory(
45 size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
46 scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
47 if (!shm->CreateAndMapAnonymous(size)) {
51 callback.Run(shm.Pass());
54 void SaveInitializationStatus(CastInitializationStatus* out_status,
55 CastInitializationStatus in_status) {
56 *out_status = in_status;
59 class TestPacketSender : public PacketSender {
62 : number_of_rtp_packets_(0),
63 number_of_rtcp_packets_(0),
66 // A singular packet implies a RTCP packet.
67 bool SendPacket(PacketRef packet, const base::Closure& cb) override {
69 stored_packet_ = packet;
73 if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
74 ++number_of_rtcp_packets_;
76 // Check that at least one RTCP packet was sent before the first RTP
77 // packet. This confirms that the receiver will have the necessary lip
78 // sync info before it has to calculate the playout time of the first
80 if (number_of_rtp_packets_ == 0)
81 EXPECT_LE(1, number_of_rtcp_packets_);
82 ++number_of_rtp_packets_;
87 int64 GetBytesSent() override { return 0; }
89 int number_of_rtp_packets() const { return number_of_rtp_packets_; }
91 int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
93 void SetPause(bool paused) {
95 if (!paused && stored_packet_.get()) {
96 SendPacket(stored_packet_, callback_);
102 int number_of_rtp_packets_;
103 int number_of_rtcp_packets_;
105 base::Closure callback_;
106 PacketRef stored_packet_;
108 DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
111 void IgnorePlayoutDelayChanges(base::TimeDelta unused_playout_delay) {
113 class PeerVideoSender : public VideoSender {
116 scoped_refptr<CastEnvironment> cast_environment,
117 const VideoSenderConfig& video_config,
118 const CastInitializationCallback& initialization_cb,
119 const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
120 const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
121 CastTransportSender* const transport_sender)
122 : VideoSender(cast_environment,
126 create_video_encode_mem_cb,
128 base::Bind(&IgnorePlayoutDelayChanges)) {}
129 using VideoSender::OnReceivedCastFeedback;
133 class VideoSenderTest : public ::testing::Test {
136 testing_clock_ = new base::SimpleTestTickClock();
137 testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
138 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
140 new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
144 last_pixel_value_ = kPixelValue;
145 net::IPEndPoint dummy_endpoint;
146 transport_sender_.reset(new CastTransportSenderImpl(
150 make_scoped_ptr(new base::DictionaryValue),
151 base::Bind(&UpdateCastTransportStatus),
152 BulkRawEventsCallback(),
158 ~VideoSenderTest() override {}
160 void TearDown() override {
161 video_sender_.reset();
162 task_runner_->RunTasks();
165 static void UpdateCastTransportStatus(CastTransportStatus status) {
166 EXPECT_EQ(TRANSPORT_VIDEO_INITIALIZED, status);
169 // If |external| is true then external video encoder (VEA) is used.
170 // |expect_init_sucess| is true if initialization is expected to succeed.
171 CastInitializationStatus InitEncoder(bool external,
172 bool expect_init_success) {
173 VideoSenderConfig video_config;
174 video_config.ssrc = 1;
175 video_config.incoming_feedback_ssrc = 2;
176 video_config.rtp_payload_type = 127;
177 video_config.use_external_encoder = external;
178 video_config.width = kWidth;
179 video_config.height = kHeight;
180 video_config.max_bitrate = 5000000;
181 video_config.min_bitrate = 1000000;
182 video_config.start_bitrate = 1000000;
183 video_config.max_qp = 56;
184 video_config.min_qp = 0;
185 video_config.max_frame_rate = 30;
186 video_config.max_number_of_video_buffers_used = 1;
187 video_config.codec = CODEC_VIDEO_VP8;
188 CastInitializationStatus status = STATUS_VIDEO_UNINITIALIZED;
191 test::FakeVideoEncodeAccelerator* fake_vea =
192 new test::FakeVideoEncodeAccelerator(
193 task_runner_, &stored_bitrates_);
194 fake_vea->SetWillInitializationSucceed(expect_init_success);
195 scoped_ptr<VideoEncodeAccelerator> fake_vea_owner(fake_vea);
197 new PeerVideoSender(cast_environment_,
199 base::Bind(&SaveInitializationStatus,
201 base::Bind(&CreateVideoEncodeAccelerator,
203 base::Passed(&fake_vea_owner)),
204 base::Bind(&CreateSharedMemory),
205 transport_sender_.get()));
208 new PeerVideoSender(cast_environment_,
210 base::Bind(&SaveInitializationStatus,
212 CreateDefaultVideoEncodeAcceleratorCallback(),
213 CreateDefaultVideoEncodeMemoryCallback(),
214 transport_sender_.get()));
216 task_runner_->RunTasks();
220 scoped_refptr<media::VideoFrame> GetNewVideoFrame() {
221 if (first_frame_timestamp_.is_null())
222 first_frame_timestamp_ = testing_clock_->NowTicks();
223 gfx::Size size(kWidth, kHeight);
224 scoped_refptr<media::VideoFrame> video_frame =
225 media::VideoFrame::CreateFrame(
226 VideoFrame::I420, size, gfx::Rect(size), size,
227 testing_clock_->NowTicks() - first_frame_timestamp_);
228 PopulateVideoFrame(video_frame.get(), last_pixel_value_++);
232 scoped_refptr<media::VideoFrame> GetLargeNewVideoFrame() {
233 if (first_frame_timestamp_.is_null())
234 first_frame_timestamp_ = testing_clock_->NowTicks();
235 gfx::Size size(kWidth, kHeight);
236 scoped_refptr<media::VideoFrame> video_frame =
237 media::VideoFrame::CreateFrame(
238 VideoFrame::I420, size, gfx::Rect(size), size,
239 testing_clock_->NowTicks() - first_frame_timestamp_);
240 PopulateVideoFrameWithNoise(video_frame.get());
244 void RunTasks(int during_ms) {
245 task_runner_->Sleep(base::TimeDelta::FromMilliseconds(during_ms));
248 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment.
249 TestPacketSender transport_;
250 scoped_ptr<CastTransportSenderImpl> transport_sender_;
251 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
252 scoped_ptr<PeerVideoSender> video_sender_;
253 std::vector<uint32> stored_bitrates_;
254 scoped_refptr<CastEnvironment> cast_environment_;
255 int last_pixel_value_;
256 base::TimeTicks first_frame_timestamp_;
258 DISALLOW_COPY_AND_ASSIGN(VideoSenderTest);
261 TEST_F(VideoSenderTest, BuiltInEncoder) {
262 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
263 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
265 const base::TimeTicks reference_time = testing_clock_->NowTicks();
266 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
268 task_runner_->RunTasks();
269 EXPECT_LE(1, transport_.number_of_rtp_packets());
270 EXPECT_LE(1, transport_.number_of_rtcp_packets());
273 TEST_F(VideoSenderTest, ExternalEncoder) {
274 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(true, true));
276 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
278 const base::TimeTicks reference_time = testing_clock_->NowTicks();
279 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
280 task_runner_->RunTasks();
281 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
282 task_runner_->RunTasks();
283 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
284 task_runner_->RunTasks();
286 // Fixed bitrate is used for external encoder. Bitrate is only once
288 EXPECT_EQ(1u, stored_bitrates_.size());
289 video_sender_.reset(NULL);
290 task_runner_->RunTasks();
293 TEST_F(VideoSenderTest, ExternalEncoderInitFails) {
294 EXPECT_EQ(STATUS_HW_VIDEO_ENCODER_NOT_SUPPORTED,
295 InitEncoder(true, false));
296 video_sender_.reset(NULL);
297 task_runner_->RunTasks();
300 TEST_F(VideoSenderTest, RtcpTimer) {
301 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
303 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
305 const base::TimeTicks reference_time = testing_clock_->NowTicks();
306 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
308 // Make sure that we send at least one RTCP packet.
309 base::TimeDelta max_rtcp_timeout =
310 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
312 RunTasks(max_rtcp_timeout.InMilliseconds());
313 EXPECT_LE(1, transport_.number_of_rtp_packets());
314 EXPECT_LE(1, transport_.number_of_rtcp_packets());
315 // Build Cast msg and expect RTCP packet.
316 RtcpCastMessage cast_feedback(1);
317 cast_feedback.media_ssrc = 2;
318 cast_feedback.ack_frame_id = 0;
319 video_sender_->OnReceivedCastFeedback(cast_feedback);
320 RunTasks(max_rtcp_timeout.InMilliseconds());
321 EXPECT_LE(1, transport_.number_of_rtcp_packets());
324 TEST_F(VideoSenderTest, ResendTimer) {
325 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
327 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
329 const base::TimeTicks reference_time = testing_clock_->NowTicks();
330 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
332 // ACK the key frame.
333 RtcpCastMessage cast_feedback(1);
334 cast_feedback.media_ssrc = 2;
335 cast_feedback.ack_frame_id = 0;
336 video_sender_->OnReceivedCastFeedback(cast_feedback);
338 video_frame = GetNewVideoFrame();
339 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
341 base::TimeDelta max_resend_timeout =
342 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs);
344 // Make sure that we do a re-send.
345 RunTasks(max_resend_timeout.InMilliseconds());
346 // Should have sent at least 3 packets.
349 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
352 TEST_F(VideoSenderTest, LogAckReceivedEvent) {
353 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
354 SimpleEventSubscriber event_subscriber;
355 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber);
358 for (int i = 0; i < num_frames; i++) {
359 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
361 const base::TimeTicks reference_time = testing_clock_->NowTicks();
362 video_sender_->InsertRawVideoFrame(video_frame, reference_time);
366 task_runner_->RunTasks();
368 RtcpCastMessage cast_feedback(1);
369 cast_feedback.ack_frame_id = num_frames - 1;
371 video_sender_->OnReceivedCastFeedback(cast_feedback);
373 std::vector<FrameEvent> frame_events;
374 event_subscriber.GetFrameEventsAndReset(&frame_events);
376 ASSERT_TRUE(!frame_events.empty());
377 EXPECT_EQ(FRAME_ACK_RECEIVED, frame_events.rbegin()->type);
378 EXPECT_EQ(VIDEO_EVENT, frame_events.rbegin()->media_type);
379 EXPECT_EQ(num_frames - 1u, frame_events.rbegin()->frame_id);
381 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber);
384 TEST_F(VideoSenderTest, StopSendingInTheAbsenceOfAck) {
385 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
386 // Send a stream of frames and don't ACK; by default we shouldn't have more
387 // than 4 frames in flight.
388 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
389 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
392 // Send 3 more frames and record the number of packets sent.
393 for (int i = 0; i < 3; ++i) {
394 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
395 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
398 const int number_of_packets_sent = transport_.number_of_rtp_packets();
400 // Send 3 more frames - they should not be encoded, as we have not received
402 for (int i = 0; i < 3; ++i) {
403 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
404 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
408 // We expect a frame to be retransmitted because of duplicated ACKs.
409 // Only one packet of the frame is re-transmitted.
410 EXPECT_EQ(number_of_packets_sent + 1,
411 transport_.number_of_rtp_packets());
413 // Start acking and make sure we're back to steady-state.
414 RtcpCastMessage cast_feedback(1);
415 cast_feedback.media_ssrc = 2;
416 cast_feedback.ack_frame_id = 0;
417 video_sender_->OnReceivedCastFeedback(cast_feedback);
420 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
422 // Empty the pipeline.
424 // Should have sent at least 7 packets.
427 transport_.number_of_rtp_packets() + transport_.number_of_rtcp_packets());
430 TEST_F(VideoSenderTest, DuplicateAckRetransmit) {
431 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
432 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
433 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
435 RtcpCastMessage cast_feedback(1);
436 cast_feedback.media_ssrc = 2;
437 cast_feedback.ack_frame_id = 0;
439 // Send 3 more frames but don't ACK.
440 for (int i = 0; i < 3; ++i) {
441 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
442 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
445 const int number_of_packets_sent = transport_.number_of_rtp_packets();
447 // Send duplicated ACKs and mix some invalid NACKs.
448 for (int i = 0; i < 10; ++i) {
449 RtcpCastMessage ack_feedback(1);
450 ack_feedback.media_ssrc = 2;
451 ack_feedback.ack_frame_id = 0;
452 RtcpCastMessage nack_feedback(1);
453 nack_feedback.media_ssrc = 2;
454 nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
455 video_sender_->OnReceivedCastFeedback(ack_feedback);
456 video_sender_->OnReceivedCastFeedback(nack_feedback);
458 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
460 // Re-transmit one packet because of duplicated ACKs.
461 for (int i = 0; i < 3; ++i) {
462 RtcpCastMessage ack_feedback(1);
463 ack_feedback.media_ssrc = 2;
464 ack_feedback.ack_frame_id = 0;
465 video_sender_->OnReceivedCastFeedback(ack_feedback);
467 EXPECT_EQ(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
470 TEST_F(VideoSenderTest, DuplicateAckRetransmitDoesNotCancelRetransmits) {
471 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
472 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
473 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
475 RtcpCastMessage cast_feedback(1);
476 cast_feedback.media_ssrc = 2;
477 cast_feedback.ack_frame_id = 0;
479 // Send 2 more frames but don't ACK.
480 for (int i = 0; i < 2; ++i) {
481 scoped_refptr<media::VideoFrame> video_frame = GetNewVideoFrame();
482 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
485 // Pause the transport
486 transport_.SetPause(true);
488 // Insert one more video frame.
489 video_frame = GetLargeNewVideoFrame();
490 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
493 const int number_of_packets_sent = transport_.number_of_rtp_packets();
495 // Send duplicated ACKs and mix some invalid NACKs.
496 for (int i = 0; i < 10; ++i) {
497 RtcpCastMessage ack_feedback(1);
498 ack_feedback.media_ssrc = 2;
499 ack_feedback.ack_frame_id = 0;
500 RtcpCastMessage nack_feedback(1);
501 nack_feedback.media_ssrc = 2;
502 nack_feedback.missing_frames_and_packets[255] = PacketIdSet();
503 video_sender_->OnReceivedCastFeedback(ack_feedback);
504 video_sender_->OnReceivedCastFeedback(nack_feedback);
506 EXPECT_EQ(number_of_packets_sent, transport_.number_of_rtp_packets());
508 // Re-transmit one packet because of duplicated ACKs.
509 for (int i = 0; i < 3; ++i) {
510 RtcpCastMessage ack_feedback(1);
511 ack_feedback.media_ssrc = 2;
512 ack_feedback.ack_frame_id = 0;
513 video_sender_->OnReceivedCastFeedback(ack_feedback);
516 transport_.SetPause(false);
518 EXPECT_LT(number_of_packets_sent + 1, transport_.number_of_rtp_packets());
521 TEST_F(VideoSenderTest, AcksCancelRetransmits) {
522 EXPECT_EQ(STATUS_VIDEO_INITIALIZED, InitEncoder(false, true));
523 transport_.SetPause(true);
524 scoped_refptr<media::VideoFrame> video_frame = GetLargeNewVideoFrame();
525 video_sender_->InsertRawVideoFrame(video_frame, testing_clock_->NowTicks());
528 // Frame should be in buffer, waiting. Now let's ack it.
529 RtcpCastMessage cast_feedback(1);
530 cast_feedback.media_ssrc = 2;
531 cast_feedback.ack_frame_id = 0;
532 video_sender_->OnReceivedCastFeedback(cast_feedback);
534 transport_.SetPause(false);
536 EXPECT_EQ(0, transport_.number_of_rtp_packets());