FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
hwcontext_amf.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 "buffer.h"
20 #include "common.h"
21 #include "hwcontext.h"
22 #include "hwcontext_amf.h"
23 #include "hwcontext_internal.h"
24 #include "hwcontext_amf_internal.h"
25 #if CONFIG_VULKAN
26 #include "hwcontext_vulkan.h"
27 #endif
28 #if CONFIG_D3D11VA
30 #endif
31 #if CONFIG_D3D12VA
33 #endif
34 #if CONFIG_DXVA2
35 #define COBJMACROS
37 #endif
38 #include "mem.h"
39 #include "pixdesc.h"
40 #include "pixfmt.h"
41 #include "imgutils.h"
42 #include "libavutil/avassert.h"
43 #include <AMF/core/Surface.h>
44 #include <AMF/core/Trace.h>
45 #ifdef _WIN32
46 #include "compat/w32dlfcn.h"
47 #else
48 #include <dlfcn.h>
49 #endif
50 #define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
51 
52 
53 typedef struct AmfTraceWriter {
54  AMFTraceWriterVtbl *vtblp;
55  void *avctx;
56  AMFTraceWriterVtbl vtbl;
58 
59 static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis,
60  const wchar_t *scope, const wchar_t *message)
61 {
62  AmfTraceWriter *tracer = (AmfTraceWriter*)pThis;
63  av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF
64 }
65 
66 static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
67 {
68 }
69 
70 static AmfTraceWriter * amf_writer_alloc(void *avctx)
71 {
72  AmfTraceWriter * writer = av_mallocz(sizeof(AmfTraceWriter));
73  if (!writer)
74  return NULL;
75 
76  writer->vtblp = &writer->vtbl;
77  writer->vtblp->Write = AMFTraceWriter_Write;
78  writer->vtblp->Flush = AMFTraceWriter_Flush;
79  writer->avctx = avctx;
80 
81  return writer;
82 }
83 
84 static void amf_writer_free(void *opaque)
85 {
86  AmfTraceWriter *writer = (AmfTraceWriter *)opaque;
87  av_freep(&writer);
88 }
89 
90 /**
91  * We still need AVHWFramesContext to utilize our hardware memory
92  * otherwise, we will receive the error "HW format requires hw_frames_ctx to be non-NULL".
93  * (libavfilter\buffersrc.c function query_formats)
94 */
95 typedef struct {
96  void *dummy;
98 
99 typedef struct AVAMFFormatMap {
101  enum AMF_SURFACE_FORMAT amf_format;
102 } FormatMap;
103 
104 const FormatMap format_map[] =
105 {
106  { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN },
107  { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 },
108  { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA },
109  { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA },
110  { AV_PIX_FMT_BGRA, AMF_SURFACE_BGRA },
111  { AV_PIX_FMT_ARGB, AMF_SURFACE_ARGB },
112  { AV_PIX_FMT_RGBA, AMF_SURFACE_RGBA },
113  { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 },
114  { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P },
115  { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 },
116  { AV_PIX_FMT_P010, AMF_SURFACE_P010 },
117  { AV_PIX_FMT_X2BGR10, AMF_SURFACE_R10G10B10A2 },
118  { AV_PIX_FMT_RGBAF16, AMF_SURFACE_RGBA_F16},
119 };
120 
121 enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
122 {
123  int i;
124  for (i = 0; i < amf_countof(format_map); i++) {
125  if (format_map[i].av_format == fmt) {
126  return format_map[i].amf_format;
127  }
128  }
129  return AMF_SURFACE_UNKNOWN;
130 }
131 
132 enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt)
133 {
134  int i;
135  for (i = 0; i < amf_countof(format_map); i++) {
136  if (format_map[i].amf_format == fmt) {
137  return format_map[i].av_format;
138  }
139  }
140  return AMF_SURFACE_UNKNOWN;
141 }
142 
143 static const enum AVPixelFormat supported_formats[] = {
149 #if CONFIG_D3D11VA
151 #endif
152 #if CONFIG_D3D12VA
154 #endif
155 #if CONFIG_DXVA2
157 #endif
158 };
159 
167 };
168 
170  const void *hwconfig,
171  AVHWFramesConstraints *constraints)
172 {
173  int i;
174 
176  sizeof(*constraints->valid_sw_formats));
177  if (!constraints->valid_sw_formats)
178  return AVERROR(ENOMEM);
179 
180  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
181  constraints->valid_sw_formats[i] = supported_formats[i];
183 
184  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
185  if (!constraints->valid_hw_formats)
186  return AVERROR(ENOMEM);
187 
188  constraints->valid_hw_formats[0] = AV_PIX_FMT_AMF_SURFACE;
189  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
190 
191  return 0;
192 }
193 
194 static void amf_dummy_free(void *opaque, uint8_t *data)
195 {
196 
197 }
198 
199 static AVBufferRef *amf_pool_alloc(void *opaque, size_t size)
200 {
201  AVHWFramesContext *hwfc = (AVHWFramesContext *)opaque;
202  AVBufferRef *buf;
203 
205  if (!buf) {
206  av_log(hwfc, AV_LOG_ERROR, "Failed to create buffer for AMF context.\n");
207  return NULL;
208  }
209  return buf;
210 }
211 
213 {
214  int i;
215 
216  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
217  if (ctx->sw_format == supported_formats[i])
218  break;
219  }
221  av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
222  av_get_pix_fmt_name(ctx->sw_format));
223  return AVERROR(ENOSYS);
224  }
225 
227  av_buffer_pool_init2(sizeof(AMFSurface), ctx,
228  &amf_pool_alloc, NULL);
229 
230  return 0;
231 }
232 
233 
235 {
236  frame->buf[0] = av_buffer_pool_get(ctx->pool);
237  if (!frame->buf[0])
238  return AVERROR(ENOMEM);
239 
240  frame->data[0] = frame->buf[0]->data;
241  frame->format = AV_PIX_FMT_AMF_SURFACE;
242  frame->width = ctx->width;
243  frame->height = ctx->height;
244  return 0;
245 }
246 
249  enum AVPixelFormat **formats)
250 {
251  enum AVPixelFormat *fmts;
252  int i;
253 
255  if (!fmts)
256  return AVERROR(ENOMEM);
258  fmts[i] = supported_transfer_formats[i];
259 
260  *formats = fmts;
261 
262  return 0;
263 }
264 
265 static void amf_free_amfsurface(void *opaque, uint8_t *data)
266 {
267  if(!!data){
268  AMFSurface *surface = (AMFSurface*)(data);
269  surface->pVtbl->Release(surface);
270  }
271 }
272 
274  const AVFrame *src)
275 {
276  AMFSurface* surface = (AMFSurface*)dst->data[0];
277  AMFPlane *plane;
278  uint8_t *dst_data[4];
279  int dst_linesize[4];
280  int planes;
281  int i;
282  int res;
283  int w = FFMIN(dst->width, src->width);
284  int h = FFMIN(dst->height, src->height);
285 
286  if (dst->hw_frames_ctx->data != (uint8_t *)ctx || src->format != ctx->sw_format)
287  return AVERROR(EINVAL);
288 
289  if (!surface) {
290  AVHWDeviceContext *hwdev_ctx = ctx->device_ctx;
291  AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hwdev_ctx->hwctx;
292  AMF_SURFACE_FORMAT format = av_av_to_amf_format(ctx->sw_format);
293  res = amf_device_ctx->context->pVtbl->AllocSurface(amf_device_ctx->context, AMF_MEMORY_HOST, format, dst->width, dst->height, &surface);
294  AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
295  dst->data[0] = (uint8_t *)surface;
296  dst->buf[1] = av_buffer_create((uint8_t *)surface, sizeof(surface),
298  NULL,
300  AMF_RETURN_IF_FALSE(ctx, !!dst->buf[1], AVERROR(ENOMEM), "av_buffer_create for amf surface failed.");
301  }
302 
303  planes = (int)surface->pVtbl->GetPlanesCount(surface);
304  av_assert0(planes < FF_ARRAY_ELEMS(dst_data));
305 
306  for (i = 0; i < planes; i++) {
307  plane = surface->pVtbl->GetPlaneAt(surface, i);
308  dst_data[i] = plane->pVtbl->GetNative(plane);
309  dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
310  }
311  av_image_copy2(dst_data, dst_linesize,
312  src->data, src->linesize, src->format,
313  w, h);
314 
315  return 0;
316 }
317 
319  const AVFrame *src)
320 {
321  AMFSurface* surface = (AMFSurface*)src->data[0];
322  AMFPlane *plane;
323  uint8_t *src_data[4];
324  int src_linesize[4];
325  int planes;
326  int i;
327  int w = FFMIN(dst->width, src->width);
328  int h = FFMIN(dst->height, src->height);
329  int ret;
330 
331  if (src->hw_frames_ctx->data != (uint8_t *)ctx || dst->format != ctx->sw_format)
332  return AVERROR(EINVAL);
333 
334  ret = surface->pVtbl->Convert(surface, AMF_MEMORY_HOST);
335  AMF_RETURN_IF_FALSE(ctx, ret == AMF_OK, AVERROR_UNKNOWN, "Convert(amf::AMF_MEMORY_HOST) failed with error %d\n", AVERROR_UNKNOWN);
336 
337  planes = (int)surface->pVtbl->GetPlanesCount(surface);
338  av_assert0(planes < FF_ARRAY_ELEMS(src_data));
339 
340  for (i = 0; i < planes; i++) {
341  plane = surface->pVtbl->GetPlaneAt(surface, i);
342  src_data[i] = plane->pVtbl->GetNative(plane);
343  src_linesize[i] = plane->pVtbl->GetHPitch(plane);
344  }
345  av_image_copy2(dst->data, dst->linesize,
346  src_data, src_linesize, dst->format,
347  w, h);
348  return 0;
349 }
350 
351 
352 
353 static void amf_device_uninit(AVHWDeviceContext *device_ctx)
354 {
355  AVAMFDeviceContext *amf_ctx = device_ctx->hwctx;
356  AMF_RESULT res = AMF_NOT_INITIALIZED;
357  AMFTrace *trace;
358 
359  if (amf_ctx->context) {
360  amf_ctx->context->pVtbl->Terminate(amf_ctx->context);
361  amf_ctx->context->pVtbl->Release(amf_ctx->context);
362  amf_ctx->context = NULL;
363  }
364 
365  if (amf_ctx->factory)
366  res = amf_ctx->factory->pVtbl->GetTrace(amf_ctx->factory, &trace);
367 
368  if (res == AMF_OK) {
369  trace->pVtbl->UnregisterWriter(trace, FFMPEG_AMF_WRITER_ID);
370  }
371 
372  if(amf_ctx->library) {
373  dlclose(amf_ctx->library);
374  amf_ctx->library = NULL;
375  }
376  if (amf_ctx->trace_writer) {
377  amf_writer_free(amf_ctx->trace_writer);
378  }
379 
380  amf_ctx->version = 0;
381 }
382 
384 {
385  AVAMFDeviceContext *amf_ctx = ctx->hwctx;
386  AMFContext1 *context1 = NULL;
387  AMF_RESULT res;
388 
389 #ifdef _WIN32
390  res = amf_ctx->context->pVtbl->InitDX11(amf_ctx->context, NULL, AMF_DX11_1);
391  if (res == AMF_OK || res == AMF_ALREADY_INITIALIZED) {
392  av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n");
393  } else {
394  res = amf_ctx->context->pVtbl->InitDX9(amf_ctx->context, NULL);
395  if (res == AMF_OK) {
396  av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n");
397  } else {
398 #endif
399  AMFGuid guid = IID_AMFContext1();
400  res = amf_ctx->context->pVtbl->QueryInterface(amf_ctx->context, &guid, (void**)&context1);
401  AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
402 
403  res = context1->pVtbl->InitVulkan(context1, NULL);
404  context1->pVtbl->Release(context1);
405  if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
406  if (res == AMF_NOT_SUPPORTED)
407  av_log(ctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n");
408  else
409  av_log(ctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res);
410  return AVERROR(ENOSYS);
411  }
412  av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n");
413 #ifdef _WIN32
414  }
415  }
416 #endif
417  return 0;
418 }
419 
420 static int amf_load_library(AVAMFDeviceContext* amf_ctx, void* avcl)
421 {
422  AMFInit_Fn init_fun;
423  AMFQueryVersion_Fn version_fun;
424  AMF_RESULT res;
425 
426  amf_ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
427  AMF_RETURN_IF_FALSE(avcl, amf_ctx->library != NULL,
428  AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA);
429 
430  init_fun = (AMFInit_Fn)dlsym(amf_ctx->library, AMF_INIT_FUNCTION_NAME);
431  AMF_RETURN_IF_FALSE(avcl, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME);
432 
433  version_fun = (AMFQueryVersion_Fn)dlsym(amf_ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
434  AMF_RETURN_IF_FALSE(avcl, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);
435 
436  res = version_fun(&amf_ctx->version);
437  AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
438  res = init_fun(AMF_FULL_VERSION, &amf_ctx->factory);
439  AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res);
440  return 0;
441 }
442 
443 static int amf_device_create(AVHWDeviceContext *device_ctx,
444  const char *device,
445  AVDictionary *opts, int flags)
446 {
447  AVAMFDeviceContext *ctx = device_ctx->hwctx;
448  AMFTrace *trace;
449  int ret;
450  if ((ret = amf_load_library(ctx, device_ctx)) == 0) {
451  ret = ctx->factory->pVtbl->GetTrace(ctx->factory, &trace);
452  if (ret == AMF_OK) {
453  int level_ff = av_log_get_level();
454  int level_amf = AMF_TRACE_TRACE;
455  amf_bool enable_log = true;
456  switch(level_ff)
457  {
458  case AV_LOG_QUIET:
459  level_amf = AMF_TRACE_ERROR;
460  enable_log = false;
461  break;
462  case AV_LOG_PANIC:
463  case AV_LOG_FATAL:
464  case AV_LOG_ERROR:
465  level_amf = AMF_TRACE_ERROR;
466  break;
467  case AV_LOG_WARNING:
468  case AV_LOG_INFO:
469  level_amf = AMF_TRACE_WARNING;
470  break;
471  case AV_LOG_VERBOSE:
472  level_amf = AMF_TRACE_INFO;
473  break;
474  case AV_LOG_DEBUG:
475  level_amf = AMF_TRACE_DEBUG;
476  break;
477  case AV_LOG_TRACE:
478  level_amf = AMF_TRACE_TRACE;
479  break;
480  }
481  if(ctx->version == AMF_MAKE_FULL_VERSION(1, 4, 35, 0)){// get around a bug in trace in AMF runtime driver 24.20
482  level_amf = AMF_TRACE_WARNING;
483  }
484 
485  trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_CONSOLE, 0);
486  trace->pVtbl->SetGlobalLevel(trace, level_amf);
487 
488  // connect AMF logger to av_log
489  ctx->trace_writer = amf_writer_alloc(device_ctx);
490  trace->pVtbl->RegisterWriter(trace, FFMPEG_AMF_WRITER_ID, (AMFTraceWriter*)ctx->trace_writer, 1);
491  trace->pVtbl->SetWriterLevel(trace, FFMPEG_AMF_WRITER_ID, level_amf);
492  trace->pVtbl->EnableWriter(trace, FFMPEG_AMF_WRITER_ID, enable_log);
493  trace->pVtbl->SetWriterLevel(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, level_amf);
494  trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, enable_log);
495  }
496 
497 
498  ret = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context);
499  if (ret == AMF_OK)
500  return 0;
501  av_log(device_ctx, AV_LOG_ERROR, "CreateContext() failed with error %d.\n", ret);
502  }
503  amf_device_uninit(device_ctx);
504  return ret;
505 }
506 
507 #if CONFIG_DXVA2
508 static int amf_init_from_dxva2_device(AVAMFDeviceContext * amf_ctx, AVHWDeviceContext *child_device_ctx)
509 {
510  AVDXVA2DeviceContext *hwctx = child_device_ctx->hwctx;
511  IDirect3DDevice9 *device;
512  HANDLE device_handle;
513  HRESULT hr;
514  AMF_RESULT res;
515  int ret;
516 
517  hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle);
518  if (FAILED(hr)) {
519  av_log(child_device_ctx, AV_LOG_ERROR, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
520  return AVERROR_EXTERNAL;
521  }
522 
523  hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE);
524  if (SUCCEEDED(hr)) {
525  IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE);
526  ret = 0;
527  } else {
528  av_log(child_device_ctx, AV_LOG_ERROR, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
530  }
531 
532 
533  IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle);
534 
535  if (ret < 0)
536  return ret;
537 
538  res = amf_ctx->context->pVtbl->InitDX9(amf_ctx->context, device);
539 
540  IDirect3DDevice9_Release(device);
541 
542  if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
543  if (res == AMF_NOT_SUPPORTED)
544  av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n");
545  else
546  av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res);
547  return AVERROR(ENODEV);
548  }
549  av_log(child_device_ctx, AV_LOG_INFO, "AMF via DXVA2.\n");
550  return 0;
551 }
552 #endif
553 
554 #if CONFIG_D3D11VA
555 static int amf_init_from_d3d11_device(AVAMFDeviceContext* amf_ctx, AVHWDeviceContext *child_device_ctx)
556 {
557  AMF_RESULT res;
558  AVD3D11VADeviceContext *hwctx = child_device_ctx->hwctx;
559  res = amf_ctx->context->pVtbl->InitDX11(amf_ctx->context, hwctx->device, AMF_DX11_1);
560  if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
561  if (res == AMF_NOT_SUPPORTED)
562  av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D11 is not supported on the given device.\n");
563  else
564  av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D11 device: %d.\n", res);
565  return AVERROR(ENODEV);
566  }
567  av_log(child_device_ctx, AV_LOG_INFO, "AMF via D3D11.\n");
568  return 0;
569 }
570 #endif
571 
572 #if CONFIG_D3D12VA
573 static int amf_init_from_d3d12_device(AVAMFDeviceContext* amf_ctx, AVHWDeviceContext *child_device_ctx)
574 {
575  AVD3D12VADeviceContext *hwctx = child_device_ctx->hwctx;
576  AMF_RESULT res;
577  AMFContext2 *context2 = NULL;
578  AMFGuid guid = IID_AMFContext2();
579  res = amf_ctx->context->pVtbl->QueryInterface(amf_ctx->context, &guid, (void**)&context2);
580  AMF_RETURN_IF_FALSE(child_device_ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext2() failed with error %d\n", res);
581  res = context2->pVtbl->InitDX12(context2, hwctx->device, AMF_DX12);
582  context2->pVtbl->Release(context2);
583  if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
584  if (res == AMF_NOT_SUPPORTED)
585  av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D12 is not supported on the given device.\n");
586  else
587  av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D12 device: %d.\n", res);
588  return AVERROR(ENODEV);
589  }
590  av_log(child_device_ctx, AV_LOG_INFO, "AMF via D3D12.\n");
591  return 0;
592 }
593 #endif
594 
595 
596 static int amf_device_derive(AVHWDeviceContext *device_ctx,
597  AVHWDeviceContext *child_device_ctx, AVDictionary *opts,
598  int flags)
599 {
600 #if CONFIG_DXVA2 || CONFIG_D3D11VA
601  AVAMFDeviceContext *amf_ctx = device_ctx->hwctx;
602 #endif
603  int ret;
604 
605  ret = amf_device_create(device_ctx, "", opts, flags);
606  if(ret < 0)
607  return ret;
608 
609  switch (child_device_ctx->type) {
610 
611 #if CONFIG_DXVA2
612  case AV_HWDEVICE_TYPE_DXVA2: {
613  return amf_init_from_dxva2_device(amf_ctx, child_device_ctx);
614  }
615  break;
616 #endif
617 
618 #if CONFIG_D3D11VA
620  return amf_init_from_d3d11_device(amf_ctx, child_device_ctx);
621  }
622  break;
623 #endif
624 #if CONFIG_D3D12VA
626  return amf_init_from_d3d12_device(amf_ctx, child_device_ctx);
627  }
628  break;
629 #endif
630  default: {
631  av_log(child_device_ctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n",
632  av_hwdevice_get_type_name(child_device_ctx->type));
633  return AVERROR(ENOSYS);
634  }
635  }
636  return 0;
637 }
638 
641  .name = "AMF",
642 
643  .device_hwctx_size = sizeof(AVAMFDeviceContext),
644  .frames_hwctx_size = sizeof(AMFFramesContext),
645 
646  .device_create = amf_device_create,
647  .device_derive = amf_device_derive,
648  .device_init = amf_device_init,
649  .device_uninit = amf_device_uninit,
650  .frames_get_constraints = amf_frames_get_constraints,
651  .frames_init = amf_frames_init,
652  .frames_get_buffer = amf_get_buffer,
653  .transfer_get_formats = amf_transfer_get_formats,
654  .transfer_data_to = amf_transfer_data_to,
655  .transfer_data_from = amf_transfer_data_from,
656 
657  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_AMF_SURFACE, AV_PIX_FMT_NONE },
658 };
flags
const SwsFlags flags[]
Definition: swscale.c:61
formats
formats
Definition: signature.h:47
AMFFramesContext::dummy
void * dummy
Definition: hwcontext_amf.c:96
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:86
FFHWFramesContext::pool_internal
AVBufferPool * pool_internal
Definition: hwcontext_internal.h:101
AVD3D12VADeviceContext::device
ID3D12Device * device
Device used for objects creation and access.
Definition: hwcontext_d3d12va.h:54
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
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
message
Definition: api-threadmessage-test.c:47
AV_LOG_QUIET
#define AV_LOG_QUIET
Print no output.
Definition: log.h:192
AV_LOG_PANIC
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
Definition: log.h:197
amf_writer_alloc
static AmfTraceWriter * amf_writer_alloc(void *avctx)
Definition: hwcontext_amf.c:70
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:410
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
amf_dummy_free
static void amf_dummy_free(void *opaque, uint8_t *data)
Definition: hwcontext_amf.c:194
data
const char data[16]
Definition: mxf.c:149
amf_device_create
static int amf_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_amf.c:443
AVDXVA2DeviceContext::devmgr
IDirect3DDeviceManager9 * devmgr
Definition: hwcontext_dxva2.h:40
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AMFTraceWriter_Write
static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, const wchar_t *scope, const wchar_t *message)
Definition: hwcontext_amf.c:59
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
AVDictionary
Definition: dict.c:32
AMF_RETURN_IF_FALSE
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value,...)
Error handling helper.
Definition: amfenc.h:166
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:447
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVAMFFormatMap
Definition: hwcontext_amf.c:99
AV_PIX_FMT_AMF_SURFACE
@ AV_PIX_FMT_AMF_SURFACE
HW acceleration through AMF.
Definition: pixfmt.h:477
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:442
av_amf_to_av_format
enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt)
Definition: hwcontext_amf.c:132
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
av_av_to_amf_format
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
Definition: hwcontext_amf.c:121
AVAMFDeviceContext::context
AMFContext * context
Definition: hwcontext_amf.h:39
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
amf_transfer_get_formats
static int amf_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_amf.c:247
avassert.h
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
ffhwframesctx
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
Definition: hwcontext_internal.h:115
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:236
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
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:454
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:390
AVAMFFormatMap::av_format
enum AVPixelFormat av_format
Definition: hwcontext_amf.c:100
AV_PIX_FMT_DXVA2_VLD
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
Definition: pixfmt.h:134
amf_frames_get_constraints
static int amf_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_amf.c:169
AVD3D11VADeviceContext::device
ID3D11Device * device
Device used for texture creation and access.
Definition: hwcontext_d3d11va.h:56
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
AmfTraceWriter::vtblp
AMFTraceWriterVtbl * vtblp
Definition: hwcontext_amf.c:54
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
amf_device_init
static int amf_device_init(AVHWDeviceContext *ctx)
Definition: hwcontext_amf.c:383
AV_HWDEVICE_TYPE_AMF
@ AV_HWDEVICE_TYPE_AMF
Definition: hwcontext.h:41
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
amf_transfer_data_to
static int amf_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_amf.c:273
ctx
AVFormatContext * ctx
Definition: movenc.c:49
FFMPEG_AMF_WRITER_ID
#define FFMPEG_AMF_WRITER_ID
Definition: hwcontext_amf.c:50
hwcontext_amf.h
AVAMFDeviceContext::version
int64_t version
version of AMF runtime
Definition: hwcontext_amf.h:38
amf_writer_free
static void amf_writer_free(void *opaque)
Definition: hwcontext_amf.c:84
av_hwdevice_get_type_name
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition: hwcontext.c:116
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
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:469
opts
AVDictionary * opts
Definition: movenc.c:51
NULL
#define NULL
Definition: coverity.c:32
amf_pool_alloc
static AVBufferRef * amf_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_amf.c:199
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
AV_HWDEVICE_TYPE_DXVA2
@ AV_HWDEVICE_TYPE_DXVA2
Definition: hwcontext.h:32
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
hwcontext_vulkan.h
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
AVAMFDeviceContext::trace_writer
void * trace_writer
Definition: hwcontext_amf.h:36
hwcontext_d3d12va.h
amf_get_buffer
static int amf_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_amf.c:234
AVAMFDeviceContext::library
void * library
Definition: hwcontext_amf.h:34
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
AmfTraceWriter
Definition: hwcontext_amf.c:53
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:597
hwcontext_dxva2.h
AV_HWDEVICE_TYPE_D3D12VA
@ AV_HWDEVICE_TYPE_D3D12VA
Definition: hwcontext.h:40
amf_free_amfsurface
static void amf_free_amfsurface(void *opaque, uint8_t *data)
Definition: hwcontext_amf.c:265
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
size
int size
Definition: twinvq_data.h:10344
AVAMFDeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_amf.h:33
ff_hwcontext_type_amf
const HWContextType ff_hwcontext_type_amf
Definition: hwcontext_amf.c:639
amf_device_uninit
static void amf_device_uninit(AVHWDeviceContext *device_ctx)
Definition: hwcontext_amf.c:353
AMFFramesContext
We still need AVHWFramesContext to utilize our hardware memory otherwise, we will receive the error "...
Definition: hwcontext_amf.c:95
buffer.h
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:336
amf_frames_init
static int amf_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_amf.c:212
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:99
planes
static const struct @509 planes[]
AVAMFFormatMap::amf_format
enum AMF_SURFACE_FORMAT amf_format
Definition: hwcontext_amf.c:101
AVD3D12VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d12va.h:43
AVAMFDeviceContext::factory
AMFFactory * factory
Definition: hwcontext_amf.h:35
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVDXVA2DeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_dxva2.h:39
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
amf_transfer_data_from
static int amf_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_amf.c:318
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:256
amf_device_derive
static int amf_device_derive(AVHWDeviceContext *device_ctx, AVHWDeviceContext *child_device_ctx, AVDictionary *opts, int flags)
Definition: hwcontext_amf.c:596
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:404
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:116
ret
ret
Definition: filter_design.txt:187
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition: log.h:204
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:73
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
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
supported_formats
static enum AVPixelFormat supported_formats[]
Definition: hwcontext_amf.c:143
hwcontext_amf_internal.h
amf_load_library
static int amf_load_library(AVAMFDeviceContext *amf_ctx, void *avcl)
Definition: hwcontext_amf.c:420
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
format_map
const FormatMap format_map[]
Definition: hwcontext_amf.c:104
AmfTraceWriter::avctx
void * avctx
Definition: hwcontext_amf.c:55
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:585
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AmfTraceWriter::vtbl
AMFTraceWriterVtbl vtbl
Definition: hwcontext_amf.c:56
hwcontext_internal.h
AMFTraceWriter_Flush
static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
Definition: hwcontext_amf.c:66
AV_PIX_FMT_RGBAF16
#define AV_PIX_FMT_RGBAF16
Definition: pixfmt.h:607
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
imgutils.h
hwcontext.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
HWContextType
Definition: hwcontext_internal.h:29
h
h
Definition: vp9dsp_template.c:2070
hwcontext_d3d11va.h
src
#define src
Definition: vp8dsp.c:248
supported_transfer_formats
static enum AVPixelFormat supported_transfer_formats[]
Definition: hwcontext_amf.c:160
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:3261