Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Side by Side Diff: media/gpu/d3d11_video_decode_accelerator_win.cc

Issue 2534313004: Add prototype D3D11VideoDecodeAccelerator. (Closed)
Patch Set: rename d3d11_video_decoder.cc and other changes Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 // This is defined here to ensure the D3D11, D3D9, and DXVA includes through
6 // this header have their GUIDs intialized.
7 #define INITGUID
8 #include "media/gpu/d3d11_video_decode_accelerator_win.h"
9 #undef INITGUID
10
11 #include <d3d11.h>
12
13 #include "base/bits.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/shared_memory.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "base/trace_event/trace_event.h"
18 #include "base/win/scoped_comptr.h"
19 #include "media/gpu/d3d11_h264_accelerator.h"
20 #include "media/gpu/h264_decoder.h"
21 #include "media/gpu/h264_dpb.h"
22 #include "third_party/angle/include/EGL/egl.h"
23 #include "third_party/angle/include/EGL/eglext.h"
24 #include "ui/gfx/color_space.h"
25 #include "ui/gl/gl_bindings.h"
26 #include "ui/gl/gl_context.h"
27 #include "ui/gl/gl_surface_egl.h"
28
29 namespace media {
30
31 #define RETURN_ON_FAILURE(result, log, ret) \
32 do { \
33 if (!(result)) { \
34 DLOG(ERROR) << log; \
35 return ret; \
36 } \
37 } while (0)
38
39 // Helper function to query the ANGLE device object. The template argument T
40 // identifies the device interface being queried. IDirect3DDevice9Ex for d3d9
41 // and ID3D11Device for dx11.
42 template <class T>
43 base::win::ScopedComPtr<T> QueryDeviceObjectFromANGLE(int object_type) {
44 base::win::ScopedComPtr<T> device_object;
45
46 EGLDisplay egl_display = nullptr;
47 intptr_t egl_device = 0;
48 intptr_t device = 0;
49
50 {
51 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. GetHardwareDisplay");
52 egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
53 }
54
55 RETURN_ON_FAILURE(gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_device_query"),
56 "EGL_EXT_device_query missing", device_object);
57
58 PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT = nullptr;
59
60 {
61 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress");
62
63 QueryDisplayAttribEXT = reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
64 eglGetProcAddress("eglQueryDisplayAttribEXT"));
65
66 RETURN_ON_FAILURE(
67 QueryDisplayAttribEXT,
68 "Failed to get the eglQueryDisplayAttribEXT function from ANGLE",
69 device_object);
70 }
71
72 PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT = nullptr;
73
74 {
75 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress");
76
77 QueryDeviceAttribEXT = reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
78 eglGetProcAddress("eglQueryDeviceAttribEXT"));
79
80 RETURN_ON_FAILURE(
81 QueryDeviceAttribEXT,
82 "Failed to get the eglQueryDeviceAttribEXT function from ANGLE",
83 device_object);
84 }
85
86 {
87 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT");
88
89 RETURN_ON_FAILURE(
90 QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device),
91 "The eglQueryDisplayAttribEXT function failed to get the EGL device",
92 device_object);
93 }
94
95 RETURN_ON_FAILURE(egl_device, "Failed to get the EGL device", device_object);
96
97 {
98 TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT");
99
100 RETURN_ON_FAILURE(
101 QueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(egl_device),
102 object_type, &device),
103 "The eglQueryDeviceAttribEXT function failed to get the device",
104 device_object);
105
106 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object);
107 }
108
109 device_object = reinterpret_cast<T*>(device);
110 return device_object;
111 }
112
113 D3D11VideoDecodeAccelerator::D3D11VideoDecodeAccelerator(
114 const GetGLContextCallback& get_gl_context_cb,
115 const MakeGLContextCurrentCallback& make_context_current_cb)
116 : get_gl_context_cb_(get_gl_context_cb),
117 make_context_current_cb_(make_context_current_cb) {}
118
119 D3D11VideoDecodeAccelerator::~D3D11VideoDecodeAccelerator() {}
120
121 bool D3D11VideoDecodeAccelerator::Initialize(const Config& config,
122 Client* client) {
123 client_ = client;
124 make_context_current_cb_.Run();
125
126 device_ = QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE);
127 device_->GetImmediateContext(device_context_.Receive());
128
129 HRESULT hr = device_context_.QueryInterface(video_context_.Receive());
130 CHECK(SUCCEEDED(hr));
131
132 hr = device_.QueryInterface(video_device_.Receive());
133 CHECK(SUCCEEDED(hr));
134
135 bool is_h264 =
136 config.profile >= H264PROFILE_MIN && config.profile <= H264PROFILE_MAX;
137 if (!is_h264)
138 return false;
139
140 GUID needed_guid;
141 memcpy(&needed_guid, &D3D11_DECODER_PROFILE_H264_VLD_NOFGT,
142 sizeof(needed_guid));
143 GUID decoder_guid = {};
144
145 {
146 // Enumerate supported video profiles and look for the H264 profile.
147 bool found = false;
148 UINT profile_count = video_device_->GetVideoDecoderProfileCount();
149 for (UINT profile_idx = 0; profile_idx < profile_count; profile_idx++) {
150 GUID profile_id = {};
151 hr = video_device_->GetVideoDecoderProfile(profile_idx, &profile_id);
152 if (SUCCEEDED(hr) && (profile_id == needed_guid)) {
153 decoder_guid = profile_id;
154 found = true;
155 break;
156 }
157 }
158 CHECK(found);
159 }
160
161 D3D11_VIDEO_DECODER_DESC desc = {};
162 desc.Guid = decoder_guid;
163 desc.SampleWidth = 1920;
164 desc.SampleHeight = 1088;
165 desc.OutputFormat = DXGI_FORMAT_NV12;
166 UINT config_count = 0;
167 hr = video_device_->GetVideoDecoderConfigCount(&desc, &config_count);
168 if (FAILED(hr) || config_count == 0)
169 CHECK(false);
170
171 D3D11_VIDEO_DECODER_CONFIG dec_config = {};
172 for (UINT i = 0; i < config_count; i++) {
173 hr = video_device_->GetVideoDecoderConfig(&desc, i, &dec_config);
174 if (FAILED(hr))
175 CHECK(false);
176 if (dec_config.ConfigBitstreamRaw == 2)
177 break;
178 }
179 memcpy(&decoder_guid_, &decoder_guid, sizeof decoder_guid_);
180
181 base::win::ScopedComPtr<ID3D11VideoDecoder> video_decoder;
182 hr = video_device_->CreateVideoDecoder(&desc, &dec_config,
183 video_decoder.Receive());
184 CHECK(video_decoder.get());
185
186 h264_accelerator_.reset(new D3D11H264Accelerator(
187 this, video_decoder, video_device_, video_context_));
188 decoder_.reset(new media::H264Decoder(h264_accelerator_.get()));
189
190 return true;
191 }
192
193 void D3D11VideoDecodeAccelerator::Decode(
194 const BitstreamBuffer& bitstream_buffer) {
195 input_buffer_queue_.push_back(bitstream_buffer);
196 base::ThreadTaskRunnerHandle::Get()->PostTask(
197 FROM_HERE, base::Bind(&D3D11VideoDecodeAccelerator::DoDecode,
198 base::Unretained(this)));
199 }
200
201 void D3D11VideoDecodeAccelerator::DoDecode() {
202 if (!bitstream_buffer_) {
203 if (input_buffer_queue_.empty())
204 return;
205 BitstreamBuffer buffer = input_buffer_queue_.front();
206 bitstream_buffer_ =
207 base::MakeUnique<base::SharedMemory>(buffer.handle(), true);
208 bitstream_buffer_->Map(buffer.size());
209 bitstream_buffer_size_ = buffer.size();
210 input_buffer_id_ = buffer.id();
211 input_buffer_queue_.pop_front();
212 decoder_->SetStream((const uint8_t*)bitstream_buffer_->memory(),
213 bitstream_buffer_size_);
214 }
215
216 while (true) {
217 media::AcceleratedVideoDecoder::DecodeResult result = decoder_->Decode();
218 if (result == media::AcceleratedVideoDecoder::kRanOutOfStreamData) {
219 client_->NotifyEndOfBitstreamBuffer(input_buffer_id_);
220 bitstream_buffer_.reset();
221 break;
222 }
223 if (result == media::AcceleratedVideoDecoder::kRanOutOfSurfaces) {
224 return;
225 }
226 if (result == media::AcceleratedVideoDecoder::kAllocateNewSurfaces) {
227 client_->ProvidePictureBuffers(20, PIXEL_FORMAT_NV12, 2,
228 decoder_->GetPicSize(),
229 GL_TEXTURE_EXTERNAL_OES);
230 return;
231
232 } else {
233 LOG(ERROR) << "VDA Error " << result;
234 CHECK(false);
235 }
236 }
237
238 base::ThreadTaskRunnerHandle::Get()->PostTask(
239 FROM_HERE, base::Bind(&D3D11VideoDecodeAccelerator::DoDecode,
240 base::Unretained(this)));
241 }
242
243 void D3D11VideoDecodeAccelerator::AssignPictureBuffers(
244 const std::vector<PictureBuffer>& buffers) {
245 D3D11_TEXTURE2D_DESC texture_desc = {};
246 texture_desc.Width = decoder_->GetPicSize().width();
247 texture_desc.Height = decoder_->GetPicSize().height();
248 texture_desc.MipLevels = 1;
249 texture_desc.ArraySize = buffers.size();
250 texture_desc.Format = DXGI_FORMAT_NV12;
251 texture_desc.SampleDesc.Count = 1;
252 texture_desc.Usage = D3D11_USAGE_DEFAULT;
253 texture_desc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
254 texture_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
255
256 base::win::ScopedComPtr<ID3D11Texture2D> out_texture;
257 HRESULT hr =
258 device_->CreateTexture2D(&texture_desc, nullptr, out_texture.Receive());
259 CHECK(SUCCEEDED(hr));
260
261 make_context_current_cb_.Run();
262 picture_buffers_.clear();
263
264 for (size_t i = 0; i < buffers.size(); i++) {
265 picture_buffers_.push_back(
266 base::MakeUnique<D3D11PictureBuffer>(buffers[i], i));
267 picture_buffers_[i]->Init(video_device_, out_texture, decoder_guid_);
268 }
269 base::ThreadTaskRunnerHandle::Get()->PostTask(
270 FROM_HERE, base::Bind(&D3D11VideoDecodeAccelerator::DoDecode,
271 base::Unretained(this)));
272 }
273
274 void D3D11VideoDecodeAccelerator::ReusePictureBuffer(
275 int32_t picture_buffer_id) {
276 make_context_current_cb_.Run();
277 for (auto& buffer : picture_buffers_) {
278 if (buffer->picture_buffer().id() == picture_buffer_id) {
279 buffer->set_in_client_use(false);
280
281 break;
282 }
283 }
284 base::ThreadTaskRunnerHandle::Get()->PostTask(
285 FROM_HERE, base::Bind(&D3D11VideoDecodeAccelerator::DoDecode,
286 base::Unretained(this)));
287 }
288
289 D3D11PictureBuffer* D3D11VideoDecodeAccelerator::GetPicture() {
290 for (auto& buffer : picture_buffers_)
291 if (!buffer->in_client_use() && !buffer->in_picture_use()) {
292 return buffer.get();
293 }
294 return nullptr;
295 }
296
297 void D3D11VideoDecodeAccelerator::Flush() {
298 client_->NotifyFlushDone();
299 }
300
301 void D3D11VideoDecodeAccelerator::Reset() {
302 client_->NotifyResetDone();
303 }
304 void D3D11VideoDecodeAccelerator::Destroy() {}
305
306 bool D3D11VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
307 const base::WeakPtr<Client>& decode_client,
308 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
309 return false;
310 }
311
312 GLenum D3D11VideoDecodeAccelerator::GetSurfaceInternalFormat() const {
313 return GL_BGRA_EXT;
314 }
315
316 size_t D3D11VideoDecodeAccelerator::input_buffer_id() const {
317 return input_buffer_id_;
318 }
319
320 void D3D11VideoDecodeAccelerator::OutputResult(D3D11PictureBuffer* buffer,
321 size_t input_buffer_id) {
322 buffer->set_in_client_use(true);
323 Picture picture(buffer->picture_buffer().id(), input_buffer_id,
324 gfx::Rect(0, 0), gfx::ColorSpace(), false);
325 client_->PictureReady(picture);
326 }
327 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/d3d11_video_decode_accelerator_win.h ('k') | media/gpu/gpu_video_decode_accelerator_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698