blob: f1073892fa7710571ec347a5fef7203a5473e4f1 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/windows/d3d11_video_context_wrapper.h"
#include <memory>
#include "base/memory/weak_ptr.h"
namespace media {
VideoContextWrapper::~VideoContextWrapper() = default;
// Specialization for sample submission
template <typename CTX>
struct BufferSubmitter;
template <>
struct BufferSubmitter<ID3D11VideoContext1> {
static HRESULT SubmitDecoderBuffers(
ComD3D11VideoContext1 context,
ID3D11VideoDecoder* decoder,
const UINT num_buffers,
const VideoContextWrapper::VideoBufferWrapper* src) {
constexpr UINT max_buffers = 4;
DCHECK_LE(num_buffers, max_buffers);
D3D11_VIDEO_DECODER_BUFFER_DESC1 buffers[max_buffers] = {};
memset(buffers, 0, sizeof(D3D11_VIDEO_DECODER_BUFFER_DESC1) * max_buffers);
for (size_t i = 0; i < num_buffers; i++) {
buffers[i].BufferType = src[i].BufferType;
buffers[i].DataOffset = src[i].DataOffset;
buffers[i].DataSize = src[i].DataSize;
buffers[i].pIV = src[i].pIV;
buffers[i].IVSize = src[i].IVSize;
buffers[i].pSubSampleMappingBlock = src[i].pSubSampleMappingBlock;
buffers[i].SubSampleMappingCount = src[i].SubSampleMappingCount;
}
return context->SubmitDecoderBuffers1(decoder, num_buffers, buffers);
}
};
template <>
struct BufferSubmitter<ID3D11VideoContext> {
static HRESULT SubmitDecoderBuffers(
ComD3D11VideoContext context,
ID3D11VideoDecoder* decoder,
const UINT num_buffers,
const VideoContextWrapper::VideoBufferWrapper* src) {
constexpr UINT max_buffers = 4;
DCHECK_LE(num_buffers, max_buffers);
D3D11_VIDEO_DECODER_BUFFER_DESC buffers[max_buffers] = {};
memset(buffers, 0, sizeof(D3D11_VIDEO_DECODER_BUFFER_DESC) * max_buffers);
for (size_t i = 0; i < num_buffers; i++) {
buffers[i].BufferType = src[i].BufferType;
buffers[i].DataOffset = src[i].DataOffset;
buffers[i].DataSize = src[i].DataSize;
DCHECK_EQ(src[i].pIV, nullptr);
DCHECK_EQ(src[i].IVSize, 0u);
DCHECK_EQ(src[i].pSubSampleMappingBlock, nullptr);
DCHECK_EQ(src[i].SubSampleMappingCount, 0u);
}
return context->SubmitDecoderBuffers(decoder, num_buffers, buffers);
}
};
// CTX is The type of D3D11VideoContext* that we are wrapping, whether that
// be D3D11VideoContext or D3D11VideoContext1. Only these types will work
// since the BufferSubmitter struct is only specialized for these two types.
template <typename CTX>
class VideoContextWrapperImpl : public VideoContextWrapper {
public:
explicit VideoContextWrapperImpl(Microsoft::WRL::ComPtr<CTX> video_context)
: video_context_(video_context) {}
~VideoContextWrapperImpl() {}
HRESULT DecoderBeginFrame(ID3D11VideoDecoder* video_decoder,
ID3D11VideoDecoderOutputView* output_view,
UINT content_key_size,
const void* content_key) override {
return video_context_->DecoderBeginFrame(video_decoder, output_view,
content_key_size, content_key);
}
HRESULT GetDecoderBuffer(ID3D11VideoDecoder* video_decoder,
D3D11_VIDEO_DECODER_BUFFER_TYPE type,
UINT* buffer_size,
void** buffer) override {
return video_context_->GetDecoderBuffer(video_decoder, type, buffer_size,
buffer);
}
HRESULT ReleaseDecoderBuffer(ID3D11VideoDecoder* video_decoder,
D3D11_VIDEO_DECODER_BUFFER_TYPE type) override {
return video_context_->ReleaseDecoderBuffer(video_decoder, type);
}
HRESULT DecoderEndFrame(ID3D11VideoDecoder* video_decoder) override {
return video_context_->DecoderEndFrame(video_decoder);
}
HRESULT SubmitDecoderBuffers(ID3D11VideoDecoder* video_decoder,
UINT num_buffers,
const VideoBufferWrapper* buffers) override {
return BufferSubmitter<CTX>::SubmitDecoderBuffers(
video_context_, video_decoder, num_buffers, buffers);
}
private:
Microsoft::WRL::ComPtr<CTX> video_context_;
};
std::unique_ptr<VideoContextWrapper> VideoContextWrapper::CreateWrapper(
D3D_FEATURE_LEVEL supported_d3d11_version,
ComD3D11DeviceContext device_context,
HRESULT* status) {
if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_0) {
ComD3D11VideoContext video_context;
*status = device_context.As(&video_context);
return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext>>(
video_context);
}
if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_1) {
ComD3D11VideoContext1 video_context;
*status = device_context.As(&video_context);
return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext1>>(
video_context);
}
*status = E_FAIL;
return nullptr;
}
} // namespace media