Commit 6cfb85e4 authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Chromium LUCI CQ

vaapi: Fix full sample decryption

Intel modified iHD so that we don't need to know full vs. subsample when
we configure the decoder. Now we configure everything properly at the
beginning of decode by knowing the encryption scheme.

BUG=b:153111783,b:155508443
TEST=Full sample H264, subsample CTR H264/HEVC/VP9, subsample CBC H264
work on volteer

Change-Id: I6f4abac5ae8945cfe7c5851d6b07cb6c9f325f64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2587760Reviewed-by: default avatarJao-ke Chin-Lee <jchinlee@chromium.org>
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Cr-Commit-Position: refs/heads/master@{#841270}
parent 010e2f54
......@@ -369,11 +369,6 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitSlice(
bool uses_crypto = false;
VAEncryptionParameters crypto_params = {};
if (IsEncryptedSession()) {
// Always indicate full sample since H264 can support that and we don't know
// yet which it is.
// TODO(jkardatzke): Fix full sample encryption, specifying true for it here
// always will cause H264 subsample to fail and we don't know which it is
// yet.
const ProtectedSessionState state = SetupDecryptDecode(
/*full_sample=*/false, size, &crypto_params, &encryption_segment_info_,
subsamples);
......
......@@ -162,6 +162,7 @@ VaapiDmaBufVideoFrameMapper::VaapiDmaBufVideoFrameMapper(
: VideoFrameMapper(format),
vaapi_wrapper_(VaapiWrapper::Create(VaapiWrapper::kVideoProcess,
VAProfileNone,
EncryptionScheme::kUnencrypted,
base::DoNothing())) {}
VaapiDmaBufVideoFrameMapper::~VaapiDmaBufVideoFrameMapper() {}
......
......@@ -29,7 +29,8 @@ VaapiImageDecoder::~VaapiImageDecoder() = default;
bool VaapiImageDecoder::Initialize(const ReportErrorToUMACB& error_uma_cb) {
vaapi_wrapper_ =
VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_, error_uma_cb);
VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_,
EncryptionScheme::kUnencrypted, error_uma_cb);
return !!vaapi_wrapper_;
}
......
......@@ -500,6 +500,7 @@ VaapiJpegEncodeAccelerator::Initialize(
client_ = client;
scoped_refptr<VaapiWrapper> vaapi_wrapper = VaapiWrapper::Create(
VaapiWrapper::kEncode, VAProfileJPEGBaseline,
EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiJpegEncodeAccelerator.VAAPIError"));
......@@ -510,6 +511,7 @@ VaapiJpegEncodeAccelerator::Initialize(
scoped_refptr<VaapiWrapper> vpp_vaapi_wrapper = VaapiWrapper::Create(
VaapiWrapper::kVideoProcess, VAProfileNone,
EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiJpegEncodeAccelerator.Vpp.VAAPIError"));
if (!vpp_vaapi_wrapper) {
......
......@@ -141,6 +141,7 @@ bool VaapiMjpegDecodeAccelerator::Initialize(
vpp_vaapi_wrapper_ = VaapiWrapper::Create(
VaapiWrapper::kVideoProcess, VAProfileNone,
EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiMjpegDecodeAccelerator.Vpp.VAAPIError"));
if (!vpp_vaapi_wrapper_) {
......
......@@ -279,7 +279,8 @@ TEST_F(VaapiTest, LowQualityEncodingSetting) {
for (const auto& profile_and_entrypoints : configurations) {
const VAProfile va_profile = profile_and_entrypoints.first;
scoped_refptr<VaapiWrapper> wrapper = VaapiWrapper::Create(
VaapiWrapper::kEncode, va_profile, base::DoNothing());
VaapiWrapper::kEncode, va_profile, EncryptionScheme::kUnencrypted,
base::DoNothing());
// Depending on the GPU Gen, flags and policies, we may or may not utilize
// all entrypoints (e.g. we might always want VAEntrypointEncSliceLP if
......
......@@ -42,6 +42,7 @@ class VaapiUtilsTest : public testing::Test {
// Create a VaapiWrapper for testing.
vaapi_wrapper_ =
VaapiWrapper::Create(VaapiWrapper::kDecode, VAProfileJPEGBaseline,
EncryptionScheme::kUnencrypted,
base::BindRepeating([](VaapiFunctions function) {
LOG(FATAL) << "Oh noes! Decoder failed";
}));
......
......@@ -205,7 +205,7 @@ bool VaapiVideoDecodeAccelerator::Initialize(const Config& config,
VLOGF(2) << "Initializing VAVDA, profile: " << GetProfileName(profile);
vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
VaapiWrapper::kDecode, profile,
VaapiWrapper::kDecode, profile, EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiVideoDecodeAccelerator.VAAPIError"));
......@@ -620,7 +620,7 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
if (profile_ != new_profile) {
profile_ = new_profile;
auto new_vaapi_wrapper = VaapiWrapper::CreateForVideoCodec(
VaapiWrapper::kDecode, profile_,
VaapiWrapper::kDecode, profile_, EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiVideoDecodeAccelerator.VAAPIError"));
RETURN_AND_NOTIFY_ON_FAILURE(new_vaapi_wrapper.get(),
......@@ -715,6 +715,7 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
if (!vpp_vaapi_wrapper_) {
vpp_vaapi_wrapper_ = VaapiWrapper::Create(
VaapiWrapper::kVideoProcess, VAProfileNone,
EncryptionScheme::kUnencrypted,
base::BindRepeating(
&ReportVaapiErrorToUMA,
"Media.VaapiVideoDecodeAccelerator.Vpp.VAAPIError"));
......
......@@ -220,7 +220,7 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
#else
VaapiWrapper::kDecode,
#endif
profile,
profile, config.encryption_scheme(),
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiVideoDecoder.VAAPIError"));
UMA_HISTOGRAM_BOOLEAN("Media.VaapiVideoDecoder.VaapiWrapperCreationSuccess",
......@@ -554,7 +554,7 @@ void VaapiVideoDecoder::ApplyResolutionChange() {
#else
VaapiWrapper::kDecode,
#endif
profile_,
profile_, encryption_scheme_,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiVideoDecoder.VAAPIError"));
if (!new_vaapi_wrapper.get()) {
......
......@@ -92,7 +92,6 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
protected_session_state_ = ProtectedSessionState::kFailed;
return protected_session_state_;
}
full_sample_ = full_sample;
// We need to start the creation of this, first part requires getting the
// hw config data from the daemon.
chromeos::ChromeOsCdmFactory::GetHwConfigData(BindToCurrentLoop(
......@@ -106,14 +105,10 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
if (encryption_scheme_ == EncryptionScheme::kCenc) {
crypto_params->encryption_type =
full_sample_ ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128;
full_sample ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128;
} else {
if (full_sample_) {
LOG(ERROR) << "CBC encryption is not supported for CENCv1";
protected_session_state_ = ProtectedSessionState::kFailed;
return protected_session_state_;
}
crypto_params->encryption_type = VA_ENCRYPTION_TYPE_CBC;
crypto_params->encryption_type =
full_sample ? VA_ENCRYPTION_TYPE_CENC_CBC : VA_ENCRYPTION_TYPE_CBC;
}
if (subsamples.empty() ||
......@@ -128,12 +123,6 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
return protected_session_state_;
}
if (full_sample_ != full_sample) {
LOG(ERROR) << "Cannot switch between full/subsample mid session";
protected_session_state_ = ProtectedSessionState::kFailed;
return protected_session_state_;
}
DCHECK(decrypt_config_);
// We also need to make sure we have the key data for the active
// DecryptConfig now that the protected session exists.
......@@ -205,8 +194,8 @@ void VaapiVideoDecoderDelegate::OnGetHwConfigData(
}
hw_identifier_.clear();
if (!vaapi_wrapper_->CreateProtectedSession(encryption_scheme_, full_sample_,
config_data, &hw_identifier_)) {
if (!vaapi_wrapper_->CreateProtectedSession(encryption_scheme_, config_data,
&hw_identifier_)) {
LOG(ERROR) << "Failed to setup protected session";
protected_session_state_ = ProtectedSessionState::kFailed;
on_protected_session_update_cb_.Run(false);
......
......@@ -116,7 +116,6 @@ class VaapiVideoDecoderDelegate {
EncryptionScheme encryption_scheme_;
ProtectedSessionState protected_session_state_;
std::unique_ptr<DecryptConfig> decrypt_config_;
bool full_sample_;
std::vector<uint8_t> hw_identifier_;
std::map<std::string, std::vector<uint8_t>> hw_key_data_map_;
......
......@@ -335,7 +335,7 @@ bool VaapiVideoEncodeAccelerator::Initialize(const Config& config,
codec == kCodecVP9 ? VaapiWrapper::kEncodeConstantQuantizationParameter
: VaapiWrapper::kEncode;
vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec(
mode, config.output_profile,
mode, config.output_profile, EncryptionScheme::kUnencrypted,
base::BindRepeating(&ReportVaapiErrorToUMA,
"Media.VaapiVideoEncodeAccelerator.VAAPIError"));
if (!vaapi_wrapper_) {
......@@ -728,6 +728,7 @@ std::unique_ptr<VaapiEncodeJob> VaapiVideoEncodeAccelerator::CreateEncodeJob(
if (!vpp_vaapi_wrapper_) {
vpp_vaapi_wrapper_ = VaapiWrapper::Create(
VaapiWrapper::kVideoProcess, VAProfileNone,
EncryptionScheme::kUnencrypted,
base::BindRepeating(
&ReportVaapiErrorToUMA,
"Media.VaapiVideoEncodeAccelerator.Vpp.VAAPIError"));
......
......@@ -787,8 +787,6 @@ bool GetRequiredAttribs(const base::Lock* va_lock,
{VAConfigAttribProtectedContentCipherBlockSize, VA_PC_BLOCK_SIZE_128});
required_attribs->push_back(
{VAConfigAttribProtectedContentCipherMode, VA_PC_CIPHER_MODE_CTR});
required_attribs->push_back({VAConfigAttribProtectedContentCipherSampleType,
VA_PC_SAMPLE_TYPE_FULLSAMPLE});
#endif
} else {
required_attribs->push_back({VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420});
......@@ -796,16 +794,8 @@ bool GetRequiredAttribs(const base::Lock* va_lock,
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (mode == VaapiWrapper::kDecodeProtected && profile != VAProfileProtected) {
// TODO(jkardatzke): Remove this workarond once the iHD bug for full vs.
// subsample dependency here is fixed. VA_ENCRYPTION_TYPE_CTR_128 works for
// VP9. VA_ENCRYPTION_TYPE_CENC_CTR is needed for H264 full sample (and also
// works for H264 subsample). We can't know full vs. subsample at this point
// though, we only know codec.
required_attribs->push_back(
{VAConfigAttribEncryption,
(profile == VAProfileVP9Profile0 || profile == VAProfileVP9Profile2)
? VA_ENCRYPTION_TYPE_CTR_128
: VA_ENCRYPTION_TYPE_CENC_CTR});
{VAConfigAttribEncryption, VA_ENCRYPTION_TYPE_CENC_CTR});
}
#endif
......@@ -1339,6 +1329,7 @@ VAImplementation VaapiWrapper::GetImplementationType() {
scoped_refptr<VaapiWrapper> VaapiWrapper::Create(
CodecMode mode,
VAProfile va_profile,
EncryptionScheme encryption_scheme,
const ReportErrorToUMACB& report_error_to_uma_cb) {
if (!VASupportedProfiles::Get().IsProfileSupported(mode, va_profile)) {
DVLOG(1) << "Unsupported va_profile: " << vaProfileStr(va_profile);
......@@ -1358,7 +1349,7 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::Create(
scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper(mode));
if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) {
if (vaapi_wrapper->Initialize(mode, va_profile))
if (vaapi_wrapper->Initialize(mode, va_profile, encryption_scheme))
return vaapi_wrapper;
}
LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: "
......@@ -1370,9 +1361,10 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::Create(
scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
CodecMode mode,
VideoCodecProfile profile,
EncryptionScheme encryption_scheme,
const ReportErrorToUMACB& report_error_to_uma_cb) {
const VAProfile va_profile = ProfileToVAProfile(profile, mode);
return Create(mode, va_profile, report_error_to_uma_cb);
return Create(mode, va_profile, encryption_scheme, report_error_to_uma_cb);
}
// static
......@@ -1738,8 +1730,7 @@ std::unique_ptr<ScopedVASurface> VaapiWrapper::CreateContextAndScopedVASurface(
}
bool VaapiWrapper::CreateProtectedSession(
media::EncryptionScheme encryption,
bool full_sample,
EncryptionScheme encryption,
const std::vector<uint8_t>& hw_config,
std::vector<uint8_t>* hw_identifier_out) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
......@@ -1748,7 +1739,7 @@ bool VaapiWrapper::CreateProtectedSession(
LOG(ERROR) << "Cannot attached protected context if not in protected mode";
return false;
}
if (encryption == media::EncryptionScheme::kUnencrypted) {
if (encryption == EncryptionScheme::kUnencrypted) {
LOG(ERROR) << "Must specify encryption scheme for protected mode";
return false;
}
......@@ -1764,16 +1755,12 @@ bool VaapiWrapper::CreateProtectedSession(
}
DCHECK(!required_attribs.empty());
// We need to adjust the attributes for encryption scheme and sample mode.
// We need to adjust the attribute for encryption scheme.
for (auto& attrib : required_attribs) {
if (attrib.type == VAConfigAttribProtectedContentCipherMode) {
attrib.value = (encryption == media::EncryptionScheme::kCbcs)
attrib.value = (encryption == EncryptionScheme::kCbcs)
? VA_PC_CIPHER_MODE_CBC
: VA_PC_CIPHER_MODE_CTR;
} else if (attrib.type ==
VAConfigAttribProtectedContentCipherSampleType) {
attrib.value = full_sample ? VA_PC_SAMPLE_TYPE_FULLSAMPLE
: VA_PC_SAMPLE_TYPE_SUBSAMPLE;
}
}
......@@ -2573,7 +2560,9 @@ VaapiWrapper::~VaapiWrapper() {
Deinitialize();
}
bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
bool VaapiWrapper::Initialize(CodecMode mode,
VAProfile va_profile,
EncryptionScheme encryption_scheme) {
#if DCHECK_IS_ON()
if (mode == kEncodeConstantQuantizationParameter) {
DCHECK_NE(va_profile, VAProfileJPEGBaseline)
......@@ -2581,6 +2570,12 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
}
#endif // DCHECK_IS_ON()
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (encryption_scheme != EncryptionScheme::kUnencrypted &&
mode != kDecodeProtected)
return false;
#endif
const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode, va_profile);
base::AutoLock auto_lock(*va_lock_);
......@@ -2590,6 +2585,18 @@ bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) {
return false;
}
if (encryption_scheme != EncryptionScheme::kUnencrypted) {
DCHECK(!required_attribs.empty());
// We need to adjust the attribute for encryption scheme.
for (auto& attrib : required_attribs) {
if (attrib.type == VAConfigAttribEncryption) {
attrib.value = (encryption_scheme == EncryptionScheme::kCbcs)
? VA_ENCRYPTION_TYPE_CENC_CBC
: VA_ENCRYPTION_TYPE_CENC_CTR;
}
}
}
const VAStatus va_res =
vaCreateConfig(va_display_, va_profile, entrypoint,
required_attribs.empty() ? nullptr : &required_attribs[0],
......
......@@ -151,6 +151,7 @@ class MEDIA_GPU_EXPORT VaapiWrapper
static scoped_refptr<VaapiWrapper> Create(
CodecMode mode,
VAProfile va_profile,
EncryptionScheme encryption_scheme,
const ReportErrorToUMACB& report_error_to_uma_cb);
// Create VaapiWrapper for VideoCodecProfile. It maps VideoCodecProfile
......@@ -160,6 +161,7 @@ class MEDIA_GPU_EXPORT VaapiWrapper
static scoped_refptr<VaapiWrapper> CreateForVideoCodec(
CodecMode mode,
VideoCodecProfile profile,
EncryptionScheme encryption_scheme,
const ReportErrorToUMACB& report_error_to_uma_cb);
// Return the supported video encode profiles.
......@@ -265,14 +267,12 @@ class MEDIA_GPU_EXPORT VaapiWrapper
// decoding context to enable encrypted video decoding. If it cannot be
// attached now, it will be attached when the decoding context is created or
// re-created. |encryption| should be the encryption scheme from the
// DecryptConfig, |full_sample| should be true if full sample (i.e. CENC v1)
// encryption is used. |hw_config| should have been obtained from the
// OEMCrypto implementation via the CdmFactoryDaemonProxy. |hw_identifier_out|
// is an output parameter which will return session specific information which
// can be passed through the ChromeOsCdmContext to retrieve encrypted key
// DecryptConfig. |hw_config| should have been obtained from the OEMCrypto
// implementation via the CdmFactoryDaemonProxy. |hw_identifier_out| is an
// output parameter which will return session specific information which can
// be passed through the ChromeOsCdmContext to retrieve encrypted key
// information. Returns true on success and false otherwise.
bool CreateProtectedSession(media::EncryptionScheme encryption,
bool full_sample,
const std::vector<uint8_t>& hw_config,
std::vector<uint8_t>* hw_identifier_out);
......@@ -476,7 +476,9 @@ class MEDIA_GPU_EXPORT VaapiWrapper
FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage);
FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping);
bool Initialize(CodecMode mode, VAProfile va_profile) WARN_UNUSED_RESULT;
bool Initialize(CodecMode mode,
VAProfile va_profile,
EncryptionScheme encryption_scheme) WARN_UNUSED_RESULT;
void Deinitialize();
bool VaInitialize(const ReportErrorToUMACB& report_error_to_uma_cb)
WARN_UNUSED_RESULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment