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/fake_video_encode_accelerator_factory.h"
19 #include "media/cast/sender/video_frame_factory.h"
20 #include "media/cast/sender/video_sender.h"
21 #include "media/cast/test/fake_single_thread_task_runner.h"
22 #include "media/cast/test/utility/default_config.h"
23 #include "media/cast/test/utility/video_utility.h"
24 #include "media/video/fake_video_encode_accelerator.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
32 static const uint8 kPixelValue
= 123;
33 static const int kWidth
= 320;
34 static const int kHeight
= 240;
37 using testing::AtLeast
;
40 void SaveOperationalStatus(OperationalStatus
* out_status
,
41 OperationalStatus in_status
) {
42 DVLOG(1) << "OperationalStatus transitioning from " << *out_status
<< " to "
44 *out_status
= in_status
;
47 class TestPacketSender
: public PacketSender
{
50 : number_of_rtp_packets_(0),
51 number_of_rtcp_packets_(0),
54 // A singular packet implies a RTCP packet.
55 bool SendPacket(PacketRef packet
, const base::Closure
& cb
) final
{
57 stored_packet_
= packet
;
61 if (Rtcp::IsRtcpPacket(&packet
->data
[0], packet
->data
.size())) {
62 ++number_of_rtcp_packets_
;
64 // Check that at least one RTCP packet was sent before the first RTP
65 // packet. This confirms that the receiver will have the necessary lip
66 // sync info before it has to calculate the playout time of the first
68 if (number_of_rtp_packets_
== 0)
69 EXPECT_LE(1, number_of_rtcp_packets_
);
70 ++number_of_rtp_packets_
;
75 int64
GetBytesSent() final
{ return 0; }
77 int number_of_rtp_packets() const { return number_of_rtp_packets_
; }
79 int number_of_rtcp_packets() const { return number_of_rtcp_packets_
; }
81 void SetPause(bool paused
) {
83 if (!paused
&& stored_packet_
.get()) {
84 SendPacket(stored_packet_
, callback_
);
90 int number_of_rtp_packets_
;
91 int number_of_rtcp_packets_
;
93 base::Closure callback_
;
94 PacketRef stored_packet_
;
96 DISALLOW_COPY_AND_ASSIGN(TestPacketSender
);
99 void IgnorePlayoutDelayChanges(base::TimeDelta unused_playout_delay
) {
102 class PeerVideoSender
: public VideoSender
{
105 scoped_refptr
<CastEnvironment
> cast_environment
,
106 const VideoSenderConfig
& video_config
,
107 const StatusChangeCallback
& status_change_cb
,
108 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
109 const CreateVideoEncodeMemoryCallback
& create_video_encode_mem_cb
,
110 CastTransportSender
* const transport_sender
)
111 : VideoSender(cast_environment
,
115 create_video_encode_mem_cb
,
117 base::Bind(&IgnorePlayoutDelayChanges
)) {}
118 using VideoSender::OnReceivedCastFeedback
;
122 class VideoSenderTest
: public ::testing::Test
{
125 : testing_clock_(new base::SimpleTestTickClock()),
126 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_
)),
127 cast_environment_(new CastEnvironment(
128 scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
132 operational_status_(STATUS_UNINITIALIZED
),
133 vea_factory_(task_runner_
) {
134 testing_clock_
->Advance(base::TimeTicks::Now() - base::TimeTicks());
135 vea_factory_
.SetAutoRespond(true);
136 last_pixel_value_
= kPixelValue
;
137 net::IPEndPoint dummy_endpoint
;
138 transport_sender_
.reset(new CastTransportSenderImpl(
143 make_scoped_ptr(new base::DictionaryValue
),
144 base::Bind(&UpdateCastTransportStatus
),
145 BulkRawEventsCallback(),
148 PacketReceiverCallback(),
152 ~VideoSenderTest() override
{}
154 void TearDown() final
{
155 video_sender_
.reset();
156 task_runner_
->RunTasks();
159 static void UpdateCastTransportStatus(CastTransportStatus status
) {
160 EXPECT_EQ(TRANSPORT_VIDEO_INITIALIZED
, status
);
163 // If |external| is true then external video encoder (VEA) is used.
164 // |expect_init_sucess| is true if initialization is expected to succeed.
165 void InitEncoder(bool external
, bool expect_init_success
) {
166 VideoSenderConfig video_config
= GetDefaultVideoSenderConfig();
167 video_config
.use_external_encoder
= external
;
169 ASSERT_EQ(operational_status_
, STATUS_UNINITIALIZED
);
172 vea_factory_
.SetInitializationWillSucceed(expect_init_success
);
173 video_sender_
.reset(new PeerVideoSender(
176 base::Bind(&SaveOperationalStatus
, &operational_status_
),
178 &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator
,
179 base::Unretained(&vea_factory_
)),
180 base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory
,
181 base::Unretained(&vea_factory_
)),
182 transport_sender_
.get()));
184 video_sender_
.reset(new PeerVideoSender(
187 base::Bind(&SaveOperationalStatus
, &operational_status_
),
188 CreateDefaultVideoEncodeAcceleratorCallback(),
189 CreateDefaultVideoEncodeMemoryCallback(),
190 transport_sender_
.get()));
192 task_runner_
->RunTasks();
195 scoped_refptr
<media::VideoFrame
> GetNewVideoFrame() {
196 if (first_frame_timestamp_
.is_null())
197 first_frame_timestamp_
= testing_clock_
->NowTicks();
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
,
202 testing_clock_
->NowTicks() - first_frame_timestamp_
);
203 PopulateVideoFrame(video_frame
.get(), last_pixel_value_
++);
207 scoped_refptr
<media::VideoFrame
> GetLargeNewVideoFrame() {
208 if (first_frame_timestamp_
.is_null())
209 first_frame_timestamp_
= testing_clock_
->NowTicks();
210 gfx::Size
size(kWidth
, kHeight
);
211 scoped_refptr
<media::VideoFrame
> video_frame
=
212 media::VideoFrame::CreateFrame(
213 VideoFrame::I420
, size
, gfx::Rect(size
), size
,
214 testing_clock_
->NowTicks() - first_frame_timestamp_
);
215 PopulateVideoFrameWithNoise(video_frame
.get());
219 void RunTasks(int during_ms
) {
220 task_runner_
->Sleep(base::TimeDelta::FromMilliseconds(during_ms
));
223 base::SimpleTestTickClock
* const testing_clock_
; // Owned by CastEnvironment.
224 const scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
225 const scoped_refptr
<CastEnvironment
> cast_environment_
;
226 OperationalStatus operational_status_
;
227 FakeVideoEncodeAcceleratorFactory vea_factory_
;
228 TestPacketSender transport_
;
229 scoped_ptr
<CastTransportSenderImpl
> transport_sender_
;
230 scoped_ptr
<PeerVideoSender
> video_sender_
;
231 int last_pixel_value_
;
232 base::TimeTicks first_frame_timestamp_
;
234 DISALLOW_COPY_AND_ASSIGN(VideoSenderTest
);
237 TEST_F(VideoSenderTest
, BuiltInEncoder
) {
238 InitEncoder(false, true);
239 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
241 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
243 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
244 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
246 task_runner_
->RunTasks();
247 EXPECT_LE(1, transport_
.number_of_rtp_packets());
248 EXPECT_LE(1, transport_
.number_of_rtcp_packets());
251 TEST_F(VideoSenderTest
, ExternalEncoder
) {
252 InitEncoder(true, true);
253 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
255 // The SizeAdaptableExternalVideoEncoder initally reports STATUS_INITIALIZED
256 // so that frames will be sent to it. Therefore, no encoder activity should
257 // have occurred at this point. Send a frame to spurn creation of the
258 // underlying ExternalVideoEncoder instance.
259 if (vea_factory_
.vea_response_count() == 0) {
260 video_sender_
->InsertRawVideoFrame(GetNewVideoFrame(),
261 testing_clock_
->NowTicks());
262 task_runner_
->RunTasks();
264 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
267 // VideoSender created an encoder for 1280x720 frames, in order to provide the
268 // INITIALIZED status.
269 EXPECT_EQ(1, vea_factory_
.vea_response_count());
270 EXPECT_EQ(3, vea_factory_
.shm_response_count());
272 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
274 for (int i
= 0; i
< 3; ++i
) {
275 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
276 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
278 // VideoSender re-created the encoder for the 320x240 frames we're
280 EXPECT_EQ(1, vea_factory_
.vea_response_count());
281 EXPECT_EQ(3, vea_factory_
.shm_response_count());
284 video_sender_
.reset(NULL
);
285 task_runner_
->RunTasks();
286 EXPECT_EQ(1, vea_factory_
.vea_response_count());
287 EXPECT_EQ(3, vea_factory_
.shm_response_count());
290 TEST_F(VideoSenderTest
, ExternalEncoderInitFails
) {
291 InitEncoder(true, false);
293 // The SizeAdaptableExternalVideoEncoder initally reports STATUS_INITIALIZED
294 // so that frames will be sent to it. Send a frame to spurn creation of the
295 // underlying ExternalVideoEncoder instance, which should result in failure.
296 if (operational_status_
== STATUS_INITIALIZED
||
297 operational_status_
== STATUS_CODEC_REINIT_PENDING
) {
298 video_sender_
->InsertRawVideoFrame(GetNewVideoFrame(),
299 testing_clock_
->NowTicks());
300 task_runner_
->RunTasks();
302 EXPECT_EQ(STATUS_CODEC_INIT_FAILED
, operational_status_
);
304 video_sender_
.reset(NULL
);
305 task_runner_
->RunTasks();
308 TEST_F(VideoSenderTest
, RtcpTimer
) {
309 InitEncoder(false, true);
310 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
312 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
314 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
315 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
317 // Make sure that we send at least one RTCP packet.
318 base::TimeDelta max_rtcp_timeout
=
319 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs
* 3 / 2);
321 RunTasks(max_rtcp_timeout
.InMilliseconds());
322 EXPECT_LE(1, transport_
.number_of_rtp_packets());
323 EXPECT_LE(1, transport_
.number_of_rtcp_packets());
324 // Build Cast msg and expect RTCP packet.
325 RtcpCastMessage
cast_feedback(1);
326 cast_feedback
.media_ssrc
= 2;
327 cast_feedback
.ack_frame_id
= 0;
328 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
329 RunTasks(max_rtcp_timeout
.InMilliseconds());
330 EXPECT_LE(1, transport_
.number_of_rtcp_packets());
333 TEST_F(VideoSenderTest
, ResendTimer
) {
334 InitEncoder(false, true);
335 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
337 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
339 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
340 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
342 // ACK the key frame.
343 RtcpCastMessage
cast_feedback(1);
344 cast_feedback
.media_ssrc
= 2;
345 cast_feedback
.ack_frame_id
= 0;
346 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
348 video_frame
= GetNewVideoFrame();
349 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
351 base::TimeDelta max_resend_timeout
=
352 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs
);
354 // Make sure that we do a re-send.
355 RunTasks(max_resend_timeout
.InMilliseconds());
356 // Should have sent at least 3 packets.
359 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets());
362 TEST_F(VideoSenderTest
, LogAckReceivedEvent
) {
363 InitEncoder(false, true);
364 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
366 SimpleEventSubscriber event_subscriber
;
367 cast_environment_
->Logging()->AddRawEventSubscriber(&event_subscriber
);
370 for (int i
= 0; i
< num_frames
; i
++) {
371 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
373 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
374 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
378 task_runner_
->RunTasks();
380 RtcpCastMessage
cast_feedback(1);
381 cast_feedback
.ack_frame_id
= num_frames
- 1;
383 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
385 std::vector
<FrameEvent
> frame_events
;
386 event_subscriber
.GetFrameEventsAndReset(&frame_events
);
388 ASSERT_TRUE(!frame_events
.empty());
389 EXPECT_EQ(FRAME_ACK_RECEIVED
, frame_events
.rbegin()->type
);
390 EXPECT_EQ(VIDEO_EVENT
, frame_events
.rbegin()->media_type
);
391 EXPECT_EQ(num_frames
- 1u, frame_events
.rbegin()->frame_id
);
393 cast_environment_
->Logging()->RemoveRawEventSubscriber(&event_subscriber
);
396 TEST_F(VideoSenderTest
, StopSendingInTheAbsenceOfAck
) {
397 InitEncoder(false, true);
398 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
400 // Send a stream of frames and don't ACK; by default we shouldn't have more
401 // than 4 frames in flight.
402 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
403 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
406 // Send 3 more frames and record the number of packets sent.
407 for (int i
= 0; i
< 3; ++i
) {
408 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
409 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
412 const int number_of_packets_sent
= transport_
.number_of_rtp_packets();
414 // Send 3 more frames - they should not be encoded, as we have not received
416 for (int i
= 0; i
< 3; ++i
) {
417 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
418 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
422 // We expect a frame to be retransmitted because of duplicated ACKs.
423 // Only one packet of the frame is re-transmitted.
424 EXPECT_EQ(number_of_packets_sent
+ 1,
425 transport_
.number_of_rtp_packets());
427 // Start acking and make sure we're back to steady-state.
428 RtcpCastMessage
cast_feedback(1);
429 cast_feedback
.media_ssrc
= 2;
430 cast_feedback
.ack_frame_id
= 0;
431 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
434 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets());
436 // Empty the pipeline.
438 // Should have sent at least 7 packets.
441 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets());
444 TEST_F(VideoSenderTest
, DuplicateAckRetransmit
) {
445 InitEncoder(false, true);
446 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
448 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
449 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
451 RtcpCastMessage
cast_feedback(1);
452 cast_feedback
.media_ssrc
= 2;
453 cast_feedback
.ack_frame_id
= 0;
455 // Send 3 more frames but don't ACK.
456 for (int i
= 0; i
< 3; ++i
) {
457 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
458 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
461 const int number_of_packets_sent
= transport_
.number_of_rtp_packets();
463 // Send duplicated ACKs and mix some invalid NACKs.
464 for (int i
= 0; i
< 10; ++i
) {
465 RtcpCastMessage
ack_feedback(1);
466 ack_feedback
.media_ssrc
= 2;
467 ack_feedback
.ack_frame_id
= 0;
468 RtcpCastMessage
nack_feedback(1);
469 nack_feedback
.media_ssrc
= 2;
470 nack_feedback
.missing_frames_and_packets
[255] = PacketIdSet();
471 video_sender_
->OnReceivedCastFeedback(ack_feedback
);
472 video_sender_
->OnReceivedCastFeedback(nack_feedback
);
474 EXPECT_EQ(number_of_packets_sent
, transport_
.number_of_rtp_packets());
476 // Re-transmit one packet because of duplicated ACKs.
477 for (int i
= 0; i
< 3; ++i
) {
478 RtcpCastMessage
ack_feedback(1);
479 ack_feedback
.media_ssrc
= 2;
480 ack_feedback
.ack_frame_id
= 0;
481 video_sender_
->OnReceivedCastFeedback(ack_feedback
);
483 EXPECT_EQ(number_of_packets_sent
+ 1, transport_
.number_of_rtp_packets());
486 TEST_F(VideoSenderTest
, DuplicateAckRetransmitDoesNotCancelRetransmits
) {
487 InitEncoder(false, true);
488 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
490 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
491 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
493 RtcpCastMessage
cast_feedback(1);
494 cast_feedback
.media_ssrc
= 2;
495 cast_feedback
.ack_frame_id
= 0;
497 // Send 2 more frames but don't ACK.
498 for (int i
= 0; i
< 2; ++i
) {
499 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
500 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
503 // Pause the transport
504 transport_
.SetPause(true);
506 // Insert one more video frame.
507 video_frame
= GetLargeNewVideoFrame();
508 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
511 const int number_of_packets_sent
= transport_
.number_of_rtp_packets();
513 // Send duplicated ACKs and mix some invalid NACKs.
514 for (int i
= 0; i
< 10; ++i
) {
515 RtcpCastMessage
ack_feedback(1);
516 ack_feedback
.media_ssrc
= 2;
517 ack_feedback
.ack_frame_id
= 0;
518 RtcpCastMessage
nack_feedback(1);
519 nack_feedback
.media_ssrc
= 2;
520 nack_feedback
.missing_frames_and_packets
[255] = PacketIdSet();
521 video_sender_
->OnReceivedCastFeedback(ack_feedback
);
522 video_sender_
->OnReceivedCastFeedback(nack_feedback
);
524 EXPECT_EQ(number_of_packets_sent
, transport_
.number_of_rtp_packets());
526 // Re-transmit one packet because of duplicated ACKs.
527 for (int i
= 0; i
< 3; ++i
) {
528 RtcpCastMessage
ack_feedback(1);
529 ack_feedback
.media_ssrc
= 2;
530 ack_feedback
.ack_frame_id
= 0;
531 video_sender_
->OnReceivedCastFeedback(ack_feedback
);
534 transport_
.SetPause(false);
536 EXPECT_LT(number_of_packets_sent
+ 1, transport_
.number_of_rtp_packets());
539 TEST_F(VideoSenderTest
, AcksCancelRetransmits
) {
540 InitEncoder(false, true);
541 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
543 transport_
.SetPause(true);
544 scoped_refptr
<media::VideoFrame
> video_frame
= GetLargeNewVideoFrame();
545 video_sender_
->InsertRawVideoFrame(video_frame
, testing_clock_
->NowTicks());
548 // Frame should be in buffer, waiting. Now let's ack it.
549 RtcpCastMessage
cast_feedback(1);
550 cast_feedback
.media_ssrc
= 2;
551 cast_feedback
.ack_frame_id
= 0;
552 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
554 transport_
.SetPause(false);
556 EXPECT_EQ(0, transport_
.number_of_rtp_packets());
559 TEST_F(VideoSenderTest
, CheckVideoFrameFactoryIsNull
) {
560 InitEncoder(false, true);
561 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
563 EXPECT_EQ(nullptr, video_sender_
->CreateVideoFrameFactory().get());
566 TEST_F(VideoSenderTest
, PopulatesResourceUtilizationInFrameMetadata
) {
567 InitEncoder(false, true);
568 ASSERT_EQ(STATUS_INITIALIZED
, operational_status_
);
570 for (int i
= 0; i
< 3; ++i
) {
571 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
572 ASSERT_FALSE(video_frame
->metadata()->HasKey(
573 media::VideoFrameMetadata::RESOURCE_UTILIZATION
));
575 const base::TimeTicks reference_time
= testing_clock_
->NowTicks();
576 video_sender_
->InsertRawVideoFrame(video_frame
, reference_time
);
578 // Run encode tasks. VideoSender::OnEncodedVideoFrame() will be called once
579 // encoding of the frame is complete, and this is when the
580 // RESOURCE_UTILIZATION metadata is populated.
583 // Check that the RESOURCE_UTILIZATION value is set and non-negative. Don't
584 // check for specific values because they are dependent on real-world CPU
585 // encode time, which can vary across test runs.
586 double utilization
= -1.0;
587 EXPECT_TRUE(video_frame
->metadata()->GetDouble(
588 media::VideoFrameMetadata::RESOURCE_UTILIZATION
, &utilization
));
589 EXPECT_LE(0.0, utilization
);
591 EXPECT_GE(1.0, utilization
); // Key frames never exceed 1.0.
592 DVLOG(1) << "Utilization computed by VideoSender is: " << utilization
;