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 {
76 
77  DXGI_FORMAT format;
78 
79  ID3D11Texture2D *staging_texture;
81 
82 static const struct {
83  DXGI_FORMAT d3d_format;
85 } supported_formats[] = {
86  { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
87  { DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
88  // Special opaque formats. The pix_fmt is merely a place holder, as the
89  // opaque format cannot be accessed directly.
90  { DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
91 };
92 
93 static void d3d11va_default_lock(void *ctx)
94 {
95  WaitForSingleObjectEx(ctx, INFINITE, FALSE);
96 }
97 
98 static void d3d11va_default_unlock(void *ctx)
99 {
100  ReleaseMutex(ctx);
101 }
102 
104 {
105  AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
107 
108  if (frames_hwctx->texture)
109  ID3D11Texture2D_Release(frames_hwctx->texture);
110  frames_hwctx->texture = NULL;
111 
112  if (s->staging_texture)
113  ID3D11Texture2D_Release(s->staging_texture);
114  s->staging_texture = NULL;
115 }
116 
118  const void *hwconfig,
119  AVHWFramesConstraints *constraints)
120 {
121  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
122  int nb_sw_formats = 0;
123  HRESULT hr;
124  int i;
125 
127  sizeof(*constraints->valid_sw_formats));
128  if (!constraints->valid_sw_formats)
129  return AVERROR(ENOMEM);
130 
131  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
132  UINT format_support = 0;
133  hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support);
134  if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
135  constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt;
136  }
137  constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
138 
139  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
140  if (!constraints->valid_hw_formats)
141  return AVERROR(ENOMEM);
142 
143  constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11;
144  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
145 
146  return 0;
147 }
148 
149 static void free_texture(void *opaque, uint8_t *data)
150 {
151  ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
152  av_free(data);
153 }
154 
155 static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
156 {
157  AVBufferRef *buf;
158  AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
159  if (!desc) {
160  ID3D11Texture2D_Release(tex);
161  return NULL;
162  }
163 
164  desc->texture = tex;
165  desc->index = index;
166 
167  buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
168  if (!buf) {
169  ID3D11Texture2D_Release(tex);
170  av_free(desc);
171  return NULL;
172  }
173 
174  return buf;
175 }
176 
178 {
180  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
181  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
182  HRESULT hr;
183  ID3D11Texture2D *tex;
184  D3D11_TEXTURE2D_DESC texDesc = {
185  .Width = ctx->width,
186  .Height = ctx->height,
187  .MipLevels = 1,
188  .Format = s->format,
189  .SampleDesc = { .Count = 1 },
190  .ArraySize = 1,
191  .Usage = D3D11_USAGE_DEFAULT,
192  .BindFlags = hwctx->BindFlags,
193  .MiscFlags = hwctx->MiscFlags,
194  };
195 
196  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
197  if (FAILED(hr)) {
198  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
199  return NULL;
200  }
201 
202  return wrap_texture_buf(tex, 0);
203 }
204 
205 static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
206 {
209  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
210  D3D11_TEXTURE2D_DESC texDesc;
211 
212  if (!hwctx->texture)
213  return d3d11va_alloc_single(ctx);
214 
215  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
216 
217  if (s->nb_surfaces_used >= texDesc.ArraySize) {
218  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
219  return NULL;
220  }
221 
222  ID3D11Texture2D_AddRef(hwctx->texture);
223  return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
224 }
225 
227 {
228  AVD3D11VAFramesContext *hwctx = ctx->hwctx;
229  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
231 
232  int i;
233  HRESULT hr;
234  D3D11_TEXTURE2D_DESC texDesc;
235 
236  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
237  if (ctx->sw_format == supported_formats[i].pix_fmt) {
238  s->format = supported_formats[i].d3d_format;
239  break;
240  }
241  }
242  if (i == FF_ARRAY_ELEMS(supported_formats)) {
243  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
245  return AVERROR(EINVAL);
246  }
247 
248  texDesc = (D3D11_TEXTURE2D_DESC){
249  .Width = ctx->width,
250  .Height = ctx->height,
251  .MipLevels = 1,
252  .Format = s->format,
253  .SampleDesc = { .Count = 1 },
254  .ArraySize = ctx->initial_pool_size,
255  .Usage = D3D11_USAGE_DEFAULT,
256  .BindFlags = hwctx->BindFlags,
257  .MiscFlags = hwctx->MiscFlags,
258  };
259 
260  if (hwctx->texture) {
261  D3D11_TEXTURE2D_DESC texDesc2;
262  ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
263 
264  if (texDesc.Width != texDesc2.Width ||
265  texDesc.Height != texDesc2.Height ||
266  texDesc.Format != texDesc2.Format) {
267  av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
268  return AVERROR(EINVAL);
269  }
270  } else if (texDesc.ArraySize > 0) {
271  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
272  if (FAILED(hr)) {
273  av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
274  return AVERROR_UNKNOWN;
275  }
276  }
277 
279  ctx, d3d11va_pool_alloc, NULL);
280  if (!ctx->internal->pool_internal)
281  return AVERROR(ENOMEM);
282 
283  return 0;
284 }
285 
287 {
289 
290  frame->buf[0] = av_buffer_pool_get(ctx->pool);
291  if (!frame->buf[0])
292  return AVERROR(ENOMEM);
293 
294  desc = (AVD3D11FrameDescriptor *)frame->buf[0]->data;
295 
296  frame->data[0] = (uint8_t *)desc->texture;
297  frame->data[1] = (uint8_t *)desc->index;
298  frame->format = AV_PIX_FMT_D3D11;
299  frame->width = ctx->width;
300  frame->height = ctx->height;
301 
302  return 0;
303 }
304 
307  enum AVPixelFormat **formats)
308 {
310  enum AVPixelFormat *fmts;
311 
312  fmts = av_malloc_array(2, sizeof(*fmts));
313  if (!fmts)
314  return AVERROR(ENOMEM);
315 
316  fmts[0] = ctx->sw_format;
317  fmts[1] = AV_PIX_FMT_NONE;
318 
319  // Don't signal support for opaque formats. Actual access would fail.
320  if (s->format == DXGI_FORMAT_420_OPAQUE)
321  fmts[0] = AV_PIX_FMT_NONE;
322 
323  *formats = fmts;
324 
325  return 0;
326 }
327 
329 {
330  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
332  HRESULT hr;
333  D3D11_TEXTURE2D_DESC texDesc = {
334  .Width = ctx->width,
335  .Height = ctx->height,
336  .MipLevels = 1,
337  .Format = s->format,
338  .SampleDesc = { .Count = 1 },
339  .ArraySize = 1,
340  .Usage = D3D11_USAGE_STAGING,
341  .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,
342  };
343 
344  hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
345  if (FAILED(hr)) {
346  av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
347  return AVERROR_UNKNOWN;
348  }
349 
350  return 0;
351 }
352 
353 static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
355  D3D11_TEXTURE2D_DESC *desc,
356  D3D11_MAPPED_SUBRESOURCE *map)
357 {
358  int i;
359 
360  for (i = 0; i < 4; i++)
361  linesize[i] = map->RowPitch;
362 
363  av_image_fill_pointers(data, ctx->sw_format, desc->Height,
364  (uint8_t*)map->pData, linesize);
365 }
366 
368  const AVFrame *src)
369 {
370  AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
372  int download = src->format == AV_PIX_FMT_D3D11;
373  const AVFrame *frame = download ? src : dst;
374  const AVFrame *other = download ? dst : src;
375  // (The interface types are compatible.)
376  ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
377  int index = (intptr_t)frame->data[1];
378  ID3D11Resource *staging;
379  int w = FFMIN(dst->width, src->width);
380  int h = FFMIN(dst->height, src->height);
381  uint8_t *map_data[4];
382  int map_linesize[4];
383  D3D11_TEXTURE2D_DESC desc;
384  D3D11_MAPPED_SUBRESOURCE map;
385  HRESULT hr;
386 
387  if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
388  return AVERROR(EINVAL);
389 
390  device_hwctx->lock(device_hwctx->lock_ctx);
391 
392  if (!s->staging_texture) {
393  int res = d3d11va_create_staging_texture(ctx);
394  if (res < 0)
395  return res;
396  }
397 
398  staging = (ID3D11Resource *)s->staging_texture;
399 
400  ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
401 
402  if (download) {
403  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
404  staging, 0, 0, 0, 0,
405  texture, index, NULL);
406 
407  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
408  staging, 0, D3D11_MAP_READ, 0, &map);
409  if (FAILED(hr))
410  goto map_failed;
411 
412  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
413 
414  av_image_copy(dst->data, dst->linesize, (const uint8_t **)map_data, map_linesize,
415  ctx->sw_format, w, h);
416 
417  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
418  } else {
419  hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
420  staging, 0, D3D11_MAP_WRITE, 0, &map);
421  if (FAILED(hr))
422  goto map_failed;
423 
424  fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
425 
426  av_image_copy(map_data, map_linesize, (const uint8_t **)src->data, src->linesize,
427  ctx->sw_format, w, h);
428 
429  ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
430 
431  ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
432  texture, index, 0, 0, 0,
433  staging, 0, NULL);
434  }
435 
436  device_hwctx->unlock(device_hwctx->lock_ctx);
437  return 0;
438 
439 map_failed:
440  av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
441  device_hwctx->unlock(device_hwctx->lock_ctx);
442  return AVERROR_UNKNOWN;
443 }
444 
446 {
447  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
448  HRESULT hr;
449 
450  if (!device_hwctx->lock) {
451  device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
452  if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
453  av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
454  return AVERROR(EINVAL);
455  }
456  device_hwctx->lock = d3d11va_default_lock;
457  device_hwctx->unlock = d3d11va_default_unlock;
458  }
459 
460  if (!device_hwctx->device_context) {
461  ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
462  if (!device_hwctx->device_context)
463  return AVERROR_UNKNOWN;
464  }
465 
466  if (!device_hwctx->video_device) {
467  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
468  (void **)&device_hwctx->video_device);
469  if (FAILED(hr))
470  return AVERROR_UNKNOWN;
471  }
472 
473  if (!device_hwctx->video_context) {
474  hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
475  (void **)&device_hwctx->video_context);
476  if (FAILED(hr))
477  return AVERROR_UNKNOWN;
478  }
479 
480  return 0;
481 }
482 
484 {
485  AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
486 
487  if (device_hwctx->device) {
488  ID3D11Device_Release(device_hwctx->device);
489  device_hwctx->device = NULL;
490  }
491 
492  if (device_hwctx->device_context) {
493  ID3D11DeviceContext_Release(device_hwctx->device_context);
494  device_hwctx->device_context = NULL;
495  }
496 
497  if (device_hwctx->video_device) {
498  ID3D11VideoDevice_Release(device_hwctx->video_device);
499  device_hwctx->video_device = NULL;
500  }
501 
502  if (device_hwctx->video_context) {
503  ID3D11VideoContext_Release(device_hwctx->video_context);
504  device_hwctx->video_context = NULL;
505  }
506 
507  if (device_hwctx->lock == d3d11va_default_lock) {
508  CloseHandle(device_hwctx->lock_ctx);
509  device_hwctx->lock_ctx = INVALID_HANDLE_VALUE;
510  device_hwctx->lock = NULL;
511  }
512 }
513 
514 static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
515  AVDictionary *opts, int flags)
516 {
517  AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
518 
519  HRESULT hr;
520  IDXGIAdapter *pAdapter = NULL;
521  ID3D10Multithread *pMultithread;
522  UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
523  int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
524  int ret;
525 
526  // (On UWP we can't check this.)
527 #if !HAVE_UWP
528  if (!LoadLibrary("d3d11_1sdklayers.dll"))
529  is_debug = 0;
530 #endif
531 
532  if (is_debug)
533  creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
534 
535  if ((ret = ff_thread_once(&functions_loaded, load_functions)) != 0)
536  return AVERROR_UNKNOWN;
538  av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n");
539  return AVERROR_UNKNOWN;
540  }
541 
542  if (device) {
543  IDXGIFactory2 *pDXGIFactory;
544  hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
545  if (SUCCEEDED(hr)) {
546  int adapter = atoi(device);
547  if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
548  pAdapter = NULL;
549  IDXGIFactory2_Release(pDXGIFactory);
550  }
551  }
552 
553  if (pAdapter) {
554  DXGI_ADAPTER_DESC desc;
555  hr = IDXGIAdapter2_GetDesc(pAdapter, &desc);
556  if (!FAILED(hr)) {
557  av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n",
558  desc.VendorId, desc.DeviceId, desc.Description);
559  }
560  }
561 
562  hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
563  D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
564  if (pAdapter)
565  IDXGIAdapter_Release(pAdapter);
566  if (FAILED(hr)) {
567  av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
568  return AVERROR_UNKNOWN;
569  }
570 
571  hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
572  if (SUCCEEDED(hr)) {
573  ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
574  ID3D10Multithread_Release(pMultithread);
575  }
576 
577 #if !HAVE_UWP && HAVE_DXGIDEBUG_H
578  if (is_debug) {
579  HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll");
580  if (dxgidebug_dll) {
581  HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug)
582  = (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface");
583  if (pf_DXGIGetDebugInterface) {
584  IDXGIDebug *dxgi_debug = NULL;
585  hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug);
586  if (SUCCEEDED(hr) && dxgi_debug)
587  IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
588  }
589  }
590  }
591 #endif
592 
593  return 0;
594 }
595 
598  .name = "D3D11VA",
599 
600  .device_hwctx_size = sizeof(AVD3D11VADeviceContext),
601  .frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
602  .frames_priv_size = sizeof(D3D11VAFramesContext),
603 
604  .device_create = d3d11va_device_create,
606  .device_uninit = d3d11va_device_uninit,
607  .frames_get_constraints = d3d11va_frames_get_constraints,
608  .frames_init = d3d11va_frames_init,
609  .frames_uninit = d3d11va_frames_uninit,
610  .frames_get_buffer = d3d11va_get_buffer,
611  .transfer_get_formats = d3d11va_transfer_get_formats,
612  .transfer_data_to = d3d11va_transfer_data,
613  .transfer_data_from = d3d11va_transfer_data,
614 
616 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
static AVOnce functions_loaded
static int d3d11va_create_staging_texture(AVHWFramesContext *ctx)
#define NULL
Definition: coverity.c:32
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
const char * desc
Definition: libsvtav1.c:79
HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
misc image utilities
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Definition: v4l2.c:192
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:499
static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static AVBufferRef * d3d11va_alloc_single(AVHWFramesContext *ctx)
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
enum AVPixelFormat pix_fmt
ID3D11Texture2D * texture
The texture in which the frame is located.
UINT MiscFlags
D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation.
UINT BindFlags
D3D11_TEXTURE2D_DESC.BindFlags used for texture creation.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:647
static const struct @299 supported_formats[]
#define AV_PIX_FMT_P010
Definition: pixfmt.h:448
AVBufferPool * pool_internal
enum AVHWDeviceType type
static int d3d11va_device_init(AVHWDeviceContext *hwdev)
uint8_t
#define av_cold
Definition: attributes.h:88
static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
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
ID3D11Device * device
Device used for texture creation and access.
D3D11 frame descriptor for pool allocation.
ptrdiff_t size
Definition: opengl_enc.c:100
#define AVOnce
Definition: thread.h:172
#define av_log(a,...)
DXGI_FORMAT d3d_format
#define src
Definition: vp8dsp.c:254
int width
Definition: frame.h:366
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
static void d3d11va_default_unlock(void *ctx)
static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice
static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
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
simple assert() macros that are a bit more flexible than ISO C assert().
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
static av_cold void load_functions(void)
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
static int d3d11va_frames_init(AVHWFramesContext *ctx)
ID3D11VideoContext * video_context
If unset, this will be set from the device_context field on init.
static void d3d11va_default_lock(void *ctx)
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
AVDictionary * opts
Definition: movenc.c:50
static void free_texture(void *opaque, uint8_t *data)
ID3D11VideoDevice * video_device
If unset, this will be set from the device field on init.
#define FFMIN(a, b)
Definition: common.h:96
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:149
uint8_t w
Definition: llviddspenc.c:38
AVFormatContext * ctx
Definition: movenc.c:48
intptr_t index
The index into the array texture element representing the frame, or 0 if the texture is not an array ...
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
#define s(width, name)
Definition: cbs_vp9.c:257
static AVBufferRef * d3d11va_pool_alloc(void *opaque, int size)
void(* unlock)(void *lock_ctx)
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:219
#define FF_ARRAY_ELEMS(a)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:381
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
#define AV_ONCE_INIT
Definition: thread.h:173
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:146
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:339
uint8_t * data
The data buffer.
Definition: buffer.h:89
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
ID3D11Texture2D * texture
The canonical texture used for pool allocation.
int index
Definition: gxfenc.c:89
static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
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
const VDPAUPixFmtMap * map
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:134
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:300
This struct is allocated as AVHWFramesContext.hwctx.
#define flags(name, subs,...)
Definition: cbs_av1.c:560
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:313
ID3D11Texture2D * staging_texture
A reference to a data buffer.
Definition: buffer.h:81
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
common internal and external API header
static AVBufferRef * wrap_texture_buf(ID3D11Texture2D *tex, int index)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
AVHWFrameTransferDirection
Definition: hwcontext.h:415
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:190
#define av_free(p)
void(* lock)(void *lock_ctx)
Callbacks for locking.
static int ff_thread_once(char *control, void(*routine)(void))
Definition: thread.h:175
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
This struct is allocated as AVHWDeviceContext.hwctx.
int height
Definition: frame.h:366
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:338
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
static void fill_texture_ptrs(uint8_t *data[4], int linesize[4], AVHWFramesContext *ctx, D3D11_TEXTURE2D_DESC *desc, D3D11_MAPPED_SUBRESOURCE *map)
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:2489
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
const HWContextType ff_hwcontext_type_d3d11va
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
static PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory
ID3D11DeviceContext * device_context
If unset, this will be set from the device field on init.
int i
Definition: input.c:407