video_frame_factory_impl_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2017 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/gpu/android/video_frame_factory_impl.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/task/single_thread_task_runner.h"
  9. #include "base/test/gmock_callback_support.h"
  10. #include "base/test/mock_callback.h"
  11. #include "base/test/task_environment.h"
  12. #include "base/threading/thread_task_runner_handle.h"
  13. #include "gpu/command_buffer/service/mock_texture_owner.h"
  14. #include "gpu/command_buffer/service/ref_counted_lock_for_test.h"
  15. #include "gpu/command_buffer/service/shared_context_state.h"
  16. #include "gpu/config/gpu_finch_features.h"
  17. #include "gpu/config/gpu_preferences.h"
  18. #include "media/base/android/test_destruction_observable.h"
  19. #include "media/base/limits.h"
  20. #include "media/gpu/android/codec_buffer_wait_coordinator.h"
  21. #include "media/gpu/android/maybe_render_early_manager.h"
  22. #include "media/gpu/android/mock_codec_image.h"
  23. #include "media/gpu/android/mock_shared_image_video_provider.h"
  24. #include "media/gpu/android/shared_image_video_provider.h"
  25. #include "testing/gmock/include/gmock/gmock.h"
  26. #include "testing/gtest/include/gtest/gtest.h"
  27. using base::test::RunOnceCallback;
  28. using testing::_;
  29. using testing::SaveArg;
  30. namespace gpu {
  31. class CommandBufferStub;
  32. } // namespace gpu
  33. namespace media {
  34. class MockMaybeRenderEarlyManager : public MaybeRenderEarlyManager {
  35. public:
  36. MOCK_METHOD1(SetSurfaceBundle, void(scoped_refptr<CodecSurfaceBundle>));
  37. MOCK_METHOD1(AddCodecImage, void(scoped_refptr<CodecImageHolder>));
  38. MOCK_METHOD0(MaybeRenderEarly, void());
  39. };
  40. class MockFrameInfoHelper : public FrameInfoHelper,
  41. public DestructionObservable {
  42. public:
  43. void GetFrameInfo(std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
  44. FrameInfoReadyCB cb) override {
  45. FrameInfo info;
  46. info.coded_size = buffer_renderer->size();
  47. info.visible_rect = gfx::Rect(info.coded_size);
  48. std::move(cb).Run(std::move(buffer_renderer), info);
  49. }
  50. };
  51. class VideoFrameFactoryImplTest : public testing::Test {
  52. public:
  53. VideoFrameFactoryImplTest()
  54. : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
  55. auto image_provider = std::make_unique<MockSharedImageVideoProvider>();
  56. image_provider_raw_ = image_provider.get();
  57. auto mre_manager = std::make_unique<MockMaybeRenderEarlyManager>();
  58. mre_manager_raw_ = mre_manager.get();
  59. auto info_helper = std::make_unique<MockFrameInfoHelper>();
  60. impl_ = std::make_unique<VideoFrameFactoryImpl>(
  61. task_runner_, gpu_preferences_, std::move(image_provider),
  62. std::move(mre_manager), std::move(info_helper),
  63. features::NeedThreadSafeAndroidMedia()
  64. ? base::MakeRefCounted<gpu::RefCountedLockForTest>()
  65. : nullptr);
  66. auto texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
  67. 0, nullptr, nullptr, true);
  68. auto codec_buffer_wait_coordinator =
  69. base::MakeRefCounted<CodecBufferWaitCoordinator>(
  70. std::move(texture_owner),
  71. features::NeedThreadSafeAndroidMedia()
  72. ? base::MakeRefCounted<gpu::RefCountedLockForTest>()
  73. : nullptr);
  74. // Provide a non-null |codec_buffer_wait_coordinator| to |impl_|.
  75. impl_->SetCodecBufferWaitCorrdinatorForTesting(
  76. std::move(codec_buffer_wait_coordinator));
  77. }
  78. ~VideoFrameFactoryImplTest() override = default;
  79. struct {
  80. gfx::Size coded_size{100, 100};
  81. gfx::Rect visible_rect{coded_size};
  82. gfx::Size natural_size{coded_size};
  83. gfx::ColorSpace color_space{gfx::ColorSpace::CreateSRGBLinear()};
  84. } video_frame_params_;
  85. void RequestVideoFrame() {
  86. auto output_buffer = CodecOutputBuffer::CreateForTesting(
  87. 0, video_frame_params_.coded_size, video_frame_params_.color_space);
  88. ASSERT_TRUE(VideoFrame::IsValidConfig(
  89. PIXEL_FORMAT_ARGB, VideoFrame::STORAGE_OPAQUE,
  90. video_frame_params_.coded_size, video_frame_params_.visible_rect,
  91. video_frame_params_.natural_size));
  92. // Save a copy in case the test wants it.
  93. output_buffer_raw_ = output_buffer.get();
  94. // We should get a call to the output callback, but no calls to the
  95. // provider.
  96. // TODO(liberato): Verify that it's sending the proper TextureOwner.
  97. // However, we haven't actually given it a TextureOwner yet.
  98. output_buffer_raw_ = output_buffer.get();
  99. EXPECT_CALL(*image_provider_raw_, MockRequestImage());
  100. impl_->CreateVideoFrame(std::move(output_buffer), base::TimeDelta(),
  101. video_frame_params_.natural_size,
  102. base::NullCallback(), output_cb_.Get());
  103. base::RunLoop().RunUntilIdle();
  104. // TODO(liberato): Verify that it requested a shared image.
  105. }
  106. // |release_cb_called_flag| will be set when the record's |release_cb| runs.
  107. SharedImageVideoProvider::ImageRecord MakeImageRecord(
  108. bool* release_cb_called_flag = nullptr) {
  109. SharedImageVideoProvider::ImageRecord record;
  110. record.mailbox = gpu::Mailbox::Generate();
  111. if (release_cb_called_flag)
  112. *release_cb_called_flag = false;
  113. record.release_cb = base::BindOnce(
  114. [](bool* flag, const gpu::SyncToken&) {
  115. if (flag)
  116. *flag = true;
  117. },
  118. base::Unretained(release_cb_called_flag));
  119. auto codec_image =
  120. base::MakeRefCounted<MockCodecImage>(gfx::Size(100, 100));
  121. record.codec_image_holder = base::MakeRefCounted<CodecImageHolder>(
  122. task_runner_, codec_image,
  123. features::NeedThreadSafeAndroidMedia()
  124. ? base::MakeRefCounted<gpu::RefCountedLockForTest>()
  125. : nullptr);
  126. return record;
  127. }
  128. base::test::TaskEnvironment task_environment_;
  129. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  130. std::unique_ptr<VideoFrameFactoryImpl> impl_;
  131. raw_ptr<MockMaybeRenderEarlyManager> mre_manager_raw_ = nullptr;
  132. raw_ptr<MockSharedImageVideoProvider> image_provider_raw_ = nullptr;
  133. // Most recently created CodecOutputBuffer.
  134. raw_ptr<CodecOutputBuffer> output_buffer_raw_ = nullptr;
  135. // Sent to |impl_| by RequestVideoFrame..
  136. base::MockCallback<VideoFrameFactory::OnceOutputCB> output_cb_;
  137. std::unique_ptr<DestructionObserver> ycbcr_destruction_observer_;
  138. gpu::GpuPreferences gpu_preferences_;
  139. };
  140. TEST_F(VideoFrameFactoryImplTest, ImageProviderInitFailure) {
  141. // If the image provider fails to init, then our init cb should be called with
  142. // no TextureOwner.
  143. EXPECT_CALL(*image_provider_raw_, Initialize_(_))
  144. .Times(1)
  145. .WillOnce(RunOnceCallback<0>(nullptr));
  146. base::MockCallback<VideoFrameFactory::InitCB> init_cb;
  147. EXPECT_CALL(init_cb, Run(scoped_refptr<gpu::TextureOwner>(nullptr)));
  148. impl_->Initialize(VideoFrameFactory::OverlayMode::kDontRequestPromotionHints,
  149. init_cb.Get());
  150. base::RunLoop().RunUntilIdle();
  151. // TODO(liberato): for testing, we could just skip calling the gpu init cb,
  152. // since |impl_| doesn't know or care if it's called. that way, we don't need
  153. // to mock out making the callback work. would be nice, though.
  154. }
  155. TEST_F(VideoFrameFactoryImplTest,
  156. SetSurfaceBundleForwardsToMaybeRenderEarlyManager) {
  157. // Sending a non-null CodecSurfaceBundle should forward it to |mre_manager|.
  158. // Also provide a non-null TextureOwner to it.
  159. scoped_refptr<CodecSurfaceBundle> surface_bundle =
  160. base::MakeRefCounted<CodecSurfaceBundle>(
  161. base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(0, nullptr,
  162. nullptr, true),
  163. features::NeedThreadSafeAndroidMedia()
  164. ? base::MakeRefCounted<gpu::RefCountedLockForTest>()
  165. : nullptr);
  166. EXPECT_CALL(*mre_manager_raw_, SetSurfaceBundle(surface_bundle));
  167. impl_->SetSurfaceBundle(surface_bundle);
  168. base::RunLoop().RunUntilIdle();
  169. }
  170. TEST_F(VideoFrameFactoryImplTest, CreateVideoFrameFailsIfUnsupportedFormat) {
  171. // Sending an unsupported format should cause an early failure, without a
  172. // thread hop.
  173. gfx::Size coded_size(limits::kMaxDimension + 1, limits::kMaxDimension + 1);
  174. gfx::Rect visible_rect(coded_size);
  175. gfx::Size natural_size(0, 0);
  176. auto output_buffer =
  177. CodecOutputBuffer::CreateForTesting(0, coded_size, gfx::ColorSpace());
  178. ASSERT_FALSE(VideoFrame::IsValidConfig(PIXEL_FORMAT_ARGB,
  179. VideoFrame::STORAGE_OPAQUE, coded_size,
  180. visible_rect, natural_size));
  181. // We should get a call to the output callback, but no calls to the provider.
  182. base::MockCallback<VideoFrameFactory::OnceOutputCB> output_cb;
  183. EXPECT_CALL(output_cb, Run(scoped_refptr<VideoFrame>(nullptr)));
  184. EXPECT_CALL(*image_provider_raw_, MockRequestImage()).Times(0);
  185. impl_->CreateVideoFrame(std::move(output_buffer), base::TimeDelta(),
  186. natural_size, base::NullCallback(), output_cb.Get());
  187. base::RunLoop().RunUntilIdle();
  188. }
  189. TEST_F(VideoFrameFactoryImplTest, CreateVideoFrameSucceeds) {
  190. // Creating a video frame calls through to the image provider, and forwards a
  191. // VideoFrame to the output cb.
  192. //
  193. // TODO(liberato): Consider testing the metadata values.
  194. RequestVideoFrame();
  195. // Call the ImageReadyCB.
  196. scoped_refptr<VideoFrame> frame;
  197. EXPECT_CALL(output_cb_, Run(_)).WillOnce(SaveArg<0>(&frame));
  198. bool release_cb_called_flag = false;
  199. auto record = MakeImageRecord(&release_cb_called_flag);
  200. scoped_refptr<CodecImage> codec_image(
  201. record.codec_image_holder->codec_image_raw());
  202. image_provider_raw_->ProvideOneRequestedImage(&record);
  203. base::RunLoop().RunUntilIdle();
  204. EXPECT_NE(frame, nullptr);
  205. // Make sure that it set the output buffer properly.
  206. EXPECT_EQ(codec_image->get_codec_output_buffer_for_testing(),
  207. output_buffer_raw_);
  208. EXPECT_EQ(frame->coded_size(), video_frame_params_.coded_size);
  209. EXPECT_EQ(frame->natural_size(), video_frame_params_.natural_size);
  210. EXPECT_EQ(frame->visible_rect(), video_frame_params_.visible_rect);
  211. EXPECT_EQ(frame->ColorSpace(), video_frame_params_.color_space);
  212. // Destroy the VideoFrame, and verify that our release cb is called.
  213. EXPECT_FALSE(release_cb_called_flag);
  214. frame = nullptr;
  215. base::RunLoop().RunUntilIdle();
  216. EXPECT_TRUE(release_cb_called_flag);
  217. }
  218. TEST_F(VideoFrameFactoryImplTest,
  219. DestroyingFactoryDuringVideoFrameCreationDoesntCrash) {
  220. // We should be able to destroy |impl_| while a VideoFrame is pending, and
  221. // nothing bad should happen.
  222. RequestVideoFrame();
  223. impl_ = nullptr;
  224. base::RunLoop().RunUntilIdle();
  225. }
  226. } // namespace media