Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / cast / sender / h264_vt_encoder_unittest.cc
blob7ef7eefdac492d54aede7da1f7652d771cbf4216
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.
5 #include <queue>
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/power_monitor/power_monitor.h"
11 #include "base/test/launcher/unit_test_launcher.h"
12 #include "base/test/power_monitor_test_base.h"
13 #include "base/test/simple_test_tick_clock.h"
14 #include "base/test/test_suite.h"
15 #include "media/base/decoder_buffer.h"
16 #include "media/base/media.h"
17 #include "media/base/media_switches.h"
18 #include "media/cast/sender/h264_vt_encoder.h"
19 #include "media/cast/sender/video_frame_factory.h"
20 #include "media/cast/test/utility/default_config.h"
21 #include "media/cast/test/utility/video_utility.h"
22 #include "media/ffmpeg/ffmpeg_common.h"
23 #include "media/filters/ffmpeg_glue.h"
24 #include "media/filters/ffmpeg_video_decoder.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace {
29 const int kVideoWidth = 1280;
30 const int kVideoHeight = 720;
32 class MediaTestSuite : public base::TestSuite {
33 public:
34 MediaTestSuite(int argc, char** argv) : TestSuite(argc, argv) {}
35 ~MediaTestSuite() final {}
37 protected:
38 void Initialize() final;
41 void MediaTestSuite::Initialize() {
42 base::TestSuite::Initialize();
43 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
44 command_line->AppendSwitch(switches::kEnableInbandTextTracks);
45 media::InitializeMediaLibrary();
48 } // namespace
50 int main(int argc, char** argv) {
52 base::AtExitManager at_exit_manager;
53 CHECK(VideoToolboxGlue::Get())
54 << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0.";
56 MediaTestSuite test_suite(argc, argv);
57 return base::LaunchUnitTests(
58 argc, argv,
59 base::Bind(&MediaTestSuite::Run, base::Unretained(&test_suite)));
62 namespace media {
63 namespace cast {
65 // See comment in end2end_unittest.cc for details on this value.
66 const double kVideoAcceptedPSNR = 38.0;
68 void SaveDecoderInitResult(bool* out_result, bool in_result) {
69 *out_result = in_result;
72 void SaveOperationalStatus(OperationalStatus* out_status,
73 OperationalStatus in_status) {
74 *out_status = in_status;
77 class MetadataRecorder : public base::RefCountedThreadSafe<MetadataRecorder> {
78 public:
79 MetadataRecorder() : count_frames_delivered_(0) {}
81 int count_frames_delivered() const { return count_frames_delivered_; }
83 void PushExpectation(uint32 expected_frame_id,
84 uint32 expected_last_referenced_frame_id,
85 uint32 expected_rtp_timestamp,
86 const base::TimeTicks& expected_reference_time) {
87 expectations_.push(Expectation{expected_frame_id,
88 expected_last_referenced_frame_id,
89 expected_rtp_timestamp,
90 expected_reference_time});
93 void CompareFrameWithExpected(scoped_ptr<SenderEncodedFrame> encoded_frame) {
94 ASSERT_LT(0u, expectations_.size());
95 auto e = expectations_.front();
96 expectations_.pop();
97 if (e.expected_frame_id != e.expected_last_referenced_frame_id) {
98 EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
99 } else {
100 EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
102 EXPECT_EQ(e.expected_frame_id, encoded_frame->frame_id);
103 EXPECT_EQ(e.expected_last_referenced_frame_id,
104 encoded_frame->referenced_frame_id)
105 << "frame id: " << e.expected_frame_id;
106 EXPECT_EQ(e.expected_rtp_timestamp, encoded_frame->rtp_timestamp);
107 EXPECT_EQ(e.expected_reference_time, encoded_frame->reference_time);
108 EXPECT_FALSE(encoded_frame->data.empty());
109 ++count_frames_delivered_;
112 private:
113 friend class base::RefCountedThreadSafe<MetadataRecorder>;
114 virtual ~MetadataRecorder() {}
116 int count_frames_delivered_;
118 struct Expectation {
119 uint32 expected_frame_id;
120 uint32 expected_last_referenced_frame_id;
121 uint32 expected_rtp_timestamp;
122 base::TimeTicks expected_reference_time;
124 std::queue<Expectation> expectations_;
126 DISALLOW_COPY_AND_ASSIGN(MetadataRecorder);
129 class EndToEndFrameChecker
130 : public base::RefCountedThreadSafe<EndToEndFrameChecker> {
131 public:
132 explicit EndToEndFrameChecker(const VideoDecoderConfig& config)
133 : decoder_(base::MessageLoop::current()->task_runner()),
134 count_frames_checked_(0) {
135 bool decoder_init_result;
136 decoder_.Initialize(
137 config, false, base::Bind(&SaveDecoderInitResult, &decoder_init_result),
138 base::Bind(&EndToEndFrameChecker::CompareFrameWithExpected,
139 base::Unretained(this)));
140 base::MessageLoop::current()->RunUntilIdle();
141 EXPECT_TRUE(decoder_init_result);
144 void PushExpectation(const scoped_refptr<VideoFrame>& frame) {
145 expectations_.push(frame);
148 void EncodeDone(scoped_ptr<SenderEncodedFrame> encoded_frame) {
149 auto buffer = DecoderBuffer::CopyFrom(encoded_frame->bytes(),
150 encoded_frame->data.size());
151 decoder_.Decode(buffer, base::Bind(&EndToEndFrameChecker::DecodeDone,
152 base::Unretained(this)));
155 void CompareFrameWithExpected(const scoped_refptr<VideoFrame>& frame) {
156 ASSERT_LT(0u, expectations_.size());
157 auto& e = expectations_.front();
158 expectations_.pop();
159 EXPECT_LE(kVideoAcceptedPSNR, I420PSNR(e, frame));
160 ++count_frames_checked_;
163 void DecodeDone(VideoDecoder::Status status) {
164 EXPECT_EQ(VideoDecoder::kOk, status);
167 int count_frames_checked() const { return count_frames_checked_; }
169 private:
170 friend class base::RefCountedThreadSafe<EndToEndFrameChecker>;
171 virtual ~EndToEndFrameChecker() {}
173 FFmpegVideoDecoder decoder_;
174 std::queue<scoped_refptr<VideoFrame>> expectations_;
175 int count_frames_checked_;
177 DISALLOW_COPY_AND_ASSIGN(EndToEndFrameChecker);
180 void CreateFrameAndMemsetPlane(VideoFrameFactory* const video_frame_factory) {
181 const scoped_refptr<media::VideoFrame> video_frame =
182 video_frame_factory->MaybeCreateFrame(
183 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta());
184 ASSERT_TRUE(video_frame.get());
185 auto cv_pixel_buffer = video_frame->cv_pixel_buffer();
186 ASSERT_TRUE(cv_pixel_buffer);
187 CVPixelBufferLockBaseAddress(cv_pixel_buffer, 0);
188 auto ptr = CVPixelBufferGetBaseAddressOfPlane(cv_pixel_buffer, 0);
189 ASSERT_TRUE(ptr);
190 memset(ptr, 0xfe, CVPixelBufferGetBytesPerRowOfPlane(cv_pixel_buffer, 0) *
191 CVPixelBufferGetHeightOfPlane(cv_pixel_buffer, 0));
192 CVPixelBufferUnlockBaseAddress(cv_pixel_buffer, 0);
195 void NoopFrameEncodedCallback(
196 scoped_ptr<media::cast::SenderEncodedFrame> /*encoded_frame*/) {
199 class TestPowerSource : public base::PowerMonitorSource {
200 public:
201 void GenerateSuspendEvent() {
202 ProcessPowerEvent(SUSPEND_EVENT);
203 base::MessageLoop::current()->RunUntilIdle();
205 void GenerateResumeEvent() {
206 ProcessPowerEvent(RESUME_EVENT);
207 base::MessageLoop::current()->RunUntilIdle();
210 private:
211 bool IsOnBatteryPowerImpl() final { return false; }
214 class H264VideoToolboxEncoderTest : public ::testing::Test {
215 protected:
216 H264VideoToolboxEncoderTest() = default;
218 void SetUp() final {
219 clock_ = new base::SimpleTestTickClock();
220 clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
222 power_source_ = new TestPowerSource();
223 power_monitor_.reset(
224 new base::PowerMonitor(scoped_ptr<TestPowerSource>(power_source_)));
226 cast_environment_ = new CastEnvironment(
227 scoped_ptr<base::TickClock>(clock_).Pass(),
228 message_loop_.task_runner(), message_loop_.task_runner(),
229 message_loop_.task_runner());
230 encoder_.reset(new H264VideoToolboxEncoder(
231 cast_environment_, video_sender_config_,
232 base::Bind(&SaveOperationalStatus, &operational_status_)));
233 message_loop_.RunUntilIdle();
234 EXPECT_EQ(STATUS_INITIALIZED, operational_status_);
237 void TearDown() final {
238 encoder_.reset();
239 message_loop_.RunUntilIdle();
240 power_monitor_.reset();
243 void AdvanceClockAndVideoFrameTimestamp() {
244 clock_->Advance(base::TimeDelta::FromMilliseconds(33));
245 frame_->set_timestamp(frame_->timestamp() +
246 base::TimeDelta::FromMilliseconds(33));
249 static void SetUpTestCase() {
250 // Reusable test data.
251 video_sender_config_ = GetDefaultVideoSenderConfig();
252 video_sender_config_.codec = CODEC_VIDEO_H264;
253 const gfx::Size size(kVideoWidth, kVideoHeight);
254 frame_ = media::VideoFrame::CreateFrame(
255 PIXEL_FORMAT_I420, size, gfx::Rect(size), size, base::TimeDelta());
256 PopulateVideoFrame(frame_.get(), 123);
259 static void TearDownTestCase() { frame_ = nullptr; }
261 static scoped_refptr<media::VideoFrame> frame_;
262 static VideoSenderConfig video_sender_config_;
264 base::SimpleTestTickClock* clock_; // Owned by CastEnvironment.
265 base::MessageLoop message_loop_;
266 scoped_refptr<CastEnvironment> cast_environment_;
267 scoped_ptr<VideoEncoder> encoder_;
268 OperationalStatus operational_status_;
269 TestPowerSource* power_source_; // Owned by the power monitor.
270 scoped_ptr<base::PowerMonitor> power_monitor_;
272 private:
273 DISALLOW_COPY_AND_ASSIGN(H264VideoToolboxEncoderTest);
276 // static
277 scoped_refptr<media::VideoFrame> H264VideoToolboxEncoderTest::frame_;
278 VideoSenderConfig H264VideoToolboxEncoderTest::video_sender_config_;
280 TEST_F(H264VideoToolboxEncoderTest, CheckFrameMetadataSequence) {
281 scoped_refptr<MetadataRecorder> metadata_recorder(new MetadataRecorder());
282 VideoEncoder::FrameEncodedCallback cb = base::Bind(
283 &MetadataRecorder::CompareFrameWithExpected, metadata_recorder.get());
285 metadata_recorder->PushExpectation(
286 0, 0, TimeDeltaToRtpDelta(frame_->timestamp(), kVideoFrequency),
287 clock_->NowTicks());
288 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
289 message_loop_.RunUntilIdle();
291 for (uint32 frame_id = 1; frame_id < 10; ++frame_id) {
292 AdvanceClockAndVideoFrameTimestamp();
293 metadata_recorder->PushExpectation(
294 frame_id, frame_id - 1,
295 TimeDeltaToRtpDelta(frame_->timestamp(), kVideoFrequency),
296 clock_->NowTicks());
297 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
300 encoder_.reset();
301 message_loop_.RunUntilIdle();
303 EXPECT_EQ(10, metadata_recorder->count_frames_delivered());
306 #if defined(USE_PROPRIETARY_CODECS)
307 TEST_F(H264VideoToolboxEncoderTest, CheckFramesAreDecodable) {
308 VideoDecoderConfig config(kCodecH264, H264PROFILE_MAIN, frame_->format(),
309 COLOR_SPACE_UNSPECIFIED, frame_->coded_size(),
310 frame_->visible_rect(), frame_->natural_size(),
311 nullptr, 0, false);
312 scoped_refptr<EndToEndFrameChecker> checker(new EndToEndFrameChecker(config));
314 VideoEncoder::FrameEncodedCallback cb =
315 base::Bind(&EndToEndFrameChecker::EncodeDone, checker.get());
316 for (uint32 frame_id = 0; frame_id < 6; ++frame_id) {
317 checker->PushExpectation(frame_);
318 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
319 AdvanceClockAndVideoFrameTimestamp();
322 encoder_.reset();
323 message_loop_.RunUntilIdle();
325 EXPECT_EQ(5, checker->count_frames_checked());
327 #endif
329 TEST_F(H264VideoToolboxEncoderTest, CheckVideoFrameFactory) {
330 auto video_frame_factory = encoder_->CreateVideoFrameFactory();
331 ASSERT_TRUE(video_frame_factory.get());
332 // The first call to |MaybeCreateFrame| will return null but post a task to
333 // the encoder to initialize for the specified frame size. We then drain the
334 // message loop. After that, the encoder should have initialized and we
335 // request a frame again.
336 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
337 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
338 message_loop_.RunUntilIdle();
339 CreateFrameAndMemsetPlane(video_frame_factory.get());
342 TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoring) {
343 // Encode a frame, suspend, encode a frame, resume, encode a frame.
345 VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback);
346 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
347 power_source_->GenerateSuspendEvent();
348 EXPECT_FALSE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
349 power_source_->GenerateResumeEvent();
350 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
353 TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoringNoInitialFrame) {
354 // Suspend, encode a frame, resume, encode a frame.
356 VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback);
357 power_source_->GenerateSuspendEvent();
358 EXPECT_FALSE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
359 power_source_->GenerateResumeEvent();
360 EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb));
363 TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoringVideoFrameFactory) {
364 VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback);
365 auto video_frame_factory = encoder_->CreateVideoFrameFactory();
366 ASSERT_TRUE(video_frame_factory.get());
368 // The first call to |MaybeCreateFrame| will return null but post a task to
369 // the encoder to initialize for the specified frame size. We then drain the
370 // message loop. After that, the encoder should have initialized and we
371 // request a frame again.
372 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
373 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
374 message_loop_.RunUntilIdle();
375 CreateFrameAndMemsetPlane(video_frame_factory.get());
377 // After a power suspension, the factory should not produce frames.
378 power_source_->GenerateSuspendEvent();
380 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
381 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
382 message_loop_.RunUntilIdle();
383 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
384 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
386 // After a power resume event, the factory should produce frames right away
387 // because the encoder re-initializes on its own.
388 power_source_->GenerateResumeEvent();
389 CreateFrameAndMemsetPlane(video_frame_factory.get());
392 TEST_F(H264VideoToolboxEncoderTest,
393 CheckPowerMonitoringVideoFrameFactoryNoInitialFrame) {
394 VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback);
395 auto video_frame_factory = encoder_->CreateVideoFrameFactory();
396 ASSERT_TRUE(video_frame_factory.get());
398 // After a power suspension, the factory should not produce frames.
399 power_source_->GenerateSuspendEvent();
401 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
402 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
403 message_loop_.RunUntilIdle();
404 ASSERT_FALSE(video_frame_factory->MaybeCreateFrame(
405 gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta()));
407 // After a power resume event, the factory should produce frames right away
408 // because the encoder re-initializes on its own.
409 power_source_->GenerateResumeEvent();
410 CreateFrameAndMemsetPlane(video_frame_factory.get());
413 } // namespace cast
414 } // namespace media