Commit 3494ea09 authored by Gil Dekel's avatar Gil Dekel Committed by Commit Bot

media/gpu: Generalize VaapiWrapper & cleanup

This CL generalizes some functions in VaapiWrapper that will be shared
by all potential implementing classes of VaapiImageDecoder.

In addition, this CL refactors (cleans up) the way VaapiImageDecoder
initializes the VaapiWrapper member.

Bug: 877694
Test: jpeg_decode_accelerator_unittest
Change-Id: Ic1fe5a1c4a104ed1cf27533af65f811e7db5e534
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1660829Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Commit-Queue: Gil Dekel <gildekel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#669868}
parent 6fdf9d29
...@@ -4,38 +4,20 @@ ...@@ -4,38 +4,20 @@
#include "media/gpu/vaapi/vaapi_image_decoder.h" #include "media/gpu/vaapi/vaapi_image_decoder.h"
#include <va/va.h>
#include "base/logging.h"
#include "media/gpu/vaapi/vaapi_wrapper.h" #include "media/gpu/vaapi/vaapi_wrapper.h"
namespace media { namespace media {
namespace { VaapiImageDecoder::VaapiImageDecoder(VAProfile va_profile)
: va_profile_(va_profile),
VAProfile ConvertToVAProfile(VaapiImageDecoder::Type type) { va_surface_id_(VA_INVALID_SURFACE),
switch (type) { va_rt_format_(kInvalidVaRtFormat) {}
case VaapiImageDecoder::Type::kJpeg:
return VAProfileJPEGBaseline;
case VaapiImageDecoder::Type::kWebP:
return VAProfileVP8Version0_3;
default:
NOTREACHED() << "Undefined Type value";
return VAProfileNone;
}
}
} // namespace
VaapiImageDecoder::VaapiImageDecoder()
: va_surface_id_(VA_INVALID_SURFACE), va_rt_format_(kInvalidVaRtFormat) {}
VaapiImageDecoder::~VaapiImageDecoder() = default; VaapiImageDecoder::~VaapiImageDecoder() = default;
bool VaapiImageDecoder::Initialize(const base::RepeatingClosure& error_uma_cb) { bool VaapiImageDecoder::Initialize(const base::RepeatingClosure& error_uma_cb) {
const VAProfile va_profile = ConvertToVAProfile(GetType());
vaapi_wrapper_ = vaapi_wrapper_ =
VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile, error_uma_cb); VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_, error_uma_cb);
return !!vaapi_wrapper_; return !!vaapi_wrapper_;
} }
......
...@@ -7,15 +7,14 @@ ...@@ -7,15 +7,14 @@
#include <stdint.h> #include <stdint.h>
#include <va/va.h>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
// This data type is defined in va/va.h using typedef, reproduced here.
typedef unsigned int VASurfaceID;
namespace media { namespace media {
class VASurface; class VASurface;
...@@ -50,15 +49,9 @@ enum class VaapiImageDecodeStatus : uint32_t { ...@@ -50,15 +49,9 @@ enum class VaapiImageDecodeStatus : uint32_t {
// more implementing classes are added (e.g. VaapiWebPDecoder). // more implementing classes are added (e.g. VaapiWebPDecoder).
class VaapiImageDecoder { class VaapiImageDecoder {
public: public:
// Type of image decoder.
enum class Type {
kJpeg,
kWebP,
};
virtual ~VaapiImageDecoder(); virtual ~VaapiImageDecoder();
// Uses GetType() to initialize |vaapi_wrapper_| in kDecode mode with the // Initializes |vaapi_wrapper_| in kDecode mode with the
// appropriate VAAPI profile and |error_uma_cb| for error reporting. // appropriate VAAPI profile and |error_uma_cb| for error reporting.
bool Initialize(const base::RepeatingClosure& error_uma_cb); bool Initialize(const base::RepeatingClosure& error_uma_cb);
...@@ -72,14 +65,13 @@ class VaapiImageDecoder { ...@@ -72,14 +65,13 @@ class VaapiImageDecoder {
base::span<const uint8_t> encoded_image, base::span<const uint8_t> encoded_image,
VaapiImageDecodeStatus* status) = 0; VaapiImageDecodeStatus* status) = 0;
// Returns the type of the current decoder.
virtual Type GetType() const = 0;
protected: protected:
VaapiImageDecoder(); VaapiImageDecoder(VAProfile va_profile);
scoped_refptr<VaapiWrapper> vaapi_wrapper_; scoped_refptr<VaapiWrapper> vaapi_wrapper_;
// The VA profile used for the current image decoder.
const VAProfile va_profile_;
// The current VA surface for decoding. // The current VA surface for decoding.
VASurfaceID va_surface_id_; VASurfaceID va_surface_id_;
// The coded size associated with |va_surface_id_|. // The coded size associated with |va_surface_id_|.
......
...@@ -140,8 +140,8 @@ static void FillSliceParameters( ...@@ -140,8 +140,8 @@ static void FillSliceParameters(
// whether a given parsed JPEG result is supported or not. // whether a given parsed JPEG result is supported or not.
static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) { static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) {
// Make sure the JPEG's chroma subsampling format is supported. // Make sure the JPEG's chroma subsampling format is supported.
if (!VaapiWrapper::IsJpegDecodingSupportedForInternalFormat( if (!VaapiWrapper::IsDecodingSupportedForInternalFormat(
VaSurfaceFormatForJpeg(jpeg.frame_header))) { VAProfileJPEGBaseline, VaSurfaceFormatForJpeg(jpeg.frame_header))) {
DLOG(ERROR) << "The JPEG's subsampling format is unsupported"; DLOG(ERROR) << "The JPEG's subsampling format is unsupported";
return false; return false;
} }
...@@ -158,12 +158,14 @@ static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) { ...@@ -158,12 +158,14 @@ static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) {
// Validate the coded size. // Validate the coded size.
gfx::Size min_jpeg_resolution; gfx::Size min_jpeg_resolution;
if (!VaapiWrapper::GetJpegDecodeMinResolution(&min_jpeg_resolution)) { if (!VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
&min_jpeg_resolution)) {
DLOG(ERROR) << "Could not get the minimum resolution"; DLOG(ERROR) << "Could not get the minimum resolution";
return false; return false;
} }
gfx::Size max_jpeg_resolution; gfx::Size max_jpeg_resolution;
if (!VaapiWrapper::GetJpegDecodeMaxResolution(&max_jpeg_resolution)) { if (!VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
&max_jpeg_resolution)) {
DLOG(ERROR) << "Could not get the maximum resolution"; DLOG(ERROR) << "Could not get the maximum resolution";
return false; return false;
} }
...@@ -210,6 +212,9 @@ unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header) { ...@@ -210,6 +212,9 @@ unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header) {
return kInvalidVaRtFormat; return kInvalidVaRtFormat;
} }
VaapiJpegDecoder::VaapiJpegDecoder()
: VaapiImageDecoder(VAProfileJPEGBaseline) {}
VaapiJpegDecoder::~VaapiJpegDecoder() { VaapiJpegDecoder::~VaapiJpegDecoder() {
if (vaapi_wrapper_) { if (vaapi_wrapper_) {
vaapi_wrapper_->DestroyContextAndSurfaces( vaapi_wrapper_->DestroyContextAndSurfaces(
...@@ -332,10 +337,6 @@ scoped_refptr<VASurface> VaapiJpegDecoder::Decode( ...@@ -332,10 +337,6 @@ scoped_refptr<VASurface> VaapiJpegDecoder::Decode(
base::DoNothing() /* release_cb */); base::DoNothing() /* release_cb */);
} }
VaapiImageDecoder::Type VaapiJpegDecoder::GetType() const {
return VaapiImageDecoder::Type::kJpeg;
}
std::unique_ptr<ScopedVAImage> VaapiJpegDecoder::GetImage( std::unique_ptr<ScopedVAImage> VaapiJpegDecoder::GetImage(
uint32_t preferred_image_fourcc, uint32_t preferred_image_fourcc,
VaapiImageDecodeStatus* status) { VaapiImageDecodeStatus* status) {
......
...@@ -26,13 +26,12 @@ unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header); ...@@ -26,13 +26,12 @@ unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header);
// hardware-accelerated JPEG decodes. // hardware-accelerated JPEG decodes.
class VaapiJpegDecoder : public VaapiImageDecoder { class VaapiJpegDecoder : public VaapiImageDecoder {
public: public:
VaapiJpegDecoder() = default; VaapiJpegDecoder();
~VaapiJpegDecoder() override; ~VaapiJpegDecoder() override;
// VaapiImageDecoder implementation. // VaapiImageDecoder implementation.
scoped_refptr<VASurface> Decode(base::span<const uint8_t> encoded_image, scoped_refptr<VASurface> Decode(base::span<const uint8_t> encoded_image,
VaapiImageDecodeStatus* status) override; VaapiImageDecodeStatus* status) override;
Type GetType() const override;
// Get the decoded data from the last Decode() call as a ScopedVAImage. The // Get the decoded data from the last Decode() call as a ScopedVAImage. The
// VAImage's format will be either |preferred_image_fourcc| if the conversion // VAImage's format will be either |preferred_image_fourcc| if the conversion
......
...@@ -417,7 +417,7 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) { ...@@ -417,7 +417,7 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) {
// Skip the image if the VAAPI driver doesn't claim to support its chroma // Skip the image if the VAAPI driver doesn't claim to support its chroma
// subsampling format. However, we expect at least 4:2:0 and 4:2:2 support. // subsampling format. However, we expect at least 4:2:0 and 4:2:2 support.
const VaapiWrapper::InternalFormats supported_internal_formats = const VaapiWrapper::InternalFormats supported_internal_formats =
VaapiWrapper::GetJpegDecodeSupportedInternalFormats(); VaapiWrapper::GetDecodeSupportedInternalFormats(VAProfileJPEGBaseline);
ASSERT_TRUE(supported_internal_formats.yuv420); ASSERT_TRUE(supported_internal_formats.yuv420);
ASSERT_TRUE(supported_internal_formats.yuv422); ASSERT_TRUE(supported_internal_formats.yuv422);
JpegParseResult parse_result; JpegParseResult parse_result;
...@@ -426,8 +426,10 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) { ...@@ -426,8 +426,10 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) {
const unsigned int rt_format = const unsigned int rt_format =
VaSurfaceFormatForJpeg(parse_result.frame_header); VaSurfaceFormatForJpeg(parse_result.frame_header);
ASSERT_NE(kInvalidVaRtFormat, rt_format); ASSERT_NE(kInvalidVaRtFormat, rt_format);
if (!VaapiWrapper::IsJpegDecodingSupportedForInternalFormat(rt_format)) if (!VaapiWrapper::IsDecodingSupportedForInternalFormat(VAProfileJPEGBaseline,
rt_format)) {
GTEST_SKIP(); GTEST_SKIP();
}
// Note that this test together with // Note that this test together with
// VaapiJpegDecoderTest.MinimalImageFormatSupport gives us two guarantees: // VaapiJpegDecoderTest.MinimalImageFormatSupport gives us two guarantees:
...@@ -478,9 +480,11 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) { ...@@ -478,9 +480,11 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) {
// TODO(andrescj): for now, this assumes 4:2:0. Handle other formats. // TODO(andrescj): for now, this assumes 4:2:0. Handle other formats.
TEST_F(VaapiJpegDecoderTest, DecodeSucceedsForSupportedSizes) { TEST_F(VaapiJpegDecoderTest, DecodeSucceedsForSupportedSizes) {
gfx::Size min_supported_size; gfx::Size min_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMinResolution(&min_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
&min_supported_size));
gfx::Size max_supported_size; gfx::Size max_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMaxResolution(&max_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
&max_supported_size));
// Ensure the maximum supported size is reasonable. // Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width()); ASSERT_GE(max_supported_size.width(), min_supported_size.width());
...@@ -522,9 +526,11 @@ TEST_F(VaapiJpegDecoderTest, DecodeSucceedsForSupportedSizes) { ...@@ -522,9 +526,11 @@ TEST_F(VaapiJpegDecoderTest, DecodeSucceedsForSupportedSizes) {
// TODO(andrescj): for now, this assumes 4:2:0. Handle other formats. // TODO(andrescj): for now, this assumes 4:2:0. Handle other formats.
TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) { TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) {
gfx::Size min_supported_size; gfx::Size min_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMinResolution(&min_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
&min_supported_size));
gfx::Size max_supported_size; gfx::Size max_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMaxResolution(&max_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
&max_supported_size));
// Ensure the maximum supported size is reasonable. // Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width()); ASSERT_GE(max_supported_size.width(), min_supported_size.width());
...@@ -573,9 +579,11 @@ TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) { ...@@ -573,9 +579,11 @@ TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) {
// TODO(andrescj): for now, this assumes 4:2:0. Handle other formats. // TODO(andrescj): for now, this assumes 4:2:0. Handle other formats.
TEST_F(VaapiJpegDecoderTest, DecodeFailsForAboveMaxSize) { TEST_F(VaapiJpegDecoderTest, DecodeFailsForAboveMaxSize) {
gfx::Size min_supported_size; gfx::Size min_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMinResolution(&min_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
&min_supported_size));
gfx::Size max_supported_size; gfx::Size max_supported_size;
ASSERT_TRUE(VaapiWrapper::GetJpegDecodeMaxResolution(&max_supported_size)); ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
&max_supported_size));
// Ensure the maximum supported size is reasonable. // Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width()); ASSERT_GE(max_supported_size.width(), min_supported_size.width());
......
...@@ -1064,36 +1064,40 @@ bool VaapiWrapper::IsJpegDecodeSupported() { ...@@ -1064,36 +1064,40 @@ bool VaapiWrapper::IsJpegDecodeSupported() {
} }
// static // static
VaapiWrapper::InternalFormats VaapiWrapper::InternalFormats VaapiWrapper::GetDecodeSupportedInternalFormats(
VaapiWrapper::GetJpegDecodeSupportedInternalFormats() { VAProfile va_profile) {
VASupportedProfiles::ProfileInfo profile_info; VASupportedProfiles::ProfileInfo profile_info;
if (!VASupportedProfiles::Get().IsProfileSupported( if (!VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile,
kDecode, VAProfileJPEGBaseline, &profile_info)) { &profile_info)) {
return InternalFormats{}; return InternalFormats{};
} }
return profile_info.supported_internal_formats; return profile_info.supported_internal_formats;
} }
// static // static
bool VaapiWrapper::IsJpegDecodingSupportedForInternalFormat( bool VaapiWrapper::IsDecodingSupportedForInternalFormat(
VAProfile va_profile,
unsigned int rt_format) { unsigned int rt_format) {
static const base::NoDestructor<VaapiWrapper::InternalFormats> static const base::NoDestructor<VaapiWrapper::InternalFormats>
supported_internal_formats( supported_internal_formats(
VaapiWrapper::GetJpegDecodeSupportedInternalFormats()); VaapiWrapper::GetDecodeSupportedInternalFormats(va_profile));
if (rt_format == VA_RT_FORMAT_YUV420) switch (rt_format) {
return supported_internal_formats->yuv420; case VA_RT_FORMAT_YUV420:
else if (rt_format == VA_RT_FORMAT_YUV422) return supported_internal_formats->yuv420;
return supported_internal_formats->yuv422; case VA_RT_FORMAT_YUV422:
else if (rt_format == VA_RT_FORMAT_YUV444) return supported_internal_formats->yuv422;
return supported_internal_formats->yuv444; case VA_RT_FORMAT_YUV444:
return supported_internal_formats->yuv444;
}
return false; return false;
} }
// static // static
bool VaapiWrapper::GetJpegDecodeMinResolution(gfx::Size* min_size) { bool VaapiWrapper::GetDecodeMinResolution(VAProfile va_profile,
gfx::Size* min_size) {
VASupportedProfiles::ProfileInfo profile_info; VASupportedProfiles::ProfileInfo profile_info;
if (!VASupportedProfiles::Get().IsProfileSupported( if (!VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile,
kDecode, VAProfileJPEGBaseline, &profile_info)) { &profile_info)) {
return false; return false;
} }
*min_size = profile_info.min_resolution; *min_size = profile_info.min_resolution;
...@@ -1101,10 +1105,11 @@ bool VaapiWrapper::GetJpegDecodeMinResolution(gfx::Size* min_size) { ...@@ -1101,10 +1105,11 @@ bool VaapiWrapper::GetJpegDecodeMinResolution(gfx::Size* min_size) {
} }
// static // static
bool VaapiWrapper::GetJpegDecodeMaxResolution(gfx::Size* max_size) { bool VaapiWrapper::GetDecodeMaxResolution(VAProfile va_profile,
gfx::Size* max_size) {
VASupportedProfiles::ProfileInfo profile_info; VASupportedProfiles::ProfileInfo profile_info;
if (!VASupportedProfiles::Get().IsProfileSupported( if (!VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile,
kDecode, VAProfileJPEGBaseline, &profile_info)) { &profile_info)) {
return false; return false;
} }
*max_size = profile_info.max_resolution; *max_size = profile_info.max_resolution;
...@@ -1115,7 +1120,7 @@ bool VaapiWrapper::GetJpegDecodeMaxResolution(gfx::Size* max_size) { ...@@ -1115,7 +1120,7 @@ bool VaapiWrapper::GetJpegDecodeMaxResolution(gfx::Size* max_size) {
bool VaapiWrapper::GetJpegDecodeSuitableImageFourCC(unsigned int rt_format, bool VaapiWrapper::GetJpegDecodeSuitableImageFourCC(unsigned int rt_format,
uint32_t preferred_fourcc, uint32_t preferred_fourcc,
uint32_t* suitable_fourcc) { uint32_t* suitable_fourcc) {
if (!IsJpegDecodingSupportedForInternalFormat(rt_format)) if (!IsDecodingSupportedForInternalFormat(VAProfileJPEGBaseline, rt_format))
return false; return false;
// Work around some driver-specific conversion issues. If you add a workaround // Work around some driver-specific conversion issues. If you add a workaround
......
...@@ -99,24 +99,26 @@ class MEDIA_GPU_EXPORT VaapiWrapper ...@@ -99,24 +99,26 @@ class MEDIA_GPU_EXPORT VaapiWrapper
// Return true when JPEG decode is supported. // Return true when JPEG decode is supported.
static bool IsJpegDecodeSupported(); static bool IsJpegDecodeSupported();
// Returns the supported internal formats for JPEG decoding. If JPEG decoding // Returns the supported internal formats for decoding using |va_profile|. If
// is not supported, returns InternalFormats{}. // decoding is not supported for that profile, returns InternalFormats{}.
static InternalFormats GetJpegDecodeSupportedInternalFormats(); static InternalFormats GetDecodeSupportedInternalFormats(
VAProfile va_profile);
// Returns true if |rt_format| is supported for JPEG decoding. If it's not or
// JPEG decoding is not supported, returns false. // Returns true if |rt_format| is supported for decoding using |va_profile|.
static bool IsJpegDecodingSupportedForInternalFormat(unsigned int rt_format); // Returns false if |rt_format| or |va_profile| is not supported for decoding.
static bool IsDecodingSupportedForInternalFormat(VAProfile va_profile,
// Gets the minimum surface size allowed for JPEG decoding. Returns true if unsigned int rt_format);
// the size can be obtained, false otherwise. If a dimension is not reported
// by the driver, the dimension is returned as 0. // Gets the minimum surface size allowed for decoding using |va_profile|.
static bool GetJpegDecodeMinResolution(gfx::Size* min_size); // Returns true if the size can be obtained, false otherwise. If a dimension
// is not reported by the driver, the dimension is returned as 0.
// Gets the maximum surface size allowed for JPEG decoding. Returns true if static bool GetDecodeMinResolution(VAProfile va_profile, gfx::Size* min_size);
// the size can be obtained, false otherwise. Because of the initialization in
// VASupportedProfiles::FillProfileInfo_Locked(), the size is guaranteed to // Gets the maximum surface size allowed for decoding using |va_profile|.
// not be empty (as long as this method returns true). // Returns true if the size can be obtained, false otherwise. Because of the
static bool GetJpegDecodeMaxResolution(gfx::Size* max_size); // initialization in VASupportedProfiles::FillProfileInfo_Locked(), the size
// is guaranteed to not be empty (as long as this method returns true).
static bool GetDecodeMaxResolution(VAProfile va_profile, gfx::Size* max_size);
// Obtains a suitable FOURCC that can be used in vaCreateImage() + // Obtains a suitable FOURCC that can be used in vaCreateImage() +
// vaGetImage(). |rt_format| corresponds to the JPEG's subsampling format. // vaGetImage(). |rt_format| corresponds to the JPEG's subsampling format.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment