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  { DXGI_FORMAT_AYUV, AV_PIX_FMT_VUYX },
93  { DXGI_FORMAT_YUY2, AV_PIX_FMT_YUYV422 },
94  { DXGI_FORMAT_Y210, AV_PIX_FMT_Y210 },
95  { DXGI_FORMAT_Y410, AV_PIX_FMT_XV30 },
96  { DXGI_FORMAT_P016, AV_PIX_FMT_P012 },
97  { DXGI_FORMAT_Y216, AV_PIX_FMT_Y212 },
98  { DXGI_FORMAT_Y416, AV_PIX_FMT_XV36 },
99  // Special opaque formats. The pix_fmt is merely a place holder, as the
100  // opaque format cannot be accessed directly.
101  { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
102 };
103 
104 static void d3d11va_default_lock(void *ctx)
105 {
106  WaitForSingleObjectEx(ctx, INFINITE, FALSE);
107 }
108 
109 static void d3d11va_default_unlock(void *ctx)
110 {
111  ReleaseMutex(ctx);
112 }
113 
115 {
116  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
117  D3D11VAFramesContext *s = ctx->internal->priv;
118 
119  if (frames_hwctx->texture)
120  ID3D11Texture2D_Release(frames_hwctx->texture);
121  frames_hwctx->texture = NULL;
122 
123  if (s->staging_texture)
124  ID3D11Texture2D_Release(s->staging_texture);
125  s->staging_texture = NULL;
126 
127  av_freep(&frames_hwctx->texture_infos);
128 }
129 
131  const void *hwconfig,
132  AVHWFramesConstraints *constraints)
133 {
134  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
135  int nb_sw_formats = 0;
136  HRESULT hr;
137  int i;
138 
140  sizeof(*constraints->valid_sw_formats));
141  if (!constraints->valid_sw_formats)
142  return AVERROR(ENOMEM);
143 
144  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
145  UINT format_support = 0;
146  hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support);
147  if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
148  constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt;
149  }
150  constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
151 
152  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
153  if (!constraints->valid_hw_formats)
154  return AVERROR(ENOMEM);
155 
156  constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11;
157  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
158 
159  return 0;
160 }
161 
162 static void free_texture(void *opaque, uint8_t *data)
163 {
164  ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
165  av_free(data);
166 }
167 
168 static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
169 {
170  AVBufferRef *buf;
172  D3D11VAFramesContext *s = ctx->internal->priv;
173  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
174  if (!desc) {
175  ID3D11Texture2D_Release(tex);
176  return NULL;
177  }
178 
179  if (s->nb_surfaces <= s->nb_surfaces_used) {
180  frames_hwctx->texture_infos = av_realloc_f(frames_hwctx->texture_infos,
181  s->nb_surfaces_used + 1,
182  sizeof(*frames_hwctx->texture_infos));
183  if (!frames_hwctx->texture_infos) {
184  ID3D11Texture2D_Release(tex);
185  return NULL;
186  }
187  s->nb_surfaces = s->nb_surfaces_used + 1;
188  }
189 
190  frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex;
191  frames_hwctx->texture_infos[s->nb_surfaces_used].index = index;
192  s->nb_surfaces_used++;
193 
194  desc->texture = tex;
195  desc->index = index;
196 
197  buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
198  if (!buf) {
199  ID3D11Texture2D_Release(tex);
200  av_free(desc);
201  return NULL;
202  }
203 
204  return buf;
205 }
206 
208 {
209  D3D11VAFramesContext *s = ctx->internal->priv;
210  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
211  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
212  HRESULT hr;
213  ID3D11Texture2D *tex;
214  D3D11_TEXTURE2D_DESC texDesc = {
215  .Width = ctx->width,
216  .Height = ctx->height,
217  .MipLevels = 1,
218  .Format = s->format,
219  .SampleDesc = { .Count = 1 },
220  .ArraySize = 1,
221  .Usage = D3D11_USAGE_DEFAULT,
222  .BindFlags = hwctx->BindFlags,
223  .MiscFlags = hwctx->MiscFlags,
224  };
225 
226  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
227  if (FAILED(hr)) {
228  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
229  return NULL;
230  }
231 
232  return wrap_texture_buf(ctx, tex, 0);
233 }
234 
235 static AVBufferRef *d3d11va_pool_alloc(void *opaque, size_t size)
236 {
238  D3D11VAFramesContext *s = ctx->internal->priv;
239  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
240  D3D11_TEXTURE2D_DESC texDesc;
241 
242  if (!hwctx->texture)
243  return d3d11va_alloc_single(ctx);
244 
245  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
246 
247  if (s->nb_surfaces_used >= texDesc.ArraySize) {
248  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
249  return NULL;
250  }
251 
252  ID3D11Texture2D_AddRef(hwctx->texture);
253  return wrap_texture_buf(ctx, hwctx->texture, s->nb_surfaces_used);
254 }
255 
257 {
258  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
259  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
260  D3D11VAFramesContext *s = ctx->internal->priv;
261 
262  int i;
263  HRESULT hr;
264  D3D11_TEXTURE2D_DESC texDesc;
265 
266  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
267  if (ctx->sw_format == supported_formats[i].pix_fmt) {
268  s->format = supported_formats[i].d3d_format;
269  break;
270  }
271  }
273  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
274  av_get_pix_fmt_name(ctx->sw_format));
275  return AVERROR(EINVAL);
276  }
277 
278  texDesc = (D3D11_TEXTURE2D_DESC){
279  .Width = ctx->width,
280  .Height = ctx->height,
281  .MipLevels = 1,
282  .Format = s->format,
283  .SampleDesc = { .Count = 1 },
284  .ArraySize = ctx->initial_pool_size,
285  .Usage = D3D11_USAGE_DEFAULT,
286  .BindFlags = hwctx->BindFlags,
287  .MiscFlags = hwctx->MiscFlags,
288  };
289 
290  if (hwctx->texture) {
291  D3D11_TEXTURE2D_DESC texDesc2;
292  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
293 
294  if (texDesc.Width != texDesc2.Width ||
295  texDesc.Height != texDesc2.Height ||
296  texDesc.Format != texDesc2.Format) {
297  av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
298  return AVERROR(EINVAL);
299  }
300 
301  ctx->initial_pool_size = texDesc2.ArraySize;
302  hwctx->BindFlags = texDesc2.BindFlags;
303  hwctx->MiscFlags = texDesc2.MiscFlags;
304  } else if (!(texDesc.BindFlags & D3D11_BIND_RENDER_TARGET) && texDesc.ArraySize > 0) {
305  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
306  if (FAILED(hr)) {
307  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
308  return AVERROR_UNKNOWN;
309  }
310  }
311 
312  hwctx->texture_infos = av_realloc_f(NULL, ctx->initial_pool_size, sizeof(*hwctx->texture_infos));
313  if (!hwctx->texture_infos)
314  return AVERROR(ENOMEM);
315  s->nb_surfaces = ctx->initial_pool_size;
316 
317  ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
319  if (!ctx->internal->pool_internal)
320  return AVERROR(ENOMEM);
321 
322  return 0;
323 }
324 
326 {
328 
329  frame->buf[0] = av_buffer_pool_get(ctx->pool);
330  if (!frame->buf[0])
331  return AVERROR(ENOMEM);
332 
334 
335  frame->data[0] = (uint8_t *)desc->texture;
336  frame->data[1] = (uint8_t *)desc->index;
338  frame->width = ctx->width;
339  frame->height = ctx->height;
340 
341  return 0;
342 }
343 
346  enum AVPixelFormat **formats)
347 {
348  D3D11VAFramesContext *s = ctx->internal->priv;
349  enum AVPixelFormat *fmts;
350 
351  fmts = av_malloc_array(2, sizeof(*fmts));
352  if (!fmts)
353  return AVERROR(ENOMEM);
354 
355  fmts[0] = ctx->sw_format;
356  fmts[1] = AV_PIX_FMT_NONE;
357 
358  // Don't signal support for opaque formats. Actual access would fail.
359  if (s->format == DXGI_FORMAT_420_OPAQUE)
360  fmts[0] = AV_PIX_FMT_NONE;
361 
362  *formats = fmts;
363 
364  return 0;
365 }
366 
368 {
369  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
370  D3D11VAFramesContext *s = ctx->internal->priv;
371  HRESULT hr;
372  D3D11_TEXTURE2D_DESC texDesc = {
373  .Width = ctx->width,
374  .Height = ctx->height,
375  .MipLevels = 1,
376  .Format = format,
377  .SampleDesc = { .Count = 1 },
378  .ArraySize = 1,
379  .Usage = D3D11_USAGE_STAGING,
380  .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,
381  };
382 
383  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
384  if (FAILED(hr)) {
385  av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
386  return AVERROR_UNKNOWN;
387  }
388 
389  return 0;
390 }
391 
392 static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
394  D3D11_TEXTURE2D_DESC *desc,
395  D3D11_MAPPED_SUBRESOURCE *map)
396 {
397  int i;
398 
399  for (i = 0; i < 4; i++)
400  linesize[i] = map->RowPitch;
401 
402  av_image_fill_pointers(data, ctx->sw_format, desc->Height,
403  (uint8_t*)map->pData, linesize);
404 }
405 
407  const AVFrame *src)
408 {
409  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
410  D3D11VAFramesContext *s = ctx->internal->priv;
411  int download = src->format == AV_PIX_FMT_D3D11;
412  const AVFrame *frame = download ? src : dst;
413  const AVFrame *other = download ? dst : src;
414  // (The interface types are compatible.)
415  ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
416  int index = (intptr_t)frame->data[1];
417  ID3D11Resource *staging;
418  int w = FFMIN(dst->width, src->width);
419  int h = FFMIN(dst->height, src->height);
420  uint8_t *map_data[4];
421  int map_linesize[4];
422  D3D11_TEXTURE2D_DESC desc;
423  D3D11_MAPPED_SUBRESOURCE map;
424  HRESULT hr;
425  int res;
426 
427  if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
428  return AVERROR(EINVAL);
429 
430  device_hwctx->lock(device_hwctx->lock_ctx);
431 
432  if (!s->staging_texture) {
433  ID3D11Texture2D_GetDesc((ID3D11Texture2D *)texture, &desc);
434  res = d3d11va_create_staging_texture(ctx, desc.Format);
435  if (res < 0)
436  return res;
437  }
438 
439  staging = (ID3D11Resource *)s->staging_texture;
440 
441  ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
442 
443  if (download) {
444  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
445  staging, 0, 0, 0, 0,
446  texture, index, NULL);
447 
448  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
449  staging, 0, D3D11_MAP_READ, 0, &map);
450  if (FAILED(hr))
451  goto map_failed;
452 
453  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
454 
455  av_image_copy2(dst->data, dst->linesize, map_data, map_linesize,
456  ctx->sw_format, w, h);
457 
458  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
459  } else {
460  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
461  staging, 0, D3D11_MAP_WRITE, 0, &map);
462  if (FAILED(hr))
463  goto map_failed;
464 
465  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
466 
467  av_image_copy2(map_data, map_linesize, src->data, src->linesize,
468  ctx->sw_format, w, h);
469 
470  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
471 
472  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
473  texture, index, 0, 0, 0,
474  staging, 0, NULL);
475  }
476 
477  device_hwctx->unlock(device_hwctx->lock_ctx);
478  return 0;
479 
480 map_failed:
481  av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
482  device_hwctx->unlock(device_hwctx->lock_ctx);
483  return AVERROR_UNKNOWN;
484 }
485 
487 {
488  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
489  HRESULT hr;
490 
491  if (!device_hwctx->lock) {
492  device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
493  if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
494  av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
495  return AVERROR(EINVAL);
496  }
497  device_hwctx->lock = d3d11va_default_lock;
498  device_hwctx->unlock = d3d11va_default_unlock;
499  }
500 
501  if (!device_hwctx->device_context) {
502  ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
503  if (!device_hwctx->device_context)
504  return AVERROR_UNKNOWN;
505  }
506 
507  if (!device_hwctx->video_device) {
508  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
509  (void **)&device_hwctx->video_device);
510  if (FAILED(hr))
511  return AVERROR_UNKNOWN;
512  }
513 
514  if (!device_hwctx->video_context) {
515  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
516  (void **)&device_hwctx->video_context);
517  if (FAILED(hr))
518  return AVERROR_UNKNOWN;
519  }
520 
521  return 0;
522 }
523 
525 {
526  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
527 
528  if (device_hwctx->device) {
529  ID3D11Device_Release(device_hwctx->device);
530  device_hwctx->device = NULL;
531  }
532 
533  if (device_hwctx->device_context) {
534  ID3D11DeviceContext_Release(device_hwctx->device_context);
535  device_hwctx->device_context = NULL;
536  }
537 
538  if (device_hwctx->video_device) {
539  ID3D11VideoDevice_Release(device_hwctx->video_device);
540  device_hwctx->video_device = NULL;
541  }
542 
543  if (device_hwctx->video_context) {
544  ID3D11VideoContext_Release(device_hwctx->video_context);
545  device_hwctx->video_context = NULL;
546  }
547 
548  if (device_hwctx->lock == d3d11va_default_lock) {
549  CloseHandle(device_hwctx->lock_ctx);
550  device_hwctx->lock_ctx = INVALID_HANDLE_VALUE;
551  device_hwctx->lock = NULL;
552  }
553 }
554 
555 static int d3d11va_device_find_adapter_by_vendor_id(AVHWDeviceContext *ctx, uint32_t flags, const char *vendor_id)
556 {
557  HRESULT hr;
558  IDXGIAdapter *adapter = NULL;
559  IDXGIFactory2 *factory;
560  int adapter_id = 0;
561  long int id = strtol(vendor_id, NULL, 0);
562 
563  hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&factory);
564  if (FAILED(hr)) {
565  av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory returned error\n");
566  return -1;
567  }
568 
569  while (IDXGIFactory2_EnumAdapters(factory, adapter_id++, &adapter) != DXGI_ERROR_NOT_FOUND) {
570  ID3D11Device* device = NULL;
571  DXGI_ADAPTER_DESC adapter_desc;
572 
573  hr = mD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL);
574  if (FAILED(hr)) {
575  av_log(ctx, AV_LOG_DEBUG, "D3D11CreateDevice returned error, try next adapter\n");
576  IDXGIAdapter_Release(adapter);
577  continue;
578  }
579 
580  hr = IDXGIAdapter2_GetDesc(adapter, &adapter_desc);
581  ID3D11Device_Release(device);
582  IDXGIAdapter_Release(adapter);
583  if (FAILED(hr)) {
584  av_log(ctx, AV_LOG_DEBUG, "IDXGIAdapter2_GetDesc returned error, try next adapter\n");
585  continue;
586  } else if (adapter_desc.VendorId == id) {
587  IDXGIFactory2_Release(factory);
588  return adapter_id - 1;
589  }
590  }
591 
592  IDXGIFactory2_Release(factory);
593  return -1;
594 }
595 
596 static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
597  AVDictionary *opts, int flags)
598 {
599  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
600 
601  HRESULT hr;
602  IDXGIAdapter *pAdapter = NULL;
603  ID3D10Multithread *pMultithread;
604  UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
605  int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
606  int ret;
607  int adapter = -1;
608 
609  // (On UWP we can't check this.)
610 #if !HAVE_UWP
611  if (!LoadLibrary("d3d11_1sdklayers.dll"))
612  is_debug = 0;
613 #endif
614 
615  if (is_debug)
616  creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
617 
619  return AVERROR_UNKNOWN;
621  av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n");
622  return AVERROR_UNKNOWN;
623  }
624 
625  if (device) {
626  adapter = atoi(device);
627  } else {
628  AVDictionaryEntry *e = av_dict_get(opts, "vendor_id", NULL, 0);
629  if (e && e->value) {
630  adapter = d3d11va_device_find_adapter_by_vendor_id(ctx, creationFlags, e->value);
631  if (adapter < 0) {
632  av_log(ctx, AV_LOG_ERROR, "Failed to find d3d11va adapter by "
633  "vendor id %s\n", e->value);
634  return AVERROR_UNKNOWN;
635  }
636  }
637  }
638 
639  if (adapter >= 0) {
640  IDXGIFactory2 *pDXGIFactory;
641 
642  av_log(ctx, AV_LOG_VERBOSE, "Selecting d3d11va adapter %d\n", adapter);
643  hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
644  if (SUCCEEDED(hr)) {
645  if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
646  pAdapter = NULL;
647  IDXGIFactory2_Release(pDXGIFactory);
648  }
649  }
650 
651  if (pAdapter) {
652  DXGI_ADAPTER_DESC desc;
653  hr = IDXGIAdapter2_GetDesc(pAdapter, &desc);
654  if (!FAILED(hr)) {
655  av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n",
656  desc.VendorId, desc.DeviceId, desc.Description);
657  }
658  }
659 
660  hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
661  D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
662  if (pAdapter)
663  IDXGIAdapter_Release(pAdapter);
664  if (FAILED(hr)) {
665  av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
666  return AVERROR_UNKNOWN;
667  }
668 
669  hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
670  if (SUCCEEDED(hr)) {
671  ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
672  ID3D10Multithread_Release(pMultithread);
673  }
674 
675 #if !HAVE_UWP && HAVE_DXGIDEBUG_H
676  if (is_debug) {
677  HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll");
678  if (dxgidebug_dll) {
679  HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug)
680  = (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface");
681  if (pf_DXGIGetDebugInterface) {
682  IDXGIDebug *dxgi_debug = NULL;
683  hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug);
684  if (SUCCEEDED(hr) && dxgi_debug)
685  IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
686  }
687  }
688  }
689 #endif
690 
691  return 0;
692 }
693 
696  .name = "D3D11VA",
697 
698  .device_hwctx_size = sizeof(AVD3D11VADeviceContext),
699  .frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
700  .frames_priv_size = sizeof(D3D11VAFramesContext),
701 
702  .device_create = d3d11va_device_create,
704  .device_uninit = d3d11va_device_uninit,
705  .frames_get_constraints = d3d11va_frames_get_constraints,
706  .frames_init = d3d11va_frames_init,
707  .frames_uninit = d3d11va_frames_uninit,
708  .frames_get_buffer = d3d11va_get_buffer,
709  .transfer_get_formats = d3d11va_transfer_get_formats,
710  .transfer_data_to = d3d11va_transfer_data,
711  .transfer_data_from = d3d11va_transfer_data,
712 
714 };
d3d11va_alloc_single
static AVBufferRef * d3d11va_alloc_single(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:207
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:93
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
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:344
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:406
AV_PIX_FMT_XV30
#define AV_PIX_FMT_XV30
Definition: pixfmt.h:538
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
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:459
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:392
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:454
supported_formats
static const struct @354 supported_formats[]
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:694
d3d11va_get_buffer
static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_d3d11va.c:325
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:367
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:114
d3d11va_default_unlock
static void d3d11va_default_unlock(void *ctx)
Definition: hwcontext_d3d11va.c:109
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:130
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:62
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:536
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:205
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:466
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:596
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
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
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:73
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:75
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:203
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:104
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:74
wrap_texture_buf
static AVBufferRef * wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *tex, int index)
Definition: hwcontext_d3d11va.c:168
AVOnce
#define AVOnce
Definition: thread.h:202
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
d3d11va_device_find_adapter_by_vendor_id
static int d3d11va_device_find_adapter_by_vendor_id(AVHWDeviceContext *ctx, uint32_t flags, const char *vendor_id)
Definition: hwcontext_d3d11va.c:555
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:541
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:533
size
int size
Definition: twinvq_data.h:10344
d3d11va_frames_init
static int d3d11va_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_d3d11va.c:256
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:162
AV_PIX_FMT_Y212
#define AV_PIX_FMT_Y212
Definition: pixfmt.h:537
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:340
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:416
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:125
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:96
mD3D11CreateDevice
static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice
Definition: hwcontext_d3d11va.c:49
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:235
pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_d3d11va.c:85
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:72
D3D11VAFramesContext
Definition: hwcontext_d3d11va.c:74
d3d11va_device_uninit
static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
Definition: hwcontext_d3d11va.c:524
D3D11VAFramesContext::staging_texture
ID3D11Texture2D * staging_texture
Definition: hwcontext_d3d11va.c:80
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:532
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:486
hwcontext_internal.h
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVDictionaryEntry
Definition: dict.h:89
AV_PIX_FMT_RGBAF16
#define AV_PIX_FMT_RGBAF16
Definition: pixfmt.h:550
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:539
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
ID3D11Device
void ID3D11Device
Definition: nvenc.h:28
h
h
Definition: vp9dsp_template.c:2038
AVDictionaryEntry::value
char * value
Definition: dict.h:91
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:410
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:2888