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 @@ ...@@ -6,6 +6,7 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "build/chromeos_buildflags.h" #include "build/chromeos_buildflags.h"
#include "media/base/cdm_context.h"
#include "media/gpu/decode_surface_handler.h" #include "media/gpu/decode_surface_handler.h"
#include "media/gpu/macros.h" #include "media/gpu/macros.h"
#include "media/gpu/vaapi/vaapi_common.h" #include "media/gpu/vaapi/vaapi_common.h"
...@@ -38,11 +39,13 @@ using DecodeStatus = H265Decoder::H265Accelerator::Status; ...@@ -38,11 +39,13 @@ using DecodeStatus = H265Decoder::H265Accelerator::Status;
H265VaapiVideoDecoderDelegate::H265VaapiVideoDecoderDelegate( H265VaapiVideoDecoderDelegate::H265VaapiVideoDecoderDelegate(
DecodeSurfaceHandler<VASurface>* const vaapi_dec, 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, : VaapiVideoDecoderDelegate(vaapi_dec,
std::move(vaapi_wrapper), std::move(vaapi_wrapper),
base::DoNothing(), std::move(on_protected_session_update_cb),
nullptr) { cdm_context) {
ref_pic_list_pocs_.reserve(kMaxRefIdxActive); ref_pic_list_pocs_.reserve(kMaxRefIdxActive);
} }
...@@ -292,6 +295,22 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice( ...@@ -292,6 +295,22 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
return DecodeStatus::kFail; 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_)); memset(&slice_param_, 0, sizeof(slice_param_));
slice_param_.slice_data_size = slice_hdr->nalu_size; slice_param_.slice_data_size = slice_hdr->nalu_size;
...@@ -418,6 +437,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice( ...@@ -418,6 +437,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitSlice(
last_slice_data_ = data; last_slice_data_ = data;
last_slice_size_ = size; last_slice_size_ = size;
if (uses_crypto &&
!vaapi_wrapper_->SubmitBuffer(VAEncryptionParameterBufferType,
sizeof(crypto_params), &crypto_params)) {
return DecodeStatus::kFail;
}
return DecodeStatus::kOk; return DecodeStatus::kOk;
} }
...@@ -430,11 +454,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitDecode( ...@@ -430,11 +454,11 @@ DecodeStatus H265VaapiVideoDecoderDelegate::SubmitDecode(
return DecodeStatus::kFail; return DecodeStatus::kFail;
} }
const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
pic->AsVaapiH265Picture()->va_surface()->id());
ref_pic_list_pocs_.clear(); ref_pic_list_pocs_.clear();
return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( encryption_segment_info_.clear();
pic->AsVaapiH265Picture()->va_surface()->id()) return success ? DecodeStatus::kOk : DecodeStatus::kFail;
? DecodeStatus::kOk
: DecodeStatus::kFail;
} }
bool H265VaapiVideoDecoderDelegate::OutputPicture( bool H265VaapiVideoDecoderDelegate::OutputPicture(
...@@ -452,9 +476,20 @@ void H265VaapiVideoDecoderDelegate::Reset() { ...@@ -452,9 +476,20 @@ void H265VaapiVideoDecoderDelegate::Reset() {
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
vaapi_wrapper_->DestroyPendingBuffers(); vaapi_wrapper_->DestroyPendingBuffers();
ref_pic_list_pocs_.clear(); ref_pic_list_pocs_.clear();
encryption_segment_info_.clear();
last_slice_data_ = nullptr; 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( void H265VaapiVideoDecoderDelegate::FillVAPicture(
VAPictureHEVC* va_pic, VAPictureHEVC* va_pic,
scoped_refptr<H265Picture> pic) { scoped_refptr<H265Picture> pic) {
......
...@@ -18,13 +18,17 @@ typedef struct _VAPictureHEVC VAPictureHEVC; ...@@ -18,13 +18,17 @@ typedef struct _VAPictureHEVC VAPictureHEVC;
namespace media { namespace media {
class CdmContext;
class H265Picture; class H265Picture;
class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator, class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
public VaapiVideoDecoderDelegate { public VaapiVideoDecoderDelegate {
public: public:
H265VaapiVideoDecoderDelegate(DecodeSurfaceHandler<VASurface>* vaapi_dec, H265VaapiVideoDecoderDelegate(
scoped_refptr<VaapiWrapper> vaapi_wrapper); DecodeSurfaceHandler<VASurface>* vaapi_dec,
scoped_refptr<VaapiWrapper> vaapi_wrapper,
ProtectedSessionUpdateCB on_protected_session_update_cb,
CdmContext* cdm_context);
H265VaapiVideoDecoderDelegate(const H265VaapiVideoDecoderDelegate&) = delete; H265VaapiVideoDecoderDelegate(const H265VaapiVideoDecoderDelegate&) = delete;
H265VaapiVideoDecoderDelegate& operator=( H265VaapiVideoDecoderDelegate& operator=(
...@@ -51,6 +55,8 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator, ...@@ -51,6 +55,8 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
Status SubmitDecode(scoped_refptr<H265Picture> pic) override; Status SubmitDecode(scoped_refptr<H265Picture> pic) override;
bool OutputPicture(scoped_refptr<H265Picture> pic) override; bool OutputPicture(scoped_refptr<H265Picture> pic) override;
void Reset() override; void Reset() override;
Status SetStream(base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config) override;
private: private:
void FillVAPicture(VAPictureHEVC* va_pic, scoped_refptr<H265Picture> pic); void FillVAPicture(VAPictureHEVC* va_pic, scoped_refptr<H265Picture> pic);
...@@ -80,6 +86,11 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator, ...@@ -80,6 +86,11 @@ class H265VaapiVideoDecoderDelegate : public H265Decoder::H265Accelerator,
// |slice_param_| filled. // |slice_param_| filled.
const uint8_t* last_slice_data_{nullptr}; const uint8_t* last_slice_data_{nullptr};
size_t last_slice_size_{0}; 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 } // namespace media
......
...@@ -162,7 +162,8 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config, ...@@ -162,7 +162,8 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
std::move(init_cb).Run(StatusCode::kDecoderMissingCdmForEncryptedContent); std::move(init_cb).Run(StatusCode::kDecoderMissingCdmForEncryptedContent);
return; return;
} }
if (config.codec() != kCodecH264 && config.codec() != kCodecVP9) { if (config.codec() != kCodecH264 && config.codec() != kCodecVP9 &&
config.codec() != kCodecHEVC) {
VLOGF(1) VLOGF(1)
<< "Vaapi decoder does not support this codec for encrypted content"; << "Vaapi decoder does not support this codec for encrypted content";
std::move(init_cb).Run(StatusCode::kEncryptedContentUnsupported); std::move(init_cb).Run(StatusCode::kEncryptedContentUnsupported);
...@@ -685,12 +686,12 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() { ...@@ -685,12 +686,12 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
DVLOGF(2); DVLOGF(2);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 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) { if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
auto accelerator = std::make_unique<H264VaapiVideoDecoderDelegate>( auto accelerator = std::make_unique<H264VaapiVideoDecoderDelegate>(
this, vaapi_wrapper_, this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
BindToCurrentLoop(base::BindRepeating(
&VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_)),
cdm_context_);
decoder_delegate_ = accelerator.get(); decoder_delegate_ = accelerator.get();
decoder_.reset( decoder_.reset(
...@@ -703,10 +704,7 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() { ...@@ -703,10 +704,7 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
decoder_.reset(new VP8Decoder(std::move(accelerator))); decoder_.reset(new VP8Decoder(std::move(accelerator)));
} else if (profile_ >= VP9PROFILE_MIN && profile_ <= VP9PROFILE_MAX) { } else if (profile_ >= VP9PROFILE_MIN && profile_ <= VP9PROFILE_MAX) {
auto accelerator = std::make_unique<VP9VaapiVideoDecoderDelegate>( auto accelerator = std::make_unique<VP9VaapiVideoDecoderDelegate>(
this, vaapi_wrapper_, this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
BindToCurrentLoop(base::BindRepeating(
&VaapiVideoDecoder::ProtectedSessionUpdate, weak_this_)),
cdm_context_);
decoder_delegate_ = accelerator.get(); decoder_delegate_ = accelerator.get();
decoder_.reset( decoder_.reset(
...@@ -714,8 +712,8 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() { ...@@ -714,8 +712,8 @@ Status VaapiVideoDecoder::CreateAcceleratedVideoDecoder() {
} }
#if BUILDFLAG(ENABLE_PLATFORM_HEVC) #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
else if (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX) { else if (profile_ >= HEVCPROFILE_MIN && profile_ <= HEVCPROFILE_MAX) {
auto accelerator = auto accelerator = std::make_unique<H265VaapiVideoDecoderDelegate>(
std::make_unique<H265VaapiVideoDecoderDelegate>(this, vaapi_wrapper_); this, vaapi_wrapper_, std::move(protected_update_cb), cdm_context_);
decoder_delegate_ = accelerator.get(); decoder_delegate_ = accelerator.get();
decoder_.reset( 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