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.
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"
30 static const int64 kStartMillisecond
= INT64_C(12345678900000);
31 static const uint8 kPixelValue
= 123;
32 static const int kWidth
= 320;
33 static const int kHeight
= 240;
36 using testing::AtLeast
;
38 void CreateVideoEncodeAccelerator(
39 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
40 scoped_ptr
<VideoEncodeAccelerator
> fake_vea
,
41 const ReceiveVideoEncodeAcceleratorCallback
& callback
) {
42 callback
.Run(task_runner
, fake_vea
.Pass());
45 void CreateSharedMemory(
46 size_t size
, const ReceiveVideoEncodeMemoryCallback
& callback
) {
47 scoped_ptr
<base::SharedMemory
> shm(new base::SharedMemory());
48 if (!shm
->CreateAndMapAnonymous(size
)) {
52 callback
.Run(shm
.Pass());
55 class TestPacketSender
: public transport::PacketSender
{
57 TestPacketSender() : number_of_rtp_packets_(0), number_of_rtcp_packets_(0) {}
59 // A singular packet implies a RTCP packet.
60 virtual bool SendPacket(transport::PacketRef packet
,
61 const base::Closure
& cb
) OVERRIDE
{
62 if (Rtcp::IsRtcpPacket(&packet
->data
[0], packet
->data
.size())) {
63 ++number_of_rtcp_packets_
;
65 ++number_of_rtp_packets_
;
70 int number_of_rtp_packets() const { return number_of_rtp_packets_
; }
72 int number_of_rtcp_packets() const { return number_of_rtcp_packets_
; }
75 int number_of_rtp_packets_
;
76 int number_of_rtcp_packets_
;
78 DISALLOW_COPY_AND_ASSIGN(TestPacketSender
);
81 class PeerVideoSender
: public VideoSender
{
84 scoped_refptr
<CastEnvironment
> cast_environment
,
85 const VideoSenderConfig
& video_config
,
86 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
87 const CreateVideoEncodeMemoryCallback
& create_video_encode_mem_cb
,
88 const CastInitializationCallback
& cast_initialization_cb
,
89 transport::CastTransportSender
* const transport_sender
)
90 : VideoSender(cast_environment
,
93 create_video_encode_mem_cb
,
94 cast_initialization_cb
,
96 using VideoSender::OnReceivedCastFeedback
;
100 class VideoSenderTest
: public ::testing::Test
{
103 testing_clock_
= new base::SimpleTestTickClock();
104 testing_clock_
->Advance(
105 base::TimeDelta::FromMilliseconds(kStartMillisecond
));
106 task_runner_
= new test::FakeSingleThreadTaskRunner(testing_clock_
);
108 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
112 net::IPEndPoint dummy_endpoint
;
113 transport_sender_
.reset(new transport::CastTransportSenderImpl(
117 base::Bind(&UpdateCastTransportStatus
),
118 transport::BulkRawEventsCallback(),
124 virtual ~VideoSenderTest() {}
126 virtual void TearDown() OVERRIDE
{
127 video_sender_
.reset();
128 task_runner_
->RunTasks();
131 static void UpdateCastTransportStatus(transport::CastTransportStatus status
) {
132 EXPECT_EQ(status
, transport::TRANSPORT_VIDEO_INITIALIZED
);
135 void InitEncoder(bool external
) {
136 VideoSenderConfig video_config
;
137 video_config
.rtp_config
.ssrc
= 1;
138 video_config
.incoming_feedback_ssrc
= 2;
139 video_config
.rtcp_c_name
= "video_test@10.1.1.1";
140 video_config
.rtp_config
.payload_type
= 127;
141 video_config
.use_external_encoder
= external
;
142 video_config
.width
= kWidth
;
143 video_config
.height
= kHeight
;
144 video_config
.max_bitrate
= 5000000;
145 video_config
.min_bitrate
= 1000000;
146 video_config
.start_bitrate
= 1000000;
147 video_config
.max_qp
= 56;
148 video_config
.min_qp
= 0;
149 video_config
.max_frame_rate
= 30;
150 video_config
.max_number_of_video_buffers_used
= 1;
151 video_config
.codec
= transport::kVp8
;
154 scoped_ptr
<VideoEncodeAccelerator
> fake_vea(
155 new test::FakeVideoEncodeAccelerator(task_runner_
));
157 new PeerVideoSender(cast_environment_
,
159 base::Bind(&CreateVideoEncodeAccelerator
,
161 base::Passed(&fake_vea
)),
162 base::Bind(&CreateSharedMemory
),
163 base::Bind(&VideoSenderTest::InitializationResult
,
164 base::Unretained(this)),
165 transport_sender_
.get()));
168 new PeerVideoSender(cast_environment_
,
170 CreateDefaultVideoEncodeAcceleratorCallback(),
171 CreateDefaultVideoEncodeMemoryCallback(),
172 base::Bind(&VideoSenderTest::InitializationResult
,
173 base::Unretained(this)),
174 transport_sender_
.get()));
178 scoped_refptr
<media::VideoFrame
> GetNewVideoFrame() {
179 gfx::Size
size(kWidth
, kHeight
);
180 scoped_refptr
<media::VideoFrame
> video_frame
=
181 media::VideoFrame::CreateFrame(
182 VideoFrame::I420
, size
, gfx::Rect(size
), size
, base::TimeDelta());
183 PopulateVideoFrame(video_frame
, kPixelValue
);
187 void RunTasks(int during_ms
) {
188 for (int i
= 0; i
< during_ms
; ++i
) {
189 // Call process the timers every 1 ms.
190 testing_clock_
->Advance(base::TimeDelta::FromMilliseconds(1));
191 task_runner_
->RunTasks();
195 void InitializationResult(CastInitializationStatus result
) {
196 EXPECT_EQ(result
, STATUS_VIDEO_INITIALIZED
);
199 base::SimpleTestTickClock
* testing_clock_
; // Owned by CastEnvironment.
200 TestPacketSender transport_
;
201 scoped_ptr
<transport::CastTransportSenderImpl
> transport_sender_
;
202 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
203 scoped_ptr
<PeerVideoSender
> video_sender_
;
204 scoped_refptr
<CastEnvironment
> cast_environment_
;
206 DISALLOW_COPY_AND_ASSIGN(VideoSenderTest
);
209 TEST_F(VideoSenderTest
, BuiltInEncoder
) {
211 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
213 base::TimeTicks capture_time
;
214 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
216 task_runner_
->RunTasks();
218 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets(),
222 TEST_F(VideoSenderTest
, ExternalEncoder
) {
224 task_runner_
->RunTasks();
226 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
228 base::TimeTicks capture_time
;
229 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
231 task_runner_
->RunTasks();
233 // We need to run the task to cleanup the GPU instance.
234 video_sender_
.reset(NULL
);
235 task_runner_
->RunTasks();
238 TEST_F(VideoSenderTest
, RtcpTimer
) {
241 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
243 base::TimeTicks capture_time
;
244 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
246 // Make sure that we send at least one RTCP packet.
247 base::TimeDelta max_rtcp_timeout
=
248 base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs
* 3 / 2);
250 RunTasks(max_rtcp_timeout
.InMilliseconds());
251 EXPECT_GE(transport_
.number_of_rtp_packets(), 1);
252 // Don't send RTCP prior to receiving an ACK.
253 EXPECT_GE(transport_
.number_of_rtcp_packets(), 0);
254 // Build Cast msg and expect RTCP packet.
255 RtcpCastMessage
cast_feedback(1);
256 cast_feedback
.media_ssrc_
= 2;
257 cast_feedback
.ack_frame_id_
= 0;
258 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
259 RunTasks(max_rtcp_timeout
.InMilliseconds());
260 EXPECT_GE(transport_
.number_of_rtcp_packets(), 1);
263 TEST_F(VideoSenderTest
, ResendTimer
) {
266 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
268 base::TimeTicks capture_time
;
269 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
271 // ACK the key frame.
272 RtcpCastMessage
cast_feedback(1);
273 cast_feedback
.media_ssrc_
= 2;
274 cast_feedback
.ack_frame_id_
= 0;
275 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
277 video_frame
= GetNewVideoFrame();
278 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
280 base::TimeDelta max_resend_timeout
=
281 base::TimeDelta::FromMilliseconds(1 + kDefaultRtpMaxDelayMs
);
283 // Make sure that we do a re-send.
284 RunTasks(max_resend_timeout
.InMilliseconds());
285 // Should have sent at least 3 packets.
287 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets(),
291 TEST_F(VideoSenderTest
, LogAckReceivedEvent
) {
293 SimpleEventSubscriber event_subscriber
;
294 cast_environment_
->Logging()->AddRawEventSubscriber(&event_subscriber
);
297 for (int i
= 0; i
< num_frames
; i
++) {
298 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
300 base::TimeTicks capture_time
;
301 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
305 task_runner_
->RunTasks();
307 RtcpCastMessage
cast_feedback(1);
308 cast_feedback
.ack_frame_id_
= num_frames
- 1;
310 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
312 std::vector
<FrameEvent
> frame_events
;
313 event_subscriber
.GetFrameEventsAndReset(&frame_events
);
315 ASSERT_TRUE(!frame_events
.empty());
316 EXPECT_EQ(kVideoAckReceived
, frame_events
.rbegin()->type
);
317 EXPECT_EQ(num_frames
- 1u, frame_events
.rbegin()->frame_id
);
319 cast_environment_
->Logging()->RemoveRawEventSubscriber(&event_subscriber
);
322 TEST_F(VideoSenderTest
, StopSendingIntheAbsenceOfAck
) {
324 // Send a stream of frames and don't ACK; by default we shouldn't have more
325 // than 4 frames in flight.
326 // Store size in packets of frame 0, as it should be resent sue to timeout.
327 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
328 base::TimeTicks capture_time
;
329 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
331 const int size_of_frame0
= transport_
.number_of_rtp_packets();
333 for (int i
= 1; i
< 4; ++i
) {
334 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
335 base::TimeTicks capture_time
;
336 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
340 const int number_of_packets_sent
= transport_
.number_of_rtp_packets();
341 // Send 4 more frames - they should not be sent to the transport, as we have
342 // received any acks.
343 for (int i
= 0; i
< 3; ++i
) {
344 scoped_refptr
<media::VideoFrame
> video_frame
= GetNewVideoFrame();
345 base::TimeTicks capture_time
;
346 video_sender_
->InsertRawVideoFrame(video_frame
, capture_time
);
350 EXPECT_EQ(number_of_packets_sent
+ size_of_frame0
,
351 transport_
.number_of_rtp_packets());
353 // Start acking and make sure we're back to steady-state.
354 RtcpCastMessage
cast_feedback(1);
355 cast_feedback
.media_ssrc_
= 2;
356 cast_feedback
.ack_frame_id_
= 0;
357 video_sender_
->OnReceivedCastFeedback(cast_feedback
);
359 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets(),
362 // Empty the pipeline.
364 // Should have sent at least 7 packets.
366 transport_
.number_of_rtp_packets() + transport_
.number_of_rtcp_packets(),