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

Add support for encrypted HEVC content in VAAPI

This adds encrypted content support to the VAAPI H265 accelerator.
This is not implemented in the driver yet, but this will facilitate
better testing by Intel if we implement it first and it's fairly
straightforward to do it.

BUG=b:153111783,chromium:1141237
TEST=Builds, clear HEVC content playback works

Change-Id: Ibe468777b663cbc301b6d2c14ab1d2bceeda8e6f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2555544
Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#831954}
parent d2877101
......@@ -6,6 +6,7 @@
#include "base/stl_util.h"
#include "build/chromeos_buildflags.h"
#include "media/base/cdm_context.h"
#include "media/gpu/decode_surface_handler.h"
#include "media/gpu/macros.h"
#include "media/gpu/vaapi/vaapi_common.h"
......@@ -38,11 +39,13 @@ using DecodeStatus = H265Decoder::H265Accelerator::Status;
H265VaapiVideoDecoderDelegate::H265VaapiVideoDecoderDelegate(
DecodeSurfaceHandler<VASurface>* const vaapi_dec,
scoped_refptr<VaapiWrapper> vaapi_wrapper)
scoped_refptr<VaapiWrapper> vaapi_wrapper,
ProtectedSessionUpdateCB on_protected_session_update_cb,
CdmContext* cdm_context)
: VaapiVideoDecoderDelegate(vaapi_dec,
std::move(vaapi_wrapper),
base::DoNothing(),
nullptr) {
std::move(on_protected_session_update_cb),
cdm_context) {
ref_pic_list_pocs_.reserve(kMaxRefIdxActive);
}
......@@ -292,6 +295,22 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
return DecodeStatus::kFail;
}
bool uses_crypto = false;
VAEncryptionParameters crypto_params = {};
if ((!subsamples.empty() && subsamples[0].cypher_bytes) ||
IsProtectedSession()) {
ProtectedSessionState state =
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 "
"session";
return DecodeStatus::kFail;
} else if (state != ProtectedSessionState::kCreated) {
return DecodeStatus::kTryAgain;
}
uses_crypto = true;
}
memset(&slice_param_, 0, sizeof(slice_param_));
slice_param_.slice_data_size = slice_hdr->nalu_size;
......@@ -418,6 +437,11 @@ 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;
}
......@@ -430,11 +454,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitDecode(
return DecodeStatus::kFail;
}
const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
pic->AsVaapiH265Picture()->va_surface()->id());
ref_pic_list_pocs_.clear();
return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
pic->AsVaapiH265Picture()->va_surface()->id())
? DecodeStatus::kOk
: DecodeStatus::kFail;
encryption_segment_info_.clear();
return success ? DecodeStatus::kOk : DecodeStatus::kFail;
}
bool H265VaapiVideoDecoderDelegate::OutputPicture(
......@@ -452,9 +476,20 @@ void H265VaapiVideoDecoderDelegate::Reset() {
DETACH_FROM_SEQUENCE(sequence_checker_);
vaapi_wrapper_->DestroyPendingBuffers();
ref_pic_list_pocs_.clear();
encryption_segment_info_.clear();
last_slice_data_ = nullptr;
}
DecodeStatus H265VaapiVideoDecoderDelegate::SetStream(
base::span<const uint8_t> /*stream*/,
const DecryptConfig* decrypt_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!decrypt_config)
return Status::kOk;
return SetDecryptConfig(decrypt_config->Clone()) ? Status::kOk
: Status::kFail;
}
void H265VaapiVideoDecoderDelegate::FillVAPicture(
VAPictureHEVC* va_pic,
scoped_refptr<H265Picture> pic) {
......
......@@ -18,13 +18,17 @@ typedef struct _VAPictureHEVC VAPictureHEVC;
namespace media {
class CdmContext;
class H265Picture;
class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
public VaapiVideoDecoderDelegate {
public:
H265VaapiVideoDecoderDelegate(DecodeSurfaceHandler<VASurface>* vaapi_dec,
scoped_refptr<VaapiWrapper> vaapi_wrapper);
H265VaapiVideoDecoderDelegate(
DecodeSurfaceHandler<VASurface>* vaapi_dec,
scoped_refptr<VaapiWrapper> vaapi_wrapper,
ProtectedSessionUpdateCB on_protected_session_update_cb,
CdmContext* cdm_context);
H265VaapiVideoDecoderDelegate(const H265VaapiVideoDecoderDelegate&) = delete;
H265VaapiVideoDecoderDelegate& operator=(
......@@ -51,6 +55,8 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
Status SubmitDecode(scoped_refptr<H265Picture> pic) override;
bool OutputPicture(scoped_refptr<H265Picture> pic) override;
void Reset() override;
Status SetStream(base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config) override;
private:
void FillVAPicture(VAPictureHEVC* va_pic, scoped_refptr<H265Picture> pic);
......@@ -80,6 +86,11 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
// |slice_param_| filled.
const uint8_t* last_slice_data_{nullptr};
size_t last_slice_size_{0};
// We need to hold onto this memory here because it's referenced by the
// mapped buffer in libva across calls. It is filled in SubmitSlice() and
// stays alive until SubmitDecode() or Reset().
std::vector<VAEncryptionSegmentInfo> encryption_segment_info_;
};
} // namespace media
......
......@@ -162,7 +162,8 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
std::move(init_cb).Run(StatusCode::kDecoderMissingCdmForEncryptedContent);
return;
}
if (config.codec() != kCodecH264 && config.codec() != kCodecVP9) {
if (config.codec() != kCodecH264 && config.codec() != kCodecVP9 &&
config.codec() != kCodecHEVC) {
VLOGF(1)
<< "Vaapi decoder does not support this codec for encrypted content";
std::move(init_cb).Run(StatusCode::kEncryptedContentUnsupported);
......@@ -685,12 +686,12 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
DVLOGF(2);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
VaapiVideoDecoderDelegate::ProtectedSessionUpdateCB protected_update_cb =
BindToCurrentLoop(base::BindRepeating(
&VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_));
if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
auto accelerator = std::make_unique<H264VaapiVideoDecoderDelegate>(
this, vaapi_wrapper_,
BindToCurrentLoop(base::BindRepeating(
&VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_)),
cdm_context_);
this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
decoder_delegate_ = accelerator.get();
decoder_.reset(
......@@ -703,10 +704,7 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
decoder_.reset(new VP8Decoder(std::move(accelerator)));
} else if (profile_ >= VP9PROFILE_MIN && profile_ <= VP9PROFILE_MAX) {
auto accelerator = std::make_unique<VP9VaapiVideoDecoderDelegate>(
this, vaapi_wrapper_,
BindToCurrentLoop(base::BindRepeating(
&VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_)),
cdm_context_);
this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
decoder_delegate_ = accelerator.get();
decoder_.reset(
......@@ -714,8 +712,8 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
}
#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
else if (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX) {
auto accelerator =
std::make_unique<H265VaapiVideoDecoderDelegate>(this, vaapi_wrapper_);
auto accelerator = std::make_unique<H265VaapiVideoDecoderDelegate>(
this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
decoder_delegate_ = accelerator.get();
decoder_.reset(
......
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