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( ...@@ -94,10 +94,6 @@ Status D3D11H264Accelerator::SubmitFrameMetadata(
const H264Picture::Vector& ref_pic_listb1, const H264Picture::Vector& ref_pic_listb1,
const scoped_refptr<H264Picture>& pic) { const scoped_refptr<H264Picture>& pic) {
const bool is_encrypted = pic->decrypt_config(); 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; 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 // This decrypt context has to be outside the if block because pKeyInfo in
......
...@@ -110,7 +110,7 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder( ...@@ -110,7 +110,7 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder(
if (isVP9(config)) { if (isVP9(config)) {
accelerated_video_decoder_ = accelerated_video_decoder_ =
std::make_unique<VP9Decoder>(std::make_unique<D3D11VP9Accelerator>( 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_)); video_context_));
return; return;
} }
...@@ -126,7 +126,6 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder( ...@@ -126,7 +126,6 @@ void D3D11VideoDecoder::InitializeAcceleratedDecoder(
// No other type of config should make it this far due to earlier checks. // No other type of config should make it this far due to earlier checks.
NOTREACHED(); NOTREACHED();
return;
} }
bool D3D11VideoDecoder::DeviceHasDecoderID(GUID decoder_guid) { bool D3D11VideoDecoder::DeviceHasDecoderID(GUID decoder_guid) {
...@@ -273,6 +272,12 @@ void D3D11VideoDecoder::Initialize( ...@@ -273,6 +272,12 @@ void D3D11VideoDecoder::Initialize(
proxy_context = cdm_context->GetCdmProxyContext(); proxy_context = cdm_context->GetCdmProxyContext();
#endif #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); InitializeAcceleratedDecoder(config, proxy_context, video_decoder);
// |cdm_context| could be null for clear playback. // |cdm_context| could be null for clear playback.
......
...@@ -9,35 +9,41 @@ ...@@ -9,35 +9,41 @@
#include <utility> #include <utility>
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "media/cdm/cdm_proxy_context.h"
#include "media/gpu/windows/d3d11_vp9_picture.h" #include "media/gpu/windows/d3d11_vp9_picture.h"
namespace media { namespace media {
#define RECORD_FAILURE(expr_name, expr_value) \ #define RETURN_ON_HR_FAILURE(expr_name, expr) \
do { \ do { \
media_log_->AddEvent(media_log_->CreateStringEvent( \ HRESULT expr_value = (expr); \
MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error", \ if (FAILED(expr_value)) { \
std::string("DX11VP9Failure(") + expr_name + \ RecordFailure(#expr_name, logging::SystemErrorCodeToString(expr_value)); \
")=" + std::to_string(expr_value))); \ return false; \
} \
} while (0) } while (0)
#define RETURN_ON_HR_FAILURE(expr_name, expr) \ std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK>
do { \ CreateSubsampleMappingBlock(const std::vector<SubsampleEntry>& from) {
HRESULT expr_value = (expr); \ std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK> to(from.size());
if (FAILED(expr_value)) { \ for (const auto& entry : from) {
RECORD_FAILURE(#expr_name, expr_value); \ D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK subsample = {
return false; \ .ClearSize = entry.clear_bytes, .EncryptedSize = entry.cypher_bytes};
} \ to.push_back(subsample);
} while (0) }
return to;
}
D3D11VP9Accelerator::D3D11VP9Accelerator( D3D11VP9Accelerator::D3D11VP9Accelerator(
D3D11VideoDecoderClient* client, D3D11VideoDecoderClient* client,
MediaLog* media_log, MediaLog* media_log,
CdmProxyContext* cdm_proxy_context,
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder, Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context) Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context)
: client_(client), : client_(client),
media_log_(media_log), media_log_(media_log),
cdm_proxy_context_(cdm_proxy_context),
status_feedback_(0), status_feedback_(0),
video_decoder_(std::move(video_decoder)), video_decoder_(std::move(video_decoder)),
video_device_(std::move(video_device)), video_device_(std::move(video_device)),
...@@ -45,6 +51,13 @@ D3D11VP9Accelerator::D3D11VP9Accelerator( ...@@ -45,6 +51,13 @@ D3D11VP9Accelerator::D3D11VP9Accelerator(
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() { scoped_refptr<VP9Picture> D3D11VP9Accelerator::CreateVP9Picture() {
D3D11PictureBuffer* picture_buffer = client_->GetPicture(); D3D11PictureBuffer* picture_buffer = client_->GetPicture();
if (!picture_buffer) if (!picture_buffer)
...@@ -63,15 +76,36 @@ bool D3D11VP9Accelerator::BeginFrame(D3D11VP9Picture* pic) { ...@@ -63,15 +76,36 @@ bool D3D11VP9Accelerator::BeginFrame(D3D11VP9Picture* pic) {
video_device_->CreateVideoDecoderOutputView( video_device_->CreateVideoDecoderOutputView(
pic->picture_buffer()->texture().Get(), &view_desc, pic->picture_buffer()->texture().Get(), &view_desc,
output_view.GetAddressOf())); 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; HRESULT hr;
do { do {
hr = video_context_->DecoderBeginFrame(video_decoder_.Get(), hr = video_context_->DecoderBeginFrame(
output_view.Get(), 0, nullptr); video_decoder_.Get(), output_view.Get(),
content_key ? sizeof(*content_key) : 0, content_key.get());
} while (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING); } while (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING);
if (FAILED(hr)) { if (FAILED(hr)) {
RECORD_FAILURE("DecoderBeginFrame", hr); RecordFailure("DecoderBeginFrame", logging::SystemErrorCodeToString(hr));
return false; return false;
} }
...@@ -281,7 +315,7 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer( ...@@ -281,7 +315,7 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer(
RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL);
constexpr int buffers_count = 3; 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].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS;
buffers[0].DataOffset = 0; buffers[0].DataOffset = 0;
buffers[0].DataSize = sizeof(pic_params); buffers[0].DataSize = sizeof(pic_params);
...@@ -292,8 +326,20 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer( ...@@ -292,8 +326,20 @@ bool D3D11VP9Accelerator::SubmitDecoderBuffer(
buffers[2].DataOffset = 0; buffers[2].DataOffset = 0;
buffers[2].DataSize = copy_size; buffers[2].DataSize = copy_size;
RETURN_ON_HR_FAILURE(SubmitDecoderBuffers, const DecryptConfig* config = pic->decrypt_config();
video_context_->SubmitDecoderBuffers( 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)); video_decoder_.Get(), buffers_count, buffers));
buffer_offset += copy_size; buffer_offset += copy_size;
} }
......
...@@ -16,14 +16,17 @@ ...@@ -16,14 +16,17 @@
#include "media/gpu/windows/d3d11_vp9_picture.h" #include "media/gpu/windows/d3d11_vp9_picture.h"
namespace media { namespace media {
class CdmProxyContext;
class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator { class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
public: public:
D3D11VP9Accelerator(D3D11VideoDecoderClient* client, D3D11VP9Accelerator(
MediaLog* media_log, D3D11VideoDecoderClient* client,
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder, MediaLog* media_log,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, CdmProxyContext* cdm_proxy_context,
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context); Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder,
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device,
Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context);
~D3D11VP9Accelerator() override; ~D3D11VP9Accelerator() override;
scoped_refptr<VP9Picture> CreateVP9Picture() override; scoped_refptr<VP9Picture> CreateVP9Picture() override;
...@@ -67,12 +70,15 @@ class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator { ...@@ -67,12 +70,15 @@ class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator {
bool SubmitDecoderBuffer(const DXVA_PicParams_VP9& pic_params, bool SubmitDecoderBuffer(const DXVA_PicParams_VP9& pic_params,
const scoped_refptr<D3D11VP9Picture>& pic); const scoped_refptr<D3D11VP9Picture>& pic);
void RecordFailure(const std::string& fail_type, const std::string& reason);
D3D11VideoDecoderClient* client_; D3D11VideoDecoderClient* client_;
MediaLog* const media_log_; MediaLog* const media_log_;
CdmProxyContext* cdm_proxy_context_;
UINT status_feedback_; UINT status_feedback_;
Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_; Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_;
Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_; Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_;
Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_; Microsoft::WRL::ComPtr<ID3D11VideoContext1> video_context_;
DISALLOW_COPY_AND_ASSIGN(D3D11VP9Accelerator); 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