Commit 9b2cdfcd authored by Ted Meyer's avatar Ted Meyer Committed by Commit Bot

Support encrypted playback for D3D11VP9Accelerator

Plumb the media::DecryptConfig from the CodecPicture to the D3D11 buffer
descriptor, and made a small refactor of some of the macros to support
error in the case where a decrypt context couldn't be acquired.

Bug: 881922
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I9ac2cd889bb59e478260e81b3b42ee3d9ff6b177
Reviewed-on: https://chromium-review.googlesource.com/c/1275289
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Reviewed-by: default avatarRintaro Kuroiwa <rkuroiwa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601315}
parent 95488d8f
......@@ -94,10 +94,6 @@ Status D3D11H264Accelerator::SubmitFrameMetadata(
const H264Picture::Vector& ref_pic_listb1,
const scoped_refptr<H264Picture>& pic) {
const bool is_encrypted = pic->decrypt_config();
if (is_encrypted && !cdm_proxy_context_) {
RecordFailure("The input is encrypted but there is no proxy context.");
return Status::kFail;
}
std::unique_ptr<D3D11_VIDEO_DECODER_BEGIN_FRAME_CRYPTO_SESSION> content_key;
// This decrypt context has to be outside the if block because pKeyInfo in
......
......@@ -110,7 +110,7 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder(
if (isVP9(config)) {
accelerated_video_decoder_ =
std::make_unique<VP9Decoder>(std::make_unique<D3D11VP9Accelerator>(
this, media_log_.get(), video_decoder, video_device_,
this, media_log_.get(), proxy_context, video_decoder, video_device_,
video_context_));
return;
}
......@@ -126,7 +126,6 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder(
// No other type of config should make it this far due to earlier checks.
NOTREACHED();
return;
}
bool D3D11VideoDecoder::DeviceHasDecoderID(GUID decoder_guid) {
......@@ -273,6 +272,12 @@ void D3D11VideoDecoder::Initialize(
proxy_context = cdm_context->GetCdmProxyContext();
#endif
// Ensure that if we are encrypted, that we have a CDM.
if (is_encrypted_ && !proxy_context) {
NotifyError("Video stream is encrypted, but no cdm was found");
return;
}
InitializeAcceleratedDecoder(config, proxy_context, video_decoder);
// |cdm_context| could be null for clear playback.
......
......@@ -9,35 +9,41 @@
#include <utility>
#include "base/memory/ptr_util.h"
#include "media/cdm/cdm_proxy_context.h"
#include "media/gpu/windows/d3d11_vp9_picture.h"
namespace media {
#define RECORD_FAILURE(expr_name, expr_value) \
do { \
media_log_->AddEvent(media_log_->CreateStringEvent( \
MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error", \
std::string("DX11VP9Failure(") + expr_name + \
")=" + std::to_string(expr_value))); \
#define RETURN_ON_HR_FAILURE(expr_name, expr) \
do { \
HRESULT expr_value = (expr); \
if (FAILED(expr_value)) { \
RecordFailure(#expr_name, logging::SystemErrorCodeToString(expr_value)); \
return false; \
} \
} while (0)
#define RETURN_ON_HR_FAILURE(expr_name, expr) \
do { \
HRESULT expr_value = (expr); \
if (FAILED(expr_value)) { \
RECORD_FAILURE(#expr_name, expr_value); \
return false; \
} \
} while (0)
std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK>
CreateSubsampleMappingBlock(const std::vector<SubsampleEntry>& from) {
std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK> to(from.size());
for (const auto& entry : from) {
D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK subsample = {
.ClearSize = entry.clear_bytes, .EncryptedSize = entry.cypher_bytes};
to.push_back(subsample);
}
return to;
}
D3D11VP9Accelerator::D3D11VP9Accelerator(
D3D11VideoDecoderClient* client,
MediaLog* media_log,
CdmProxyContext* cdm_proxy_context,
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context)
Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context)
: client_(client),
media_log_(media_log),
cdm_proxy_context_(cdm_proxy_context),
status_feedback_(0),
video_decoder_(std::move(video_decoder)),
video_device_(std::move(video_device)),
......@@ -45,6 +51,13 @@ D3D11VP9Accelerator::D3D11VP9Accelerator(
D3D11VP9Accelerator::~D3D11VP9Accelerator() {}
void D3D11VP9Accelerator::RecordFailure(const std::string& fail_type,
const std::string& reason) {
media_log_->AddEvent(media_log_->CreateStringEvent(
MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error",
std::string("DX11VP9Failure(") + fail_type + ")=" + reason));
}
scoped_refptr<VP9Picture> D3D11VP9Accelerator::CreateVP9Picture() {
D3D11PictureBuffer* picture_buffer = client_->GetPicture();
if (!picture_buffer)
......@@ -63,15 +76,36 @@ bool D3D11VP9Accelerator::BeginFrame(D3D11VP9Picture* pic) {
video_device_->CreateVideoDecoderOutputView(
pic->picture_buffer()->texture().Get(), &view_desc,
output_view.GetAddressOf()));
// This |decrypt_context| has to be outside the if block because pKeyInfo in
// D3D11_VIDEO_DECODER_BEGIN_FRAME_CRYPTO_SESSION is a pointer (to a GUID).
base::Optional<CdmProxyContext::D3D11DecryptContext> decrypt_context;
std::unique_ptr<D3D11_VIDEO_DECODER_BEGIN_FRAME_CRYPTO_SESSION> content_key;
if (const DecryptConfig* config = pic->decrypt_config()) {
decrypt_context = cdm_proxy_context_->GetD3D11DecryptContext(
CdmProxy::KeyType::kDecryptAndDecode, config->key_id());
if (!decrypt_context) {
RecordFailure("crypto_config",
"Cannot find the decrypt context for the frame.");
return false; // TODO(crbug.com/894573): support kTryAgain.
}
content_key =
std::make_unique<D3D11_VIDEO_DECODER_BEGIN_FRAME_CRYPTO_SESSION>();
content_key->pCryptoSession = decrypt_context->crypto_session;
content_key->pBlob = const_cast<void*>(decrypt_context->key_blob);
content_key->BlobSize = decrypt_context->key_blob_size;
content_key->pKeyInfoId = &decrypt_context->key_info_guid;
}
HRESULT hr;
do {
hr = video_context_->DecoderBeginFrame(video_decoder_.Get(),
output_view.Get(), 0, nullptr);
hr = video_context_->DecoderBeginFrame(
video_decoder_.Get(), output_view.Get(),
content_key ? sizeof(*content_key) : 0, content_key.get());
} while (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING);
if (FAILED(hr)) {
RECORD_FAILURE("DecoderBeginFrame", hr);
RecordFailure("DecoderBeginFrame", logging::SystemErrorCodeToString(hr));
return false;
}
......@@ -281,7 +315,7 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer(
RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL);
constexpr int buffers_count = 3;
D3D11_VIDEO_DECODER_BUFFER_DESC buffers[buffers_count] = {};
D3D11_VIDEO_DECODER_BUFFER_DESC1 buffers[buffers_count] = {};
buffers[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
buffers[0].DataOffset = 0;
buffers[0].DataSize = sizeof(pic_params);
......@@ -292,8 +326,20 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer(
buffers[2].DataOffset = 0;
buffers[2].DataSize = copy_size;
RETURN_ON_HR_FAILURE(SubmitDecoderBuffers,
video_context_->SubmitDecoderBuffers(
const DecryptConfig* config = pic->decrypt_config();
if (config) {
buffers[2].pIV = const_cast<char*>(config->iv().data());
buffers[2].IVSize = config->iv().size();
// Subsamples matter iff there is IV, for decryption.
if (!config->subsamples().empty()) {
buffers[2].pSubSampleMappingBlock =
CreateSubsampleMappingBlock(config->subsamples()).data();
buffers[2].SubSampleMappingCount = config->subsamples().size();
}
}
RETURN_ON_HR_FAILURE(SubmitDecoderBuffers1,
video_context_->SubmitDecoderBuffers1(
video_decoder_.Get(), buffers_count, buffers));
buffer_offset += copy_size;
}
......
......@@ -16,14 +16,17 @@
#include "media/gpu/windows/d3d11_vp9_picture.h"
namespace media {
class CdmProxyContext;
class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
public:
D3D11VP9Accelerator(D3D11VideoDecoderClient* client,
MediaLog* media_log,
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context);
D3D11VP9Accelerator(
D3D11VideoDecoderClient* client,
MediaLog* media_log,
CdmProxyContext* cdm_proxy_context,
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context);
~D3D11VP9Accelerator() override;
scoped_refptr<VP9Picture> CreateVP9Picture() override;
......@@ -67,12 +70,15 @@ class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
bool SubmitDecoderBuffer(const DXVA_PicParams_VP9& pic_params,
const scoped_refptr<D3D11VP9Picture>& pic);
void RecordFailure(const std::string& fail_type, const std::string& reason);
D3D11VideoDecoderClient* client_;
MediaLog* const media_log_;
CdmProxyContext* cdm_proxy_context_;
UINT status_feedback_;
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_;
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_;
Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context_;
DISALLOW_COPY_AND_ASSIGN(D3D11VP9Accelerator);
};
......
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