Commit 30f3caca authored by Jeffrey Kardatzke's avatar Jeffrey Kardatzke Committed by Chromium LUCI CQ

vaapi: Fix multi-slice encrypted content

This fixes multi-slice content. The proper way of doing it is to
aggregate all of the encryption parameters into one buffer for all the
slices and send that. Previously it was sending an encryption parameter
buffer for each slice.

BUG=b:153111783
TEST=Encrypted H264/HEVC work with single and multi-slice

Change-Id: I57abbc839d1c6878da7c6a13b8b6da9889329179
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2631466
Auto-Submit: Jeffrey Kardatzke <jkardatzke@google.com>
Reviewed-by: default avatarJao-ke Chin-Lee <jchinlee@chromium.org>
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Cr-Commit-Position: refs/heads/master@{#843874}
parent ff7a4bae
......@@ -88,6 +88,7 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitFrameMetadata(
"H264VaapiVideoDecoderDelegate::SubmitFrameMetadata");
VAPictureParameterBufferH264 pic_param;
memset(&pic_param, 0, sizeof(pic_param));
memset(&crypto_params_, 0, sizeof(crypto_params_));
#define FROM_SPS_TO_PP(a) pic_param.a = sps->a
#define FROM_SPS_TO_PP2(a, b) pic_param.b = sps->a
......@@ -366,11 +367,9 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitSlice(
: DecodeStatus::kFail;
}
bool uses_crypto = false;
VAEncryptionParameters crypto_params = {};
if (IsEncryptedSession()) {
const ProtectedSessionState state = SetupDecryptDecode(
/*full_sample=*/false, size, &crypto_params, &encryption_segment_info_,
/*full_sample=*/false, size, &crypto_params_, &encryption_segment_info_,
subsamples);
if (state == ProtectedSessionState::kFailed) {
LOG(ERROR) << "SubmitSlice fails because we couldn't setup the protected "
......@@ -379,7 +378,6 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitSlice(
} else if (state != ProtectedSessionState::kCreated) {
return DecodeStatus::kTryAgain;
}
uses_crypto = true;
}
VASliceParameterBufferH264 slice_param;
memset(&slice_param, 0, sizeof(slice_param));
......@@ -469,11 +467,6 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitSlice(
FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]);
}
if (uses_crypto &&
!vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
sizeof(crypto_params), &crypto_params)) {
return DecodeStatus::kFail;
}
return vaapi_wrapper_->SubmitBuffers(
{{VASliceParameterBufferType, sizeof(slice_param), &slice_param},
{VASliceDataBufferType, size, data}})
......@@ -486,6 +479,11 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitDecode(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitDecode");
if (IsEncryptedSession() &&
!vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
sizeof(crypto_params_), &crypto_params_)) {
return DecodeStatus::kFail;
}
const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
pic->AsVaapiH264Picture()->va_surface()->id());
encryption_segment_info_.clear();
......
......@@ -73,6 +73,10 @@ class H264VaapiVideoDecoderDelegate : public H264Decoder::H264Accelerator,
// stays alive until SubmitDecode() or Reset().
std::vector<VAEncryptionSegmentInfo> encryption_segment_info_;
// We need to retain this for the multi-slice case since that will aggregate
// the encryption details across all the slices.
VAEncryptionParameters crypto_params_;
DISALLOW_COPY_AND_ASSIGN(H264VaapiVideoDecoderDelegate);
};
......
......@@ -73,6 +73,7 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitFrameMetadata(
VAPictureParameterBufferHEVC pic_param;
memset(&pic_param, 0, sizeof(pic_param));
memset(&crypto_params_, 0, sizeof(crypto_params_));
int highest_tid = sps->sps_max_sub_layers_minus1;
#define FROM_SPS_TO_PP(a) pic_param.a = sps->a
......@@ -297,11 +298,9 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
return DecodeStatus::kFail;
}
bool uses_crypto = false;
VAEncryptionParameters crypto_params = {};
if (IsEncryptedSession()) {
const ProtectedSessionState state =
SetupDecryptDecode(/*full_sample=*/false, size, &crypto_params,
SetupDecryptDecode(/*full_sample=*/false, size, &crypto_params_,
&encryption_segment_info_, subsamples);
if (state == ProtectedSessionState::kFailed) {
LOG(ERROR) << "SubmitSlice fails because we couldn't setup the protected "
......@@ -310,7 +309,6 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
} else if (state != ProtectedSessionState::kCreated) {
return DecodeStatus::kTryAgain;
}
uses_crypto = true;
}
memset(&slice_param_, 0, sizeof(slice_param_));
......@@ -438,11 +436,6 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
last_slice_data_ = data;
last_slice_size_ = size;
if (uses_crypto &&
!vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
sizeof(crypto_params), &crypto_params)) {
return DecodeStatus::kFail;
}
return DecodeStatus::kOk;
}
......@@ -455,6 +448,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitDecode(
return DecodeStatus::kFail;
}
if (IsEncryptedSession() &&
!vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
sizeof(crypto_params_), &crypto_params_)) {
return DecodeStatus::kFail;
}
const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
pic->AsVaapiH265Picture()->va_surface()->id());
ref_pic_list_pocs_.clear();
......
......@@ -92,6 +92,10 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
// mapped buffer in libva across calls. It is filled in SubmitSlice() and
// stays alive until SubmitDecode() or Reset().
std::vector<VAEncryptionSegmentInfo> encryption_segment_info_;
// We need to retain this for the multi-slice case since that will aggregate
// the encryption details across all the slices.
VAEncryptionParameters crypto_params_;
};
} // namespace media
......
......@@ -111,15 +111,22 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
full_sample ? VA_ENCRYPTION_TYPE_CENC_CBC : VA_ENCRYPTION_TYPE_CBC;
}
// For multi-slice we may already have segment information in here, so
// calculate the current offset.
size_t offset = 0;
for (const auto& segment : *segments)
offset += segment.segment_length;
if (subsamples.empty() ||
(subsamples.size() == 1 && subsamples[0].cypher_bytes == 0)) {
// We still need to specify the crypto params to the driver for some reason
// and indicate the entire content is clear.
VAEncryptionSegmentInfo segment_info = {};
segment_info.segment_start_offset = offset;
segment_info.segment_length = segment_info.init_byte_length = size;
segments->emplace_back(std::move(segment_info));
crypto_params->num_segments = 1;
crypto_params->segment_info = &segments->back();
crypto_params->num_segments++;
crypto_params->segment_info = &segments->front();
return protected_session_state_;
}
......@@ -138,9 +145,7 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
return ProtectedSessionState::kInProcess;
}
crypto_params->num_segments = subsamples.size();
// For multi-slice, we may already have segment info in the vector.
const size_t segment_vec_offset = segments->size();
crypto_params->num_segments += subsamples.size();
if (decrypt_config_->HasPattern()) {
if (subsamples.size() != 1) {
LOG(ERROR) << "Need single subsample for encryption pattern";
......@@ -152,6 +157,7 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
crypto_params->blocks_stripe_clear =
decrypt_config_->encryption_pattern()->skip_byte_block();
VAEncryptionSegmentInfo segment_info = {};
segment_info.segment_start_offset = offset;
segment_info.init_byte_length = subsamples[0].clear_bytes;
segment_info.segment_length =
subsamples[0].clear_bytes + subsamples[0].cypher_bytes;
......@@ -159,7 +165,6 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
DecryptConfig::kDecryptionKeySize);
segments->emplace_back(std::move(segment_info));
} else {
size_t offset = 0;
for (const auto& entry : subsamples) {
VAEncryptionSegmentInfo segment_info = {};
segment_info.segment_start_offset = offset;
......@@ -176,7 +181,7 @@ VaapiVideoDecoderDelegate::SetupDecryptDecode(
memcpy(crypto_params->wrapped_decrypt_blob,
hw_key_data_map_[decrypt_config_->key_id()].data(),
DecryptConfig::kDecryptionKeySize);
crypto_params->segment_info = &segments->at(segment_vec_offset);
crypto_params->segment_info = &segments->front();
#else // if BUILDFLAG(IS_CHROMEOS_ASH)
protected_session_state_ = ProtectedSessionState::kFailed;
#endif
......
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