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.
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "media/base/video_frame.h"
11 #include "media/cast/cast_defines.h"
12 #include "media/cast/cast_environment.h"
13 #include "media/cast/sender/external_video_encoder.h"
14 #include "media/cast/test/fake_single_thread_task_runner.h"
15 #include "media/cast/test/fake_video_encode_accelerator.h"
16 #include "media/cast/test/utility/video_utility.h"
17 #include "testing/gmock/include/gmock/gmock.h"
28 VEAFactory(const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
29 scoped_ptr
<VideoEncodeAccelerator
> vea
)
30 : task_runner_(task_runner
), vea_(vea
.Pass()) {}
32 void CreateVideoEncodeAccelerator(
33 const ReceiveVideoEncodeAcceleratorCallback
& callback
) {
34 create_cb_
= callback
;
37 void FinishCreatingVideoEncodeAccelerator() {
38 create_cb_
.Run(task_runner_
, vea_
.Pass());
42 const scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
43 scoped_ptr
<VideoEncodeAccelerator
> vea_
;
44 ReceiveVideoEncodeAcceleratorCallback create_cb_
;
47 void CreateSharedMemory(
48 size_t size
, const ReceiveVideoEncodeMemoryCallback
& callback
) {
49 scoped_ptr
<base::SharedMemory
> shm(new base::SharedMemory());
50 if (!shm
->CreateAndMapAnonymous(size
)) {
54 callback
.Run(shm
.Pass());
57 class TestVideoEncoderCallback
58 : public base::RefCountedThreadSafe
<TestVideoEncoderCallback
> {
60 TestVideoEncoderCallback() {}
62 void SetExpectedResult(uint32 expected_frame_id
,
63 uint32 expected_last_referenced_frame_id
,
64 const base::TimeTicks
& expected_capture_time
) {
65 expected_frame_id_
= expected_frame_id
;
66 expected_last_referenced_frame_id_
= expected_last_referenced_frame_id
;
67 expected_capture_time_
= expected_capture_time
;
70 void DeliverEncodedVideoFrame(
71 scoped_ptr
<EncodedFrame
> encoded_frame
) {
72 if (expected_frame_id_
== expected_last_referenced_frame_id_
) {
73 EXPECT_EQ(EncodedFrame::KEY
, encoded_frame
->dependency
);
75 EXPECT_EQ(EncodedFrame::DEPENDENT
,
76 encoded_frame
->dependency
);
78 EXPECT_EQ(expected_frame_id_
, encoded_frame
->frame_id
);
79 EXPECT_EQ(expected_last_referenced_frame_id_
,
80 encoded_frame
->referenced_frame_id
);
81 EXPECT_EQ(expected_capture_time_
, encoded_frame
->reference_time
);
85 virtual ~TestVideoEncoderCallback() {}
88 friend class base::RefCountedThreadSafe
<TestVideoEncoderCallback
>;
90 bool expected_key_frame_
;
91 uint32 expected_frame_id_
;
92 uint32 expected_last_referenced_frame_id_
;
93 base::TimeTicks expected_capture_time_
;
95 DISALLOW_COPY_AND_ASSIGN(TestVideoEncoderCallback
);
99 class ExternalVideoEncoderTest
: public ::testing::Test
{
101 ExternalVideoEncoderTest()
102 : test_video_encoder_callback_(new TestVideoEncoderCallback()) {
103 video_config_
.ssrc
= 1;
104 video_config_
.incoming_feedback_ssrc
= 2;
105 video_config_
.rtp_payload_type
= 127;
106 video_config_
.use_external_encoder
= true;
107 video_config_
.width
= 320;
108 video_config_
.height
= 240;
109 video_config_
.max_bitrate
= 5000000;
110 video_config_
.min_bitrate
= 1000000;
111 video_config_
.start_bitrate
= 2000000;
112 video_config_
.max_qp
= 56;
113 video_config_
.min_qp
= 0;
114 video_config_
.max_frame_rate
= 30;
115 video_config_
.max_number_of_video_buffers_used
= 3;
116 video_config_
.codec
= CODEC_VIDEO_VP8
;
117 gfx::Size
size(video_config_
.width
, video_config_
.height
);
118 video_frame_
= media::VideoFrame::CreateFrame(
119 VideoFrame::I420
, size
, gfx::Rect(size
), size
, base::TimeDelta());
120 PopulateVideoFrame(video_frame_
.get(), 123);
122 testing_clock_
= new base::SimpleTestTickClock();
123 task_runner_
= new test::FakeSingleThreadTaskRunner(testing_clock_
);
125 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
130 fake_vea_
= new test::FakeVideoEncodeAccelerator(task_runner_
,
132 scoped_ptr
<VideoEncodeAccelerator
> fake_vea(fake_vea_
);
133 VEAFactory
vea_factory(task_runner_
, fake_vea
.Pass());
134 video_encoder_
.reset(new ExternalVideoEncoder(
137 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator
,
138 base::Unretained(&vea_factory
)),
139 base::Bind(&CreateSharedMemory
)));
140 vea_factory
.FinishCreatingVideoEncodeAccelerator();
143 virtual ~ExternalVideoEncoderTest() {}
145 base::SimpleTestTickClock
* testing_clock_
; // Owned by CastEnvironment.
146 test::FakeVideoEncodeAccelerator
* fake_vea_
; // Owned by video_encoder_.
147 std::vector
<uint32
> stored_bitrates_
;
148 scoped_refptr
<TestVideoEncoderCallback
> test_video_encoder_callback_
;
149 VideoSenderConfig video_config_
;
150 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
151 scoped_ptr
<VideoEncoder
> video_encoder_
;
152 scoped_refptr
<media::VideoFrame
> video_frame_
;
153 scoped_refptr
<CastEnvironment
> cast_environment_
;
155 DISALLOW_COPY_AND_ASSIGN(ExternalVideoEncoderTest
);
158 TEST_F(ExternalVideoEncoderTest
, EncodePattern30fpsRunningOutOfAck
) {
159 task_runner_
->RunTasks(); // Run the initializer on the correct thread.
161 VideoEncoder::FrameEncodedCallback frame_encoded_callback
=
162 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame
,
163 test_video_encoder_callback_
.get());
165 base::TimeTicks capture_time
;
166 capture_time
+= base::TimeDelta::FromMilliseconds(33);
167 test_video_encoder_callback_
->SetExpectedResult(0, 0, capture_time
);
168 video_encoder_
->SetBitRate(2000);
169 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
170 video_frame_
, capture_time
, frame_encoded_callback
));
171 task_runner_
->RunTasks();
173 for (int i
= 0; i
< 6; ++i
) {
174 capture_time
+= base::TimeDelta::FromMilliseconds(33);
175 test_video_encoder_callback_
->SetExpectedResult(i
+ 1, i
, capture_time
);
176 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
177 video_frame_
, capture_time
, frame_encoded_callback
));
178 task_runner_
->RunTasks();
180 // We need to run the task to cleanup the GPU instance.
181 video_encoder_
.reset(NULL
);
182 task_runner_
->RunTasks();
184 ASSERT_EQ(1u, stored_bitrates_
.size());
185 EXPECT_EQ(2000u, stored_bitrates_
[0]);
188 TEST_F(ExternalVideoEncoderTest
, StreamHeader
) {
189 task_runner_
->RunTasks(); // Run the initializer on the correct thread.
191 VideoEncoder::FrameEncodedCallback frame_encoded_callback
=
192 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame
,
193 test_video_encoder_callback_
.get());
195 // Force the FakeVideoEncodeAccelerator to return a dummy non-key frame first.
196 fake_vea_
->SendDummyFrameForTesting(false);
198 // Verify the first returned bitstream buffer is still a key frame.
199 base::TimeTicks capture_time
;
200 capture_time
+= base::TimeDelta::FromMilliseconds(33);
201 test_video_encoder_callback_
->SetExpectedResult(0, 0, capture_time
);
202 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
203 video_frame_
, capture_time
, frame_encoded_callback
));
204 task_runner_
->RunTasks();
206 // We need to run the task to cleanup the GPU instance.
207 video_encoder_
.reset(NULL
);
208 task_runner_
->RunTasks();
211 // Verify that everything goes well even if ExternalVideoEncoder is destroyed
212 // before it has a chance to receive the VEA creation callback.
213 TEST(ExternalVideoEncoderEarlyDestroyTest
, DestroyBeforeVEACreatedCallback
) {
214 VideoSenderConfig video_config
;
215 base::SimpleTestTickClock
* testing_clock
= new base::SimpleTestTickClock();
216 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner(
217 new test::FakeSingleThreadTaskRunner(testing_clock
));
218 scoped_refptr
<CastEnvironment
> cast_environment(
219 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock
).Pass(),
224 std::vector
<uint32
> stored_bitrates
;
225 scoped_ptr
<VideoEncodeAccelerator
> fake_vea(
226 new test::FakeVideoEncodeAccelerator(task_runner
, &stored_bitrates
));
227 VEAFactory
vea_factory(task_runner
, fake_vea
.Pass());
229 scoped_ptr
<ExternalVideoEncoder
> video_encoder(new ExternalVideoEncoder(
232 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator
,
233 base::Unretained(&vea_factory
)),
234 base::Bind(&CreateSharedMemory
)));
236 video_encoder
.reset();
237 vea_factory
.FinishCreatingVideoEncodeAccelerator();
238 task_runner
->RunTasks();