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

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

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

Powered by Google App Engine
This is Rietveld 408576698