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