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"
26 void IgnoreInitializationStatus(CastInitializationStatus status
) {}
30 VEAFactory(const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
31 scoped_ptr
<VideoEncodeAccelerator
> vea
)
32 : task_runner_(task_runner
), vea_(vea
.Pass()) {}
34 void CreateVideoEncodeAccelerator(
35 const ReceiveVideoEncodeAcceleratorCallback
& callback
) {
36 create_cb_
= callback
;
39 void FinishCreatingVideoEncodeAccelerator() {
40 create_cb_
.Run(task_runner_
, vea_
.Pass());
44 const scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
45 scoped_ptr
<VideoEncodeAccelerator
> vea_
;
46 ReceiveVideoEncodeAcceleratorCallback create_cb_
;
49 void CreateSharedMemory(
50 size_t size
, const ReceiveVideoEncodeMemoryCallback
& callback
) {
51 scoped_ptr
<base::SharedMemory
> shm(new base::SharedMemory());
52 if (!shm
->CreateAndMapAnonymous(size
)) {
56 callback
.Run(shm
.Pass());
59 class TestVideoEncoderCallback
60 : public base::RefCountedThreadSafe
<TestVideoEncoderCallback
> {
62 TestVideoEncoderCallback() {}
64 void SetExpectedResult(uint32 expected_frame_id
,
65 uint32 expected_last_referenced_frame_id
,
66 const base::TimeTicks
& expected_capture_time
) {
67 expected_frame_id_
= expected_frame_id
;
68 expected_last_referenced_frame_id_
= expected_last_referenced_frame_id
;
69 expected_capture_time_
= expected_capture_time
;
72 void DeliverEncodedVideoFrame(
73 scoped_ptr
<EncodedFrame
> encoded_frame
) {
74 if (expected_frame_id_
== expected_last_referenced_frame_id_
) {
75 EXPECT_EQ(EncodedFrame::KEY
, encoded_frame
->dependency
);
77 EXPECT_EQ(EncodedFrame::DEPENDENT
,
78 encoded_frame
->dependency
);
80 EXPECT_EQ(expected_frame_id_
, encoded_frame
->frame_id
);
81 EXPECT_EQ(expected_last_referenced_frame_id_
,
82 encoded_frame
->referenced_frame_id
);
83 EXPECT_EQ(expected_capture_time_
, encoded_frame
->reference_time
);
87 virtual ~TestVideoEncoderCallback() {}
90 friend class base::RefCountedThreadSafe
<TestVideoEncoderCallback
>;
92 bool expected_key_frame_
;
93 uint32 expected_frame_id_
;
94 uint32 expected_last_referenced_frame_id_
;
95 base::TimeTicks expected_capture_time_
;
97 DISALLOW_COPY_AND_ASSIGN(TestVideoEncoderCallback
);
101 class ExternalVideoEncoderTest
: public ::testing::Test
{
103 ExternalVideoEncoderTest()
104 : test_video_encoder_callback_(new TestVideoEncoderCallback()) {
105 video_config_
.ssrc
= 1;
106 video_config_
.incoming_feedback_ssrc
= 2;
107 video_config_
.rtp_payload_type
= 127;
108 video_config_
.use_external_encoder
= true;
109 video_config_
.width
= 320;
110 video_config_
.height
= 240;
111 video_config_
.max_bitrate
= 5000000;
112 video_config_
.min_bitrate
= 1000000;
113 video_config_
.start_bitrate
= 2000000;
114 video_config_
.max_qp
= 56;
115 video_config_
.min_qp
= 0;
116 video_config_
.max_frame_rate
= 30;
117 video_config_
.max_number_of_video_buffers_used
= 3;
118 video_config_
.codec
= CODEC_VIDEO_VP8
;
119 gfx::Size
size(video_config_
.width
, video_config_
.height
);
120 video_frame_
= media::VideoFrame::CreateFrame(
121 VideoFrame::I420
, size
, gfx::Rect(size
), size
, base::TimeDelta());
122 PopulateVideoFrame(video_frame_
.get(), 123);
124 testing_clock_
= new base::SimpleTestTickClock();
125 task_runner_
= new test::FakeSingleThreadTaskRunner(testing_clock_
);
127 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock_
).Pass(),
132 fake_vea_
= new test::FakeVideoEncodeAccelerator(task_runner_
,
134 scoped_ptr
<VideoEncodeAccelerator
> fake_vea(fake_vea_
);
135 VEAFactory
vea_factory(task_runner_
, fake_vea
.Pass());
136 video_encoder_
.reset(new ExternalVideoEncoder(
139 base::Bind(&IgnoreInitializationStatus
),
140 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator
,
141 base::Unretained(&vea_factory
)),
142 base::Bind(&CreateSharedMemory
)));
143 vea_factory
.FinishCreatingVideoEncodeAccelerator();
146 virtual ~ExternalVideoEncoderTest() {}
148 base::SimpleTestTickClock
* testing_clock_
; // Owned by CastEnvironment.
149 test::FakeVideoEncodeAccelerator
* fake_vea_
; // Owned by video_encoder_.
150 std::vector
<uint32
> stored_bitrates_
;
151 scoped_refptr
<TestVideoEncoderCallback
> test_video_encoder_callback_
;
152 VideoSenderConfig video_config_
;
153 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner_
;
154 scoped_ptr
<VideoEncoder
> video_encoder_
;
155 scoped_refptr
<media::VideoFrame
> video_frame_
;
156 scoped_refptr
<CastEnvironment
> cast_environment_
;
158 DISALLOW_COPY_AND_ASSIGN(ExternalVideoEncoderTest
);
161 TEST_F(ExternalVideoEncoderTest
, EncodePattern30fpsRunningOutOfAck
) {
162 task_runner_
->RunTasks(); // Run the initializer on the correct thread.
164 VideoEncoder::FrameEncodedCallback frame_encoded_callback
=
165 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame
,
166 test_video_encoder_callback_
.get());
168 base::TimeTicks capture_time
;
169 capture_time
+= base::TimeDelta::FromMilliseconds(33);
170 test_video_encoder_callback_
->SetExpectedResult(0, 0, capture_time
);
171 video_encoder_
->SetBitRate(2000);
172 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
173 video_frame_
, capture_time
, frame_encoded_callback
));
174 task_runner_
->RunTasks();
176 for (int i
= 0; i
< 6; ++i
) {
177 capture_time
+= base::TimeDelta::FromMilliseconds(33);
178 test_video_encoder_callback_
->SetExpectedResult(i
+ 1, i
, capture_time
);
179 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
180 video_frame_
, capture_time
, frame_encoded_callback
));
181 task_runner_
->RunTasks();
183 // We need to run the task to cleanup the GPU instance.
184 video_encoder_
.reset(NULL
);
185 task_runner_
->RunTasks();
187 ASSERT_EQ(1u, stored_bitrates_
.size());
188 EXPECT_EQ(2000u, stored_bitrates_
[0]);
191 TEST_F(ExternalVideoEncoderTest
, StreamHeader
) {
192 task_runner_
->RunTasks(); // Run the initializer on the correct thread.
194 VideoEncoder::FrameEncodedCallback frame_encoded_callback
=
195 base::Bind(&TestVideoEncoderCallback::DeliverEncodedVideoFrame
,
196 test_video_encoder_callback_
.get());
198 // Force the FakeVideoEncodeAccelerator to return a dummy non-key frame first.
199 fake_vea_
->SendDummyFrameForTesting(false);
201 // Verify the first returned bitstream buffer is still a key frame.
202 base::TimeTicks capture_time
;
203 capture_time
+= base::TimeDelta::FromMilliseconds(33);
204 test_video_encoder_callback_
->SetExpectedResult(0, 0, capture_time
);
205 EXPECT_TRUE(video_encoder_
->EncodeVideoFrame(
206 video_frame_
, capture_time
, frame_encoded_callback
));
207 task_runner_
->RunTasks();
209 // We need to run the task to cleanup the GPU instance.
210 video_encoder_
.reset(NULL
);
211 task_runner_
->RunTasks();
214 // Verify that everything goes well even if ExternalVideoEncoder is destroyed
215 // before it has a chance to receive the VEA creation callback.
216 TEST(ExternalVideoEncoderEarlyDestroyTest
, DestroyBeforeVEACreatedCallback
) {
217 VideoSenderConfig video_config
;
218 base::SimpleTestTickClock
* testing_clock
= new base::SimpleTestTickClock();
219 scoped_refptr
<test::FakeSingleThreadTaskRunner
> task_runner(
220 new test::FakeSingleThreadTaskRunner(testing_clock
));
221 scoped_refptr
<CastEnvironment
> cast_environment(
222 new CastEnvironment(scoped_ptr
<base::TickClock
>(testing_clock
).Pass(),
227 std::vector
<uint32
> stored_bitrates
;
228 scoped_ptr
<VideoEncodeAccelerator
> fake_vea(
229 new test::FakeVideoEncodeAccelerator(task_runner
, &stored_bitrates
));
230 VEAFactory
vea_factory(task_runner
, fake_vea
.Pass());
232 scoped_ptr
<ExternalVideoEncoder
> video_encoder(new ExternalVideoEncoder(
235 base::Bind(&IgnoreInitializationStatus
),
236 base::Bind(&VEAFactory::CreateVideoEncodeAccelerator
,
237 base::Unretained(&vea_factory
)),
238 base::Bind(&CreateSharedMemory
)));
240 video_encoder
.reset();
241 vea_factory
.FinishCreatingVideoEncodeAccelerator();
242 task_runner
->RunTasks();