FFmpeg
hwcontext_d3d11va.c
Go to the documentation of this file.
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 "config.h"
20 
21 #include <windows.h>
22 
23 #define COBJMACROS
24 
25 #include <initguid.h>
26 #include <d3d11.h>
27 #include <dxgi1_2.h>
28 
29 #if HAVE_DXGIDEBUG_H
30 #include <dxgidebug.h>
31 #endif
32 
33 #include "avassert.h"
34 #include "common.h"
35 #include "hwcontext.h"
36 #include "hwcontext_d3d11va.h"
37 #include "hwcontext_internal.h"
38 #include "imgutils.h"
39 #include "pixdesc.h"
40 #include "pixfmt.h"
41 #include "thread.h"
42 #include "compat/w32dlfcn.h"
43 
44 typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
45 
47 
49 static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice;
50 
51 static av_cold void load_functions(void)
52 {
53 #if !HAVE_UWP
54  // We let these "leak" - this is fine, as unloading has no great benefit, and
55  // Windows will mark a DLL as loaded forever if its internal refcount overflows
56  // from too many LoadLibrary calls.
57  HANDLE d3dlib, dxgilib;
58 
59  d3dlib = dlopen("d3d11.dll", 0);
60  dxgilib = dlopen("dxgi.dll", 0);
61  if (!d3dlib || !dxgilib)
62  return;
63 
64  mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice");
65  mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory1");
66  if (!mCreateDXGIFactory)
67  mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory");
68 #else
69  // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't available,
70  // only CreateDXGIFactory1
71  mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
72  mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
73 #endif
74 }
75 
76 typedef struct D3D11VAFramesContext {
79 
80  DXGI_FORMAT format;
81 
82  ID3D11Texture2D *staging_texture;
84 
85 static const struct {
86  DXGI_FORMAT d3d_format;
88 } supported_formats[] = {
89  { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
90  { DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
92  { DXGI_FORMAT_R10G10B10A2_UNORM, AV_PIX_FMT_X2BGR10 },
94  { DXGI_FORMAT_AYUV, AV_PIX_FMT_VUYX },
95  { DXGI_FORMAT_YUY2, AV_PIX_FMT_YUYV422 },
96  { DXGI_FORMAT_Y210, AV_PIX_FMT_Y210 },
97  { DXGI_FORMAT_Y410, AV_PIX_FMT_XV30 },
98  { DXGI_FORMAT_P016, AV_PIX_FMT_P012 },
99  { DXGI_FORMAT_Y216, AV_PIX_FMT_Y212 },
100  { DXGI_FORMAT_Y416, AV_PIX_FMT_XV36 },
101  // Special opaque formats. The pix_fmt is merely a place holder, as the
102  // opaque format cannot be accessed directly.
103  { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
104 };
105 
106 static void d3d11va_default_lock(void *ctx)
107 {
108  WaitForSingleObjectEx(ctx, INFINITE, FALSE);
109 }
110 
111 static void d3d11va_default_unlock(void *ctx)
112 {
113  ReleaseMutex(ctx);
114 }
115 
117 {
118  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
119  D3D11VAFramesContext *s = ctx->internal->priv;
120 
121  if (frames_hwctx->texture)
122  ID3D11Texture2D_Release(frames_hwctx->texture);
123  frames_hwctx->texture = NULL;
124 
125  if (s->staging_texture)
126  ID3D11Texture2D_Release(s->staging_texture);
127  s->staging_texture = NULL;
128 
129  av_freep(&frames_hwctx->texture_infos);
130 }
131 
133  const void *hwconfig,
134  AVHWFramesConstraints *constraints)
135 {
136  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
137  int nb_sw_formats = 0;
138  HRESULT hr;
139  int i;
140 
142  sizeof(*constraints->valid_sw_formats));
143  if (!constraints->valid_sw_formats)
144  return AVERROR(ENOMEM);
145 
146  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
147  UINT format_support = 0;
148  hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support);
149  if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
150  constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt;
151  }
152  constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
153 
154  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
155  if (!constraints->valid_hw_formats)
156  return AVERROR(ENOMEM);
157 
158  constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11;
159  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
160 
161  return 0;
162 }
163 
164 static void free_texture(void *opaque, uint8_t *data)
165 {
166  ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
167  av_free(data);
168 }
169 
170 static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
171 {
172  AVBufferRef *buf;
174  D3D11VAFramesContext *s = ctx->internal->priv;
175  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
176  if (!desc) {
177  ID3D11Texture2D_Release(tex);
178  return NULL;
179  }
180 
181  if (s->nb_surfaces <= s->nb_surfaces_used) {
182  frames_hwctx->texture_infos = av_realloc_f(frames_hwctx->texture_infos,
183  s->nb_surfaces_used + 1,
184  sizeof(*frames_hwctx->texture_infos));
185  if (!frames_hwctx->texture_infos) {
186  ID3D11Texture2D_Release(tex);
187  return NULL;
188  }
189  s->nb_surfaces = s->nb_surfaces_used + 1;
190  }
191 
192  frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex;
193  frames_hwctx->texture_infos[s->nb_surfaces_used].index = index;
194  s->nb_surfaces_used++;
195 
196  desc->texture = tex;
197  desc->index = index;
198 
199  buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
200  if (!buf) {
201  ID3D11Texture2D_Release(tex);
202  av_free(desc);
203  return NULL;
204  }
205 
206  return buf;
207 }
208 
210 {
211  D3D11VAFramesContext *s = ctx->internal->priv;
212  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
213  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
214  HRESULT hr;
215  ID3D11Texture2D *tex;
216  D3D11_TEXTURE2D_DESC texDesc = {
217  .Width = ctx->width,
218  .Height = ctx->height,
219  .MipLevels = 1,
220  .Format = s->format,
221  .SampleDesc = { .Count = 1 },
222  .ArraySize = 1,
223  .Usage = D3D11_USAGE_DEFAULT,
224  .BindFlags = hwctx->BindFlags,
225  .MiscFlags = hwctx->MiscFlags,
226  };
227 
228  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
229  if (FAILED(hr)) {
230  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
231  return NULL;
232  }
233 
234  return wrap_texture_buf(ctx, tex, 0);
235 }
236 
237 static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
238 {
240  D3D11VAFramesContext *s = ctx->internal->priv;
241  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
242  D3D11_TEXTURE2D_DESC texDesc;
243 
244  if (!hwctx->texture)
245  return d3d11va_alloc_single(ctx);
246 
247  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
248 
249  if (s->nb_surfaces_used >= texDesc.ArraySize) {
250  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
251  return NULL;
252  }
253 
254  ID3D11Texture2D_AddRef(hwctx->texture);
255  return wrap_texture_buf(ctx, hwctx->texture, s->nb_surfaces_used);
256 }
257 
259 {
260  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
261  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
262  D3D11VAFramesContext *s = ctx->internal->priv;
263 
264  int i;
265  HRESULT hr;
266  D3D11_TEXTURE2D_DESC texDesc;
267 
268  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
269  if (ctx->sw_format == supported_formats[i].pix_fmt) {
270  s->format = supported_formats[i].d3d_format;
271  break;
272  }
273  }
275  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
276  av_get_pix_fmt_name(ctx->sw_format));
277  return AVERROR(EINVAL);
278  }
279 
280  texDesc = (D3D11_TEXTURE2D_DESC){
281  .Width = ctx->width,
282  .Height = ctx->height,
283  .MipLevels = 1,
284  .Format = s->format,
285  .SampleDesc = { .Count = 1 },
286  .ArraySize = ctx->initial_pool_size,
287  .Usage = D3D11_USAGE_DEFAULT,
288  .BindFlags = hwctx->BindFlags,
289  .MiscFlags = hwctx->MiscFlags,
290  };
291 
292  if (hwctx->texture) {
293  D3D11_TEXTURE2D_DESC texDesc2;
294  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
295 
296  if (texDesc.Width != texDesc2.Width ||
297  texDesc.Height != texDesc2.Height ||
298  texDesc.Format != texDesc2.Format) {
299  av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
300  return AVERROR(EINVAL);
301  }
302 
303  ctx->initial_pool_size = texDesc2.ArraySize;
304  hwctx->BindFlags = texDesc2.BindFlags;
305  hwctx->MiscFlags = texDesc2.MiscFlags;
306  } else if (!(texDesc.BindFlags & D3D11_BIND_RENDER_TARGET) && texDesc.ArraySize > 0) {
307  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
308  if (FAILED(hr)) {
309  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
310  return AVERROR_UNKNOWN;
311  }
312  }
313 
314  hwctx->texture_infos = av_realloc_f(NULL, ctx->initial_pool_size, sizeof(*hwctx->texture_infos));
315  if (!hwctx->texture_infos)
316  return AVERROR(ENOMEM);
317  s->nb_surfaces = ctx->initial_pool_size;
318 
319  ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
321  if (!ctx->internal->pool_internal)
322  return AVERROR(ENOMEM);
323 
324  return 0;
325 }
326 
328 {
330 
331  frame->buf[0] = av_buffer_pool_get(ctx->pool);
332  if (!frame->buf[0])
333  return AVERROR(ENOMEM);
334 
336 
337  frame->data[0] = (uint8_t *)desc->texture;
338  frame->data[1] = (uint8_t *)desc->index;
340  frame->width = ctx->width;
341  frame->height = ctx->height;
342 
343  return 0;
344 }
345 
348  enum AVPixelFormat **formats)
349 {
350  D3D11VAFramesContext *s = ctx->internal->priv;
351  enum AVPixelFormat *fmts;
352 
353  fmts = av_malloc_array(2, sizeof(*fmts));
354  if (!fmts)
355  return AVERROR(ENOMEM);
356 
357  fmts[0] = ctx->sw_format;
358  fmts[1] = AV_PIX_FMT_NONE;
359 
360  // Don't signal support for opaque formats. Actual access would fail.
361  if (s->format == DXGI_FORMAT_420_OPAQUE)
362  fmts[0] = AV_PIX_FMT_NONE;
363 
364  *formats = fmts;
365 
366  return 0;
367 }
368 
370 {
371  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
372  D3D11VAFramesContext *s = ctx->internal->priv;
373  HRESULT hr;
374  D3D11_TEXTURE2D_DESC texDesc = {
375  .Width = ctx->width,
376  .Height = ctx->height,
377  .MipLevels = 1,
378  .Format = format,
379  .SampleDesc = { .Count = 1 },
380  .ArraySize = 1,
381  .Usage = D3D11_USAGE_STAGING,
382  .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,
383  };
384 
385  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
386  if (FAILED(hr)) {
387  av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
388  return AVERROR_UNKNOWN;
389  }
390 
391  return 0;
392 }
393 
394 static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
396  D3D11_TEXTURE2D_DESC *desc,
397  D3D11_MAPPED_SUBRESOURCE *map)
398 {
399  int i;
400 
401  for (i = 0; i < 4; i++)
402  linesize[i] = map->RowPitch;
403 
404  av_image_fill_pointers(data, ctx->sw_format, desc->Height,
405  (uint8_t*)map->pData, linesize);
406 }
407 
409  const AVFrame *src)
410 {
411  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
412  D3D11VAFramesContext *s = ctx->internal->priv;
413  int download = src->format == AV_PIX_FMT_D3D11;
414  const AVFrame *frame = download ? src : dst;
415  const AVFrame *other = download ? dst : src;
416  // (The interface types are compatible.)
417  ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
418  int index = (intptr_t)frame->data[1];
419  ID3D11Resource *staging;
420  int w = FFMIN(dst->width, src->width);
421  int h = FFMIN(dst->height, src->height);
422  uint8_t *map_data[4];
423  int map_linesize[4];
424  D3D11_TEXTURE2D_DESC desc;
425  D3D11_MAPPED_SUBRESOURCE map;
426  HRESULT hr;
427  int res;
428 
429  if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
430  return AVERROR(EINVAL);
431 
432  device_hwctx->lock(device_hwctx->lock_ctx);
433 
434  if (!s->staging_texture) {
435  ID3D11Texture2D_GetDesc((ID3D11Texture2D *)texture, &desc);
436  res = d3d11va_create_staging_texture(ctx, desc.Format);
437  if (res < 0)
438  return res;
439  }
440 
441  staging = (ID3D11Resource *)s->staging_texture;
442 
443  ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
444 
445  if (download) {
446  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
447  staging, 0, 0, 0, 0,
448  texture, index, NULL);
449 
450  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
451  staging, 0, D3D11_MAP_READ, 0, &map);
452  if (FAILED(hr))
453  goto map_failed;
454 
455  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
456 
457  av_image_copy2(dst->data, dst->linesize, map_data, map_linesize,
458  ctx->sw_format, w, h);
459 
460  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
461  } else {
462  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
463  staging, 0, D3D11_MAP_WRITE, 0, &map);
464  if (FAILED(hr))
465  goto map_failed;
466 
467  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
468 
469  av_image_copy2(map_data, map_linesize, src->data, src->linesize,
470  ctx->sw_format, w, h);
471 
472  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
473 
474  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
475  texture, index, 0, 0, 0,
476  staging, 0, NULL);
477  }
478 
479  device_hwctx->unlock(device_hwctx->lock_ctx);
480  return 0;
481 
482 map_failed:
483  av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
484  device_hwctx->unlock(device_hwctx->lock_ctx);
485  return AVERROR_UNKNOWN;
486 }
487 
489 {
490  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
491  HRESULT hr;
492 
493  if (!device_hwctx->lock) {
494  device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
495  if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
496  av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
497  return AVERROR(EINVAL);
498  }
499  device_hwctx->lock = d3d11va_default_lock;
500  device_hwctx->unlock = d3d11va_default_unlock;
501  }
502 
503  if (!device_hwctx->device_context) {
504  ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
505  if (!device_hwctx->device_context)
506  return AVERROR_UNKNOWN;
507  }
508 
509  if (!device_hwctx->video_device) {
510  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
511  (void **)&device_hwctx->video_device);
512  if (FAILED(hr))
513  return AVERROR_UNKNOWN;
514  }
515 
516  if (!device_hwctx->video_context) {
517  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
518  (void **)&device_hwctx->video_context);
519  if (FAILED(hr))
520  return AVERROR_UNKNOWN;
521  }
522 
523  return 0;
524 }
525 
527 {
528  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
529 
530  if (device_hwctx->device) {
531  ID3D11Device_Release(device_hwctx->device);
532  device_hwctx->device = NULL;
533  }
534 
535  if (device_hwctx->device_context) {
536  ID3D11DeviceContext_Release(device_hwctx->device_context);
537  device_hwctx->device_context = NULL;
538  }
539 
540  if (device_hwctx->video_device) {
541  ID3D11VideoDevice_Release(device_hwctx->video_device);
542  device_hwctx->video_device = NULL;
543  }
544 
545  if (device_hwctx->video_context) {
546  ID3D11VideoContext_Release(device_hwctx->video_context);
547  device_hwctx->video_context = NULL;
548  }
549 
550  if (device_hwctx->lock == d3d11va_default_lock) {
551  CloseHandle(device_hwctx->lock_ctx);
552  device_hwctx->lock_ctx = INVALID_HANDLE_VALUE;
553  device_hwctx->lock = NULL;
554  }
555 }
556 
557 static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
558  AVDictionary *opts, int flags)
559 {
560  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
561 
562  HRESULT hr;
563  IDXGIAdapter *pAdapter = NULL;
564  ID3D10Multithread *pMultithread;
565  UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
566  int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
567  int ret;
568 
569  // (On UWP we can't check this.)
570 #if !HAVE_UWP
571  if (!LoadLibrary("d3d11_1sdklayers.dll"))
572  is_debug = 0;
573 #endif
574 
575  if (is_debug)
576  creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
577 
579  return AVERROR_UNKNOWN;
581  av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n");
582  return AVERROR_UNKNOWN;
583  }
584 
585  if (device) {
586  IDXGIFactory2 *pDXGIFactory;
587  hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
588  if (SUCCEEDED(hr)) {
589  int adapter = atoi(device);
590  if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
591  pAdapter = NULL;
592  IDXGIFactory2_Release(pDXGIFactory);
593  }
594  }
595 
596  if (pAdapter) {
597  DXGI_ADAPTER_DESC desc;
598  hr = IDXGIAdapter2_GetDesc(pAdapter, &desc);
599  if (!FAILED(hr)) {
600  av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n",
601  desc.VendorId, desc.DeviceId, desc.Description);
602  }
603  }
604 
605  hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
606  D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
607  if (pAdapter)
608  IDXGIAdapter_Release(pAdapter);
609  if (FAILED(hr)) {
610  av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
611  return AVERROR_UNKNOWN;
612  }
613 
614  hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
615  if (SUCCEEDED(hr)) {
616  ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
617  ID3D10Multithread_Release(pMultithread);
618  }
619 
620 #if !HAVE_UWP && HAVE_DXGIDEBUG_H
621  if (is_debug) {
622  HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll");
623  if (dxgidebug_dll) {
624  HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug)
625  = (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface");
626  if (pf_DXGIGetDebugInterface) {
627  IDXGIDebug *dxgi_debug = NULL;
628  hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug);
629  if (SUCCEEDED(hr) && dxgi_debug)
630  IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
631  }
632  }
633  }
634 #endif
635 
636  return 0;
637 }
638 
641  .name = "D3D11VA",
642 
643  .device_hwctx_size = sizeof(AVD3D11VADeviceContext),
644  .frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
645  .frames_priv_size = sizeof(D3D11VAFramesContext),
646 
647  .device_create = d3d11va_device_create,
649  .device_uninit = d3d11va_device_uninit,
650  .frames_get_constraints = d3d11va_frames_get_constraints,
651  .frames_init = d3d11va_frames_init,
652  .frames_uninit = d3d11va_frames_uninit,
653  .frames_get_buffer = d3d11va_get_buffer,
654  .transfer_get_formats = d3d11va_transfer_get_formats,
655  .transfer_data_to = d3d11va_transfer_data,
656  .transfer_data_from = d3d11va_transfer_data,
657 
659 };
d3d11va_alloc_single
static AVBufferRef * d3d11va_alloc_single(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:209
formats
formats
Definition: signature.h:48
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
DXGI_FORMAT_B8G8R8A8_UNORM
@ DXGI_FORMAT_B8G8R8A8_UNORM
Definition: dds.c:91
thread.h
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
d3d11va_transfer_get_formats
static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_d3d11va.c:346
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
pixdesc.h
AVFrame::width
int width
Definition: frame.h:412
AVD3D11VAFramesContext::MiscFlags
UINT MiscFlags
D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation.
Definition: hwcontext_d3d11va.h:166
w
uint8_t w
Definition: llviddspenc.c:38
data
const char data[16]
Definition: mxf.c:148
d3d11va_transfer_data
static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_d3d11va.c:408
AV_PIX_FMT_XV30
#define AV_PIX_FMT_XV30
Definition: pixfmt.h:524
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
AVDictionary
Definition: dict.c:34
AVHWFramesConstraints::valid_hw_formats
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:458
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:590
fill_texture_ptrs
static void fill_texture_ptrs(uint8_t *data[4], int linesize[4], AVHWFramesContext *ctx, D3D11_TEXTURE2D_DESC *desc, D3D11_MAPPED_SUBRESOURCE *map)
Definition: hwcontext_d3d11va.c:394
PFN_CREATE_DXGI_FACTORY
HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
Definition: hwcontext_d3d11va.c:44
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
AVD3D11VAFramesContext::BindFlags
UINT BindFlags
D3D11_TEXTURE2D_DESC.BindFlags used for texture creation.
Definition: hwcontext_d3d11va.h:160
ff_hwcontext_type_d3d11va
const HWContextType ff_hwcontext_type_d3d11va
Definition: hwcontext_d3d11va.c:639
d3d11va_get_buffer
static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_d3d11va.c:327
d3d_format
DXGI_FORMAT d3d_format
Definition: hwcontext_d3d11va.c:86
AVD3D11FrameDescriptor::texture
ID3D11Texture2D * texture
The texture in which the frame is located.
Definition: hwcontext_d3d11va.h:117
d3d11va_create_staging_texture
static int d3d11va_create_staging_texture(AVHWFramesContext *ctx, DXGI_FORMAT format)
Definition: hwcontext_d3d11va.c:369
D3D11VAFramesContext::format
DXGI_FORMAT format
Definition: hwcontext_d3d11va.c:80
AV_HWDEVICE_TYPE_D3D11VA
@ AV_HWDEVICE_TYPE_D3D11VA
Definition: hwcontext.h:35
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
d3d11va_frames_uninit
static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:116
d3d11va_default_unlock
static void d3d11va_default_unlock(void *ctx)
Definition: hwcontext_d3d11va.c:111
D3D11VAFramesContext::nb_surfaces_used
int nb_surfaces_used
Definition: hwcontext_d3d11va.c:78
av_image_fill_pointers
int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, uint8_t *ptr, const int linesizes[4])
Fill plane data pointers for an image with pixel format pix_fmt and height height.
Definition: imgutils.c:145
d3d11va_frames_get_constraints
static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_d3d11va.c:132
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:522
avassert.h
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
ff_thread_once
static int ff_thread_once(char *control, void(*routine)(void))
Definition: thread.h:203
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
load_functions
static av_cold void load_functions(void)
Definition: hwcontext_d3d11va.c:51
device_init
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Definition: v4l2.c:204
AVHWFramesConstraints::valid_sw_formats
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:465
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:62
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:384
AVD3D11VADeviceContext::video_context
ID3D11VideoContext * video_context
If unset, this will be set from the device_context field on init.
Definition: hwcontext_d3d11va.h:80
s
#define s(width, name)
Definition: cbs_vp9.c:198
AVD3D11VADeviceContext::device
ID3D11Device * device
Device used for texture creation and access.
Definition: hwcontext_d3d11va.h:56
d3d11va_device_create
static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_d3d11va.c:557
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
functions_loaded
static AVOnce functions_loaded
Definition: hwcontext_d3d11va.c:46
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:304
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
frame
static AVFrame * frame
Definition: demux_decode.c:54
av_realloc_f
#define av_realloc_f(p, o, n)
Definition: tableprint_vlc.h:32
opts
AVDictionary * opts
Definition: movenc.c:50
D3D11VAFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_d3d11va.c:77
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:201
AVD3D11VAFramesContext::texture_infos
AVD3D11FrameDescriptor * texture_infos
In case if texture structure member above is not NULL contains the same texture pointer for all eleme...
Definition: hwcontext_d3d11va.h:175
AVD3D11VADeviceContext::lock_ctx
void * lock_ctx
Definition: hwcontext_d3d11va.h:96
NULL
#define NULL
Definition: coverity.c:32
d3d11va_default_lock
static void d3d11va_default_lock(void *ctx)
Definition: hwcontext_d3d11va.c:106
AVD3D11VADeviceContext::video_device
ID3D11VideoDevice * video_device
If unset, this will be set from the device field on init.
Definition: hwcontext_d3d11va.h:72
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
wrap_texture_buf
static AVBufferRef * wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
Definition: hwcontext_d3d11va.c:170
AVOnce
#define AVOnce
Definition: thread.h:200
index
int index
Definition: gxfenc.c:89
AVD3D11VADeviceContext::unlock
void(* unlock)(void *lock_ctx)
Definition: hwcontext_d3d11va.h:95
AVD3D11VAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_d3d11va.h:131
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:527
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:519
size
int size
Definition: twinvq_data.h:10344
d3d11va_frames_init
static int d3d11va_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:258
mCreateDXGIFactory
static PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory
Definition: hwcontext_d3d11va.c:48
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:427
free_texture
static void free_texture(void *opaque, uint8_t *data)
Definition: hwcontext_d3d11va.c:164
AV_PIX_FMT_Y212
#define AV_PIX_FMT_Y212
Definition: pixfmt.h:523
AVD3D11VAFramesContext::texture
ID3D11Texture2D * texture
The canonical texture used for pool allocation.
Definition: hwcontext_d3d11va.h:152
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:333
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
DXGI_FORMAT_R16G16B16A16_FLOAT
@ DXGI_FORMAT_R16G16B16A16_FLOAT
Definition: dds.c:62
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
AVD3D11VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d11va.h:45
AVD3D11FrameDescriptor::index
intptr_t index
The index into the array texture element representing the frame, or 0 if the texture is not an array ...
Definition: hwcontext_d3d11va.h:125
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AVD3D11VADeviceContext::lock
void(* lock)(void *lock_ctx)
Callbacks for locking.
Definition: hwcontext_d3d11va.h:94
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:415
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
ret
ret
Definition: filter_design.txt:187
pixfmt.h
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
mD3D11CreateDevice
static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice
Definition: hwcontext_d3d11va.c:49
supported_formats
static const struct @341 supported_formats[]
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:752
AVFrame::height
int height
Definition: frame.h:412
d3d11va_pool_alloc
static AVBufferRef * d3d11va_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_d3d11va.c:237
pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_d3d11va.c:87
av_image_copy2
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition: imgutils.h:184
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
D3D11VAFramesContext
Definition: hwcontext_d3d11va.c:76
d3d11va_device_uninit
static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
Definition: hwcontext_d3d11va.c:526
D3D11VAFramesContext::staging_texture
ID3D11Texture2D * staging_texture
Definition: hwcontext_d3d11va.c:82
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:518
desc
const char * desc
Definition: libsvtav1.c:83
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
d3d11va_device_init
static int d3d11va_device_init(AVHWDeviceContext *hwdev)
Definition: hwcontext_d3d11va.c:488
hwcontext_internal.h
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AV_PIX_FMT_RGBAF16
#define AV_PIX_FMT_RGBAF16
Definition: pixfmt.h:536
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
AVD3D11FrameDescriptor
D3D11 frame descriptor for pool allocation.
Definition: hwcontext_d3d11va.h:109
imgutils.h
AV_PIX_FMT_XV36
#define AV_PIX_FMT_XV36
Definition: pixfmt.h:525
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
hwcontext.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:385
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
HWContextType
Definition: hwcontext_internal.h:29
AVD3D11VADeviceContext::device_context
ID3D11DeviceContext * device_context
If unset, this will be set from the device field on init.
Definition: hwcontext_d3d11va.h:64
h
h
Definition: vp9dsp_template.c:2038
AV_PIX_FMT_VUYX
@ AV_PIX_FMT_VUYX
packed VUYX 4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined
Definition: pixfmt.h:403
hwcontext_d3d11va.h
w32dlfcn.h
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2884