vaapi_utils_unittest.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright 2019 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/vaapi/vaapi_utils.h"
  5. #include <va/va.h>
  6. #include <memory>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/logging.h"
  10. #include "base/memory/scoped_refptr.h"
  11. #include "base/numerics/safe_conversions.h"
  12. #include "base/synchronization/lock.h"
  13. #include "base/test/gtest_util.h"
  14. #include "media/gpu/vaapi/vaapi_wrapper.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #include "ui/gfx/geometry/size.h"
  17. namespace media {
  18. namespace {
  19. constexpr VAImageFormat kImageFormatI420 = {
  20. .fourcc = VA_FOURCC_I420,
  21. .byte_order = VA_LSB_FIRST,
  22. .bits_per_pixel = 12,
  23. };
  24. } // namespace
  25. class VaapiUtilsTest : public testing::Test {
  26. public:
  27. VaapiUtilsTest(const VaapiUtilsTest&) = delete;
  28. VaapiUtilsTest& operator=(const VaapiUtilsTest&) = delete;
  29. protected:
  30. VaapiUtilsTest() = default;
  31. void SetUp() override {
  32. // Create a VaapiWrapper for testing.
  33. vaapi_wrapper_ =
  34. VaapiWrapper::Create(VaapiWrapper::kDecode, VAProfileJPEGBaseline,
  35. EncryptionScheme::kUnencrypted,
  36. base::BindRepeating([](VaapiFunctions function) {
  37. LOG(FATAL) << "Oh noes! Decoder failed";
  38. }));
  39. ASSERT_TRUE(vaapi_wrapper_);
  40. }
  41. protected:
  42. scoped_refptr<VaapiWrapper> vaapi_wrapper_;
  43. };
  44. TEST_F(VaapiUtilsTest, ScopedVABuffer) {
  45. const std::pair<VABufferType, size_t> kBufferParameters[] = {
  46. {VASliceDataBufferType, 1024},
  47. {VAEncCodedBufferType, 2048},
  48. {VAProcPipelineParameterBufferType,
  49. sizeof(VAProcPipelineParameterBuffer)},
  50. };
  51. constexpr gfx::Size kCodedSize(64, 64);
  52. ASSERT_TRUE(vaapi_wrapper_->CreateContext(kCodedSize));
  53. for (size_t i = 0; i < std::size(kBufferParameters); i++) {
  54. const VABufferType buffer_type = kBufferParameters[i].first;
  55. const size_t buffer_size = kBufferParameters[i].second;
  56. auto scoped_va_buffer =
  57. vaapi_wrapper_->CreateVABuffer(buffer_type, buffer_size);
  58. ASSERT_TRUE(scoped_va_buffer);
  59. EXPECT_NE(scoped_va_buffer->id(), VA_INVALID_ID);
  60. EXPECT_EQ(scoped_va_buffer->type(), buffer_type);
  61. EXPECT_EQ(scoped_va_buffer->size(), buffer_size);
  62. }
  63. }
  64. // This test exercises the usual ScopedVAImage lifetime.
  65. TEST_F(VaapiUtilsTest, ScopedVAImage) {
  66. std::vector<VASurfaceID> va_surfaces;
  67. const gfx::Size coded_size(64, 64);
  68. ASSERT_TRUE(vaapi_wrapper_->CreateContextAndSurfaces(
  69. VA_RT_FORMAT_YUV420, coded_size,
  70. std::vector<VaapiWrapper::SurfaceUsageHint>{
  71. VaapiWrapper::SurfaceUsageHint::kGeneric},
  72. 1, &va_surfaces));
  73. ASSERT_EQ(va_surfaces.size(), 1u);
  74. std::unique_ptr<ScopedVAImage> scoped_image;
  75. {
  76. // On Stoney-Ridge devices the output image format is dependent on the
  77. // surface format. However when context has not been executed the output
  78. // image format seems to default to I420. https://crbug.com/828119
  79. VAImageFormat va_image_format = kImageFormatI420;
  80. base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
  81. scoped_image = std::make_unique<ScopedVAImage>(
  82. vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, va_surfaces[0],
  83. &va_image_format, coded_size);
  84. EXPECT_TRUE(scoped_image->image());
  85. ASSERT_TRUE(scoped_image->IsValid());
  86. EXPECT_TRUE(scoped_image->va_buffer()->IsValid());
  87. EXPECT_TRUE(scoped_image->va_buffer()->data());
  88. }
  89. vaapi_wrapper_->DestroyContextAndSurfaces(va_surfaces);
  90. }
  91. // This test exercises creation of a ScopedVAImage with a bad VASurfaceID.
  92. TEST_F(VaapiUtilsTest, BadScopedVAImage) {
  93. #if DCHECK_IS_ON()
  94. ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  95. #endif
  96. const std::vector<VASurfaceID> va_surfaces = {VA_INVALID_ID};
  97. const gfx::Size coded_size(64, 64);
  98. std::unique_ptr<ScopedVAImage> scoped_image;
  99. {
  100. VAImageFormat va_image_format = kImageFormatI420;
  101. base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
  102. scoped_image = std::make_unique<ScopedVAImage>(
  103. vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, va_surfaces[0],
  104. &va_image_format, coded_size);
  105. EXPECT_TRUE(scoped_image->image());
  106. EXPECT_FALSE(scoped_image->IsValid());
  107. #if DCHECK_IS_ON()
  108. EXPECT_DCHECK_DEATH(scoped_image->va_buffer());
  109. #else
  110. EXPECT_FALSE(scoped_image->va_buffer());
  111. #endif
  112. }
  113. }
  114. // This test exercises creation of a ScopedVABufferMapping with bad VABufferIDs.
  115. TEST_F(VaapiUtilsTest, BadScopedVABufferMapping) {
  116. ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  117. base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
  118. // A ScopedVABufferMapping with a VA_INVALID_ID VABufferID is DCHECK()ed.
  119. EXPECT_DCHECK_DEATH(std::make_unique<ScopedVABufferMapping>(
  120. vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, VA_INVALID_ID));
  121. // This should not hit any DCHECK() but will create an invalid
  122. // ScopedVABufferMapping.
  123. auto scoped_buffer = std::make_unique<ScopedVABufferMapping>(
  124. vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, VA_INVALID_ID - 1);
  125. EXPECT_FALSE(scoped_buffer->IsValid());
  126. }
  127. // This test exercises the creation of a valid ScopedVASurface.
  128. TEST_F(VaapiUtilsTest, ScopedVASurface) {
  129. const gfx::Size coded_size(64, 64);
  130. auto scoped_va_surfaces = vaapi_wrapper_->CreateContextAndScopedVASurfaces(
  131. VA_RT_FORMAT_YUV420, coded_size,
  132. {VaapiWrapper::SurfaceUsageHint::kGeneric}, 1u,
  133. /*visible_size=*/absl::nullopt);
  134. ASSERT_FALSE(scoped_va_surfaces.empty());
  135. auto scoped_va_surface = std::move(scoped_va_surfaces[0]);
  136. EXPECT_TRUE(scoped_va_surface->IsValid());
  137. EXPECT_EQ(VA_RT_FORMAT_YUV420,
  138. base::checked_cast<int>(scoped_va_surface->format()));
  139. EXPECT_EQ(coded_size, scoped_va_surface->size());
  140. }
  141. // This test exercises the creation of a ScopedVASurface where the requested
  142. // size and the visible size are different.
  143. TEST_F(VaapiUtilsTest, ScopedVASurfaceWithVisibleSize) {
  144. const gfx::Size coded_size(64, 64);
  145. const gfx::Size visible_size(60, 60);
  146. auto scoped_va_surfaces = vaapi_wrapper_->CreateContextAndScopedVASurfaces(
  147. VA_RT_FORMAT_YUV420, coded_size,
  148. {VaapiWrapper::SurfaceUsageHint::kGeneric}, 1u, visible_size);
  149. ASSERT_FALSE(scoped_va_surfaces.empty());
  150. auto scoped_va_surface = std::move(scoped_va_surfaces[0]);
  151. EXPECT_TRUE(scoped_va_surface->IsValid());
  152. EXPECT_EQ(VA_RT_FORMAT_YUV420,
  153. base::checked_cast<int>(scoped_va_surface->format()));
  154. EXPECT_EQ(visible_size, scoped_va_surface->size());
  155. }
  156. // This test exercises the creation of a ScopedVASurface with an invalid
  157. // size.
  158. TEST_F(VaapiUtilsTest, ScopedVASurfaceInvalidSizeRequest) {
  159. const gfx::Size invalid_size(0, 0);
  160. EXPECT_TRUE(vaapi_wrapper_
  161. ->CreateContextAndScopedVASurfaces(
  162. VA_RT_FORMAT_YUV420, invalid_size,
  163. {VaapiWrapper::SurfaceUsageHint::kGeneric}, 1u,
  164. /*visible_size=*/absl::nullopt)
  165. .empty());
  166. }
  167. // This test exercises the creation of a ScopedVASurface with an invalid
  168. // RT format.
  169. TEST_F(VaapiUtilsTest, ScopedVASurfaceInvalidRTFormatRequest) {
  170. const gfx::Size coded_size(64, 64);
  171. EXPECT_TRUE(vaapi_wrapper_
  172. ->CreateContextAndScopedVASurfaces(
  173. kInvalidVaRtFormat, coded_size,
  174. {VaapiWrapper::SurfaceUsageHint::kGeneric}, 1u,
  175. /*visible_size=*/absl::nullopt)
  176. .empty());
  177. }
  178. } // namespace media