1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/gpu/windows/d3d11_video_context_wrapper.h"
6 
7 #include <memory>
8 
9 #include "base/memory/weak_ptr.h"
10 
11 namespace media {
12 
13 VideoContextWrapper::~VideoContextWrapper() = default;
14 
15 // Specialization for sample submission
16 template <typename CTX>
17 struct BufferSubmitter;
18 
19 template <>
20 struct BufferSubmitter<ID3D11VideoContext1> {
SubmitDecoderBuffersmedia::BufferSubmitter21   static HRESULT SubmitDecoderBuffers(
22       ComD3D11VideoContext1 context,
23       ID3D11VideoDecoder* decoder,
24       const UINT num_buffers,
25       const VideoContextWrapper::VideoBufferWrapper* src) {
26     constexpr UINT max_buffers = 4;
27     DCHECK_LE(num_buffers, max_buffers);
28     D3D11_VIDEO_DECODER_BUFFER_DESC1 buffers[max_buffers] = {};
29     memset(buffers, 0, sizeof(D3D11_VIDEO_DECODER_BUFFER_DESC1) * max_buffers);
30     for (size_t i = 0; i < num_buffers; i++) {
31       buffers[i].BufferType = src[i].BufferType;
32       buffers[i].DataOffset = src[i].DataOffset;
33       buffers[i].DataSize = src[i].DataSize;
34       buffers[i].pIV = src[i].pIV;
35       buffers[i].IVSize = src[i].IVSize;
36       buffers[i].pSubSampleMappingBlock = src[i].pSubSampleMappingBlock;
37       buffers[i].SubSampleMappingCount = src[i].SubSampleMappingCount;
38     }
39     return context->SubmitDecoderBuffers1(decoder, num_buffers, buffers);
40   }
41 };
42 
43 template <>
44 struct BufferSubmitter<ID3D11VideoContext> {
SubmitDecoderBuffersmedia::BufferSubmitter45   static HRESULT SubmitDecoderBuffers(
46       ComD3D11VideoContext context,
47       ID3D11VideoDecoder* decoder,
48       const UINT num_buffers,
49       const VideoContextWrapper::VideoBufferWrapper* src) {
50     constexpr UINT max_buffers = 4;
51     DCHECK_LE(num_buffers, max_buffers);
52     D3D11_VIDEO_DECODER_BUFFER_DESC buffers[max_buffers] = {};
53     memset(buffers, 0, sizeof(D3D11_VIDEO_DECODER_BUFFER_DESC) * max_buffers);
54     for (size_t i = 0; i < num_buffers; i++) {
55       buffers[i].BufferType = src[i].BufferType;
56       buffers[i].DataOffset = src[i].DataOffset;
57       buffers[i].DataSize = src[i].DataSize;
58       DCHECK_EQ(src[i].pIV, nullptr);
59       DCHECK_EQ(src[i].IVSize, 0u);
60       DCHECK_EQ(src[i].pSubSampleMappingBlock, nullptr);
61       DCHECK_EQ(src[i].SubSampleMappingCount, 0u);
62     }
63     return context->SubmitDecoderBuffers(decoder, num_buffers, buffers);
64   }
65 };
66 
67 // CTX is The type of D3D11VideoContext* that we are wrapping, whether that
68 // be D3D11VideoContext or D3D11VideoContext1. Only these types will work
69 // since the BufferSubmitter struct is only specialized for these two types.
70 template <typename CTX>
71 class VideoContextWrapperImpl : public VideoContextWrapper {
72  public:
VideoContextWrapperImpl(Microsoft::WRL::ComPtr<CTX> video_context)73   explicit VideoContextWrapperImpl(Microsoft::WRL::ComPtr<CTX> video_context)
74       : video_context_(video_context) {}
~VideoContextWrapperImpl()75   ~VideoContextWrapperImpl() {}
76 
DecoderBeginFrame(ID3D11VideoDecoder * video_decoder,ID3D11VideoDecoderOutputView * output_view,UINT content_key_size,const void * content_key)77   HRESULT DecoderBeginFrame(ID3D11VideoDecoder* video_decoder,
78                             ID3D11VideoDecoderOutputView* output_view,
79                             UINT content_key_size,
80                             const void* content_key) override {
81     return video_context_->DecoderBeginFrame(video_decoder, output_view,
82                                              content_key_size, content_key);
83   }
84 
GetDecoderBuffer(ID3D11VideoDecoder * video_decoder,D3D11_VIDEO_DECODER_BUFFER_TYPE type,UINT * buffer_size,void ** buffer)85   HRESULT GetDecoderBuffer(ID3D11VideoDecoder* video_decoder,
86                            D3D11_VIDEO_DECODER_BUFFER_TYPE type,
87                            UINT* buffer_size,
88                            void** buffer) override {
89     return video_context_->GetDecoderBuffer(video_decoder, type, buffer_size,
90                                             buffer);
91   }
92 
ReleaseDecoderBuffer(ID3D11VideoDecoder * video_decoder,D3D11_VIDEO_DECODER_BUFFER_TYPE type)93   HRESULT ReleaseDecoderBuffer(ID3D11VideoDecoder* video_decoder,
94                                D3D11_VIDEO_DECODER_BUFFER_TYPE type) override {
95     return video_context_->ReleaseDecoderBuffer(video_decoder, type);
96   }
97 
DecoderEndFrame(ID3D11VideoDecoder * video_decoder)98   HRESULT DecoderEndFrame(ID3D11VideoDecoder* video_decoder) override {
99     return video_context_->DecoderEndFrame(video_decoder);
100   }
101 
SubmitDecoderBuffers(ID3D11VideoDecoder * video_decoder,UINT num_buffers,const VideoBufferWrapper * buffers)102   HRESULT SubmitDecoderBuffers(ID3D11VideoDecoder* video_decoder,
103                                UINT num_buffers,
104                                const VideoBufferWrapper* buffers) override {
105     return BufferSubmitter<CTX>::SubmitDecoderBuffers(
106         video_context_, video_decoder, num_buffers, buffers);
107   }
108 
109  private:
110   Microsoft::WRL::ComPtr<CTX> video_context_;
111 };
112 
CreateWrapper(D3D_FEATURE_LEVEL supported_d3d11_version,ComD3D11DeviceContext device_context,HRESULT * status)113 std::unique_ptr<VideoContextWrapper> VideoContextWrapper::CreateWrapper(
114     D3D_FEATURE_LEVEL supported_d3d11_version,
115     ComD3D11DeviceContext device_context,
116     HRESULT* status) {
117   if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_0) {
118     ComD3D11VideoContext video_context;
119     *status = device_context.As(&video_context);
120     return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext>>(
121         video_context);
122   }
123 
124   if (supported_d3d11_version == D3D_FEATURE_LEVEL_11_1) {
125     ComD3D11VideoContext1 video_context;
126     *status = device_context.As(&video_context);
127     return std::make_unique<VideoContextWrapperImpl<ID3D11VideoContext1>>(
128         video_context);
129   }
130 
131   *status = E_FAIL;
132   return nullptr;
133 }
134 
135 }  // namespace media
136