video_encode_accelerator_adapter_test.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. // Copyright 2020 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.
  4. #include "media/video/video_encode_accelerator_adapter.h"
  5. #include <memory>
  6. #include <string>
  7. #include "base/callback_helpers.h"
  8. #include "base/logging.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/scoped_refptr.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/task/thread_pool.h"
  13. #include "base/test/bind.h"
  14. #include "base/test/gmock_callback_support.h"
  15. #include "base/test/task_environment.h"
  16. #include "base/threading/sequenced_task_runner_handle.h"
  17. #include "base/threading/thread.h"
  18. #include "base/time/time.h"
  19. #include "build/build_config.h"
  20. #include "media/base/bitrate.h"
  21. #include "media/base/media_util.h"
  22. #include "media/base/video_frame.h"
  23. #include "media/base/video_util.h"
  24. #include "media/video/fake_video_encode_accelerator.h"
  25. #include "media/video/gpu_video_accelerator_factories.h"
  26. #include "media/video/mock_gpu_video_accelerator_factories.h"
  27. #include "media/video/mock_video_encode_accelerator.h"
  28. #include "testing/gtest/include/gtest/gtest.h"
  29. #include "third_party/libyuv/include/libyuv.h"
  30. using ::testing::_;
  31. using ::testing::AtLeast;
  32. using ::testing::Field;
  33. using ::testing::Invoke;
  34. using ::testing::Return;
  35. using ::testing::SaveArg;
  36. using ::testing::Values;
  37. using ::testing::WithArgs;
  38. namespace media {
  39. class VideoEncodeAcceleratorAdapterTest
  40. : public ::testing::TestWithParam<VideoPixelFormat> {
  41. public:
  42. VideoEncodeAcceleratorAdapterTest() = default;
  43. void SetUp() override {
  44. vea_runner_ = base::ThreadPool::CreateSequencedTaskRunner({});
  45. vea_ = new FakeVideoEncodeAccelerator(vea_runner_);
  46. gpu_factories_ =
  47. std::make_unique<MockGpuVideoAcceleratorFactories>(nullptr);
  48. supported_profiles_ = {
  49. VideoEncodeAccelerator::SupportedProfile(
  50. profile_,
  51. /*max_resolution=*/gfx::Size(3840, 2160),
  52. /*max_framerate_numerator=*/30,
  53. /*max_framerate_denominator=*/1,
  54. /*rc_modes=*/VideoEncodeAccelerator::kConstantMode |
  55. VideoEncodeAccelerator::kVariableMode),
  56. };
  57. EXPECT_CALL(*gpu_factories_.get(),
  58. GetVideoEncodeAcceleratorSupportedProfiles())
  59. .WillRepeatedly(Return(supported_profiles_));
  60. EXPECT_CALL(*gpu_factories_.get(), DoCreateVideoEncodeAccelerator())
  61. .WillRepeatedly(Return(vea_.get()));
  62. EXPECT_CALL(*gpu_factories_.get(), GetTaskRunner())
  63. .WillRepeatedly(Return(vea_runner_));
  64. auto media_log = std::make_unique<NullMediaLog>();
  65. callback_runner_ = base::SequencedTaskRunnerHandle::Get();
  66. vae_adapter_ = std::make_unique<VideoEncodeAcceleratorAdapter>(
  67. gpu_factories_.get(), media_log->Clone(), callback_runner_);
  68. }
  69. void TearDown() override {
  70. vea_runner_->DeleteSoon(FROM_HERE, std::move(vae_adapter_));
  71. RunUntilIdle();
  72. }
  73. void RunUntilIdle() { task_environment_.RunUntilIdle(); }
  74. VideoEncodeAcceleratorAdapter* adapter() { return vae_adapter_.get(); }
  75. FakeVideoEncodeAccelerator* vea() { return vea_; }
  76. scoped_refptr<VideoFrame> CreateGreenGpuFrame(gfx::Size size,
  77. base::TimeDelta timestamp) {
  78. auto gmb = gpu_factories_->CreateGpuMemoryBuffer(
  79. size, gfx::BufferFormat::YUV_420_BIPLANAR,
  80. gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE);
  81. if (!gmb || !gmb->Map())
  82. return nullptr;
  83. // Green NV12 frame (Y:0x96, U:0x40, V:0x40)
  84. const auto gmb_size = gmb->GetSize();
  85. memset(static_cast<uint8_t*>(gmb->memory(0)), 0x96,
  86. gmb->stride(0) * gmb_size.height());
  87. memset(static_cast<uint8_t*>(gmb->memory(1)), 0x28,
  88. gmb->stride(1) * gmb_size.height() / 2);
  89. gmb->Unmap();
  90. gpu::MailboxHolder empty_mailboxes[media::VideoFrame::kMaxPlanes];
  91. return VideoFrame::WrapExternalGpuMemoryBuffer(
  92. gfx::Rect(gmb_size), size, std::move(gmb), empty_mailboxes,
  93. base::NullCallback(), timestamp);
  94. }
  95. scoped_refptr<VideoFrame> CreateGreenCpuFrame(gfx::Size size,
  96. base::TimeDelta timestamp) {
  97. auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size,
  98. gfx::Rect(size), size, timestamp);
  99. // Green I420 frame (Y:0x96, U:0x40, V:0x40)
  100. libyuv::I420Rect(
  101. frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane),
  102. frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane),
  103. frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane),
  104. 0, // left
  105. 0, // top
  106. frame->visible_rect().width(), // right
  107. frame->visible_rect().height(), // bottom
  108. 0x96, // Y color
  109. 0x40, // U color
  110. 0x40); // V color
  111. return frame;
  112. }
  113. scoped_refptr<VideoFrame> CreateGreenCpuFrameARGB(gfx::Size size,
  114. base::TimeDelta timestamp) {
  115. auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_XRGB, size,
  116. gfx::Rect(size), size, timestamp);
  117. // Green XRGB frame (R:0x3B, G:0xD9, B:0x24)
  118. libyuv::ARGBRect(frame->data(VideoFrame::kARGBPlane),
  119. frame->stride(VideoFrame::kARGBPlane),
  120. 0, // left
  121. 0, // top
  122. frame->visible_rect().width(), // right
  123. frame->visible_rect().height(), // bottom
  124. 0x24D93B00); // V color
  125. return frame;
  126. }
  127. scoped_refptr<VideoFrame> CreateGreenFrame(gfx::Size size,
  128. VideoPixelFormat format,
  129. base::TimeDelta timestamp) {
  130. switch (format) {
  131. case PIXEL_FORMAT_I420:
  132. return CreateGreenCpuFrame(size, timestamp);
  133. case PIXEL_FORMAT_NV12:
  134. return CreateGreenGpuFrame(size, timestamp);
  135. case PIXEL_FORMAT_XRGB:
  136. return CreateGreenCpuFrameARGB(size, timestamp);
  137. default:
  138. EXPECT_TRUE(false) << "not supported pixel format";
  139. return nullptr;
  140. }
  141. }
  142. VideoEncoder::EncoderStatusCB ValidatingStatusCB(
  143. base::Location loc = FROM_HERE) {
  144. struct CallEnforcer {
  145. bool called = false;
  146. std::string location;
  147. ~CallEnforcer() {
  148. EXPECT_TRUE(called) << "Callback created: " << location;
  149. }
  150. };
  151. auto enforcer = std::make_unique<CallEnforcer>();
  152. enforcer->location = loc.ToString();
  153. return base::BindLambdaForTesting(
  154. [this, enforcer{std::move(enforcer)}](EncoderStatus s) {
  155. EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence());
  156. EXPECT_TRUE(s.is_ok()) << " Callback created: " << enforcer->location
  157. << " Error: " << s.message();
  158. enforcer->called = true;
  159. });
  160. }
  161. protected:
  162. VideoCodecProfile profile_ = VP8PROFILE_ANY;
  163. std::vector<VideoEncodeAccelerator::SupportedProfile> supported_profiles_;
  164. base::test::TaskEnvironment task_environment_;
  165. raw_ptr<FakeVideoEncodeAccelerator> vea_; // owned by |vae_adapter_|
  166. std::unique_ptr<MockGpuVideoAcceleratorFactories> gpu_factories_;
  167. std::unique_ptr<VideoEncodeAcceleratorAdapter> vae_adapter_;
  168. scoped_refptr<base::SequencedTaskRunner> vea_runner_;
  169. scoped_refptr<base::SequencedTaskRunner> callback_runner_;
  170. };
  171. TEST_F(VideoEncodeAcceleratorAdapterTest, PreInitialize) {
  172. VideoEncoder::Options options;
  173. options.frame_size = gfx::Size(640, 480);
  174. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  175. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  176. });
  177. adapter()->Initialize(profile_, options, std::move(output_cb),
  178. ValidatingStatusCB());
  179. RunUntilIdle();
  180. }
  181. TEST_F(VideoEncodeAcceleratorAdapterTest, InitializeAfterFirstFrame) {
  182. VideoEncoder::Options options;
  183. options.frame_size = gfx::Size(640, 480);
  184. int outputs_count = 0;
  185. auto pixel_format = PIXEL_FORMAT_I420;
  186. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  187. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  188. outputs_count++;
  189. });
  190. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  191. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  192. EXPECT_EQ(keyframe, true);
  193. EXPECT_EQ(frame->format(), pixel_format);
  194. EXPECT_EQ(frame->coded_size(), options.frame_size);
  195. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  196. }));
  197. adapter()->Initialize(profile_, options, std::move(output_cb),
  198. ValidatingStatusCB());
  199. auto frame =
  200. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  201. adapter()->Encode(frame, true, ValidatingStatusCB());
  202. RunUntilIdle();
  203. EXPECT_EQ(outputs_count, 1);
  204. }
  205. TEST_F(VideoEncodeAcceleratorAdapterTest, TemporalSvc) {
  206. VideoEncoder::Options options;
  207. options.frame_size = gfx::Size(640, 480);
  208. options.scalability_mode = SVCScalabilityMode::kL1T3;
  209. int outputs_count = 0;
  210. auto pixel_format = PIXEL_FORMAT_I420;
  211. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  212. [&](VideoEncoderOutput output,
  213. absl::optional<VideoEncoder::CodecDescription>) {
  214. if (output.timestamp == base::Milliseconds(1))
  215. EXPECT_EQ(output.temporal_id, 1);
  216. else if (output.timestamp == base::Milliseconds(2))
  217. EXPECT_EQ(output.temporal_id, 1);
  218. else if (output.timestamp == base::Milliseconds(3))
  219. EXPECT_EQ(output.temporal_id, 2);
  220. else
  221. EXPECT_EQ(output.temporal_id, 2);
  222. outputs_count++;
  223. });
  224. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  225. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  226. BitstreamBufferMetadata result(1, keyframe, frame->timestamp());
  227. if (frame->timestamp() == base::Milliseconds(1)) {
  228. result.h264 = H264Metadata();
  229. result.h264->temporal_idx = 1;
  230. } else if (frame->timestamp() == base::Milliseconds(2)) {
  231. result.vp8 = Vp8Metadata();
  232. result.vp8->temporal_idx = 1;
  233. } else if (frame->timestamp() == base::Milliseconds(3)) {
  234. result.vp9 = Vp9Metadata();
  235. result.vp9->temporal_idx = 2;
  236. } else {
  237. result.av1 = Av1Metadata();
  238. result.av1->temporal_idx = 2;
  239. }
  240. return result;
  241. }));
  242. adapter()->Initialize(profile_, options, std::move(output_cb),
  243. ValidatingStatusCB());
  244. auto frame1 =
  245. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  246. auto frame2 =
  247. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(2));
  248. auto frame3 =
  249. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(3));
  250. auto frame4 =
  251. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(4));
  252. adapter()->Encode(frame1, true, ValidatingStatusCB());
  253. RunUntilIdle();
  254. adapter()->Encode(frame2, true, ValidatingStatusCB());
  255. RunUntilIdle();
  256. adapter()->Encode(frame3, true, ValidatingStatusCB());
  257. RunUntilIdle();
  258. adapter()->Encode(frame4, true, ValidatingStatusCB());
  259. RunUntilIdle();
  260. EXPECT_EQ(outputs_count, 4);
  261. }
  262. TEST_F(VideoEncodeAcceleratorAdapterTest, FlushDuringInitialize) {
  263. VideoEncoder::Options options;
  264. options.frame_size = gfx::Size(640, 480);
  265. int outputs_count = 0;
  266. auto pixel_format = PIXEL_FORMAT_I420;
  267. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  268. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  269. outputs_count++;
  270. });
  271. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  272. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  273. EXPECT_EQ(keyframe, true);
  274. EXPECT_EQ(frame->format(), pixel_format);
  275. EXPECT_EQ(frame->coded_size(), options.frame_size);
  276. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  277. }));
  278. adapter()->Initialize(profile_, options, std::move(output_cb),
  279. ValidatingStatusCB());
  280. auto frame =
  281. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  282. adapter()->Encode(frame, true, ValidatingStatusCB());
  283. adapter()->Flush(base::BindLambdaForTesting([&](EncoderStatus s) {
  284. EXPECT_TRUE(s.is_ok());
  285. EXPECT_EQ(outputs_count, 1);
  286. }));
  287. RunUntilIdle();
  288. }
  289. TEST_F(VideoEncodeAcceleratorAdapterTest, InitializationError) {
  290. VideoEncoder::Options options;
  291. options.frame_size = gfx::Size(640, 480);
  292. int outputs_count = 0;
  293. auto pixel_format = PIXEL_FORMAT_I420;
  294. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  295. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  296. outputs_count++;
  297. });
  298. VideoEncoder::EncoderStatusCB expect_error_done_cb =
  299. base::BindLambdaForTesting(
  300. [&](EncoderStatus s) { EXPECT_FALSE(s.is_ok()); });
  301. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  302. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  303. EXPECT_TRUE(false) << "should never come here";
  304. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  305. }));
  306. adapter()->Initialize(
  307. VIDEO_CODEC_PROFILE_UNKNOWN, options, std::move(output_cb),
  308. base::BindLambdaForTesting([](EncoderStatus s) {
  309. EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderInitializationError);
  310. }));
  311. auto frame =
  312. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  313. adapter()->Encode(frame, true, std::move(expect_error_done_cb));
  314. RunUntilIdle();
  315. EXPECT_EQ(outputs_count, 0);
  316. }
  317. TEST_F(VideoEncodeAcceleratorAdapterTest, EncodingError) {
  318. VideoEncoder::Options options;
  319. options.frame_size = gfx::Size(640, 480);
  320. int outputs_count = 0;
  321. auto pixel_format = PIXEL_FORMAT_I420;
  322. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  323. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  324. outputs_count++;
  325. });
  326. VideoEncoder::EncoderStatusCB expect_error_done_cb =
  327. base::BindLambdaForTesting(
  328. [&](EncoderStatus s) { EXPECT_FALSE(s.is_ok()); });
  329. adapter()->Initialize(profile_, options, std::move(output_cb),
  330. ValidatingStatusCB());
  331. vea()->SetWillEncodingSucceed(false);
  332. auto frame =
  333. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  334. adapter()->Encode(frame, true, std::move(expect_error_done_cb));
  335. RunUntilIdle();
  336. EXPECT_EQ(outputs_count, 0);
  337. }
  338. TEST_P(VideoEncodeAcceleratorAdapterTest, TwoFramesResize) {
  339. VideoEncoder::Options options;
  340. options.frame_size = gfx::Size(640, 480);
  341. int outputs_count = 0;
  342. gfx::Size small_size(480, 320);
  343. gfx::Size large_size(800, 600);
  344. auto pixel_format = GetParam();
  345. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  346. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  347. outputs_count++;
  348. });
  349. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  350. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  351. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  352. EXPECT_EQ(frame->format(),
  353. IsYuvPlanar(pixel_format) ? pixel_format : PIXEL_FORMAT_I420);
  354. #else
  355. // Everywhere except on Linux resize switches frame into CPU mode.
  356. EXPECT_EQ(frame->format(), PIXEL_FORMAT_I420);
  357. #endif
  358. EXPECT_EQ(frame->coded_size(), options.frame_size);
  359. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  360. }));
  361. adapter()->Initialize(profile_, options, std::move(output_cb),
  362. ValidatingStatusCB());
  363. auto small_frame =
  364. CreateGreenFrame(small_size, pixel_format, base::Milliseconds(1));
  365. auto large_frame =
  366. CreateGreenFrame(large_size, pixel_format, base::Milliseconds(2));
  367. adapter()->Encode(small_frame, true, ValidatingStatusCB());
  368. adapter()->Encode(large_frame, false, ValidatingStatusCB());
  369. RunUntilIdle();
  370. EXPECT_EQ(outputs_count, 2);
  371. }
  372. TEST_F(VideoEncodeAcceleratorAdapterTest, AutomaticResizeSupport) {
  373. VideoEncoder::Options options;
  374. options.frame_size = gfx::Size(640, 480);
  375. int outputs_count = 0;
  376. gfx::Size small_size(480, 320);
  377. auto pixel_format = PIXEL_FORMAT_NV12;
  378. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  379. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  380. outputs_count++;
  381. });
  382. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  383. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  384. EXPECT_EQ(frame->coded_size(), small_size);
  385. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  386. }));
  387. vea()->SupportResize();
  388. adapter()->Initialize(profile_, options, std::move(output_cb),
  389. ValidatingStatusCB());
  390. auto frame1 =
  391. CreateGreenFrame(small_size, pixel_format, base::Milliseconds(1));
  392. auto frame2 =
  393. CreateGreenFrame(small_size, pixel_format, base::Milliseconds(2));
  394. adapter()->Encode(frame1, true, ValidatingStatusCB());
  395. adapter()->Encode(frame2, false, ValidatingStatusCB());
  396. RunUntilIdle();
  397. EXPECT_EQ(outputs_count, 2);
  398. }
  399. TEST_P(VideoEncodeAcceleratorAdapterTest, RunWithAllPossibleInputConversions) {
  400. VideoEncoder::Options options;
  401. options.frame_size = gfx::Size(640, 480);
  402. int outputs_count = 0;
  403. gfx::Size small_size(480, 320);
  404. gfx::Size same_size = options.frame_size;
  405. gfx::Size large_size(800, 600);
  406. int frames_to_encode = 33;
  407. auto pixel_format = GetParam();
  408. auto input_kind =
  409. (pixel_format == PIXEL_FORMAT_NV12)
  410. ? VideoEncodeAcceleratorAdapter::InputBufferKind::GpuMemBuf
  411. : VideoEncodeAcceleratorAdapter::InputBufferKind::CpuMemBuf;
  412. adapter()->SetInputBufferPreferenceForTesting(input_kind);
  413. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  414. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  415. outputs_count++;
  416. });
  417. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  418. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  419. EXPECT_EQ(frame->format(),
  420. IsYuvPlanar(pixel_format) ? pixel_format : PIXEL_FORMAT_I420);
  421. EXPECT_EQ(frame->coded_size(), options.frame_size);
  422. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  423. }));
  424. adapter()->Initialize(profile_, options, std::move(output_cb),
  425. ValidatingStatusCB());
  426. for (int frame_index = 0; frame_index < frames_to_encode; frame_index++) {
  427. gfx::Size size;
  428. if (frame_index % 4 == 0)
  429. size = large_size;
  430. else if (frame_index % 4 == 1)
  431. size = small_size;
  432. else
  433. size = same_size;
  434. // Every 4 frames switch between the 3 supported formats.
  435. const int rem = frame_index % 12;
  436. auto format = PIXEL_FORMAT_XRGB;
  437. if (rem < 4)
  438. format = PIXEL_FORMAT_I420;
  439. else if (rem < 8)
  440. format = PIXEL_FORMAT_NV12;
  441. bool key = frame_index % 9 == 0;
  442. auto frame =
  443. CreateGreenFrame(size, format, base::Milliseconds(frame_index));
  444. adapter()->Encode(frame, key, ValidatingStatusCB());
  445. }
  446. RunUntilIdle();
  447. EXPECT_EQ(outputs_count, frames_to_encode);
  448. }
  449. TEST_F(VideoEncodeAcceleratorAdapterTest, DroppedFrame) {
  450. VideoEncoder::Options options;
  451. options.frame_size = gfx::Size(640, 480);
  452. auto pixel_format = PIXEL_FORMAT_I420;
  453. std::vector<base::TimeDelta> output_timestamps;
  454. VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting(
  455. [&](VideoEncoderOutput output,
  456. absl::optional<VideoEncoder::CodecDescription>) {
  457. output_timestamps.push_back(output.timestamp);
  458. });
  459. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  460. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  461. size_t size = keyframe ? 1 : 0; // Drop non-key frame
  462. return BitstreamBufferMetadata(size, keyframe, frame->timestamp());
  463. }));
  464. adapter()->Initialize(profile_, options, std::move(output_cb),
  465. ValidatingStatusCB());
  466. auto frame1 =
  467. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  468. auto frame2 =
  469. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(2));
  470. auto frame3 =
  471. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(3));
  472. adapter()->Encode(frame1, true, ValidatingStatusCB());
  473. adapter()->Encode(frame2, false, ValidatingStatusCB());
  474. adapter()->Encode(frame3, true, ValidatingStatusCB());
  475. RunUntilIdle();
  476. ASSERT_EQ(output_timestamps.size(), 2u);
  477. EXPECT_EQ(output_timestamps[0], base::Milliseconds(1));
  478. EXPECT_EQ(output_timestamps[1], base::Milliseconds(3));
  479. }
  480. TEST_F(VideoEncodeAcceleratorAdapterTest,
  481. ChangeOptions_ChangeVariableBitrateSmokeTest) {
  482. VideoEncoder::Options options;
  483. options.frame_size = gfx::Size(640, 480);
  484. options.bitrate = Bitrate::VariableBitrate(1111u, 2222u);
  485. auto pixel_format = PIXEL_FORMAT_I420;
  486. int output_count_before_change = 0;
  487. int output_count_after_change = 0;
  488. VideoEncoder::OutputCB first_output_cb = base::BindLambdaForTesting(
  489. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  490. output_count_before_change++;
  491. });
  492. VideoEncoder::OutputCB second_output_cb = base::BindLambdaForTesting(
  493. [&](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) {
  494. output_count_after_change++;
  495. });
  496. vea()->SetEncodingCallback(base::BindLambdaForTesting(
  497. [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
  498. EXPECT_EQ(keyframe, true);
  499. EXPECT_EQ(frame->format(), pixel_format);
  500. EXPECT_EQ(frame->coded_size(), options.frame_size);
  501. return BitstreamBufferMetadata(1, keyframe, frame->timestamp());
  502. }));
  503. adapter()->Initialize(profile_, options, std::move(first_output_cb),
  504. ValidatingStatusCB());
  505. // We must encode one frame before we can change options.
  506. auto first_frame =
  507. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1));
  508. adapter()->Encode(first_frame, true, ValidatingStatusCB());
  509. RunUntilIdle();
  510. options.bitrate = Bitrate::VariableBitrate(12345u, 23456u);
  511. adapter()->ChangeOptions(options, std::move(second_output_cb),
  512. ValidatingStatusCB());
  513. auto second_frame =
  514. CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(2));
  515. adapter()->Encode(second_frame, true, ValidatingStatusCB());
  516. RunUntilIdle();
  517. EXPECT_EQ(output_count_before_change, 1);
  518. EXPECT_EQ(output_count_after_change, 1);
  519. }
  520. INSTANTIATE_TEST_SUITE_P(VideoEncodeAcceleratorAdapterTest,
  521. VideoEncodeAcceleratorAdapterTest,
  522. ::testing::Values(PIXEL_FORMAT_I420,
  523. PIXEL_FORMAT_NV12,
  524. PIXEL_FORMAT_XRGB));
  525. } // namespace media