vaapi: Enable AV1 protected content for AMD
This enables AV1 playback of protected content on AMD platforms that
support it. In the cdm-oemcrypto daemon, we take the transcrypted data
that AMD generates and hide it inside of a padding OBU. Then we extract
that here because that is the only data marked as the encrypted range.
We expect there to be 2 subsamples because there is a single trailing
unencrypted byte at the end of the padding OBU.
BUG=b:232908730
TEST=protected AV1 playback works on skyrim
Change-Id: Ie9843505ea8d49febd9cba9595a6c3851208f2e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3696487
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Cr-Commit-Position: refs/heads/main@{#1042634}
diff --git a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
index 7c7214d..fbc0e61 100644
--- a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
+++ b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
@@ -738,6 +738,7 @@
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!picture_params_);
DCHECK(!crypto_params_);
+ DCHECK(!protected_params_);
}
scoped_refptr<AV1Picture> AV1VaapiVideoDecoderDelegate::CreateAV1Picture(
@@ -852,22 +853,47 @@
// also be adjusted.
// Create VASliceData buffer |encoded_data| every frame so that decoding can
// be more asynchronous than reusing the buffer.
- auto encoded_data =
- vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType, data.size_bytes());
- if (!encoded_data)
- return DecodeStatus::kFail;
+ std::unique_ptr<ScopedVABuffer> encoded_data;
std::vector<std::pair<VABufferID, VaapiWrapper::VABufferDescriptor>> buffers =
{{picture_params_->id(),
- {picture_params_->type(), picture_params_->size(), &pic_param}},
- {encoded_data->id(),
- {encoded_data->type(), encoded_data->size(), data.data()}}};
- for (size_t i = 0; i < slice_params.size(); ++i) {
- buffers.push_back({slice_params_va_buffers[i]->id(),
- {slice_params_va_buffers[i]->type(),
- slice_params_va_buffers[i]->size(), &slice_params[i]}});
- }
+ {picture_params_->type(), picture_params_->size(), &pic_param}}};
+ buffers.reserve(3 + slice_params.size());
#if BUILDFLAG(IS_CHROMEOS_ASH)
+ if (IsTranscrypted()) {
+ CHECK(decrypt_config);
+ CHECK_EQ(decrypt_config->subsamples().size(), 2u);
+ if (!protected_params_) {
+ protected_params_ = vaapi_wrapper_->CreateVABuffer(
+ VAProtectedSliceDataBufferType, decrypt_config->key_id().length());
+ if (!protected_params_)
+ return DecodeStatus::kFail;
+ }
+ DCHECK_EQ(decrypt_config->key_id().length(), protected_params_->size());
+ buffers.push_back({protected_params_->id(),
+ {protected_params_->type(), protected_params_->size(),
+ decrypt_config->key_id().data()}});
+ encoded_data = vaapi_wrapper_->CreateVABuffer(
+ VASliceDataBufferType,
+ base::strict_cast<size_t>(
+ decrypt_config->subsamples()[0].cypher_bytes));
+ if (!encoded_data)
+ return DecodeStatus::kFail;
+ buffers.push_back(
+ {encoded_data->id(),
+ {encoded_data->type(), encoded_data->size(),
+ data.data() + decrypt_config->subsamples()[0].clear_bytes}});
+ } else {
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+ encoded_data = vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType,
+ data.size_bytes());
+ if (!encoded_data)
+ return DecodeStatus::kFail;
+ buffers.push_back(
+ {encoded_data->id(),
+ {encoded_data->type(), encoded_data->size(), data.data()}});
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ }
if (uses_crypto) {
buffers.push_back(
{crypto_params_->id(),
@@ -875,6 +901,12 @@
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+ for (size_t i = 0; i < slice_params.size(); ++i) {
+ buffers.push_back({slice_params_va_buffers[i]->id(),
+ {slice_params_va_buffers[i]->type(),
+ slice_params_va_buffers[i]->size(), &slice_params[i]}});
+ }
+
const auto* vaapi_pic = static_cast<const VaapiAV1Picture*>(&pic);
const bool success = vaapi_wrapper_->MapAndCopyAndExecute(
vaapi_pic->reconstruct_va_surface()->id(), buffers);
@@ -892,5 +924,6 @@
// that will be destroyed soon.
picture_params_.reset();
crypto_params_.reset();
+ protected_params_.reset();
}
} // namespace media
diff --git a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h
index 31fd5a4..dfc38c0 100644
--- a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h
+++ b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.h
@@ -44,6 +44,7 @@
private:
std::unique_ptr<ScopedVABuffer> picture_params_;
std::unique_ptr<ScopedVABuffer> crypto_params_;
+ std::unique_ptr<ScopedVABuffer> protected_params_;
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_AV1_VAAPI_VIDEO_DECODER_DELEGATE_H_