vaapi_webp_decoder.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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_webp_decoder.h"
  5. #include <va/va.h>
  6. #include "base/logging.h"
  7. #include "base/numerics/safe_conversions.h"
  8. #include "media/gpu/macros.h"
  9. #include "media/gpu/vaapi/vaapi_utils.h"
  10. #include "media/gpu/vaapi/vaapi_wrapper.h"
  11. #include "media/gpu/vp8_reference_frame_vector.h"
  12. #include "media/parsers/vp8_parser.h"
  13. #include "media/parsers/webp_parser.h"
  14. #include "ui/gfx/geometry/size.h"
  15. namespace media {
  16. namespace {
  17. constexpr VAProfile kWebPVAProfile = VAProfileVP8Version0_3;
  18. constexpr unsigned int kWebPVARtFormat = VA_RT_FORMAT_YUV420;
  19. static bool IsVaapiSupportedWebP(const Vp8FrameHeader& webp_header) {
  20. if (!VaapiWrapper::IsDecodingSupportedForInternalFormat(kWebPVAProfile,
  21. kWebPVARtFormat)) {
  22. DLOG(ERROR) << "The WebP's subsampling format is unsupported";
  23. return false;
  24. }
  25. // Validate the size.
  26. // TODO(crbug.com/984971): Make sure visible size and coded size are treated
  27. // similarly here: we don't currently know if we really have to provide the
  28. // coded size to the VAAPI. So far, it seems to work by just passing the
  29. // visible size, but we have to learn more, probably by looking into the
  30. // driver. If we need to pass the coded size, then when checking against the
  31. // min/max resolutions, we should use the coded size and not the visible size.
  32. const gfx::Size webp_size(base::strict_cast<int>(webp_header.width),
  33. base::strict_cast<int>(webp_header.height));
  34. if (webp_size.IsEmpty()) {
  35. DLOG(ERROR) << "Width or height cannot be zero: " << webp_size.ToString();
  36. return false;
  37. }
  38. gfx::Size min_webp_resolution;
  39. gfx::Size max_webp_resolution;
  40. if (!VaapiWrapper::GetSupportedResolutions(
  41. kWebPVAProfile, VaapiWrapper::CodecMode::kDecode, min_webp_resolution,
  42. max_webp_resolution)) {
  43. DLOG(ERROR) << "Could not get the minimum and maximum resolutions";
  44. return false;
  45. }
  46. if (webp_size.width() < min_webp_resolution.width() ||
  47. webp_size.height() < min_webp_resolution.height()) {
  48. DLOG(ERROR) << "VAAPI doesn't support size " << webp_size.ToString()
  49. << ": under minimum resolution "
  50. << min_webp_resolution.ToString();
  51. return false;
  52. }
  53. if (webp_size.width() > max_webp_resolution.width() ||
  54. webp_size.height() > max_webp_resolution.height()) {
  55. DLOG(ERROR) << "VAAPI doesn't support size " << webp_size.ToString()
  56. << ": above maximum resolution "
  57. << max_webp_resolution.ToString();
  58. return false;
  59. }
  60. return true;
  61. }
  62. } // namespace
  63. VaapiWebPDecoder::VaapiWebPDecoder() : VaapiImageDecoder(kWebPVAProfile) {}
  64. VaapiWebPDecoder::~VaapiWebPDecoder() = default;
  65. gpu::ImageDecodeAcceleratorType VaapiWebPDecoder::GetType() const {
  66. return gpu::ImageDecodeAcceleratorType::kWebP;
  67. }
  68. SkYUVColorSpace VaapiWebPDecoder::GetYUVColorSpace() const {
  69. return SkYUVColorSpace::kRec601_SkYUVColorSpace;
  70. }
  71. VaapiImageDecodeStatus VaapiWebPDecoder::AllocateVASurfaceAndSubmitVABuffers(
  72. base::span<const uint8_t> encoded_image) {
  73. DCHECK(vaapi_wrapper_);
  74. std::unique_ptr<Vp8FrameHeader> parse_result = ParseWebPImage(encoded_image);
  75. if (!parse_result)
  76. return VaapiImageDecodeStatus::kParseFailed;
  77. // Make sure this WebP can be decoded.
  78. if (!IsVaapiSupportedWebP(*parse_result))
  79. return VaapiImageDecodeStatus::kUnsupportedImage;
  80. // Prepare the VaSurface for decoding.
  81. const gfx::Size new_visible_size(
  82. base::strict_cast<int>(parse_result->width),
  83. base::strict_cast<int>(parse_result->height));
  84. DCHECK(!scoped_va_context_and_surface_ ||
  85. scoped_va_context_and_surface_->IsValid());
  86. DCHECK(!scoped_va_context_and_surface_ ||
  87. (scoped_va_context_and_surface_->format() == kWebPVARtFormat));
  88. if (!scoped_va_context_and_surface_ ||
  89. new_visible_size != scoped_va_context_and_surface_->size()) {
  90. scoped_va_context_and_surface_.reset();
  91. auto scoped_va_surfaces = vaapi_wrapper_->CreateContextAndScopedVASurfaces(
  92. kWebPVARtFormat, new_visible_size,
  93. {VaapiWrapper::SurfaceUsageHint::kGeneric}, 1u,
  94. /*visible_size=*/absl::nullopt);
  95. if (scoped_va_surfaces.empty()) {
  96. VLOGF(1) << "CreateContextAndScopedVASurface() failed";
  97. return VaapiImageDecodeStatus::kSurfaceCreationFailed;
  98. }
  99. scoped_va_context_and_surface_ =
  100. ScopedVAContextAndSurface(scoped_va_surfaces[0].release());
  101. DCHECK(scoped_va_context_and_surface_->IsValid());
  102. }
  103. DCHECK_NE(scoped_va_context_and_surface_->id(), VA_INVALID_SURFACE);
  104. VAIQMatrixBufferVP8 iq_matrix_buf{};
  105. VAProbabilityDataBufferVP8 prob_buf{};
  106. VAPictureParameterBufferVP8 pic_param{};
  107. VASliceParameterBufferVP8 slice_param{};
  108. FillVP8DataStructures(*parse_result, Vp8ReferenceFrameVector(),
  109. &iq_matrix_buf, &prob_buf, &pic_param, &slice_param);
  110. const bool success = vaapi_wrapper_->SubmitBuffers(
  111. {{VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf},
  112. {VAProbabilityBufferType, sizeof(prob_buf), &prob_buf},
  113. {VAPictureParameterBufferType, sizeof(pic_param), &pic_param},
  114. {VASliceParameterBufferType, sizeof(slice_param), &slice_param},
  115. {VASliceDataBufferType, parse_result->frame_size, parse_result->data}});
  116. return success ? VaapiImageDecodeStatus::kSuccess
  117. : VaapiImageDecodeStatus::kSubmitVABuffersFailed;
  118. }
  119. } // namespace media