summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/vaapi
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-09-29 16:16:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-11-09 10:04:06 +0000
commita95a7417ad456115a1ef2da4bb8320531c0821f1 (patch)
treeedcd59279e486d2fd4a8f88a7ed025bcf925c6e6 /chromium/media/gpu/vaapi
parent33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (diff)
downloadqtwebengine-chromium-a95a7417ad456115a1ef2da4bb8320531c0821f1.tar.gz
BASELINE: Update Chromium to 106.0.5249.126
Change-Id: Ib0bb21c437a7d1686e21c33f2d329f2ac425b7ab Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438936 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/gpu/vaapi')
-rw-r--r--chromium/media/gpu/vaapi/BUILD.gn23
-rw-r--r--chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc55
-rw-r--r--chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc25
-rw-r--r--chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc5
-rw-r--r--chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h1
-rw-r--r--chromium/media/gpu/vaapi/vaapi_image_decoder.cc12
-rw-r--r--chromium/media/gpu/vaapi/vaapi_jpeg_decoder.cc12
-rw-r--r--chromium/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc21
-rw-r--r--chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc1
-rw-r--r--chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc1
-rw-r--r--chromium/media/gpu/vaapi/vaapi_picture_tfp.h3
-rw-r--r--chromium/media/gpu/vaapi/vaapi_unittest.cc111
-rw-r--r--chromium/media/gpu/vaapi/vaapi_utils.cc4
-rw-r--r--chromium/media/gpu/vaapi/vaapi_utils.h7
-rw-r--r--chromium/media/gpu/vaapi/vaapi_utils_unittest.cc6
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc1
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h3
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc6
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decoder.cc14
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decoder.h3
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.cc56
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.h7
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.cc80
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.h3
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc3
-rw-r--r--chromium/media/gpu/vaapi/vaapi_webp_decoder.cc15
-rw-r--r--chromium/media/gpu/vaapi/vaapi_webp_decoder_unittest.cc2
-rw-r--r--chromium/media/gpu/vaapi/vaapi_wrapper.cc409
-rw-r--r--chromium/media/gpu/vaapi/vaapi_wrapper.h25
-rw-r--r--chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc10
-rw-r--r--chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h8
-rw-r--r--chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc12
-rw-r--r--chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h8
-rw-r--r--chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc32
34 files changed, 656 insertions, 328 deletions
diff --git a/chromium/media/gpu/vaapi/BUILD.gn b/chromium/media/gpu/vaapi/BUILD.gn
index f701a807823..8fbc73ddac3 100644
--- a/chromium/media/gpu/vaapi/BUILD.gn
+++ b/chromium/media/gpu/vaapi/BUILD.gn
@@ -207,6 +207,7 @@ source_set("common") {
"//third_party/libyuv",
"//ui/base:features",
"//ui/gfx:memory_buffer",
+ "//ui/gfx/linux:drm",
"//ui/gl",
]
if (use_ozone) {
@@ -354,6 +355,10 @@ test("vaapi_unittest") {
":webp_decoder_unit_test",
]
}
+
+ if (use_ozone && is_linux) {
+ deps += [ "//ui/ozone" ]
+ }
}
group("vaapi_fuzzers") {
@@ -368,6 +373,12 @@ executable("decode_test") {
"test/av1_decoder.cc",
"test/av1_decoder.h",
"test/decode.cc",
+ "test/h264_decoder.cc",
+ "test/h264_decoder.h",
+ "test/h264_dpb.cc",
+ "test/h264_dpb.h",
+ "test/h264_vaapi_wrapper.cc",
+ "test/h264_vaapi_wrapper.h",
"test/macros.h",
"test/scoped_va_config.cc",
"test/scoped_va_config.h",
@@ -384,6 +395,18 @@ executable("decode_test") {
"test/vp9_decoder.cc",
"test/vp9_decoder.h",
]
+
+ if (enable_platform_hevc) {
+ sources += [
+ "test/h265_decoder.cc",
+ "test/h265_decoder.h",
+ "test/h265_dpb.cc",
+ "test/h265_dpb.h",
+ "test/h265_vaapi_wrapper.cc",
+ "test/h265_vaapi_wrapper.h",
+ ]
+ }
+
deps = [
":libva_stubs",
"//base",
diff --git a/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc b/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
index ffc25c1e82d..904767443ab 100644
--- a/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
+++ b/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate.cc
@@ -12,8 +12,10 @@
#include "base/bits.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "media/base/media_switches.h"
+#include "media/base/video_bitrate_allocation.h"
#include "media/gpu/gpu_video_encode_accelerator_helpers.h"
#include "media/gpu/macros.h"
#include "media/gpu/vaapi/vaapi_common.h"
@@ -72,6 +74,7 @@ VAEncMiscParam& AllocateMiscParameterBuffer(
}
void CreateVAEncRateControlParams(uint32_t bps,
+ uint32_t target_percentage,
uint32_t window_size,
uint32_t initial_qp,
uint32_t min_qp,
@@ -83,6 +86,7 @@ void CreateVAEncRateControlParams(uint32_t bps,
AllocateMiscParameterBuffer<VAEncMiscParameterRateControl>(
misc_buffers[0], VAEncMiscParameterTypeRateControl);
rate_control_param.bits_per_second = bps;
+ rate_control_param.target_percentage = target_percentage;
rate_control_param.window_size = window_size;
rate_control_param.initial_qp = initial_qp;
rate_control_param.min_qp = min_qp;
@@ -233,7 +237,7 @@ bool H264VaapiVideoEncoderDelegate::Initialize(
DVLOGF(1) << "The pixel sizes are not even: " << visible_size_.ToString();
return false;
}
- constexpr size_t kH264MacroblockSizeInPixels = 16;
+ constexpr int kH264MacroblockSizeInPixels = 16;
coded_size_ = gfx::Size(
base::bits::AlignUp(visible_size_.width(), kH264MacroblockSizeInPixels),
base::bits::AlignUp(visible_size_.height(), kH264MacroblockSizeInPixels));
@@ -306,6 +310,11 @@ bool H264VaapiVideoEncoderDelegate::Initialize(
UpdateSPS();
UpdatePPS();
+ // If we don't set the stored BitrateAllocation to the right type, UpdateRates
+ // will mistakenly reject the bitrate when the requested type in the config is
+ // not the default (constant bitrate).
+ curr_params_.bitrate_allocation =
+ VideoBitrateAllocation(config.bitrate.mode());
return UpdateRates(AllocateBitrateForDefaultEncoding(config),
initial_framerate);
}
@@ -420,6 +429,15 @@ bool H264VaapiVideoEncoderDelegate::UpdateRates(
uint32_t framerate) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (bitrate_allocation.GetMode() !=
+ curr_params_.bitrate_allocation.GetMode()) {
+ DVLOGF(1) << "Unexpected bitrate mode, requested rate "
+ << bitrate_allocation.GetSumBitrate().ToString()
+ << ", expected mode to match "
+ << curr_params_.bitrate_allocation.GetSumBitrate().ToString();
+ return false;
+ }
+
uint32_t bitrate = bitrate_allocation.GetSumBps();
if (bitrate == 0 || framerate == 0)
return false;
@@ -551,7 +569,14 @@ void H264VaapiVideoEncoderDelegate::UpdateSPS() {
(curr_params_.cpb_size_bits >>
(kCPBSizeScale + H264SPS::kCPBSizeScaleConstantTerm)) -
1;
- current_sps_.cbr_flag[0] = true;
+ switch (curr_params_.bitrate_allocation.GetMode()) {
+ case (Bitrate::Mode::kConstant):
+ current_sps_.cbr_flag[0] = true;
+ break;
+ case (Bitrate::Mode::kVariable):
+ current_sps_.cbr_flag[0] = false;
+ break;
+ }
current_sps_.initial_cpb_removal_delay_length_minus_1 =
H264SPS::kDefaultInitialCPBRemovalDelayLength - 1;
current_sps_.cpb_removal_delay_length_minus1 =
@@ -854,6 +879,27 @@ bool H264VaapiVideoEncoderDelegate::SubmitFrameParameters(
const absl::optional<size_t>& ref_frame_index) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ const Bitrate bitrate = encode_params.bitrate_allocation.GetSumBitrate();
+ uint32_t bitrate_bps = bitrate.target_bps();
+ uint32_t target_percentage = 100u;
+ if (bitrate.mode() == Bitrate::Mode::kVariable) {
+ // In VA-API, the sequence parameter's bits_per_second represents the
+ // maximum bitrate. Above, we use the target_bps for |bitrate_bps|; this is
+ // because 1) for constant bitrates, peak and target are equal, and 2)
+ // |Bitrate| class does not store a peak_bps for constant bitrates. Here,
+ // we use the peak, because it exists for variable bitrates.
+ bitrate_bps = bitrate.peak_bps();
+ DCHECK_NE(bitrate.peak_bps(), 0u);
+ base::CheckedNumeric<uint32_t> checked_percentage =
+ base::CheckDiv(base::CheckMul<uint32_t>(bitrate.target_bps(), 100u),
+ bitrate.peak_bps());
+ if (!checked_percentage.AssignIfValid(&target_percentage)) {
+ DVLOGF(1)
+ << "Integer overflow while computing target percentage for bitrate.";
+ return false;
+ }
+ target_percentage = checked_percentage.ValueOrDefault(100u);
+ }
VAEncSequenceParameterBufferH264 seq_param = {};
#define SPS_TO_SP(a) seq_param.a = sps.a;
@@ -863,7 +909,7 @@ bool H264VaapiVideoEncoderDelegate::SubmitFrameParameters(
seq_param.intra_period = kIPeriod;
seq_param.intra_idr_period = kIDRPeriod;
seq_param.ip_period = kIPPeriod;
- seq_param.bits_per_second = encode_params.bitrate_allocation.GetSumBps();
+ seq_param.bits_per_second = bitrate_bps;
SPS_TO_SP(max_num_ref_frames);
absl::optional<gfx::Size> coded_size = sps.GetCodedSize();
@@ -972,8 +1018,7 @@ bool H264VaapiVideoEncoderDelegate::SubmitFrameParameters(
std::vector<uint8_t> misc_buffers[3];
CreateVAEncRateControlParams(
- encode_params.bitrate_allocation.GetSumBps(),
- encode_params.cpb_window_size_ms,
+ bitrate_bps, target_percentage, encode_params.cpb_window_size_ms,
base::strict_cast<uint32_t>(pic_param.pic_init_qp),
base::strict_cast<uint32_t>(encode_params.min_qp),
base::strict_cast<uint32_t>(encode_params.max_qp),
diff --git a/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc b/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
index 18b8a3e916a..93569661f1c 100644
--- a/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
+++ b/chromium/media/gpu/vaapi/h264_vaapi_video_encoder_delegate_unittest.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "build/build_config.h"
+#include "media/base/video_bitrate_allocation.h"
#include "media/gpu/vaapi/va_surface.h"
#include "media/gpu/vaapi/vaapi_common.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
@@ -308,6 +309,30 @@ TEST_F(H264VaapiVideoEncoderDelegateTest, Initialize) {
ExpectLevel(H264SPS::kLevelIDC5p1);
}
+TEST_F(H264VaapiVideoEncoderDelegateTest, ChangeBitrateModeFails) {
+ auto vea_config = kDefaultVEAConfig;
+ const auto vea_delegate_config = kDefaultVEADelegateConfig;
+ EXPECT_TRUE(encoder_->Initialize(vea_config, vea_delegate_config));
+
+ const uint32_t new_bitrate_bps = kDefaultVEAConfig.bitrate.target_bps();
+ VideoBitrateAllocation new_allocation =
+ VideoBitrateAllocation(Bitrate::Mode::kVariable);
+ new_allocation.SetBitrate(0, 0, new_bitrate_bps);
+ EXPECT_TRUE(new_allocation.SetPeakBps(2u * new_bitrate_bps));
+
+ ASSERT_FALSE(encoder_->UpdateRates(
+ new_allocation, VideoEncodeAccelerator::kDefaultFramerate));
+}
+
+TEST_F(H264VaapiVideoEncoderDelegateTest, VariableBitrate_Initialize) {
+ auto vea_config = kDefaultVEAConfig;
+ const uint32_t bitrate_bps = vea_config.bitrate.target_bps();
+ vea_config.bitrate = Bitrate::VariableBitrate(bitrate_bps, 2u * bitrate_bps);
+ const auto vea_delegate_config = kDefaultVEADelegateConfig;
+
+ ASSERT_TRUE(encoder_->Initialize(vea_config, vea_delegate_config));
+}
+
TEST_P(H264VaapiVideoEncoderDelegateTest, EncodeTemporalLayerRequest) {
const uint8_t num_temporal_layers = GetParam();
const bool initialize_success = num_temporal_layers <= 3;
diff --git a/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc b/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc
index c9230428aac..ed283709f74 100644
--- a/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc
+++ b/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.cc
@@ -59,6 +59,11 @@ scoped_refptr<H265Picture> H265VaapiVideoDecoderDelegate::CreateH265Picture() {
return new VaapiH265Picture(std::move(va_surface));
}
+bool H265VaapiVideoDecoderDelegate::IsChromaSamplingSupported(
+ VideoChromaSampling chroma_sampling) {
+ return chroma_sampling == VideoChromaSampling::k420;
+}
+
DecodeStatus H265VaapiVideoDecoderDelegate::SubmitFrameMetadata(
const H265SPS* sps,
const H265PPS* pps,
diff --git a/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h b/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h
index 09adc1d011f..9c699998131 100644
--- a/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h
+++ b/chromium/media/gpu/vaapi/h265_vaapi_video_decoder_delegate.h
@@ -62,6 +62,7 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
void Reset() override;
Status SetStream(base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config) override;
+ bool IsChromaSamplingSupported(VideoChromaSampling chroma_sampling) override;
private:
void FillVAPicture(VAPictureHEVC* va_pic, scoped_refptr<H265Picture> pic);
diff --git a/chromium/media/gpu/vaapi/vaapi_image_decoder.cc b/chromium/media/gpu/vaapi/vaapi_image_decoder.cc
index 1c92c7b6fa8..91b26f9ebd2 100644
--- a/chromium/media/gpu/vaapi/vaapi_image_decoder.cc
+++ b/chromium/media/gpu/vaapi/vaapi_image_decoder.cc
@@ -74,13 +74,11 @@ VaapiImageDecoder::GetSupportedProfile() const {
DCHECK_NE(gpu::ImageDecodeAcceleratorType::kUnknown, profile.image_type);
// Note that since |vaapi_wrapper_| was created successfully, we expect the
- // following calls to be successful. Hence the DCHECKs.
- const bool got_min_resolution = VaapiWrapper::GetDecodeMinResolution(
- va_profile_, &profile.min_encoded_dimensions);
- DCHECK(got_min_resolution);
- const bool got_max_resolution = VaapiWrapper::GetDecodeMaxResolution(
- va_profile_, &profile.max_encoded_dimensions);
- DCHECK(got_max_resolution);
+ // following call to be successful. Hence the DCHECK.
+ const bool got_supported_resolutions = VaapiWrapper::GetSupportedResolutions(
+ va_profile_, VaapiWrapper::CodecMode::kDecode,
+ profile.min_encoded_dimensions, profile.max_encoded_dimensions);
+ DCHECK(got_supported_resolutions);
// TODO(andrescj): Ideally, we would advertise support for all the formats
// supported by the driver. However, for now, we will only support exposing
diff --git a/chromium/media/gpu/vaapi/vaapi_jpeg_decoder.cc b/chromium/media/gpu/vaapi/vaapi_jpeg_decoder.cc
index 4ea2b6cbb0f..7c3e8e8b316 100644
--- a/chromium/media/gpu/vaapi/vaapi_jpeg_decoder.cc
+++ b/chromium/media/gpu/vaapi/vaapi_jpeg_decoder.cc
@@ -154,15 +154,11 @@ static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) {
// Validate the coded size.
gfx::Size min_jpeg_resolution;
- if (!VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
- &min_jpeg_resolution)) {
- DLOG(ERROR) << "Could not get the minimum resolution";
- return false;
- }
gfx::Size max_jpeg_resolution;
- if (!VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
- &max_jpeg_resolution)) {
- DLOG(ERROR) << "Could not get the maximum resolution";
+ if (!VaapiWrapper::GetSupportedResolutions(
+ VAProfileJPEGBaseline, VaapiWrapper::CodecMode::kDecode,
+ min_jpeg_resolution, max_jpeg_resolution)) {
+ DLOG(ERROR) << "Could not get the minimum and maximum resolutions";
return false;
}
const int actual_jpeg_coded_width =
diff --git a/chromium/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc b/chromium/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
index 2130b6a6134..730dcb94b6f 100644
--- a/chromium/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
@@ -409,11 +409,10 @@ TEST_P(VaapiJpegDecoderTest, DecodeSucceeds) {
// state is retained.
TEST_F(VaapiJpegDecoderTest, DecodeSucceedsForSupportedSizes) {
gfx::Size min_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
- &min_supported_size));
gfx::Size max_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
- &max_supported_size));
+ ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+ VAProfileJPEGBaseline, VaapiWrapper::CodecMode::kDecode,
+ min_supported_size, max_supported_size));
// Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width());
@@ -597,11 +596,10 @@ TEST_P(VaapiJpegDecoderWithDmaBufsTest, DecodeSucceeds) {
// TODO(andrescj): for now, this assumes 4:2:0. Handle other formats.
TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) {
gfx::Size min_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
- &min_supported_size));
gfx::Size max_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
- &max_supported_size));
+ ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+ VAProfileJPEGBaseline, VaapiWrapper::CodecMode::kDecode,
+ min_supported_size, max_supported_size));
// Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width());
@@ -648,11 +646,10 @@ TEST_F(VaapiJpegDecoderTest, DecodeFailsForBelowMinSize) {
// TODO(andrescj): for now, this assumes 4:2:0. Handle other formats.
TEST_F(VaapiJpegDecoderTest, DecodeFailsForAboveMaxSize) {
gfx::Size min_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(VAProfileJPEGBaseline,
- &min_supported_size));
gfx::Size max_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(VAProfileJPEGBaseline,
- &max_supported_size));
+ ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+ VAProfileJPEGBaseline, VaapiWrapper::CodecMode::kDecode,
+ min_supported_size, max_supported_size));
// Ensure the maximum supported size is reasonable.
ASSERT_GE(max_supported_size.width(), min_supported_size.width());
diff --git a/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc b/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
index c7d85aae7c0..17d70682b06 100644
--- a/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
+++ b/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
@@ -78,6 +78,7 @@ VaapiStatus VaapiPictureNativePixmapEgl::Allocate(gfx::BufferFormat format) {
if (make_context_current_cb_ && !make_context_current_cb_.Run())
return VaapiStatus::Codes::kBadContext;
+ // TODO(b/220336463): plumb the right color space.
auto image =
base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
// Create an EGLImage from a gl texture
diff --git a/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc b/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
index be4e2fd439f..a53056a32c4 100644
--- a/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
+++ b/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
@@ -79,6 +79,7 @@ VaapiStatus VaapiPictureNativePixmapOzone::Initialize(
const gfx::BufferFormat format = pixmap->GetBufferFormat();
+ // TODO(b/220336463): plumb the right color space.
auto image =
base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
if (!image->Initialize(std::move(pixmap))) {
diff --git a/chromium/media/gpu/vaapi/vaapi_picture_tfp.h b/chromium/media/gpu/vaapi/vaapi_picture_tfp.h
index 74b69956fca..37d6e947a42 100644
--- a/chromium/media/gpu/vaapi/vaapi_picture_tfp.h
+++ b/chromium/media/gpu/vaapi/vaapi_picture_tfp.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "media/gpu/vaapi/vaapi_picture.h"
#include "ui/gfx/geometry/size.h"
@@ -50,7 +51,7 @@ class VaapiTFPPicture : public VaapiPicture {
private:
VaapiStatus Initialize();
- x11::Connection* const connection_;
+ const raw_ptr<x11::Connection> connection_;
x11::Pixmap x_pixmap_;
scoped_refptr<gl::GLImageGLX> glx_image_;
diff --git a/chromium/media/gpu/vaapi/vaapi_unittest.cc b/chromium/media/gpu/vaapi/vaapi_unittest.cc
index 0c79566591d..8658dc7749d 100644
--- a/chromium/media/gpu/vaapi/vaapi_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_unittest.cc
@@ -41,6 +41,12 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/linux/gbm_defines.h"
+#if defined(USE_OZONE) && BUILDFLAG(IS_LINUX)
+// GN doesn't understand conditional includes, so we need nogncheck here.
+// See crbug.com/1125897.
+#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#endif
+
namespace media {
namespace {
@@ -57,6 +63,7 @@ absl::optional<VAProfile> ConvertToVAProfile(VideoCodecProfile profile) {
{AV1PROFILE_PROFILE_MAIN, VAProfileAV1Profile0},
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
{HEVCPROFILE_MAIN, VAProfileHEVCMain},
+ {HEVCPROFILE_MAIN_STILL_PICTURE, VAProfileHEVCMain},
{HEVCPROFILE_MAIN10, VAProfileHEVCMain10},
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
};
@@ -264,7 +271,7 @@ std::map<VAProfile, std::vector<VAEntrypoint>> ParseVainfo(
return info;
}
-std::map<VAProfile, std::vector<VAEntrypoint>> RetrieveVAInfoOutput() {
+std::string GetVaInfo(std::vector<std::string> argv) {
int fds[2];
PCHECK(pipe(fds) == 0);
base::File read_pipe(fds[0]);
@@ -272,16 +279,21 @@ std::map<VAProfile, std::vector<VAEntrypoint>> RetrieveVAInfoOutput() {
base::LaunchOptions options;
options.fds_to_remap.emplace_back(write_pipe_fd.get(), STDOUT_FILENO);
- std::vector<std::string> argv = {"vainfo"};
EXPECT_TRUE(LaunchProcess(argv, options).IsValid());
write_pipe_fd.reset();
- char buf[4096] = {};
+ char buf[262144] = {};
int n = read_pipe.ReadAtCurrentPos(buf, sizeof(buf));
PCHECK(n >= 0);
- EXPECT_LT(n, 4096);
+ EXPECT_LT(n, 262144);
std::string output(buf, n);
DVLOG(4) << output;
+ return output;
+}
+
+std::map<VAProfile, std::vector<VAEntrypoint>> RetrieveVAInfoOutput() {
+ std::vector<std::string> argv = {"vainfo"};
+ std::string output = GetVaInfo(argv);
return ParseVainfo(output);
}
@@ -335,6 +347,56 @@ TEST_F(VaapiTest, GetSupportedEncodeProfiles) {
}
}
+// Verifies that the resolutions of profiles for VBR and CBR are the same.
+TEST_F(VaapiTest, VbrAndCbrResolutionsMatch) {
+ struct ResolutionInfo {
+ VaapiWrapper::CodecMode mode;
+ gfx::Size min;
+ gfx::Size max;
+ };
+ std::map<VAProfile, std::vector<ResolutionInfo>> supported_resolutions;
+ for (const VaapiWrapper::CodecMode codec_mode :
+ {VaapiWrapper::kEncodeConstantBitrate,
+ VaapiWrapper::kEncodeConstantQuantizationParameter,
+ VaapiWrapper::kEncodeVariableBitrate}) {
+ const std::map<VAProfile, std::vector<VAEntrypoint>> configurations =
+ VaapiWrapper::GetSupportedConfigurationsForCodecModeForTesting(
+ codec_mode);
+ for (const auto& configuration : configurations) {
+ const VAProfile va_profile = configuration.first;
+ ResolutionInfo res_info{.mode = codec_mode};
+ ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+ va_profile, codec_mode, res_info.min, res_info.max))
+ << " Failed get resolutions: "
+ << "profile=" << va_profile << ", mode=" << codec_mode;
+
+ supported_resolutions[va_profile].push_back(res_info);
+ }
+ }
+
+ for (const auto& r : supported_resolutions) {
+ const VAProfile va_profile = r.first;
+ const auto& resolution_info = r.second;
+
+ for (size_t i = 0; i < resolution_info.size(); ++i) {
+ for (size_t j = i + 1; j < resolution_info.size(); ++j) {
+ EXPECT_EQ(resolution_info[i].min, resolution_info[j].min)
+ << " Minimum supported resolution mismatch for profile="
+ << VAProfileToString(va_profile) << ": " << resolution_info[i].mode
+ << " (" << resolution_info[i].min.ToString() << ") and "
+ << resolution_info[j].mode << " ("
+ << resolution_info[j].min.ToString() << ")";
+ EXPECT_EQ(resolution_info[i].max, resolution_info[j].max)
+ << " Maximum supported resolution mismatch for profile="
+ << VAProfileToString(va_profile) << ": " << resolution_info[i].mode
+ << " (" << resolution_info[i].max.ToString() << ") and "
+ << resolution_info[j].mode << " ("
+ << resolution_info[j].max.ToString() << ")";
+ }
+ }
+ }
+}
+
#if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
// Verifies that VAProfileProtected is indeed supported by the command line
// vainfo utility.
@@ -428,7 +490,7 @@ TEST_F(VaapiTest, LowQualityEncodingSetting) {
VAConfigAttrib attrib{};
attrib.type = VAConfigAttribEncQualityRange;
{
- base::AutoLockMaybe auto_lock(wrapper->va_lock_);
+ base::AutoLockMaybe auto_lock(wrapper->va_lock_.get());
VAStatus va_res = vaGetConfigAttributes(
wrapper->va_display_, va_profile, entrypoint, &attrib, 1);
ASSERT_EQ(va_res, VA_STATUS_SUCCESS);
@@ -448,7 +510,7 @@ TEST_F(VaapiTest, LowQualityEncodingSetting) {
ASSERT_TRUE(wrapper->CreateContext(gfx::Size(640, 368)));
ASSERT_EQ(wrapper->pending_va_buffers_.size(), 1u);
{
- base::AutoLockMaybe auto_lock(wrapper->va_lock_);
+ base::AutoLockMaybe auto_lock(wrapper->va_lock_.get());
ScopedVABufferMapping mapping(wrapper->va_lock_, wrapper->va_display_,
wrapper->pending_va_buffers_.front());
ASSERT_TRUE(mapping.IsValid());
@@ -669,12 +731,10 @@ TEST_P(VaapiMinigbmTest, AllocateAndCompareWithMinigbm) {
}
gfx::Size minimum_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMinResolution(va_profile,
- &minimum_supported_size));
gfx::Size maximum_supported_size;
- ASSERT_TRUE(VaapiWrapper::GetDecodeMaxResolution(va_profile,
- &maximum_supported_size));
-
+ ASSERT_TRUE(VaapiWrapper::GetSupportedResolutions(
+ va_profile, VaapiWrapper::CodecMode::kDecode, minimum_supported_size,
+ maximum_supported_size));
if (resolution.width() < minimum_supported_size.width() ||
resolution.height() < minimum_supported_size.height() ||
resolution.width() > maximum_supported_size.width() ||
@@ -704,7 +764,7 @@ TEST_P(VaapiMinigbmTest, AllocateAndCompareWithMinigbm) {
// Request the underlying DRM metadata for |scoped_va_surface|.
VADRMPRIMESurfaceDescriptor va_descriptor{};
{
- base::AutoLockMaybe auto_lock(wrapper->va_lock_);
+ base::AutoLockMaybe auto_lock(wrapper->va_lock_.get());
VAStatus va_res =
vaSyncSurface(wrapper->va_display_, scoped_va_surface->id());
ASSERT_EQ(va_res, VA_STATUS_SUCCESS);
@@ -738,8 +798,19 @@ TEST_P(VaapiMinigbmTest, AllocateAndCompareWithMinigbm) {
EXPECT_GE(va_descriptor.objects[1].size,
base::checked_cast<uint32_t>(2 * uv_width * uv_height));
}
- const auto expected_drm_modifier =
- backend == VAImplementation::kIntelIHD ? I915_FORMAT_MOD_Y_TILED : 0x0;
+
+ base::AutoLockMaybe auto_lock(wrapper->va_lock_.get());
+ const std::string va_vendor_string
+ = vaQueryVendorString(wrapper->va_display_);
+ uint64_t expected_drm_modifier = DRM_FORMAT_MOD_LINEAR;
+
+ if (backend == VAImplementation::kIntelIHD) {
+ expected_drm_modifier = I915_FORMAT_MOD_Y_TILED;
+ } else if (backend == VAImplementation::kMesaGallium) {
+ if (va_vendor_string.find("STONEY") != std::string::npos) {
+ expected_drm_modifier = DRM_FORMAT_MOD_INVALID;
+ }
+ }
EXPECT_EQ(va_descriptor.objects[0].drm_format_modifier,
expected_drm_modifier);
// TODO(mcasas): |num_layers| actually depends on |va_descriptor.va_fourcc|.
@@ -866,6 +937,18 @@ int main(int argc, char** argv) {
// creates a ScopedFeatureList and multiple concurrent ScopedFeatureLists
// are not allowed.
auto scoped_feature_list = media::CreateScopedFeatureList();
+
+#if defined(USE_OZONE) && BUILDFLAG(IS_LINUX)
+ // Initialize Ozone so that the VADisplayState can decide if we're running
+ // on top of a platform that can deal with VA-API buffers.
+ // TODO(b/230370976): we may no longer need to initialize Ozone since we
+ // don't use it for buffer allocation.
+ ui::OzonePlatform::InitParams params;
+ params.single_process = true;
+ ui::OzonePlatform::InitializeForUI(params);
+ ui::OzonePlatform::InitializeForGPU(params);
+#endif
+
// PreSandboxInitialization() loads and opens the driver, queries its
// capabilities and fills in the VASupportedProfiles.
media::VaapiWrapper::PreSandboxInitialization();
diff --git a/chromium/media/gpu/vaapi/vaapi_utils.cc b/chromium/media/gpu/vaapi/vaapi_utils.cc
index 74cb79f83df..0e57649173b 100644
--- a/chromium/media/gpu/vaapi/vaapi_utils.cc
+++ b/chromium/media/gpu/vaapi/vaapi_utils.cc
@@ -127,7 +127,7 @@ ScopedVABuffer::~ScopedVABuffer() {
if (!va_display_)
return; // Don't call VA-API function in test.
- base::AutoLockMaybe auto_lock(lock_);
+ base::AutoLockMaybe auto_lock(lock_.get());
VAStatus va_res = vaDestroyBuffer(va_display_, va_buffer_id_);
LOG_IF(ERROR, va_res != VA_STATUS_SUCCESS)
<< "Failed to destroy a VA buffer: " << vaErrorStr(va_res);
@@ -163,7 +163,7 @@ ScopedVAImage::ScopedVAImage(base::Lock* lock,
ScopedVAImage::~ScopedVAImage() {
CHECK(sequence_checker_.CalledOnValidSequence());
if (image_->image_id != VA_INVALID_ID) {
- base::AutoLockMaybe auto_lock(lock_);
+ base::AutoLockMaybe auto_lock(lock_.get());
// |va_buffer_| has to be deleted before vaDestroyImage().
va_buffer_.reset();
diff --git a/chromium/media/gpu/vaapi/vaapi_utils.h b/chromium/media/gpu/vaapi/vaapi_utils.h
index c0cb8f0fd5d..1f0e5ac384e 100644
--- a/chromium/media/gpu/vaapi/vaapi_utils.h
+++ b/chromium/media/gpu/vaapi/vaapi_utils.h
@@ -9,6 +9,7 @@
#include "base/callback_forward.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/thread_annotations.h"
#include "ui/gfx/geometry/size.h"
@@ -52,7 +53,7 @@ class ScopedVABufferMapping {
VAStatus Unmap();
private:
- const base::Lock* lock_; // Only for AssertAcquired() calls.
+ raw_ptr<const base::Lock> lock_; // Only for AssertAcquired() calls.
const VADisplay va_display_;
const VABufferID buffer_id_;
@@ -100,7 +101,7 @@ class ScopedVABuffer {
VABufferType va_buffer_type,
size_t size);
- base::Lock* const lock_;
+ const raw_ptr<base::Lock> lock_;
const VADisplay va_display_ GUARDED_BY(lock_);
base::SequenceCheckerImpl sequence_checker_;
@@ -142,7 +143,7 @@ class ScopedVAImage {
}
private:
- base::Lock* lock_;
+ raw_ptr<base::Lock> lock_;
const VADisplay va_display_ GUARDED_BY(lock_);
std::unique_ptr<VAImage> image_;
std::unique_ptr<ScopedVABufferMapping> va_buffer_;
diff --git a/chromium/media/gpu/vaapi/vaapi_utils_unittest.cc b/chromium/media/gpu/vaapi/vaapi_utils_unittest.cc
index e50ea2ae979..a06db699e14 100644
--- a/chromium/media/gpu/vaapi/vaapi_utils_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_utils_unittest.cc
@@ -91,7 +91,7 @@ TEST_F(VaapiUtilsTest, ScopedVAImage) {
// surface format. However when context has not been executed the output
// image format seems to default to I420. https://crbug.com/828119
VAImageFormat va_image_format = kImageFormatI420;
- base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_);
+ base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
scoped_image = std::make_unique<ScopedVAImage>(
vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, va_surfaces[0],
&va_image_format, coded_size);
@@ -116,7 +116,7 @@ TEST_F(VaapiUtilsTest, BadScopedVAImage) {
std::unique_ptr<ScopedVAImage> scoped_image;
{
VAImageFormat va_image_format = kImageFormatI420;
- base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_);
+ base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
scoped_image = std::make_unique<ScopedVAImage>(
vaapi_wrapper_->va_lock_, vaapi_wrapper_->va_display_, va_surfaces[0],
&va_image_format, coded_size);
@@ -134,7 +134,7 @@ TEST_F(VaapiUtilsTest, BadScopedVAImage) {
// This test exercises creation of a ScopedVABufferMapping with bad VABufferIDs.
TEST_F(VaapiUtilsTest, BadScopedVABufferMapping) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
- base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_);
+ base::AutoLockMaybe auto_lock(vaapi_wrapper_->va_lock_.get());
// A ScopedVABufferMapping with a VA_INVALID_ID VABufferID is DCHECK()ed.
EXPECT_DCHECK_DEATH(std::make_unique<ScopedVABufferMapping>(
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
index 3a07fa21be8..bf791d813b4 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -44,7 +44,6 @@
#include "media/gpu/vp8_decoder.h"
#include "media/gpu/vp9_decoder.h"
#include "media/video/picture.h"
-#include "ui/gl/gl_image.h"
namespace media {
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
index bc5bc19b45c..3444ebf2d6c 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
@@ -19,6 +19,7 @@
#include "base/containers/queue.h"
#include "base/containers/small_map.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
@@ -259,7 +260,7 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
// TODO(crbug.com/1022246): Instead of having the raw pointer here, getting
// the pointer from AcceleratedVideoDecoder.
- VaapiVideoDecoderDelegate* decoder_delegate_ = nullptr;
+ raw_ptr<VaapiVideoDecoderDelegate> decoder_delegate_ = nullptr;
// Filled in during Initialize().
BufferAllocationMode buffer_allocation_mode_;
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
index 0cd77859cbe..9f7c69007f5 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h"
@@ -63,6 +64,7 @@ class MockAcceleratedVideoDecoder : public AcceleratedVideoDecoder {
MOCK_CONST_METHOD0(GetPicSize, gfx::Size());
MOCK_CONST_METHOD0(GetProfile, VideoCodecProfile());
MOCK_CONST_METHOD0(GetBitDepth, uint8_t());
+ MOCK_CONST_METHOD0(GetChromaSampling, VideoChromaSampling());
MOCK_CONST_METHOD0(GetVisibleRect, gfx::Rect());
MOCK_CONST_METHOD0(GetRequiredNumOfPictures, size_t());
MOCK_CONST_METHOD0(GetNumReferenceFrames, size_t());
@@ -397,8 +399,8 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
base::Thread decoder_thread_;
// Ownership passed to |vda_|, but we retain a pointer to it for MOCK checks.
- MockAcceleratedVideoDecoder* mock_decoder_;
- MockVaapiPictureFactory* mock_vaapi_picture_factory_;
+ raw_ptr<MockAcceleratedVideoDecoder> mock_decoder_;
+ raw_ptr<MockVaapiPictureFactory> mock_vaapi_picture_factory_;
scoped_refptr<MockVaapiWrapper> mock_vaapi_wrapper_;
scoped_refptr<MockVaapiWrapper> mock_vpp_vaapi_wrapper_;
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decoder.cc b/chromium/media/gpu/vaapi/vaapi_video_decoder.cc
index 0ef047f707d..551b8aa70b6 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decoder.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -619,9 +619,11 @@ void VaapiVideoDecoder::ApplyResolutionChange() {
// NOTE: Only use this for protected content as other requirements for using
// it are tied to protected content.
#if BUILDFLAG(IS_CHROMEOS_ASH)
- chromeos::ChromeOsCdmFactory::GetScreenResolutions(BindToCurrentLoop(
- base::BindOnce(&VaapiVideoDecoder::ApplyResolutionChangeWithScreenSizes,
- weak_this_)));
+ cdm_context_ref_->GetCdmContext()
+ ->GetChromeOsCdmContext()
+ ->GetScreenResolutions(BindToCurrentLoop(base::BindOnce(
+ &VaapiVideoDecoder::ApplyResolutionChangeWithScreenSizes,
+ weak_this_)));
return;
#endif
}
@@ -944,13 +946,13 @@ bool VaapiVideoDecoder::NeedsTranscryption() {
DCHECK(state_ == State::kWaitingForInput);
#if BUILDFLAG(IS_CHROMEOS_ASH)
- // We do not need to invoke transcryption if this is coming from ARC since
- // that will already be done.
+ // We do not need to invoke transcryption if this is coming from a remote CDM
+ // since it will already have been done.
if (cdm_context_ref_ &&
cdm_context_ref_->GetCdmContext()->GetChromeOsCdmContext() &&
cdm_context_ref_->GetCdmContext()
->GetChromeOsCdmContext()
- ->UsingArcCdm()) {
+ ->IsRemoteCdm()) {
return false;
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decoder.h b/chromium/media/gpu/vaapi/vaapi_video_decoder.h
index 7c2e40a4578..a3ecd231fbd 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decoder.h
+++ b/chromium/media/gpu/vaapi/vaapi_video_decoder.h
@@ -15,6 +15,7 @@
#include "base/containers/lru_cache.h"
#include "base/containers/queue.h"
#include "base/containers/small_map.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -268,7 +269,7 @@ class VaapiVideoDecoder : public VideoDecoderMixin,
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
// TODO(crbug.com/1022246): Instead of having the raw pointer here, getting
// the pointer from AcceleratedVideoDecoder.
- VaapiVideoDecoderDelegate* decoder_delegate_ = nullptr;
+ raw_ptr<VaapiVideoDecoderDelegate> decoder_delegate_ = nullptr;
// This is used on AMD protected content implementations to indicate that the
// DecoderBuffers we receive have been transcrypted and need special handling.
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.cc b/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
index bc5888edf73..4e2dc91c33a 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
@@ -97,19 +97,11 @@ bool VaapiVideoDecoderDelegate::HasInitiatedProtectedRecovery() {
bool VaapiVideoDecoderDelegate::SetDecryptConfig(
std::unique_ptr<DecryptConfig> decrypt_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // It is possible to switch between clear and encrypted (and vice versa), but
- // we should not be changing encryption schemes across encrypted portions.
+ // It is possible to switch between clear and encrypted (and vice versa).
if (!decrypt_config)
return true;
- // TODO(jkardatzke): Handle changing encryption modes midstream, the latest
- // OEMCrypto spec allows this, although we won't hit it in reality for now.
- // Check to make sure they are compatible.
- if (!transcryption_ &&
- decrypt_config->encryption_scheme() != encryption_scheme_) {
- LOG(ERROR) << "Cannot change encryption modes midstream";
- return false;
- }
decrypt_config_ = std::move(decrypt_config);
+ encryption_scheme_ = decrypt_config_->encryption_scheme();
return true;
}
@@ -136,7 +128,7 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
}
// We need to start the creation of this, first part requires getting the
// hw config data from the daemon.
- chromeos::ChromeOsCdmFactory::GetHwConfigData(BindToCurrentLoop(
+ chromeos_cdm_context_->GetHwConfigData(BindToCurrentLoop(
base::BindOnce(&VaapiVideoDecoderDelegate::OnGetHwConfigData,
weak_factory_.GetWeakPtr())));
protected_session_state_ = ProtectedSessionState::kInProcess;
@@ -180,6 +172,18 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
return protected_session_state_;
}
+ // On Intel if we change encryption modes after we have started decrypting
+ // then we need to rebuild the protected session.
+ if (!IsTranscrypted() &&
+ last_used_encryption_scheme_ != EncryptionScheme::kUnencrypted &&
+ last_used_encryption_scheme_ != encryption_scheme_) {
+ LOG(WARNING) << "Forcing rebuild since encryption mode changed midstream";
+ RecoverProtectedSession();
+ last_used_encryption_scheme_ = EncryptionScheme::kUnencrypted;
+ return protected_session_state_;
+ }
+
+ last_used_encryption_scheme_ = encryption_scheme_;
DCHECK(decrypt_config_);
// We also need to make sure we have the key data for the active
// DecryptConfig now that the protected session exists.
@@ -214,7 +218,11 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
}
crypto_params->num_segments += subsamples.size();
- if (decrypt_config_->HasPattern()) {
+ // If the pattern has no skip blocks, which means the entire thing is
+ // encrypted, then don't specify a pattern at all as Intel's implementation
+ // does not expect that.
+ if (decrypt_config_->HasPattern() &&
+ decrypt_config_->encryption_pattern()->skip_byte_block()) {
crypto_params->blocks_stripe_encrypted =
decrypt_config_->encryption_pattern()->crypt_byte_block();
crypto_params->blocks_stripe_clear =
@@ -267,11 +275,7 @@ bool VaapiVideoDecoderDelegate::NeedsProtectedSessionRecovery() {
return false;
}
- LOG(WARNING) << "Protected session loss detected, initiating recovery";
- protected_session_state_ = ProtectedSessionState::kNeedsRecovery;
- hw_key_data_map_.clear();
- hw_identifier_.clear();
- vaapi_wrapper_->DestroyProtectedSession();
+ RecoverProtectedSession();
return true;
}
@@ -347,4 +351,22 @@ void VaapiVideoDecoderDelegate::OnGetHwKeyData(
on_protected_session_update_cb_.Run(true);
}
+void VaapiVideoDecoderDelegate::RecoverProtectedSession() {
+ LOG(WARNING) << "Protected session loss detected, initiating recovery";
+ protected_session_state_ = ProtectedSessionState::kNeedsRecovery;
+ hw_key_data_map_.clear();
+ hw_identifier_.clear();
+ vaapi_wrapper_->DestroyProtectedSession();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ if (chromeos_cdm_context_ && chromeos_cdm_context_->UsingArcCdm()) {
+ // The ARC decoder doesn't handle the WaitingCB that'll get invoked so we
+ // need to trigger a protected update ourselves in order to get decoding
+ // running again.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindRepeating(on_protected_session_update_cb_, true));
+ }
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+}
+
} // namespace media
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.h b/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.h
index ecec665c3e8..075ccf28987 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.h
+++ b/chromium/media/gpu/vaapi/vaapi_video_decoder_delegate.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
@@ -132,7 +133,7 @@ class VaapiVideoDecoderDelegate {
std::string GetDecryptKeyId() const;
// Both owned by caller.
- DecodeSurfaceHandler<VASurface>* const vaapi_dec_;
+ const raw_ptr<DecodeSurfaceHandler<VASurface>> vaapi_dec_;
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -142,13 +143,15 @@ class VaapiVideoDecoderDelegate {
void OnGetHwKeyData(const std::string& key_id,
Decryptor::Status status,
const std::vector<uint8_t>& key_data);
+ void RecoverProtectedSession();
// All members below pertain to protected content playback.
ProtectedSessionUpdateCB on_protected_session_update_cb_;
+ EncryptionScheme encryption_scheme_;
#if BUILDFLAG(IS_CHROMEOS_ASH)
chromeos::ChromeOsCdmContext* chromeos_cdm_context_{nullptr}; // Not owned.
+ EncryptionScheme last_used_encryption_scheme_{EncryptionScheme::kUnencrypted};
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
- EncryptionScheme encryption_scheme_;
ProtectedSessionState protected_session_state_;
std::unique_ptr<DecryptConfig> decrypt_config_;
std::vector<uint8_t> hw_identifier_;
diff --git a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
index 0d571e9c985..c97d6952f1c 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -6,8 +6,6 @@
#include <string.h>
#include <va/va.h>
-#include <va/va_enc_h264.h>
-#include <va/va_enc_vp8.h>
#include <algorithm>
#include <memory>
@@ -70,33 +68,6 @@ constexpr size_t kMinNumFramesInFlight = 4;
// VASurfaceIDs internal format.
constexpr unsigned int kVaSurfaceFormat = VA_RT_FORMAT_YUV420;
-void FillVAEncRateControlParams(
- uint32_t bps,
- uint32_t window_size,
- uint32_t initial_qp,
- uint32_t min_qp,
- uint32_t max_qp,
- uint32_t framerate,
- uint32_t buffer_size,
- VAEncMiscParameterRateControl& rate_control_param,
- VAEncMiscParameterFrameRate& framerate_param,
- VAEncMiscParameterHRD& hrd_param) {
- memset(&rate_control_param, 0, sizeof(rate_control_param));
- rate_control_param.bits_per_second = bps;
- rate_control_param.window_size = window_size;
- rate_control_param.initial_qp = initial_qp;
- rate_control_param.min_qp = min_qp;
- rate_control_param.max_qp = max_qp;
- rate_control_param.rc_flags.bits.disable_frame_skip = true;
-
- memset(&framerate_param, 0, sizeof(framerate_param));
- framerate_param.framerate = framerate;
-
- memset(&hrd_param, 0, sizeof(hrd_param));
- hrd_param.buffer_size = buffer_size;
- hrd_param.initial_buffer_fullness = buffer_size / 2;
-}
-
// Creates one |encode_size| ScopedVASurface using |vaapi_wrapper|.
std::unique_ptr<ScopedVASurface> CreateScopedSurface(
VaapiWrapper& vaapi_wrapper,
@@ -108,6 +79,7 @@ std::unique_ptr<ScopedVASurface> CreateScopedSurface(
/*va_fourcc=*/absl::nullopt);
return surfaces.empty() ? nullptr : std::move(surfaces.front());
}
+
} // namespace
struct VaapiVideoEncodeAccelerator::InputFrameRef {
@@ -249,14 +221,23 @@ bool VaapiVideoEncodeAccelerator::Initialize(
return false;
}
- switch (config.input_format) {
- case PIXEL_FORMAT_I420:
- case PIXEL_FORMAT_NV12:
- break;
- default:
+ if (config.bitrate.mode() == Bitrate::Mode::kVariable) {
+ if (!base::FeatureList::IsEnabled(kChromeOSHWVBREncoding)) {
+ MEDIA_LOG(ERROR, media_log.get()) << "Variable bitrate is disabled.";
+ return false;
+ }
+ if (codec != VideoCodec::kH264) {
MEDIA_LOG(ERROR, media_log.get())
- << "Unsupported input format: " << config.input_format;
+ << "Variable bitrate is only supported with H264 encoding.";
return false;
+ }
+ }
+
+ if (config.input_format != PIXEL_FORMAT_I420 &&
+ config.input_format != PIXEL_FORMAT_NV12) {
+ MEDIA_LOG(ERROR, media_log.get())
+ << "Unsupported input format: " << config.input_format;
+ return false;
}
if (config.storage_type.value_or(Config::StorageType::kShmem) ==
@@ -318,10 +299,23 @@ void VaapiVideoEncodeAccelerator::InitializeTask(const Config& config) {
output_codec_ = VideoCodecProfileToVideoCodec(config.output_profile);
DCHECK_EQ(IsConfiguredForTesting(), !!vaapi_wrapper_);
if (!IsConfiguredForTesting()) {
- const auto mode =
- (output_codec_ == VideoCodec::kVP9 || output_codec_ == VideoCodec::kVP8)
- ? VaapiWrapper::kEncodeConstantQuantizationParameter
- : VaapiWrapper::kEncodeConstantBitrate;
+ VaapiWrapper::CodecMode mode;
+ switch (output_codec_) {
+ case VideoCodec::kH264:
+ mode = config.bitrate.mode() == Bitrate::Mode::kConstant
+ ? VaapiWrapper::kEncodeConstantBitrate
+ : VaapiWrapper::kEncodeVariableBitrate;
+ break;
+ case VideoCodec::kVP8:
+ case VideoCodec::kVP9:
+ mode = VaapiWrapper::kEncodeConstantQuantizationParameter;
+ break;
+ default:
+ NOTIFY_ERROR(kInvalidArgumentError,
+ "Unsupported codec: " + GetCodecName(output_codec_));
+ return;
+ }
+
vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
mode, config.output_profile, EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
@@ -974,13 +968,6 @@ void VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask(
void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange(
const Bitrate& bitrate,
uint32_t framerate) {
- // If this is changed to use variable bitrate encoding, change the mode check
- // to check that the mode matches the current mode.
- if (bitrate.mode() != Bitrate::Mode::kConstant) {
- VLOGF(1) << "Failed to update rates due to invalid bitrate mode.";
- return;
- }
-
DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_);
VideoBitrateAllocation allocation;
@@ -1078,7 +1065,6 @@ void VaapiVideoEncodeAccelerator::DestroyTask() {
vaapi_wrapper_->DestroyContext();
available_encode_surfaces_.clear();
- available_va_buffer_ids_.clear();
if (vpp_vaapi_wrapper_)
vpp_vaapi_wrapper_->DestroyContext();
diff --git a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.h b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.h
index a00720a170f..13a062f2a27 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.h
+++ b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator.h
@@ -278,9 +278,6 @@ class MEDIA_GPU_EXPORT VaapiVideoEncodeAccelerator
// indexed by a layer resolution.
EncodeSurfacesCountMap encode_surfaces_count_;
- // VA buffers for coded frames.
- std::vector<VABufferID> available_va_buffer_ids_;
-
// Queue of input frames to be encoded.
base::queue<std::unique_ptr<InputFrameRef>> input_queue_;
diff --git a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
index 71a48b750fc..e73e47997af 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/bits.h"
+#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h"
@@ -650,7 +651,7 @@ class VaapiVideoEncodeAcceleratorTest
std::unique_ptr<VideoEncodeAccelerator> encoder_;
scoped_refptr<MockVaapiWrapper> mock_vaapi_wrapper_;
scoped_refptr<MockVaapiWrapper> mock_vpp_vaapi_wrapper_;
- MockVP9VaapiVideoEncoderDelegate* mock_encoder_ = nullptr;
+ raw_ptr<MockVP9VaapiVideoEncoderDelegate> mock_encoder_ = nullptr;
};
struct VaapiVideoEncodeAcceleratorTestParam {
diff --git a/chromium/media/gpu/vaapi/vaapi_webp_decoder.cc b/chromium/media/gpu/vaapi/vaapi_webp_decoder.cc
index 3e8dfab111a..afb71b35daa 100644
--- a/chromium/media/gpu/vaapi/vaapi_webp_decoder.cc
+++ b/chromium/media/gpu/vaapi/vaapi_webp_decoder.cc
@@ -45,9 +45,11 @@ static bool IsVaapiSupportedWebP(const Vp8FrameHeader& webp_header) {
}
gfx::Size min_webp_resolution;
- if (!VaapiWrapper::GetDecodeMinResolution(kWebPVAProfile,
- &min_webp_resolution)) {
- DLOG(ERROR) << "Could not get the minimum resolution";
+ gfx::Size max_webp_resolution;
+ if (!VaapiWrapper::GetSupportedResolutions(
+ kWebPVAProfile, VaapiWrapper::CodecMode::kDecode, min_webp_resolution,
+ max_webp_resolution)) {
+ DLOG(ERROR) << "Could not get the minimum and maximum resolutions";
return false;
}
if (webp_size.width() < min_webp_resolution.width() ||
@@ -57,13 +59,6 @@ static bool IsVaapiSupportedWebP(const Vp8FrameHeader& webp_header) {
<< min_webp_resolution.ToString();
return false;
}
-
- gfx::Size max_webp_resolution;
- if (!VaapiWrapper::GetDecodeMaxResolution(kWebPVAProfile,
- &max_webp_resolution)) {
- DLOG(ERROR) << "Could not get the maximum resolution";
- return false;
- }
if (webp_size.width() > max_webp_resolution.width() ||
webp_size.height() > max_webp_resolution.height()) {
DLOG(ERROR) << "VAAPI doesn't support size " << webp_size.ToString()
diff --git a/chromium/media/gpu/vaapi/vaapi_webp_decoder_unittest.cc b/chromium/media/gpu/vaapi/vaapi_webp_decoder_unittest.cc
index 9119275f2ae..49342d29c97 100644
--- a/chromium/media/gpu/vaapi/vaapi_webp_decoder_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_webp_decoder_unittest.cc
@@ -28,7 +28,7 @@
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include "media/parsers/vp8_parser.h"
#include "media/parsers/webp_parser.h"
-#include "third_party/libwebp/src/webp/decode.h"
+#include "third_party/libwebp/src/src/webp/decode.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/media/gpu/vaapi/vaapi_wrapper.cc b/chromium/media/gpu/vaapi/vaapi_wrapper.cc
index cdbd4fb2c73..dc1b731ea25 100644
--- a/chromium/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/chromium/media/gpu/vaapi/vaapi_wrapper.cc
@@ -5,6 +5,7 @@
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include <dlfcn.h>
+#include <drm_fourcc.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
@@ -42,6 +43,7 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/base/media_switches.h"
+#include "media/base/video_codecs.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/gpu/macros.h"
@@ -53,6 +55,7 @@
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/linux/native_pixmap_dmabuf.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/native_pixmap_handle.h"
@@ -258,6 +261,152 @@ bool UseGlobalVaapiLock(media::VAImplementation implementation_type) {
base::FeatureList::IsEnabled(media::kGlobalVaapiLock);
}
+bool FillVADRMPRIMESurfaceDescriptor(const gfx::NativePixmap& pixmap,
+ VADRMPRIMESurfaceDescriptor& descriptor) {
+ memset(&descriptor, 0, sizeof(VADRMPRIMESurfaceDescriptor));
+
+ const gfx::BufferFormat buffer_format = pixmap.GetBufferFormat();
+ const uint32_t va_fourcc = BufferFormatToVAFourCC(buffer_format);
+ DCHECK(va_fourcc);
+
+ const gfx::Size size = pixmap.GetBufferSize();
+ const size_t num_planes = pixmap.GetNumberOfPlanes();
+ const int drm_fourcc = ui::GetFourCCFormatFromBufferFormat(buffer_format);
+ if (drm_fourcc == DRM_FORMAT_INVALID) {
+ LOG(ERROR) << "Failed to get the DRM format from the buffer format";
+ return false;
+ }
+ if (num_planes > std::size(descriptor.objects)) {
+ LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes
+ << " but the maximum number is "
+ << std::size(descriptor.objects);
+ return false;
+ }
+ static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers) ==
+ std::size(VADRMPRIMESurfaceDescriptor{}.objects));
+ static_assert(
+ std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].object_index) ==
+ std::size(VADRMPRIMESurfaceDescriptor{}.objects));
+ static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].offset) ==
+ std::size(VADRMPRIMESurfaceDescriptor{}.objects));
+ static_assert(std::size(VADRMPRIMESurfaceDescriptor{}.layers[0].pitch) ==
+ std::size(VADRMPRIMESurfaceDescriptor{}.objects));
+
+ descriptor.fourcc = va_fourcc;
+ descriptor.width = base::checked_cast<uint32_t>(size.width());
+ descriptor.height = base::checked_cast<uint32_t>(size.height());
+
+ // We can pass the planes as separate layers or all in one layer. The choice
+ // of doing the latter was arbitrary.
+ descriptor.num_layers = 1u;
+ descriptor.layers[0].drm_format = base::checked_cast<uint32_t>(drm_fourcc);
+ descriptor.layers[0].num_planes = base::checked_cast<uint32_t>(num_planes);
+
+ descriptor.num_objects = base::checked_cast<uint32_t>(num_planes);
+ for (size_t i = 0u; i < num_planes; i++) {
+ const int dma_buf_fd = pixmap.GetDmaBufFd(i);
+ if (dma_buf_fd < 0) {
+ LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
+ return false;
+ }
+ const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END);
+ if (data_size == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to get the size of the dma-buf";
+ return false;
+ }
+ if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to reset the file offset of the dma-buf";
+ return false;
+ }
+
+ descriptor.objects[i].fd = dma_buf_fd;
+ descriptor.objects[i].size = base::checked_cast<uint32_t>(data_size);
+ descriptor.objects[i].drm_format_modifier =
+ pixmap.GetBufferFormatModifier();
+
+ descriptor.layers[0].object_index[i] = base::checked_cast<uint32_t>(i);
+ if (!base::IsValueInRangeForNumericType<uint32_t>(
+ pixmap.GetDmaBufOffset(i))) {
+ LOG(ERROR) << "The offset for plane " << i << " is out-of-range";
+ return false;
+ }
+ descriptor.layers[0].offset[i] =
+ base::checked_cast<uint32_t>(pixmap.GetDmaBufOffset(i));
+ descriptor.layers[0].pitch[i] = pixmap.GetDmaBufPitch(i);
+ }
+
+ return true;
+}
+
+struct VASurfaceAttribExternalBuffersAndFD {
+ VASurfaceAttribExternalBuffers va_attrib_extbuf;
+ uintptr_t fd;
+};
+
+bool FillVASurfaceAttribExternalBuffers(
+ const gfx::NativePixmap& pixmap,
+ VASurfaceAttribExternalBuffersAndFD& va_attrib_extbuf_and_fd) {
+ VASurfaceAttribExternalBuffers& va_attrib_extbuf =
+ va_attrib_extbuf_and_fd.va_attrib_extbuf;
+ memset(&va_attrib_extbuf_and_fd, 0,
+ sizeof(VASurfaceAttribExternalBuffersAndFD));
+
+ const uint32_t va_fourcc = BufferFormatToVAFourCC(pixmap.GetBufferFormat());
+ DCHECK(va_fourcc);
+
+ const gfx::Size size = pixmap.GetBufferSize();
+ const size_t num_planes = pixmap.GetNumberOfPlanes();
+
+ va_attrib_extbuf.pixel_format = va_fourcc;
+ va_attrib_extbuf.width = base::checked_cast<uint32_t>(size.width());
+ va_attrib_extbuf.height = base::checked_cast<uint32_t>(size.height());
+
+ static_assert(std::size(VASurfaceAttribExternalBuffers{}.pitches) ==
+ std::size(VASurfaceAttribExternalBuffers{}.offsets));
+ if (num_planes > std::size(va_attrib_extbuf.pitches)) {
+ LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes
+ << " but the maximum number is "
+ << std::size(va_attrib_extbuf.pitches);
+ return false;
+ }
+ for (size_t i = 0; i < num_planes; ++i) {
+ va_attrib_extbuf.pitches[i] = pixmap.GetDmaBufPitch(i);
+ va_attrib_extbuf.offsets[i] =
+ base::checked_cast<uint32_t>(pixmap.GetDmaBufOffset(i));
+ DVLOG(4) << "plane " << i << ": pitch: " << va_attrib_extbuf.pitches[i]
+ << " offset: " << va_attrib_extbuf.offsets[i];
+ }
+ va_attrib_extbuf.num_planes = base::checked_cast<uint32_t>(num_planes);
+
+ const int dma_buf_fd = pixmap.GetDmaBufFd(0);
+ if (dma_buf_fd < 0) {
+ LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
+ return false;
+ }
+ const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END);
+ if (data_size == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to get the size of the dma-buf";
+ return false;
+ }
+ if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) {
+ PLOG(ERROR) << "Failed to reset the file offset of the dma-buf";
+ return false;
+ }
+ // If the data size doesn't fit in a uint32_t, we probably have bigger
+ // problems.
+ va_attrib_extbuf.data_size = base::checked_cast<uint32_t>(data_size);
+
+ // We only have to pass the first file descriptor to a driver. A VA-API driver
+ // shall create a VASurface from the single fd correctly.
+ va_attrib_extbuf_and_fd.fd = base::checked_cast<uintptr_t>(dma_buf_fd);
+ va_attrib_extbuf.buffers = &va_attrib_extbuf_and_fd.fd;
+ va_attrib_extbuf.num_buffers = 1u;
+
+ DCHECK_EQ(va_attrib_extbuf.flags, 0u);
+ DCHECK_EQ(va_attrib_extbuf.private_data, nullptr);
+ return true;
+}
+
} // namespace
namespace media {
@@ -448,6 +597,7 @@ const ProfileCodecMap& GetProfileCodecMap() {
// {AV1PROFILE_PROFILE_HIGH, VAProfileAV1Profile1},
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
{HEVCPROFILE_MAIN, VAProfileHEVCMain},
+ {HEVCPROFILE_MAIN_STILL_PICTURE, VAProfileHEVCMain},
{HEVCPROFILE_MAIN10, VAProfileHEVCMain10},
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
});
@@ -963,6 +1113,10 @@ class VASupportedProfiles {
// Determines if |mode| supports |va_profile| (and |va_entrypoint| if defined
// and valid). If so, returns a const pointer to its ProfileInfo, otherwise
// returns nullptr.
+ // TODO(hiroh): If VAEntrypoint is kVAEntrypointInvalid, the default entry
+ // point acquired by GetDefaultVaEntryPoint() is used. If the default entry
+ // point is not supported, the earlier supported entrypoint in
+ // |kAllowedEntryPopints| is used.
const ProfileInfo* IsProfileSupported(
VaapiWrapper::CodecMode mode,
VAProfile va_profile,
@@ -1433,6 +1587,24 @@ bool IsLowPowerEncSupported(VAProfile va_profile) {
return false;
}
+bool IsVBREncodingSupported(VAProfile va_profile) {
+ if (!base::FeatureList::IsEnabled(kChromeOSHWVBREncoding))
+ return false;
+
+ auto mode = VaapiWrapper::CodecMode::kCodecModeMax;
+ switch (va_profile) {
+ case VAProfileH264ConstrainedBaseline:
+ case VAProfileH264Main:
+ case VAProfileH264High:
+ mode = VaapiWrapper::CodecMode::kEncodeVariableBitrate;
+ break;
+ default:
+ return false;
+ }
+
+ return VASupportedProfiles::Get().IsProfileSupported(mode, va_profile);
+}
+
} // namespace
NativePixmapAndSizeInfo::NativePixmapAndSizeInfo() = default;
@@ -1550,8 +1722,13 @@ VaapiWrapper::GetSupportedEncodeProfiles() {
constexpr int kMaxEncoderFramerate = 30;
profile.max_framerate_numerator = kMaxEncoderFramerate;
profile.max_framerate_denominator = 1;
- // TODO(b/193680666): remove hard-coding when VBR is supported
profile.rate_control_modes = media::VideoEncodeAccelerator::kConstantMode;
+ // This code assumes that the resolutions are the same between CBR and VBR.
+ // This is checked in a test in vaapi_unittest.cc: VbrAndCbrResolutionsMatch
+ if (IsVBREncodingSupported(va_profile)) {
+ profile.rate_control_modes |=
+ media::VideoEncodeAccelerator::kVariableMode;
+ }
profile.scalability_modes =
GetSupportedScalabilityModes(media_profile, va_profile);
profiles.push_back(profile);
@@ -1616,26 +1793,18 @@ bool VaapiWrapper::IsDecodingSupportedForInternalFormat(
}
// static
-bool VaapiWrapper::GetDecodeMinResolution(VAProfile va_profile,
- gfx::Size* min_size) {
+bool VaapiWrapper::GetSupportedResolutions(VAProfile va_profile,
+ CodecMode codec_mode,
+ gfx::Size& min_size,
+ gfx::Size& max_size) {
const VASupportedProfiles::ProfileInfo* profile_info =
- VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile);
- if (!profile_info)
+ VASupportedProfiles::Get().IsProfileSupported(codec_mode, va_profile);
+ if (!profile_info || profile_info->max_resolution.IsEmpty())
return false;
- *min_size = gfx::Size(std::max(1, profile_info->min_resolution.width()),
- std::max(1, profile_info->min_resolution.height()));
- return true;
-}
-// static
-bool VaapiWrapper::GetDecodeMaxResolution(VAProfile va_profile,
- gfx::Size* max_size) {
- const VASupportedProfiles::ProfileInfo* profile_info =
- VASupportedProfiles::Get().IsProfileSupported(kDecode, va_profile);
- if (!profile_info)
- return false;
-
- *max_size = profile_info->max_resolution;
+ min_size = gfx::Size(std::max(1, profile_info->min_resolution.width()),
+ std::max(1, profile_info->min_resolution.height()));
+ max_size = profile_info->max_resolution;
return true;
}
@@ -1921,7 +2090,7 @@ bool VaapiWrapper::CreateProtectedSession(
const VAProfile va_profile = VAProfileProtected;
const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode_, va_profile);
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
std::vector<VAConfigAttrib> required_attribs;
if (!GetRequiredAttribs(va_lock_, va_display_, mode_, va_profile,
entrypoint, &required_attribs)) {
@@ -1958,7 +2127,7 @@ bool VaapiWrapper::CreateProtectedSession(
std::unique_ptr<ScopedVABuffer> hw_update = CreateVABuffer(
VAProtectedSessionExecuteBufferType, sizeof(hw_update_buf));
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
constexpr size_t kHwIdentifierMaxSize = 64;
memset(&hw_update_buf, 0, sizeof(hw_update_buf));
hw_update_buf.function_id = VA_TEE_EXEC_TEE_FUNCID_HW_UPDATE;
@@ -2032,7 +2201,7 @@ bool VaapiWrapper::IsProtectedSessionDead(
tee_exec_buf.output.data_size = sizeof(alive);
tee_exec_buf.output.data = &alive;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VABufferID buf_id;
VAStatus va_res = vaCreateBuffer(
va_display_, va_protected_session_id, VAProtectedSessionExecuteBufferType,
@@ -2065,7 +2234,7 @@ void VaapiWrapper::DestroyProtectedSession() {
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (va_protected_session_id_ == VA_INVALID_ID)
return;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res =
vaDestroyProtectedSession(va_display_, va_protected_session_id_);
VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroyProtectedSession);
@@ -2088,7 +2257,7 @@ bool VaapiWrapper::CreateContext(const gfx::Size& size) {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
DVLOG(2) << "Creating context";
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
// vaCreateContext() doesn't really need an array of VASurfaceIDs (see
// https://lists.01.org/pipermail/intel-vaapi-media/2017-July/000052.html and
@@ -2147,65 +2316,34 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap(
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
const gfx::BufferFormat buffer_format = pixmap->GetBufferFormat();
-
- const uint32_t va_fourcc = BufferFormatToVAFourCC(buffer_format);
- if (!va_fourcc) {
+ if (!BufferFormatToVAFourCC(buffer_format)) {
LOG(ERROR) << "Failed to get the VA fourcc from the buffer format";
return nullptr;
}
- const size_t num_planes = pixmap->GetNumberOfPlanes();
-
- // Create a VASurface for a NativePixmap by importing the underlying dmabufs.
- const gfx::Size size = pixmap->GetBufferSize();
- VASurfaceAttribExternalBuffers va_attrib_extbuf{};
- va_attrib_extbuf.pixel_format = va_fourcc;
- va_attrib_extbuf.width = base::checked_cast<uint32_t>(size.width());
- va_attrib_extbuf.height = base::checked_cast<uint32_t>(size.height());
-
- static_assert(std::size(va_attrib_extbuf.pitches) ==
- std::size(va_attrib_extbuf.offsets));
- if (num_planes > std::size(va_attrib_extbuf.pitches)) {
- LOG(ERROR) << "Too many planes in the NativePixmap; got " << num_planes
- << " but the maximum number is "
- << std::size(va_attrib_extbuf.pitches);
- return nullptr;
- }
- for (size_t i = 0; i < num_planes; ++i) {
- va_attrib_extbuf.pitches[i] = pixmap->GetDmaBufPitch(i);
- va_attrib_extbuf.offsets[i] =
- base::checked_cast<uint32_t>(pixmap->GetDmaBufOffset(i));
- DVLOG(4) << "plane " << i << ": pitch: " << va_attrib_extbuf.pitches[i]
- << " offset: " << va_attrib_extbuf.offsets[i];
- }
- va_attrib_extbuf.num_planes = base::checked_cast<uint32_t>(num_planes);
+ // TODO(b/233894465): use the DRM_PRIME_2 API with the Mesa Gallium driver
+ // when AMD supports it.
+ // TODO(b/233924862): use the DRM_PRIME_2 API with protected content.
+ // TODO(b/233929647): use the DRM_PRIME_2 API with the i965 driver.
+ // TODO(b/236746283): remove the kNoModifier check once the modifier is
+ // plumbed for JPEG decoding and encoding.
+ const bool use_drm_prime_2 =
+ GetImplementationType() == VAImplementation::kIntelIHD &&
+ !protected_content &&
+ pixmap->GetBufferFormatModifier() != gfx::NativePixmapHandle::kNoModifier;
+
+ union {
+ VADRMPRIMESurfaceDescriptor descriptor;
+ VASurfaceAttribExternalBuffersAndFD va_attrib_extbuf_and_fd;
+ };
- const int dma_buf_fd = pixmap->GetDmaBufFd(0);
- if (dma_buf_fd < 0) {
- LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
- return nullptr;
- }
- const off_t data_size = lseek(dma_buf_fd, /*offset=*/0, SEEK_END);
- if (data_size == static_cast<off_t>(-1)) {
- PLOG(ERROR) << "Failed to get the size of the dma-buf";
- return nullptr;
- }
- if (lseek(dma_buf_fd, /*offset=*/0, SEEK_SET) == static_cast<off_t>(-1)) {
- PLOG(ERROR) << "Failed to reset the file offset of the dma-buf";
- return nullptr;
+ if (use_drm_prime_2) {
+ if (!FillVADRMPRIMESurfaceDescriptor(*pixmap, descriptor))
+ return nullptr;
+ } else {
+ if (!FillVASurfaceAttribExternalBuffers(*pixmap, va_attrib_extbuf_and_fd))
+ return nullptr;
}
- // If the data size doesn't fit in a uint32_t, we probably have bigger
- // problems.
- va_attrib_extbuf.data_size = base::checked_cast<uint32_t>(data_size);
-
- // We only have to pass the first file descriptor to a driver. A VA-API driver
- // shall create a VASurface from the single fd correctly.
- uintptr_t fd = base::checked_cast<uintptr_t>(dma_buf_fd);
- va_attrib_extbuf.buffers = &fd;
- va_attrib_extbuf.num_buffers = 1u;
-
- DCHECK_EQ(va_attrib_extbuf.flags, 0u);
- DCHECK_EQ(va_attrib_extbuf.private_data, nullptr);
unsigned int va_format =
base::strict_cast<unsigned int>(BufferFormatToVARTFormat(buffer_format));
@@ -2215,10 +2353,12 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap(
}
if (protected_content) {
- if (GetImplementationType() == VAImplementation::kMesaGallium)
+ if (GetImplementationType() == VAImplementation::kMesaGallium) {
va_format |= VA_RT_FORMAT_PROTECTED;
- else
- va_attrib_extbuf.flags = VA_SURFACE_EXTBUF_DESC_PROTECTED;
+ } else {
+ va_attrib_extbuf_and_fd.va_attrib_extbuf.flags =
+ VA_SURFACE_EXTBUF_DESC_PROTECTED;
+ }
}
std::vector<VASurfaceAttrib> va_attribs(2);
@@ -2226,16 +2366,21 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap(
va_attribs[0].type = VASurfaceAttribMemoryType;
va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
va_attribs[0].value.type = VAGenericValueTypeInteger;
- va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+ va_attribs[0].value.value.i = use_drm_prime_2
+ ? VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2
+ : VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor;
va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
va_attribs[1].value.type = VAGenericValueTypePointer;
- va_attribs[1].value.value.p = &va_attrib_extbuf;
+ va_attribs[1].value.value.p = use_drm_prime_2
+ ? static_cast<void*>(&descriptor)
+ : &va_attrib_extbuf_and_fd.va_attrib_extbuf;
+ const gfx::Size size = pixmap->GetBufferSize();
VASurfaceID va_surface_id = VA_INVALID_ID;
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaCreateSurfaces(
va_display_, va_format, base::checked_cast<unsigned int>(size.width()),
base::checked_cast<unsigned int>(size.height()), &va_surface_id, 1,
@@ -2285,7 +2430,7 @@ scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForUserPtr(
VASurfaceID va_surface_id = VA_INVALID_ID;
const unsigned int va_format = VA_RT_FORMAT_RGBP;
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaCreateSurfaces(
va_display_, va_format, base::checked_cast<unsigned int>(size.width()),
base::checked_cast<unsigned int>(size.height()), &va_surface_id, 1,
@@ -2321,7 +2466,7 @@ VaapiWrapper::ExportVASurfaceAsNativePixmapDmaBufUnwrapped(
DCHECK(!va_surface_size.IsEmpty());
VADRMPRIMESurfaceDescriptor descriptor;
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, nullptr);
va_res = vaExportSurfaceHandle(
@@ -2442,7 +2587,7 @@ bool VaapiWrapper::SyncSurface(VASurfaceID va_surface_id) {
sequence_checker_.CalledOnValidSequence());
DCHECK_NE(va_surface_id, VA_INVALID_ID);
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, false);
@@ -2455,7 +2600,7 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBuffer");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
return SubmitBuffer_Locked({va_buffer_type, size, data});
}
@@ -2464,7 +2609,7 @@ bool VaapiWrapper::SubmitBuffers(
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBuffers");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
for (const VABufferDescriptor& va_buffer : va_buffers) {
if (!SubmitBuffer_Locked(va_buffer))
return false;
@@ -2476,7 +2621,7 @@ void VaapiWrapper::DestroyPendingBuffers() {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::DestroyPendingBuffers");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
DestroyPendingBuffers_Locked();
}
@@ -2495,7 +2640,7 @@ void VaapiWrapper::DestroyPendingBuffers_Locked() {
bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
bool result = Execute_Locked(va_surface_id, pending_va_buffers_);
DestroyPendingBuffers_Locked();
return result;
@@ -2509,7 +2654,7 @@ bool VaapiWrapper::MapAndCopyAndExecute(
DCHECK_NE(va_surface_id, VA_INVALID_SURFACE);
TRACE_EVENT0("media,gpu", "VaapiWrapper::MapAndCopyAndExecute");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
std::vector<VABufferID> va_buffer_ids;
for (const auto& va_buffer : va_buffers) {
@@ -2532,7 +2677,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
gfx::Size dest_size) {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, false);
@@ -2555,7 +2700,7 @@ std::unique_ptr<ScopedVAImage> VaapiWrapper::CreateVaImage(
sequence_checker_.CalledOnValidSequence());
std::unique_ptr<ScopedVAImage> scoped_image;
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVASyncSurface, nullptr);
@@ -2572,7 +2717,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface(const VideoFrame& frame,
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::UploadVideoFrameToSurface");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
TRACE_EVENT0("media,gpu", "VaapiWrapper::UploadVideoFrameToSurfaceLocked");
if (frame.visible_rect().origin() != gfx::Point(0, 0)) {
@@ -2634,42 +2779,18 @@ bool VaapiWrapper::UploadVideoFrameToSurface(const VideoFrame& frame,
std::unique_ptr<base::AutoUnlock> auto_unlock;
if (va_lock_)
auto_unlock = std::make_unique<base::AutoUnlock>(*va_lock_);
- switch (frame.format()) {
- case PIXEL_FORMAT_I420:
- ret = libyuv::I420ToNV12(
- frame.data(VideoFrame::kYPlane), frame.stride(VideoFrame::kYPlane),
- frame.data(VideoFrame::kUPlane), frame.stride(VideoFrame::kUPlane),
- frame.data(VideoFrame::kVPlane), frame.stride(VideoFrame::kVPlane),
- image_ptr + image.offsets[0], image.pitches[0],
- image_ptr + image.offsets[1], image.pitches[1],
- visible_size.width(), visible_size.height());
- break;
- case PIXEL_FORMAT_NV12: {
- int uv_width = visible_size.width();
- if (visible_size.width() % 2 != 0 &&
- !base::CheckAdd<int>(visible_size.width(), 1)
- .AssignIfValid(&uv_width)) {
- return false;
- }
-
- int uv_height = 0;
- if (!(base::CheckAdd<int>(visible_size.height(), 1) / 2)
- .AssignIfValid(&uv_height)) {
- return false;
- }
-
- libyuv::CopyPlane(frame.data(VideoFrame::kYPlane),
- frame.stride(VideoFrame::kYPlane),
- image_ptr + image.offsets[0], image.pitches[0],
- visible_size.width(), visible_size.height());
- libyuv::CopyPlane(frame.data(VideoFrame::kUVPlane),
- frame.stride(VideoFrame::kUVPlane),
- image_ptr + image.offsets[1], image.pitches[1],
- uv_width, uv_height);
- } break;
- default:
- LOG(ERROR) << "Unsupported pixel format: " << frame.format();
- return false;
+ if (frame.format() == PIXEL_FORMAT_I420) {
+ ret = libyuv::I420ToNV12(
+ frame.data(VideoFrame::kYPlane), frame.stride(VideoFrame::kYPlane),
+ frame.data(VideoFrame::kUPlane), frame.stride(VideoFrame::kUPlane),
+ frame.data(VideoFrame::kVPlane), frame.stride(VideoFrame::kVPlane),
+ image_ptr + image.offsets[0], image.pitches[0],
+ image_ptr + image.offsets[1], image.pitches[1], visible_size.width(),
+ visible_size.height());
+ } else {
+ LOG(ERROR) << "Unsupported pixel format: "
+ << VideoPixelFormatToString(frame.format());
+ return false;
}
}
if (needs_va_put_image) {
@@ -2686,7 +2807,7 @@ std::unique_ptr<ScopedVABuffer> VaapiWrapper::CreateVABuffer(VABufferType type,
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::CreateVABuffer");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
TRACE_EVENT2("media,gpu", "VaapiWrapper::CreateVABufferLocked", "type", type,
"size", size);
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -2707,7 +2828,7 @@ uint64_t VaapiWrapper::GetEncodedChunkSize(VABufferID buffer_id,
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSize");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
TRACE_EVENT0("media,gpu", "VaapiWrapper::GetEncodedChunkSizeLocked");
// vaSyncSurface() is not necessary on Intel platforms as long as there is a
@@ -2745,7 +2866,7 @@ bool VaapiWrapper::DownloadFromVABuffer(
sequence_checker_.CalledOnValidSequence());
DCHECK(target_ptr);
TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABuffer");
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
TRACE_EVENT0("media,gpu", "VaapiWrapper::DownloadFromVABufferLocked");
// vaSyncSurface() is not necessary on Intel platforms as long as there is a
@@ -2803,7 +2924,7 @@ bool VaapiWrapper::GetVAEncMaxNumOfRefFrames(VideoCodecProfile profile,
VAConfigAttrib attrib;
attrib.type = VAConfigAttribEncMaxRefFrames;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAStatus va_res = vaGetConfigAttributes(va_display_, va_profile,
va_entrypoint_, &attrib, 1);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAGetConfigAttributes, false);
@@ -2822,7 +2943,7 @@ bool VaapiWrapper::GetSupportedPackedHeaders(VideoCodecProfile profile,
ProfileToVAProfile(profile, CodecMode::kEncodeConstantBitrate);
VAConfigAttrib attrib{};
attrib.type = VAConfigAttribEncPackedHeaders;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
const VAStatus va_res = vaGetConfigAttributes(va_display_, va_profile,
va_entrypoint_, &attrib, 1);
VA_SUCCESS_OR_RETURN(va_res, VaapiFunctions::kVAGetConfigAttributes, false);
@@ -2836,7 +2957,7 @@ bool VaapiWrapper::GetSupportedPackedHeaders(VideoCodecProfile profile,
bool VaapiWrapper::IsRotationSupported() {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
VAProcPipelineCaps pipeline_caps;
memset(&pipeline_caps, 0, sizeof(pipeline_caps));
VAStatus va_res = vaQueryVideoProcPipelineCaps(va_display_, va_context_id_,
@@ -2864,7 +2985,7 @@ bool VaapiWrapper::BlitSurface(const VASurface& va_surface_src,
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
DCHECK_EQ(mode_, kVideoProcess);
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
// Create a buffer for VPP if it has not been created.
if (!va_buffer_for_vpp_) {
@@ -3045,7 +3166,7 @@ bool VaapiWrapper::Initialize(VAProfile va_profile,
const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode_, va_profile);
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
std::vector<VAConfigAttrib> required_attribs;
if (!GetRequiredAttribs(va_lock_, va_display_, mode_, va_profile, entrypoint,
&required_attribs)) {
@@ -3081,7 +3202,7 @@ void VaapiWrapper::Deinitialize() {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (va_protected_session_id_ != VA_INVALID_ID) {
VAStatus va_res =
@@ -3122,7 +3243,7 @@ bool VaapiWrapper::VaInitialize(
}
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
va_display_ = VADisplayState::Get()->va_display();
DCHECK(va_display_) << "VADisplayState hasn't been properly Initialize()d";
}
@@ -3132,7 +3253,7 @@ bool VaapiWrapper::VaInitialize(
void VaapiWrapper::DestroyContext() {
CHECK(!enforce_sequence_affinity_ ||
sequence_checker_.CalledOnValidSequence());
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
DVLOG(2) << "Destroying context";
if (va_context_id_ != VA_INVALID_ID) {
@@ -3180,7 +3301,7 @@ bool VaapiWrapper::CreateSurfaces(
VAStatus va_res;
{
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
va_res = vaCreateSurfaces(
va_display_, va_format, base::checked_cast<unsigned int>(size.width()),
base::checked_cast<unsigned int>(size.height()), va_surfaces->data(),
@@ -3227,7 +3348,7 @@ VaapiWrapper::CreateScopedVASurfaces(
attribs[1].value.type = VAGenericValueTypeInteger;
attribs[1].value.value.i = base::checked_cast<int32_t>(*va_fourcc);
}
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
std::vector<VASurfaceID> va_surface_ids(num_surfaces, VA_INVALID_ID);
const VAStatus va_res = vaCreateSurfaces(
va_display_, va_rt_format, base::checked_cast<unsigned int>(size.width()),
@@ -3263,7 +3384,7 @@ void VaapiWrapper::DestroySurfaces(std::vector<VASurfaceID> va_surfaces) {
if (va_surfaces.empty())
return;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
const VAStatus va_res =
vaDestroySurfaces(va_display_, va_surfaces.data(), va_surfaces.size());
VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroySurfaces);
@@ -3275,7 +3396,7 @@ void VaapiWrapper::DestroySurface(VASurfaceID va_surface_id) {
if (va_surface_id == VA_INVALID_SURFACE)
return;
DVLOG(3) << __func__ << " " << va_surface_id;
- base::AutoLockMaybe auto_lock(va_lock_);
+ base::AutoLockMaybe auto_lock(va_lock_.get());
const VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1);
VA_LOG_ON_ERROR(va_res, VaapiFunctions::kVADestroySurfaces);
}
diff --git a/chromium/media/gpu/vaapi/vaapi_wrapper.h b/chromium/media/gpu/vaapi/vaapi_wrapper.h
index d6feb85cb35..c59f9798f07 100644
--- a/chromium/media/gpu/vaapi/vaapi_wrapper.h
+++ b/chromium/media/gpu/vaapi/vaapi_wrapper.h
@@ -21,6 +21,7 @@
#include "base/files/file.h"
#include "base/gtest_prod_util.h"
+#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
@@ -208,18 +209,16 @@ class MEDIA_GPU_EXPORT VaapiWrapper
// Returns false if |rt_format| or |va_profile| is not supported for decoding.
static bool IsDecodingSupportedForInternalFormat(VAProfile va_profile,
unsigned int rt_format);
-
- // Gets the minimum surface size allowed for decoding using |va_profile|.
- // Returns true if the size can be obtained, false otherwise. The minimum
- // dimension (width or height) returned is 1. Particularly, if a dimension is
- // not reported by the driver, the dimension is returned as 1.
- static bool GetDecodeMinResolution(VAProfile va_profile, gfx::Size* min_size);
-
- // Gets the maximum surface size allowed for decoding using |va_profile|.
- // Returns true if the size can be obtained, false otherwise. Because of the
- // 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);
+ // Gets the minimum and maximum surface sizes allowed for |va_profile| in
+ // |codec_mode|. Returns true if both sizes can be obtained, false otherwise.
+ // Each dimension in |min_size| will be at least 1 (as long as this method
+ // returns true). Additionally, because of the initialization in
+ // VASupportedProfiles::FillProfileInfo_Locked(), the |max_size| is guaranteed
+ // to not be empty (as long as this method returns true).
+ static bool GetSupportedResolutions(VAProfile va_profile,
+ CodecMode codec_mode,
+ gfx::Size& min_size,
+ gfx::Size& max_size);
// Obtains a suitable FOURCC that can be used in vaCreateImage() +
// vaGetImage(). |rt_format| corresponds to the JPEG's subsampling format.
@@ -628,7 +627,7 @@ class MEDIA_GPU_EXPORT VaapiWrapper
// If using global VA lock, this is a pointer to VADisplayState's member
// |va_lock_|. Guaranteed to be valid for the lifetime of VaapiWrapper.
- base::Lock* va_lock_;
+ raw_ptr<base::Lock> va_lock_;
// VA handles.
// All valid after successful Initialize() and until Deinitialize().
diff --git a/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc b/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
index 2979fa60363..1b0de54c241 100644
--- a/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
+++ b/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
@@ -274,6 +274,11 @@ bool VP8VaapiVideoEncoderDelegate::Initialize(
return false;
}
+ if (config.bitrate.mode() == Bitrate::Mode::kVariable) {
+ DVLOGF(1) << "Invalid configuraiton. VBR is not supported for VP8.";
+ return false;
+ }
+
if (config.HasSpatialLayer()) {
DVLOGF(1) << "Invalid configuration. Spatial layers not supported in VP8";
return false;
@@ -414,6 +419,11 @@ bool VP8VaapiVideoEncoderDelegate::UpdateRates(
uint32_t framerate) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (bitrate_allocation.GetMode() != Bitrate::Mode::kConstant) {
+ DLOG(ERROR) << "VBR is not supported for VP8 but was requested.";
+ return false;
+ }
+
uint32_t bitrate = bitrate_allocation.GetSumBps();
if (bitrate == 0 || framerate == 0)
return false;
diff --git a/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h b/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h
index a67bc6c3e7f..732eebe8667 100644
--- a/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h
+++ b/chromium/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.h
@@ -9,9 +9,9 @@
#include "media/base/video_bitrate_allocation.h"
#include "media/gpu/vaapi/vaapi_video_encoder_delegate.h"
+#include "media/gpu/video_rate_control.h"
#include "media/gpu/vp8_picture.h"
#include "media/gpu/vp8_reference_frame_vector.h"
-#include "media/gpu/vpx_rate_control.h"
#include "media/parsers/vp8_parser.h"
namespace libvpx {
@@ -95,9 +95,9 @@ class VP8VaapiVideoEncoderDelegate : public VaapiVideoEncoderDelegate {
Vp8ReferenceFrameVector reference_frames_;
- using VP8RateControl = VPXRateControl<libvpx::VP8RateControlRtcConfig,
- libvpx::VP8RateControlRTC,
- libvpx::VP8FrameParamsQpRTC>;
+ using VP8RateControl = VideoRateControl<libvpx::VP8RateControlRtcConfig,
+ libvpx::VP8RateControlRTC,
+ libvpx::VP8FrameParamsQpRTC>;
std::unique_ptr<VP8RateControl> rate_ctrl_;
};
diff --git a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
index f2ab04a6105..a58e65942ec 100644
--- a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
+++ b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
@@ -17,8 +17,8 @@
#include "media/gpu/macros.h"
#include "media/gpu/vaapi/vaapi_common.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "media/gpu/video_rate_control.h"
#include "media/gpu/vp9_svc_layers.h"
-#include "media/gpu/vpx_rate_control.h"
#include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
namespace media {
@@ -185,6 +185,11 @@ bool VP9VaapiVideoEncoderDelegate::Initialize(
return false;
}
+ if (config.bitrate.mode() == Bitrate::Mode::kVariable) {
+ DVLOGF(1) << "Invalid configuraiton. VBR is not supported for VP9.";
+ return false;
+ }
+
visible_size_ = config.input_visible_size;
coded_size_ = gfx::Size(base::bits::AlignUp(visible_size_.width(), 16),
base::bits::AlignUp(visible_size_.height(), 16));
@@ -387,6 +392,11 @@ bool VP9VaapiVideoEncoderDelegate::UpdateRates(
uint32_t framerate) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (bitrate_allocation.GetMode() != Bitrate::Mode::kConstant) {
+ DLOG(ERROR) << "VBR is not supported for VP9 but was requested.";
+ return false;
+ }
+
if (bitrate_allocation.GetSumBps() == 0u || framerate == 0)
return false;
diff --git a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
index 3bdac33c0c6..d135b0beea1 100644
--- a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
+++ b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
@@ -12,9 +12,9 @@
#include "media/base/video_bitrate_allocation.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/vaapi/vaapi_video_encoder_delegate.h"
+#include "media/gpu/video_rate_control.h"
#include "media/gpu/vp9_picture.h"
#include "media/gpu/vp9_reference_frame_vector.h"
-#include "media/gpu/vpx_rate_control.h"
namespace libvpx {
struct VP9FrameParamsQpRTC;
@@ -68,9 +68,9 @@ class VP9VaapiVideoEncoderDelegate : public VaapiVideoEncoderDelegate {
friend class VP9VaapiVideoEncoderDelegateTest;
friend class VaapiVideoEncodeAcceleratorTest;
- using VP9RateControl = VPXRateControl<libvpx::VP9RateControlRtcConfig,
- libvpx::VP9RateControlRTC,
- libvpx::VP9FrameParamsQpRTC>;
+ using VP9RateControl = VideoRateControl<libvpx::VP9RateControlRtcConfig,
+ libvpx::VP9RateControlRTC,
+ libvpx::VP9FrameParamsQpRTC>;
void set_rate_ctrl_for_testing(std::unique_ptr<VP9RateControl> rate_ctrl);
bool ApplyPendingUpdateRates();
diff --git a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
index 8f07a9f1285..d966194387e 100644
--- a/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
+++ b/chromium/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
@@ -14,13 +14,14 @@
#include "base/callback_helpers.h"
#include "base/cxx17_backports.h"
#include "base/logging.h"
+#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/gpu_video_encode_accelerator_helpers.h"
#include "media/gpu/vaapi/vaapi_common.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "media/gpu/video_rate_control.h"
#include "media/gpu/vp9_svc_layers.h"
-#include "media/gpu/vpx_rate_control.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -239,9 +240,9 @@ class MockVaapiWrapper : public VaapiWrapper {
};
class MockVP9RateControl
- : public VPXRateControl<libvpx::VP9RateControlRtcConfig,
- libvpx::VP9RateControlRTC,
- libvpx::VP9FrameParamsQpRTC> {
+ : public VideoRateControl<libvpx::VP9RateControlRtcConfig,
+ libvpx::VP9RateControlRTC,
+ libvpx::VP9FrameParamsQpRTC> {
public:
MockVP9RateControl() = default;
~MockVP9RateControl() override = default;
@@ -296,7 +297,7 @@ class VP9VaapiVideoEncoderDelegateTest
std::unique_ptr<VP9VaapiVideoEncoderDelegate> encoder_;
scoped_refptr<MockVaapiWrapper> mock_vaapi_wrapper_;
- MockVP9RateControl* mock_rate_ctrl_ = nullptr;
+ raw_ptr<MockVP9RateControl> mock_rate_ctrl_ = nullptr;
};
void VP9VaapiVideoEncoderDelegateTest::ResetEncoder() {
@@ -344,7 +345,7 @@ void VP9VaapiVideoEncoderDelegateTest::InitializeVP9VaapiVideoEncoderDelegate(
auto initial_bitrate_allocation = AllocateDefaultBitrateForTesting(
num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate.target_bps(), false);
+ kDefaultVideoEncodeAcceleratorConfig.bitrate);
std::vector<gfx::Size> svc_layer_size =
GetDefaultSpatialLayerResolutions(num_spatial_layers);
if (num_spatial_layers > 1u || num_temporal_layers > 1u) {
@@ -365,12 +366,12 @@ void VP9VaapiVideoEncoderDelegateTest::InitializeVP9VaapiVideoEncoderDelegate(
}
}
- EXPECT_CALL(*mock_rate_ctrl_, UpdateRateControl(MatchRtcConfigWithRates(
- AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers,
- config.bitrate.target_bps(), false),
- VideoEncodeAccelerator::kDefaultFramerate,
- num_temporal_layers, svc_layer_size)))
+ EXPECT_CALL(*mock_rate_ctrl_,
+ UpdateRateControl(MatchRtcConfigWithRates(
+ AllocateDefaultBitrateForTesting(
+ num_spatial_layers, num_temporal_layers, config.bitrate),
+ VideoEncodeAccelerator::kDefaultFramerate,
+ num_temporal_layers, svc_layer_size)))
.Times(1)
.WillOnce(Return());
@@ -496,7 +497,8 @@ void VP9VaapiVideoEncoderDelegateTest::UpdateRatesTest(
uint8_t expected_temporal_layer_id,
uint32_t bitrate, uint32_t framerate) {
auto bitrate_allocation = AllocateDefaultBitrateForTesting(
- num_spatial_layers, num_temporal_layers, bitrate, false);
+ num_spatial_layers, num_temporal_layers,
+ media::Bitrate::ConstantBitrate(bitrate));
UpdateRatesAndEncode(bitrate_allocation, framerate,
/*valid_rates_request=*/true, is_key_pic,
spatial_layer_resolutions, num_temporal_layers,
@@ -627,7 +629,7 @@ TEST_P(VP9VaapiVideoEncoderDelegateTest, DeactivateActivateSpatialLayers) {
const VideoBitrateAllocation kDefaultBitrateAllocation =
AllocateDefaultBitrateForTesting(
num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate.target_bps(), false);
+ kDefaultVideoEncodeAcceleratorConfig.bitrate);
const std::vector<gfx::Size> kDefaultSpatialLayers =
GetDefaultSpatialLayerResolutions(num_spatial_layers);
const uint32_t kFramerate =
@@ -657,7 +659,7 @@ TEST_P(VP9VaapiVideoEncoderDelegateTest, FailsWithInvalidSpatialLayers) {
const VideoBitrateAllocation kDefaultBitrateAllocation =
AllocateDefaultBitrateForTesting(
num_spatial_layers, num_temporal_layers,
- kDefaultVideoEncodeAcceleratorConfig.bitrate.target_bps(), false);
+ kDefaultVideoEncodeAcceleratorConfig.bitrate);
std::vector<VideoBitrateAllocation> invalid_bitrate_allocations;
constexpr uint32_t kBitrate = 1234u;
auto bitrate_allocation = kDefaultBitrateAllocation;