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, "CreateDXGIFactory");
66 #else
67  // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't available,
68  // only CreateDXGIFactory1
69  mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
70  mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
71 #endif
72 }
73 
74 typedef struct D3D11VAFramesContext {
77 
78  DXGI_FORMAT format;
79 
80  ID3D11Texture2D *staging_texture;
82 
83 static const struct {
84  DXGI_FORMAT d3d_format;
86 } supported_formats[] = {
87  { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
88  { DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
90  { DXGI_FORMAT_R10G10B10A2_UNORM, AV_PIX_FMT_X2BGR10 },
92  // Special opaque formats. The pix_fmt is merely a place holder, as the
93  // opaque format cannot be accessed directly.
94  { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
95 };
96 
97 static void d3d11va_default_lock(void *ctx)
98 {
99  WaitForSingleObjectEx(ctx, INFINITE, FALSE);
100 }
101 
102 static void d3d11va_default_unlock(void *ctx)
103 {
104  ReleaseMutex(ctx);
105 }
106 
108 {
109  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
110  D3D11VAFramesContext *s = ctx->internal->priv;
111 
112  if (frames_hwctx->texture)
113  ID3D11Texture2D_Release(frames_hwctx->texture);
114  frames_hwctx->texture = NULL;
115 
116  if (s->staging_texture)
117  ID3D11Texture2D_Release(s->staging_texture);
118  s->staging_texture = NULL;
119 
120  av_freep(&frames_hwctx->texture_infos);
121 }
122 
124  const void *hwconfig,
125  AVHWFramesConstraints *constraints)
126 {
127  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
128  int nb_sw_formats = 0;
129  HRESULT hr;
130  int i;
131 
133  sizeof(*constraints->valid_sw_formats));
134  if (!constraints->valid_sw_formats)
135  return AVERROR(ENOMEM);
136 
137  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
138  UINT format_support = 0;
139  hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support);
140  if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
141  constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt;
142  }
143  constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
144 
145  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
146  if (!constraints->valid_hw_formats)
147  return AVERROR(ENOMEM);
148 
149  constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11;
150  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
151 
152  return 0;
153 }
154 
155 static void free_texture(void *opaque, uint8_t *data)
156 {
157  ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
158  av_free(data);
159 }
160 
161 static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
162 {
163  AVBufferRef *buf;
165  D3D11VAFramesContext *s = ctx->internal->priv;
166  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
167  if (!desc) {
168  ID3D11Texture2D_Release(tex);
169  return NULL;
170  }
171 
172  if (s->nb_surfaces <= s->nb_surfaces_used) {
173  frames_hwctx->texture_infos = av_realloc_f(frames_hwctx->texture_infos,
174  s->nb_surfaces_used + 1,
175  sizeof(*frames_hwctx->texture_infos));
176  if (!frames_hwctx->texture_infos) {
177  ID3D11Texture2D_Release(tex);
178  return NULL;
179  }
180  s->nb_surfaces = s->nb_surfaces_used + 1;
181  }
182 
183  frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex;
184  frames_hwctx->texture_infos[s->nb_surfaces_used].index = index;
185  s->nb_surfaces_used++;
186 
187  desc->texture = tex;
188  desc->index = index;
189 
190  buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
191  if (!buf) {
192  ID3D11Texture2D_Release(tex);
193  av_free(desc);
194  return NULL;
195  }
196 
197  return buf;
198 }
199 
201 {
202  D3D11VAFramesContext *s = ctx->internal->priv;
203  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
204  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
205  HRESULT hr;
206  ID3D11Texture2D *tex;
207  D3D11_TEXTURE2D_DESC texDesc = {
208  .Width = ctx->width,
209  .Height = ctx->height,
210  .MipLevels = 1,
211  .Format = s->format,
212  .SampleDesc = { .Count = 1 },
213  .ArraySize = 1,
214  .Usage = D3D11_USAGE_DEFAULT,
215  .BindFlags = hwctx->BindFlags,
216  .MiscFlags = hwctx->MiscFlags,
217  };
218 
219  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
220  if (FAILED(hr)) {
221  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
222  return NULL;
223  }
224 
225  return wrap_texture_buf(ctx, tex, 0);
226 }
227 
228 static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
229 {
231  D3D11VAFramesContext *s = ctx->internal->priv;
232  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
233  D3D11_TEXTURE2D_DESC texDesc;
234 
235  if (!hwctx->texture)
236  return d3d11va_alloc_single(ctx);
237 
238  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
239 
240  if (s->nb_surfaces_used >= texDesc.ArraySize) {
241  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
242  return NULL;
243  }
244 
245  ID3D11Texture2D_AddRef(hwctx->texture);
246  return wrap_texture_buf(ctx, hwctx->texture, s->nb_surfaces_used);
247 }
248 
250 {
251  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
252  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
253  D3D11VAFramesContext *s = ctx->internal->priv;
254 
255  int i;
256  HRESULT hr;
257  D3D11_TEXTURE2D_DESC texDesc;
258 
259  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
260  if (ctx->sw_format == supported_formats[i].pix_fmt) {
261  s->format = supported_formats[i].d3d_format;
262  break;
263  }
264  }
266  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
267  av_get_pix_fmt_name(ctx->sw_format));
268  return AVERROR(EINVAL);
269  }
270 
271  texDesc = (D3D11_TEXTURE2D_DESC){
272  .Width = ctx->width,
273  .Height = ctx->height,
274  .MipLevels = 1,
275  .Format = s->format,
276  .SampleDesc = { .Count = 1 },
277  .ArraySize = ctx->initial_pool_size,
278  .Usage = D3D11_USAGE_DEFAULT,
279  .BindFlags = hwctx->BindFlags,
280  .MiscFlags = hwctx->MiscFlags,
281  };
282 
283  if (hwctx->texture) {
284  D3D11_TEXTURE2D_DESC texDesc2;
285  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
286 
287  if (texDesc.Width != texDesc2.Width ||
288  texDesc.Height != texDesc2.Height ||
289  texDesc.Format != texDesc2.Format) {
290  av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
291  return AVERROR(EINVAL);
292  }
293 
294  ctx->initial_pool_size = texDesc2.ArraySize;
295  hwctx->BindFlags = texDesc2.BindFlags;
296  hwctx->MiscFlags = texDesc2.MiscFlags;
297  } else if (!(texDesc.BindFlags & D3D11_BIND_RENDER_TARGET) && texDesc.ArraySize > 0) {
298  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
299  if (FAILED(hr)) {
300  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
301  return AVERROR_UNKNOWN;
302  }
303  }
304 
305  hwctx->texture_infos = av_realloc_f(NULL, ctx->initial_pool_size, sizeof(*hwctx->texture_infos));
306  if (!hwctx->texture_infos)
307  return AVERROR(ENOMEM);
308  s->nb_surfaces = ctx->initial_pool_size;
309 
310  ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
312  if (!ctx->internal->pool_internal)
313  return AVERROR(ENOMEM);
314 
315  return 0;
316 }
317 
319 {
321 
322  frame->buf[0] = av_buffer_pool_get(ctx->pool);
323  if (!frame->buf[0])
324  return AVERROR(ENOMEM);
325 
326  desc = (AVD3D11FrameDescriptor *)frame->buf[0]->data;
327 
328  frame->data[0] = (uint8_t *)desc->texture;
329  frame->data[1] = (uint8_t *)desc->index;
330  frame->format = AV_PIX_FMT_D3D11;
331  frame->width = ctx->width;
332  frame->height = ctx->height;
333 
334  return 0;
335 }
336 
339  enum AVPixelFormat **formats)
340 {
341  D3D11VAFramesContext *s = ctx->internal->priv;
342  enum AVPixelFormat *fmts;
343 
344  fmts = av_malloc_array(2, sizeof(*fmts));
345  if (!fmts)
346  return AVERROR(ENOMEM);
347 
348  fmts[0] = ctx->sw_format;
349  fmts[1] = AV_PIX_FMT_NONE;
350 
351  // Don't signal support for opaque formats. Actual access would fail.
352  if (s->format == DXGI_FORMAT_420_OPAQUE)
353  fmts[0] = AV_PIX_FMT_NONE;
354 
355  *formats = fmts;
356 
357  return 0;
358 }
359 
361 {
362  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
363  D3D11VAFramesContext *s = ctx->internal->priv;
364  HRESULT hr;
365  D3D11_TEXTURE2D_DESC texDesc = {
366  .Width = ctx->width,
367  .Height = ctx->height,
368  .MipLevels = 1,
369  .Format = format,
370  .SampleDesc = { .Count = 1 },
371  .ArraySize = 1,
372  .Usage = D3D11_USAGE_STAGING,
373  .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,
374  };
375 
376  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
377  if (FAILED(hr)) {
378  av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
379  return AVERROR_UNKNOWN;
380  }
381 
382  return 0;
383 }
384 
385 static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
387  D3D11_TEXTURE2D_DESC *desc,
388  D3D11_MAPPED_SUBRESOURCE *map)
389 {
390  int i;
391 
392  for (i = 0; i < 4; i++)
393  linesize[i] = map->RowPitch;
394 
395  av_image_fill_pointers(data, ctx->sw_format, desc->Height,
396  (uint8_t*)map->pData, linesize);
397 }
398 
400  const AVFrame *src)
401 {
402  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
403  D3D11VAFramesContext *s = ctx->internal->priv;
404  int download = src->format == AV_PIX_FMT_D3D11;
405  const AVFrame *frame = download ? src : dst;
406  const AVFrame *other = download ? dst : src;
407  // (The interface types are compatible.)
408  ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
409  int index = (intptr_t)frame->data[1];
410  ID3D11Resource *staging;
411  int w = FFMIN(dst->width, src->width);
412  int h = FFMIN(dst->height, src->height);
413  uint8_t *map_data[4];
414  int map_linesize[4];
415  D3D11_TEXTURE2D_DESC desc;
416  D3D11_MAPPED_SUBRESOURCE map;
417  HRESULT hr;
418  int res;
419 
420  if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
421  return AVERROR(EINVAL);
422 
423  device_hwctx->lock(device_hwctx->lock_ctx);
424 
425  if (!s->staging_texture) {
426  ID3D11Texture2D_GetDesc((ID3D11Texture2D *)texture, &desc);
427  res = d3d11va_create_staging_texture(ctx, desc.Format);
428  if (res < 0)
429  return res;
430  }
431 
432  staging = (ID3D11Resource *)s->staging_texture;
433 
434  ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
435 
436  if (download) {
437  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
438  staging, 0, 0, 0, 0,
439  texture, index, NULL);
440 
441  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
442  staging, 0, D3D11_MAP_READ, 0, &map);
443  if (FAILED(hr))
444  goto map_failed;
445 
446  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
447 
448  av_image_copy(dst->data, dst->linesize, (const uint8_t **)map_data, map_linesize,
449  ctx->sw_format, w, h);
450 
451  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
452  } else {
453  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
454  staging, 0, D3D11_MAP_WRITE, 0, &map);
455  if (FAILED(hr))
456  goto map_failed;
457 
458  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
459 
460  av_image_copy(map_data, map_linesize, (const uint8_t **)src->data, src->linesize,
461  ctx->sw_format, w, h);
462 
463  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
464 
465  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
466  texture, index, 0, 0, 0,
467  staging, 0, NULL);
468  }
469 
470  device_hwctx->unlock(device_hwctx->lock_ctx);
471  return 0;
472 
473 map_failed:
474  av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
475  device_hwctx->unlock(device_hwctx->lock_ctx);
476  return AVERROR_UNKNOWN;
477 }
478 
480 {
481  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
482  HRESULT hr;
483 
484  if (!device_hwctx->lock) {
485  device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
486  if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
487  av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
488  return AVERROR(EINVAL);
489  }
490  device_hwctx->lock = d3d11va_default_lock;
491  device_hwctx->unlock = d3d11va_default_unlock;
492  }
493 
494  if (!device_hwctx->device_context) {
495  ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
496  if (!device_hwctx->device_context)
497  return AVERROR_UNKNOWN;
498  }
499 
500  if (!device_hwctx->video_device) {
501  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
502  (void **)&device_hwctx->video_device);
503  if (FAILED(hr))
504  return AVERROR_UNKNOWN;
505  }
506 
507  if (!device_hwctx->video_context) {
508  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
509  (void **)&device_hwctx->video_context);
510  if (FAILED(hr))
511  return AVERROR_UNKNOWN;
512  }
513 
514  return 0;
515 }
516 
518 {
519  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
520 
521  if (device_hwctx->device) {
522  ID3D11Device_Release(device_hwctx->device);
523  device_hwctx->device = NULL;
524  }
525 
526  if (device_hwctx->device_context) {
527  ID3D11DeviceContext_Release(device_hwctx->device_context);
528  device_hwctx->device_context = NULL;
529  }
530 
531  if (device_hwctx->video_device) {
532  ID3D11VideoDevice_Release(device_hwctx->video_device);
533  device_hwctx->video_device = NULL;
534  }
535 
536  if (device_hwctx->video_context) {
537  ID3D11VideoContext_Release(device_hwctx->video_context);
538  device_hwctx->video_context = NULL;
539  }
540 
541  if (device_hwctx->lock == d3d11va_default_lock) {
542  CloseHandle(device_hwctx->lock_ctx);
543  device_hwctx->lock_ctx = INVALID_HANDLE_VALUE;
544  device_hwctx->lock = NULL;
545  }
546 }
547 
548 static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
549  AVDictionary *opts, int flags)
550 {
551  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
552 
553  HRESULT hr;
554  IDXGIAdapter *pAdapter = NULL;
555  ID3D10Multithread *pMultithread;
556  UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
557  int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
558  int ret;
559 
560  // (On UWP we can't check this.)
561 #if !HAVE_UWP
562  if (!LoadLibrary("d3d11_1sdklayers.dll"))
563  is_debug = 0;
564 #endif
565 
566  if (is_debug)
567  creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
568 
570  return AVERROR_UNKNOWN;
572  av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n");
573  return AVERROR_UNKNOWN;
574  }
575 
576  if (device) {
577  IDXGIFactory2 *pDXGIFactory;
578  hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
579  if (SUCCEEDED(hr)) {
580  int adapter = atoi(device);
581  if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
582  pAdapter = NULL;
583  IDXGIFactory2_Release(pDXGIFactory);
584  }
585  }
586 
587  if (pAdapter) {
588  DXGI_ADAPTER_DESC desc;
589  hr = IDXGIAdapter2_GetDesc(pAdapter, &desc);
590  if (!FAILED(hr)) {
591  av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n",
592  desc.VendorId, desc.DeviceId, desc.Description);
593  }
594  }
595 
596  hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
597  D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
598  if (pAdapter)
599  IDXGIAdapter_Release(pAdapter);
600  if (FAILED(hr)) {
601  av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
602  return AVERROR_UNKNOWN;
603  }
604 
605  hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
606  if (SUCCEEDED(hr)) {
607  ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
608  ID3D10Multithread_Release(pMultithread);
609  }
610 
611 #if !HAVE_UWP && HAVE_DXGIDEBUG_H
612  if (is_debug) {
613  HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll");
614  if (dxgidebug_dll) {
615  HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug)
616  = (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface");
617  if (pf_DXGIGetDebugInterface) {
618  IDXGIDebug *dxgi_debug = NULL;
619  hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug);
620  if (SUCCEEDED(hr) && dxgi_debug)
621  IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
622  }
623  }
624  }
625 #endif
626 
627  return 0;
628 }
629 
632  .name = "D3D11VA",
633 
634  .device_hwctx_size = sizeof(AVD3D11VADeviceContext),
635  .frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
636  .frames_priv_size = sizeof(D3D11VAFramesContext),
637 
638  .device_create = d3d11va_device_create,
640  .device_uninit = d3d11va_device_uninit,
641  .frames_get_constraints = d3d11va_frames_get_constraints,
642  .frames_init = d3d11va_frames_init,
643  .frames_uninit = d3d11va_frames_uninit,
644  .frames_get_buffer = d3d11va_get_buffer,
645  .transfer_get_formats = d3d11va_transfer_get_formats,
646  .transfer_data_to = d3d11va_transfer_data,
647  .transfer_data_from = d3d11va_transfer_data,
648 
650 };
d3d11va_alloc_single
static AVBufferRef * d3d11va_alloc_single(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:200
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
d3d11va_transfer_get_formats
static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_d3d11va.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
pixdesc.h
AVFrame::width
int width
Definition: frame.h:402
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:146
d3d11va_transfer_data
static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_d3d11va.c:399
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
AVDictionary
Definition: dict.c:32
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
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:385
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:351
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:630
d3d11va_get_buffer
static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_d3d11va.c:318
d3d_format
DXGI_FORMAT d3d_format
Definition: hwcontext_d3d11va.c:84
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:360
D3D11VAFramesContext::format
DXGI_FORMAT format
Definition: hwcontext_d3d11va.c:78
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:107
d3d11va_default_unlock
static void d3d11va_default_unlock(void *ctx)
Definition: hwcontext_d3d11va.c:102
D3D11VAFramesContext::nb_surfaces_used
int nb_surfaces_used
Definition: hwcontext_d3d11va.c:76
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:123
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
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:184
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:60
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:256
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:548
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:296
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
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:75
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:182
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:97
AVD3D11VADeviceContext::video_device
ID3D11VideoDevice * video_device
If unset, this will be set from the device field on init.
Definition: hwcontext_d3d11va.h:72
wrap_texture_buf
static AVBufferRef * wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
Definition: hwcontext_d3d11va.c:161
AVOnce
#define AVOnce
Definition: thread.h:181
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:517
size
int size
Definition: twinvq_data.h:10344
d3d11va_frames_init
static int d3d11va_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:249
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:417
free_texture
static void free_texture(void *opaque, uint8_t *data)
Definition: hwcontext_d3d11va.c:155
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:269
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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
mD3D11CreateDevice
static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice
Definition: hwcontext_d3d11va.c:49
AVFrame::height
int height
Definition: frame.h:402
d3d11va_pool_alloc
static AVBufferRef * d3d11va_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_d3d11va.c:228
av_image_copy
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], const uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Copy image in src_data to dst_data.
Definition: imgutils.c:422
pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_d3d11va.c:85
supported_formats
static const struct @323 supported_formats[]
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
D3D11VAFramesContext
Definition: hwcontext_d3d11va.c:74
d3d11va_device_uninit
static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
Definition: hwcontext_d3d11va.c:517
D3D11VAFramesContext::staging_texture
ID3D11Texture2D * staging_texture
Definition: hwcontext_d3d11va.c:80
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:508
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:479
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:524
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
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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:375
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
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:2808