blob: 4ed0d56aea7282e50e3a0edaa2a142eba1094e70
1 | /* |
2 | * This file is part of FFmpeg. |
3 | * |
4 | * FFmpeg is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * FFmpeg is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with FFmpeg; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include <windows.h> |
20 | |
21 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 |
22 | #undef _WIN32_WINNT |
23 | #define _WIN32_WINNT 0x0600 |
24 | #endif |
25 | #define DXVA2API_USE_BITFIELDS |
26 | #define COBJMACROS |
27 | |
28 | #include <d3d9.h> |
29 | #include <dxva2api.h> |
30 | #include <initguid.h> |
31 | |
32 | #include "avassert.h" |
33 | #include "common.h" |
34 | #include "hwcontext.h" |
35 | #include "hwcontext_dxva2.h" |
36 | #include "hwcontext_internal.h" |
37 | #include "imgutils.h" |
38 | #include "pixdesc.h" |
39 | #include "pixfmt.h" |
40 | #include "compat/w32dlfcn.h" |
41 | |
42 | typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT); |
43 | typedef HRESULT WINAPI pDirect3DCreate9Ex(UINT, IDirect3D9Ex **); |
44 | typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **); |
45 | |
46 | #define FF_D3DCREATE_FLAGS (D3DCREATE_SOFTWARE_VERTEXPROCESSING | \ |
47 | D3DCREATE_MULTITHREADED | \ |
48 | D3DCREATE_FPU_PRESERVE) |
49 | |
50 | static const D3DPRESENT_PARAMETERS dxva2_present_params = { |
51 | .Windowed = TRUE, |
52 | .BackBufferWidth = 640, |
53 | .BackBufferHeight = 480, |
54 | .BackBufferCount = 0, |
55 | .SwapEffect = D3DSWAPEFFECT_DISCARD, |
56 | .Flags = D3DPRESENTFLAG_VIDEO, |
57 | }; |
58 | |
59 | typedef struct DXVA2Mapping { |
60 | uint32_t palette_dummy[256]; |
61 | } DXVA2Mapping; |
62 | |
63 | typedef struct DXVA2FramesContext { |
64 | IDirect3DSurface9 **surfaces_internal; |
65 | int nb_surfaces_used; |
66 | |
67 | HANDLE device_handle; |
68 | IDirectXVideoAccelerationService *service; |
69 | |
70 | D3DFORMAT format; |
71 | } DXVA2FramesContext; |
72 | |
73 | typedef struct DXVA2DevicePriv { |
74 | HMODULE d3dlib; |
75 | HMODULE dxva2lib; |
76 | |
77 | HANDLE device_handle; |
78 | |
79 | IDirect3D9 *d3d9; |
80 | IDirect3DDevice9 *d3d9device; |
81 | } DXVA2DevicePriv; |
82 | |
83 | static const struct { |
84 | D3DFORMAT d3d_format; |
85 | enum AVPixelFormat pix_fmt; |
86 | } supported_formats[] = { |
87 | { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 }, |
88 | { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 }, |
89 | { D3DFMT_P8, AV_PIX_FMT_PAL8 }, |
90 | }; |
91 | |
92 | DEFINE_GUID(video_decoder_service, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); |
93 | DEFINE_GUID(video_processor_service, 0xfc51a552, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); |
94 | |
95 | static void dxva2_frames_uninit(AVHWFramesContext *ctx) |
96 | { |
97 | AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx; |
98 | AVDXVA2FramesContext *frames_hwctx = ctx->hwctx; |
99 | DXVA2FramesContext *s = ctx->internal->priv; |
100 | int i; |
101 | |
102 | if (frames_hwctx->decoder_to_release) |
103 | IDirectXVideoDecoder_Release(frames_hwctx->decoder_to_release); |
104 | |
105 | if (s->surfaces_internal) { |
106 | for (i = 0; i < frames_hwctx->nb_surfaces; i++) { |
107 | if (s->surfaces_internal[i]) |
108 | IDirect3DSurface9_Release(s->surfaces_internal[i]); |
109 | } |
110 | } |
111 | av_freep(&s->surfaces_internal); |
112 | |
113 | if (s->service) { |
114 | IDirectXVideoAccelerationService_Release(s->service); |
115 | s->service = NULL; |
116 | } |
117 | |
118 | if (s->device_handle != INVALID_HANDLE_VALUE) { |
119 | IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, s->device_handle); |
120 | s->device_handle = INVALID_HANDLE_VALUE; |
121 | } |
122 | } |
123 | |
124 | static AVBufferRef *dxva2_pool_alloc(void *opaque, int size) |
125 | { |
126 | AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; |
127 | DXVA2FramesContext *s = ctx->internal->priv; |
128 | AVDXVA2FramesContext *hwctx = ctx->hwctx; |
129 | |
130 | if (s->nb_surfaces_used < hwctx->nb_surfaces) { |
131 | s->nb_surfaces_used++; |
132 | return av_buffer_create((uint8_t*)s->surfaces_internal[s->nb_surfaces_used - 1], |
133 | sizeof(*hwctx->surfaces), NULL, 0, 0); |
134 | } |
135 | |
136 | return NULL; |
137 | } |
138 | |
139 | static int dxva2_init_pool(AVHWFramesContext *ctx) |
140 | { |
141 | AVDXVA2FramesContext *frames_hwctx = ctx->hwctx; |
142 | AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx; |
143 | DXVA2FramesContext *s = ctx->internal->priv; |
144 | int decode = (frames_hwctx->surface_type == DXVA2_VideoDecoderRenderTarget); |
145 | |
146 | int i; |
147 | HRESULT hr; |
148 | |
149 | if (ctx->initial_pool_size <= 0) |
150 | return 0; |
151 | |
152 | hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &s->device_handle); |
153 | if (FAILED(hr)) { |
154 | av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); |
155 | return AVERROR_UNKNOWN; |
156 | } |
157 | |
158 | hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, |
159 | s->device_handle, |
160 | decode ? &video_decoder_service : &video_processor_service, |
161 | (void **)&s->service); |
162 | if (FAILED(hr)) { |
163 | av_log(ctx, AV_LOG_ERROR, "Failed to create the video service\n"); |
164 | return AVERROR_UNKNOWN; |
165 | } |
166 | |
167 | for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { |
168 | if (ctx->sw_format == supported_formats[i].pix_fmt) { |
169 | s->format = supported_formats[i].d3d_format; |
170 | break; |
171 | } |
172 | } |
173 | if (i == FF_ARRAY_ELEMS(supported_formats)) { |
174 | av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", |
175 | av_get_pix_fmt_name(ctx->sw_format)); |
176 | return AVERROR(EINVAL); |
177 | } |
178 | |
179 | s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size, |
180 | sizeof(*s->surfaces_internal)); |
181 | if (!s->surfaces_internal) |
182 | return AVERROR(ENOMEM); |
183 | |
184 | hr = IDirectXVideoAccelerationService_CreateSurface(s->service, |
185 | ctx->width, ctx->height, |
186 | ctx->initial_pool_size - 1, |
187 | s->format, D3DPOOL_DEFAULT, 0, |
188 | frames_hwctx->surface_type, |
189 | s->surfaces_internal, NULL); |
190 | if (FAILED(hr)) { |
191 | av_log(ctx, AV_LOG_ERROR, "Could not create the surfaces\n"); |
192 | return AVERROR_UNKNOWN; |
193 | } |
194 | |
195 | ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(*s->surfaces_internal), |
196 | ctx, dxva2_pool_alloc, NULL); |
197 | if (!ctx->internal->pool_internal) |
198 | return AVERROR(ENOMEM); |
199 | |
200 | frames_hwctx->surfaces = s->surfaces_internal; |
201 | frames_hwctx->nb_surfaces = ctx->initial_pool_size; |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | static int dxva2_frames_init(AVHWFramesContext *ctx) |
207 | { |
208 | AVDXVA2FramesContext *hwctx = ctx->hwctx; |
209 | DXVA2FramesContext *s = ctx->internal->priv; |
210 | int ret; |
211 | |
212 | if (hwctx->surface_type != DXVA2_VideoDecoderRenderTarget && |
213 | hwctx->surface_type != DXVA2_VideoProcessorRenderTarget) { |
214 | av_log(ctx, AV_LOG_ERROR, "Unknown surface type: %lu\n", |
215 | hwctx->surface_type); |
216 | return AVERROR(EINVAL); |
217 | } |
218 | |
219 | s->device_handle = INVALID_HANDLE_VALUE; |
220 | |
221 | /* init the frame pool if the caller didn't provide one */ |
222 | if (!ctx->pool) { |
223 | ret = dxva2_init_pool(ctx); |
224 | if (ret < 0) { |
225 | av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n"); |
226 | return ret; |
227 | } |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | static int dxva2_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) |
234 | { |
235 | frame->buf[0] = av_buffer_pool_get(ctx->pool); |
236 | if (!frame->buf[0]) |
237 | return AVERROR(ENOMEM); |
238 | |
239 | frame->data[3] = frame->buf[0]->data; |
240 | frame->format = AV_PIX_FMT_DXVA2_VLD; |
241 | frame->width = ctx->width; |
242 | frame->height = ctx->height; |
243 | |
244 | return 0; |
245 | } |
246 | |
247 | static int dxva2_transfer_get_formats(AVHWFramesContext *ctx, |
248 | enum AVHWFrameTransferDirection dir, |
249 | enum AVPixelFormat **formats) |
250 | { |
251 | enum AVPixelFormat *fmts; |
252 | |
253 | fmts = av_malloc_array(2, sizeof(*fmts)); |
254 | if (!fmts) |
255 | return AVERROR(ENOMEM); |
256 | |
257 | fmts[0] = ctx->sw_format; |
258 | fmts[1] = AV_PIX_FMT_NONE; |
259 | |
260 | *formats = fmts; |
261 | |
262 | return 0; |
263 | } |
264 | |
265 | static void dxva2_unmap_frame(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) |
266 | { |
267 | IDirect3DSurface9 *surface = (IDirect3DSurface9*)hwmap->source->data[3]; |
268 | IDirect3DSurface9_UnlockRect(surface); |
269 | av_freep(&hwmap->priv); |
270 | } |
271 | |
272 | static int dxva2_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, |
273 | int flags) |
274 | { |
275 | IDirect3DSurface9 *surface = (IDirect3DSurface9*)src->data[3]; |
276 | DXVA2Mapping *map; |
277 | D3DSURFACE_DESC surfaceDesc; |
278 | D3DLOCKED_RECT LockedRect; |
279 | HRESULT hr; |
280 | int i, err, nb_planes; |
281 | int lock_flags = 0; |
282 | |
283 | nb_planes = av_pix_fmt_count_planes(dst->format); |
284 | |
285 | hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); |
286 | if (FAILED(hr)) { |
287 | av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n"); |
288 | return AVERROR_UNKNOWN; |
289 | } |
290 | |
291 | if (!(flags & AV_HWFRAME_MAP_WRITE)) |
292 | lock_flags |= D3DLOCK_READONLY; |
293 | if (flags & AV_HWFRAME_MAP_OVERWRITE) |
294 | lock_flags |= D3DLOCK_DISCARD; |
295 | |
296 | hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, lock_flags); |
297 | if (FAILED(hr)) { |
298 | av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); |
299 | return AVERROR_UNKNOWN; |
300 | } |
301 | |
302 | map = av_mallocz(sizeof(*map)); |
303 | if (!map) |
304 | goto fail; |
305 | |
306 | err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, |
307 | dxva2_unmap_frame, map); |
308 | if (err < 0) { |
309 | av_freep(&map); |
310 | goto fail; |
311 | } |
312 | |
313 | for (i = 0; i < nb_planes; i++) |
314 | dst->linesize[i] = LockedRect.Pitch; |
315 | |
316 | av_image_fill_pointers(dst->data, dst->format, surfaceDesc.Height, |
317 | (uint8_t*)LockedRect.pBits, dst->linesize); |
318 | |
319 | if (dst->format == AV_PIX_FMT_PAL8) |
320 | dst->data[1] = (uint8_t*)map->palette_dummy; |
321 | |
322 | return 0; |
323 | fail: |
324 | IDirect3DSurface9_UnlockRect(surface); |
325 | return err; |
326 | } |
327 | |
328 | static int dxva2_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, |
329 | const AVFrame *src) |
330 | { |
331 | AVFrame *map; |
332 | int ret; |
333 | |
334 | if (src->format != ctx->sw_format) |
335 | return AVERROR(ENOSYS); |
336 | |
337 | map = av_frame_alloc(); |
338 | if (!map) |
339 | return AVERROR(ENOMEM); |
340 | map->format = dst->format; |
341 | |
342 | ret = dxva2_map_frame(ctx, map, dst, AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE); |
343 | if (ret < 0) |
344 | goto fail; |
345 | |
346 | av_image_copy(map->data, map->linesize, src->data, src->linesize, |
347 | ctx->sw_format, src->width, src->height); |
348 | |
349 | fail: |
350 | av_frame_free(&map); |
351 | return ret; |
352 | } |
353 | |
354 | static int dxva2_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, |
355 | const AVFrame *src) |
356 | { |
357 | AVFrame *map; |
358 | ptrdiff_t src_linesize[4], dst_linesize[4]; |
359 | int ret, i; |
360 | |
361 | if (dst->format != ctx->sw_format) |
362 | return AVERROR(ENOSYS); |
363 | |
364 | map = av_frame_alloc(); |
365 | if (!map) |
366 | return AVERROR(ENOMEM); |
367 | map->format = dst->format; |
368 | |
369 | ret = dxva2_map_frame(ctx, map, src, AV_HWFRAME_MAP_READ); |
370 | if (ret < 0) |
371 | goto fail; |
372 | |
373 | for (i = 0; i < 4; i++) { |
374 | dst_linesize[i] = dst->linesize[i]; |
375 | src_linesize[i] = map->linesize[i]; |
376 | } |
377 | av_image_copy_uc_from(dst->data, dst_linesize, map->data, src_linesize, |
378 | ctx->sw_format, src->width, src->height); |
379 | fail: |
380 | av_frame_free(&map); |
381 | return ret; |
382 | } |
383 | |
384 | static int dxva2_map_from(AVHWFramesContext *ctx, |
385 | AVFrame *dst, const AVFrame *src, int flags) |
386 | { |
387 | int err; |
388 | |
389 | if (dst->format != AV_PIX_FMT_NONE && dst->format != ctx->sw_format) |
390 | return AVERROR(ENOSYS); |
391 | dst->format = ctx->sw_format; |
392 | |
393 | err = dxva2_map_frame(ctx, dst, src, flags); |
394 | if (err < 0) |
395 | return err; |
396 | |
397 | err = av_frame_copy_props(dst, src); |
398 | if (err < 0) |
399 | return err; |
400 | |
401 | return 0; |
402 | } |
403 | |
404 | static void dxva2_device_free(AVHWDeviceContext *ctx) |
405 | { |
406 | AVDXVA2DeviceContext *hwctx = ctx->hwctx; |
407 | DXVA2DevicePriv *priv = ctx->user_opaque; |
408 | |
409 | if (hwctx->devmgr && priv->device_handle != INVALID_HANDLE_VALUE) |
410 | IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->device_handle); |
411 | |
412 | if (hwctx->devmgr) |
413 | IDirect3DDeviceManager9_Release(hwctx->devmgr); |
414 | |
415 | if (priv->d3d9device) |
416 | IDirect3DDevice9_Release(priv->d3d9device); |
417 | |
418 | if (priv->d3d9) |
419 | IDirect3D9_Release(priv->d3d9); |
420 | |
421 | if (priv->d3dlib) |
422 | dlclose(priv->d3dlib); |
423 | |
424 | if (priv->dxva2lib) |
425 | dlclose(priv->dxva2lib); |
426 | |
427 | av_freep(&ctx->user_opaque); |
428 | } |
429 | |
430 | static int dxva2_device_create9(AVHWDeviceContext *ctx, UINT adapter) |
431 | { |
432 | DXVA2DevicePriv *priv = ctx->user_opaque; |
433 | D3DPRESENT_PARAMETERS d3dpp = dxva2_present_params; |
434 | D3DDISPLAYMODE d3ddm; |
435 | HRESULT hr; |
436 | pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)dlsym(priv->d3dlib, "Direct3DCreate9"); |
437 | if (!createD3D) { |
438 | av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n"); |
439 | return AVERROR_UNKNOWN; |
440 | } |
441 | |
442 | priv->d3d9 = createD3D(D3D_SDK_VERSION); |
443 | if (!priv->d3d9) { |
444 | av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n"); |
445 | return AVERROR_UNKNOWN; |
446 | } |
447 | |
448 | IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm); |
449 | |
450 | d3dpp.BackBufferFormat = d3ddm.Format; |
451 | |
452 | hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(), |
453 | FF_D3DCREATE_FLAGS, |
454 | &d3dpp, &priv->d3d9device); |
455 | if (FAILED(hr)) { |
456 | av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n"); |
457 | return AVERROR_UNKNOWN; |
458 | } |
459 | |
460 | return 0; |
461 | } |
462 | |
463 | static int dxva2_device_create9ex(AVHWDeviceContext *ctx, UINT adapter) |
464 | { |
465 | DXVA2DevicePriv *priv = ctx->user_opaque; |
466 | D3DPRESENT_PARAMETERS d3dpp = dxva2_present_params; |
467 | D3DDISPLAYMODEEX modeex = {0}; |
468 | IDirect3D9Ex *d3d9ex = NULL; |
469 | IDirect3DDevice9Ex *exdev = NULL; |
470 | HRESULT hr; |
471 | pDirect3DCreate9Ex *createD3DEx = (pDirect3DCreate9Ex *)dlsym(priv->d3dlib, "Direct3DCreate9Ex"); |
472 | if (!createD3DEx) |
473 | return AVERROR(ENOSYS); |
474 | |
475 | hr = createD3DEx(D3D_SDK_VERSION, &d3d9ex); |
476 | if (FAILED(hr)) |
477 | return AVERROR_UNKNOWN; |
478 | |
479 | IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, adapter, &modeex, NULL); |
480 | |
481 | d3dpp.BackBufferFormat = modeex.Format; |
482 | |
483 | hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(), |
484 | FF_D3DCREATE_FLAGS, |
485 | &d3dpp, NULL, &exdev); |
486 | if (FAILED(hr)) { |
487 | IDirect3D9Ex_Release(d3d9ex); |
488 | return AVERROR_UNKNOWN; |
489 | } |
490 | |
491 | av_log(ctx, AV_LOG_VERBOSE, "Using D3D9Ex device.\n"); |
492 | priv->d3d9 = (IDirect3D9 *)d3d9ex; |
493 | priv->d3d9device = (IDirect3DDevice9 *)exdev; |
494 | return 0; |
495 | } |
496 | |
497 | static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device, |
498 | AVDictionary *opts, int flags) |
499 | { |
500 | AVDXVA2DeviceContext *hwctx = ctx->hwctx; |
501 | DXVA2DevicePriv *priv; |
502 | pCreateDeviceManager9 *createDeviceManager = NULL; |
503 | unsigned resetToken = 0; |
504 | UINT adapter = D3DADAPTER_DEFAULT; |
505 | HRESULT hr; |
506 | int err; |
507 | |
508 | if (device) |
509 | adapter = atoi(device); |
510 | |
511 | priv = av_mallocz(sizeof(*priv)); |
512 | if (!priv) |
513 | return AVERROR(ENOMEM); |
514 | |
515 | ctx->user_opaque = priv; |
516 | ctx->free = dxva2_device_free; |
517 | |
518 | priv->device_handle = INVALID_HANDLE_VALUE; |
519 | |
520 | priv->d3dlib = dlopen("d3d9.dll", 0); |
521 | if (!priv->d3dlib) { |
522 | av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n"); |
523 | return AVERROR_UNKNOWN; |
524 | } |
525 | priv->dxva2lib = dlopen("dxva2.dll", 0); |
526 | if (!priv->dxva2lib) { |
527 | av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n"); |
528 | return AVERROR_UNKNOWN; |
529 | } |
530 | |
531 | createDeviceManager = (pCreateDeviceManager9 *)dlsym(priv->dxva2lib, |
532 | "DXVA2CreateDirect3DDeviceManager9"); |
533 | if (!createDeviceManager) { |
534 | av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); |
535 | return AVERROR_UNKNOWN; |
536 | } |
537 | |
538 | if (dxva2_device_create9ex(ctx, adapter) < 0) { |
539 | // Retry with "classic" d3d9 |
540 | err = dxva2_device_create9(ctx, adapter); |
541 | if (err < 0) |
542 | return err; |
543 | } |
544 | |
545 | hr = createDeviceManager(&resetToken, &hwctx->devmgr); |
546 | if (FAILED(hr)) { |
547 | av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n"); |
548 | return AVERROR_UNKNOWN; |
549 | } |
550 | |
551 | hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken); |
552 | if (FAILED(hr)) { |
553 | av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n"); |
554 | return AVERROR_UNKNOWN; |
555 | } |
556 | |
557 | hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle); |
558 | if (FAILED(hr)) { |
559 | av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); |
560 | return AVERROR_UNKNOWN; |
561 | } |
562 | |
563 | return 0; |
564 | } |
565 | |
566 | const HWContextType ff_hwcontext_type_dxva2 = { |
567 | .type = AV_HWDEVICE_TYPE_DXVA2, |
568 | .name = "DXVA2", |
569 | |
570 | .device_hwctx_size = sizeof(AVDXVA2DeviceContext), |
571 | .frames_hwctx_size = sizeof(AVDXVA2FramesContext), |
572 | .frames_priv_size = sizeof(DXVA2FramesContext), |
573 | |
574 | .device_create = dxva2_device_create, |
575 | .frames_init = dxva2_frames_init, |
576 | .frames_uninit = dxva2_frames_uninit, |
577 | .frames_get_buffer = dxva2_get_buffer, |
578 | .transfer_get_formats = dxva2_transfer_get_formats, |
579 | .transfer_data_to = dxva2_transfer_data_to, |
580 | .transfer_data_from = dxva2_transfer_data_from, |
581 | .map_from = dxva2_map_from, |
582 | |
583 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_DXVA2_VLD, AV_PIX_FMT_NONE }, |
584 | }; |
585 |