| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662 |
- /*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "buffer.h"
- #include "common.h"
- #include "hwcontext.h"
- #include "hwcontext_amf.h"
- #include "hwcontext_internal.h"
- #include "hwcontext_amf_internal.h"
- #if CONFIG_VULKAN
- #include "hwcontext_vulkan.h"
- #endif
- #if CONFIG_D3D11VA
- #include "libavutil/hwcontext_d3d11va.h"
- #endif
- #if CONFIG_D3D12VA
- #include "libavutil/hwcontext_d3d12va.h"
- #endif
- #if CONFIG_DXVA2
- #define COBJMACROS
- #include "libavutil/hwcontext_dxva2.h"
- #endif
- #include "mem.h"
- #include "pixdesc.h"
- #include "pixfmt.h"
- #include "imgutils.h"
- #include "libavutil/avassert.h"
- #include <AMF/core/Surface.h>
- #include <AMF/core/Trace.h>
- #ifdef _WIN32
- #include "compat/w32dlfcn.h"
- #else
- #include <dlfcn.h>
- #endif
- #define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
- typedef struct AmfTraceWriter {
- AMFTraceWriterVtbl *vtblp;
- void *avctx;
- AMFTraceWriterVtbl vtbl;
- } AmfTraceWriter;
- static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis,
- const wchar_t *scope, const wchar_t *message)
- {
- AmfTraceWriter *tracer = (AmfTraceWriter*)pThis;
- av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF
- }
- static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
- {
- }
- static AmfTraceWriter * amf_writer_alloc(void *avctx)
- {
- AmfTraceWriter * writer = av_mallocz(sizeof(AmfTraceWriter));
- if (!writer)
- return NULL;
- writer->vtblp = &writer->vtbl;
- writer->vtblp->Write = AMFTraceWriter_Write;
- writer->vtblp->Flush = AMFTraceWriter_Flush;
- writer->avctx = avctx;
- return writer;
- }
- static void amf_writer_free(void *opaque)
- {
- AmfTraceWriter *writer = (AmfTraceWriter *)opaque;
- av_freep(&writer);
- }
- /**
- * We still need AVHWFramesContext to utilize our hardware memory
- * otherwise, we will receive the error "HW format requires hw_frames_ctx to be non-NULL".
- * (libavfilter\buffersrc.c function query_formats)
- */
- typedef struct {
- void *dummy;
- } AMFFramesContext;
- typedef struct AVAMFFormatMap {
- enum AVPixelFormat av_format;
- enum AMF_SURFACE_FORMAT amf_format;
- } FormatMap;
- const FormatMap format_map[] =
- {
- { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN },
- { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 },
- { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA },
- { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA },
- { AV_PIX_FMT_BGRA, AMF_SURFACE_BGRA },
- { AV_PIX_FMT_ARGB, AMF_SURFACE_ARGB },
- { AV_PIX_FMT_RGBA, AMF_SURFACE_RGBA },
- { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 },
- { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P },
- { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 },
- { AV_PIX_FMT_P010, AMF_SURFACE_P010 },
- { AV_PIX_FMT_X2BGR10, AMF_SURFACE_R10G10B10A2 },
- { AV_PIX_FMT_RGBAF16, AMF_SURFACE_RGBA_F16},
- };
- enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
- {
- int i;
- for (i = 0; i < amf_countof(format_map); i++) {
- if (format_map[i].av_format == fmt) {
- return format_map[i].amf_format;
- }
- }
- return AMF_SURFACE_UNKNOWN;
- }
- enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt)
- {
- int i;
- for (i = 0; i < amf_countof(format_map); i++) {
- if (format_map[i].amf_format == fmt) {
- return format_map[i].av_format;
- }
- }
- return AV_PIX_FMT_NONE;
- }
- static const enum AVPixelFormat supported_formats[] = {
- AV_PIX_FMT_NV12,
- AV_PIX_FMT_YUV420P,
- AV_PIX_FMT_BGRA,
- AV_PIX_FMT_RGBA,
- AV_PIX_FMT_P010,
- #if CONFIG_D3D11VA
- AV_PIX_FMT_D3D11,
- #endif
- #if CONFIG_D3D12VA
- AV_PIX_FMT_D3D12,
- #endif
- #if CONFIG_DXVA2
- AV_PIX_FMT_DXVA2_VLD,
- #endif
- };
- static const enum AVPixelFormat supported_transfer_formats[] = {
- AV_PIX_FMT_NV12,
- AV_PIX_FMT_YUV420P,
- AV_PIX_FMT_BGRA,
- AV_PIX_FMT_RGBA,
- AV_PIX_FMT_P010,
- AV_PIX_FMT_NONE,
- };
- static int amf_frames_get_constraints(AVHWDeviceContext *ctx,
- const void *hwconfig,
- AVHWFramesConstraints *constraints)
- {
- int i;
- constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1,
- sizeof(*constraints->valid_sw_formats));
- if (!constraints->valid_sw_formats)
- return AVERROR(ENOMEM);
- for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
- constraints->valid_sw_formats[i] = supported_formats[i];
- constraints->valid_sw_formats[FF_ARRAY_ELEMS(supported_formats)] = AV_PIX_FMT_NONE;
- constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
- if (!constraints->valid_hw_formats)
- return AVERROR(ENOMEM);
- constraints->valid_hw_formats[0] = AV_PIX_FMT_AMF_SURFACE;
- constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
- return 0;
- }
- static void amf_dummy_free(void *opaque, uint8_t *data)
- {
- }
- static AVBufferRef *amf_pool_alloc(void *opaque, size_t size)
- {
- AVHWFramesContext *hwfc = (AVHWFramesContext *)opaque;
- AVBufferRef *buf;
- buf = av_buffer_create(NULL, 0, amf_dummy_free, hwfc, AV_BUFFER_FLAG_READONLY);
- if (!buf) {
- av_log(hwfc, AV_LOG_ERROR, "Failed to create buffer for AMF context.\n");
- return NULL;
- }
- return buf;
- }
- static int amf_frames_init(AVHWFramesContext *ctx)
- {
- int i;
- for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
- if (ctx->sw_format == supported_formats[i])
- break;
- }
- if (i == FF_ARRAY_ELEMS(supported_formats)) {
- av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
- av_get_pix_fmt_name(ctx->sw_format));
- return AVERROR(ENOSYS);
- }
- ffhwframesctx(ctx)->pool_internal =
- av_buffer_pool_init2(sizeof(AMFSurface), ctx,
- &amf_pool_alloc, NULL);
- return 0;
- }
- static int amf_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
- {
- frame->buf[0] = av_buffer_pool_get(ctx->pool);
- if (!frame->buf[0])
- return AVERROR(ENOMEM);
- frame->data[0] = frame->buf[0]->data;
- frame->format = AV_PIX_FMT_AMF_SURFACE;
- frame->width = ctx->width;
- frame->height = ctx->height;
- return 0;
- }
- static int amf_transfer_get_formats(AVHWFramesContext *ctx,
- enum AVHWFrameTransferDirection dir,
- enum AVPixelFormat **formats)
- {
- enum AVPixelFormat *fmts;
- int i;
- fmts = av_malloc_array(FF_ARRAY_ELEMS(supported_transfer_formats), sizeof(*fmts));
- if (!fmts)
- return AVERROR(ENOMEM);
- for (i = 0; i < FF_ARRAY_ELEMS(supported_transfer_formats); i++)
- fmts[i] = supported_transfer_formats[i];
- *formats = fmts;
- return 0;
- }
- static void amf_free_amfsurface(void *opaque, uint8_t *data)
- {
- if(!!data){
- AMFSurface *surface = (AMFSurface*)(data);
- surface->pVtbl->Release(surface);
- }
- }
- static int amf_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
- const AVFrame *src)
- {
- AMFSurface* surface = (AMFSurface*)dst->data[0];
- AMFPlane *plane;
- uint8_t *dst_data[4];
- int dst_linesize[4];
- int planes;
- int i;
- int res;
- int w = FFMIN(dst->width, src->width);
- int h = FFMIN(dst->height, src->height);
- if (dst->hw_frames_ctx->data != (uint8_t *)ctx || src->format != ctx->sw_format)
- return AVERROR(EINVAL);
- if (!surface) {
- AVHWDeviceContext *hwdev_ctx = ctx->device_ctx;
- AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hwdev_ctx->hwctx;
- AMF_SURFACE_FORMAT format = av_av_to_amf_format(ctx->sw_format);
- res = amf_device_ctx->context->pVtbl->AllocSurface(amf_device_ctx->context, AMF_MEMORY_HOST, format, dst->width, dst->height, &surface);
- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
- dst->data[0] = (uint8_t *)surface;
- dst->buf[1] = av_buffer_create((uint8_t *)surface, sizeof(surface),
- amf_free_amfsurface,
- NULL,
- AV_BUFFER_FLAG_READONLY);
- AMF_RETURN_IF_FALSE(ctx, !!dst->buf[1], AVERROR(ENOMEM), "av_buffer_create for amf surface failed.");
- }
- planes = (int)surface->pVtbl->GetPlanesCount(surface);
- av_assert0(planes < FF_ARRAY_ELEMS(dst_data));
- for (i = 0; i < planes; i++) {
- plane = surface->pVtbl->GetPlaneAt(surface, i);
- dst_data[i] = plane->pVtbl->GetNative(plane);
- dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
- }
- av_image_copy2(dst_data, dst_linesize,
- src->data, src->linesize, src->format,
- w, h);
- return 0;
- }
- static int amf_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
- const AVFrame *src)
- {
- AMFSurface* surface = (AMFSurface*)src->data[0];
- AMFPlane *plane;
- uint8_t *src_data[4];
- int src_linesize[4];
- int planes;
- int i;
- int w = FFMIN(dst->width, src->width);
- int h = FFMIN(dst->height, src->height);
- int ret;
- if (src->hw_frames_ctx->data != (uint8_t *)ctx || dst->format != ctx->sw_format)
- return AVERROR(EINVAL);
- ret = surface->pVtbl->Convert(surface, AMF_MEMORY_HOST);
- AMF_RETURN_IF_FALSE(ctx, ret == AMF_OK, AVERROR_UNKNOWN, "Convert(amf::AMF_MEMORY_HOST) failed with error %d\n", AVERROR_UNKNOWN);
- planes = (int)surface->pVtbl->GetPlanesCount(surface);
- av_assert0(planes < FF_ARRAY_ELEMS(src_data));
- for (i = 0; i < planes; i++) {
- plane = surface->pVtbl->GetPlaneAt(surface, i);
- src_data[i] = plane->pVtbl->GetNative(plane);
- src_linesize[i] = plane->pVtbl->GetHPitch(plane);
- }
- av_image_copy2(dst->data, dst->linesize,
- src_data, src_linesize, dst->format,
- w, h);
- return 0;
- }
- static void amf_device_uninit(AVHWDeviceContext *device_ctx)
- {
- AVAMFDeviceContext *amf_ctx = device_ctx->hwctx;
- AMF_RESULT res = AMF_NOT_INITIALIZED;
- AMFTrace *trace;
- if (amf_ctx->context) {
- amf_ctx->context->pVtbl->Terminate(amf_ctx->context);
- amf_ctx->context->pVtbl->Release(amf_ctx->context);
- amf_ctx->context = NULL;
- }
- if (amf_ctx->factory)
- res = amf_ctx->factory->pVtbl->GetTrace(amf_ctx->factory, &trace);
- if (res == AMF_OK) {
- trace->pVtbl->UnregisterWriter(trace, FFMPEG_AMF_WRITER_ID);
- }
- if(amf_ctx->library) {
- dlclose(amf_ctx->library);
- amf_ctx->library = NULL;
- }
- if (amf_ctx->trace_writer) {
- amf_writer_free(amf_ctx->trace_writer);
- }
- amf_ctx->version = 0;
- ff_mutex_destroy(&amf_ctx->mutex);
- }
- static int amf_device_init(AVHWDeviceContext *ctx)
- {
- AVAMFDeviceContext *amf_ctx = ctx->hwctx;
- AMFContext1 *context1 = NULL;
- AMF_RESULT res;
- #ifdef _WIN32
- res = amf_ctx->context->pVtbl->InitDX11(amf_ctx->context, NULL, AMF_DX11_1);
- if (res == AMF_OK || res == AMF_ALREADY_INITIALIZED) {
- av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n");
- } else {
- res = amf_ctx->context->pVtbl->InitDX9(amf_ctx->context, NULL);
- if (res == AMF_OK) {
- av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n");
- } else {
- #endif
- AMFGuid guid = IID_AMFContext1();
- res = amf_ctx->context->pVtbl->QueryInterface(amf_ctx->context, &guid, (void**)&context1);
- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res);
- res = context1->pVtbl->InitVulkan(context1, NULL);
- context1->pVtbl->Release(context1);
- if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
- if (res == AMF_NOT_SUPPORTED)
- av_log(ctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n");
- else
- av_log(ctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res);
- return AVERROR(ENOSYS);
- }
- av_log(ctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n");
- #ifdef _WIN32
- }
- }
- #endif
- ff_mutex_init(&amf_ctx->mutex, NULL);
- return 0;
- }
- static int amf_load_library(AVAMFDeviceContext* amf_ctx, void* avcl)
- {
- AMFInit_Fn init_fun;
- AMFQueryVersion_Fn version_fun;
- AMF_RESULT res;
- amf_ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
- AMF_RETURN_IF_FALSE(avcl, amf_ctx->library != NULL,
- AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA);
- init_fun = (AMFInit_Fn)dlsym(amf_ctx->library, AMF_INIT_FUNCTION_NAME);
- 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);
- version_fun = (AMFQueryVersion_Fn)dlsym(amf_ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
- 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);
- res = version_fun(&amf_ctx->version);
- AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
- res = init_fun(AMF_FULL_VERSION, &amf_ctx->factory);
- AMF_RETURN_IF_FALSE(avcl, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res);
- return 0;
- }
- static int amf_device_create(AVHWDeviceContext *device_ctx,
- const char *device,
- AVDictionary *opts, int flags)
- {
- AVAMFDeviceContext *ctx = device_ctx->hwctx;
- AMFTrace *trace;
- int ret;
- if ((ret = amf_load_library(ctx, device_ctx)) == 0) {
- ret = ctx->factory->pVtbl->GetTrace(ctx->factory, &trace);
- if (ret == AMF_OK) {
- int level_ff = av_log_get_level();
- int level_amf = AMF_TRACE_TRACE;
- amf_bool enable_log = true;
- switch(level_ff)
- {
- case AV_LOG_QUIET:
- level_amf = AMF_TRACE_ERROR;
- enable_log = false;
- break;
- case AV_LOG_PANIC:
- case AV_LOG_FATAL:
- case AV_LOG_ERROR:
- level_amf = AMF_TRACE_ERROR;
- break;
- case AV_LOG_WARNING:
- case AV_LOG_INFO:
- level_amf = AMF_TRACE_WARNING;
- break;
- case AV_LOG_VERBOSE:
- level_amf = AMF_TRACE_INFO;
- break;
- case AV_LOG_DEBUG:
- level_amf = AMF_TRACE_DEBUG;
- break;
- case AV_LOG_TRACE:
- level_amf = AMF_TRACE_TRACE;
- break;
- }
- if(ctx->version == AMF_MAKE_FULL_VERSION(1, 4, 35, 0)){// get around a bug in trace in AMF runtime driver 24.20
- level_amf = AMF_TRACE_WARNING;
- }
- trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_CONSOLE, 0);
- trace->pVtbl->SetGlobalLevel(trace, level_amf);
- // connect AMF logger to av_log
- ctx->trace_writer = amf_writer_alloc(device_ctx);
- trace->pVtbl->RegisterWriter(trace, FFMPEG_AMF_WRITER_ID, (AMFTraceWriter*)ctx->trace_writer, 1);
- trace->pVtbl->SetWriterLevel(trace, FFMPEG_AMF_WRITER_ID, level_amf);
- trace->pVtbl->EnableWriter(trace, FFMPEG_AMF_WRITER_ID, enable_log);
- trace->pVtbl->SetWriterLevel(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, level_amf);
- trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, enable_log);
- }
- ret = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context);
- if (ret == AMF_OK) {
- AMF_ASSIGN_PROPERTY_INT64(ret, ctx->context, L"DeviceSurfaceCacheSize", 50 );
- return 0;
- }
- av_log(device_ctx, AV_LOG_ERROR, "CreateContext() failed with error %d.\n", ret);
- }
- amf_device_uninit(device_ctx);
- return ret;
- }
- #if CONFIG_DXVA2
- static int amf_init_from_dxva2_device(AVAMFDeviceContext * amf_ctx, AVHWDeviceContext *child_device_ctx)
- {
- AVDXVA2DeviceContext *hwctx = child_device_ctx->hwctx;
- IDirect3DDevice9 *device;
- HANDLE device_handle;
- HRESULT hr;
- AMF_RESULT res;
- int ret;
- hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle);
- if (FAILED(hr)) {
- av_log(child_device_ctx, AV_LOG_ERROR, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
- return AVERROR_EXTERNAL;
- }
- hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE);
- if (SUCCEEDED(hr)) {
- IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE);
- ret = 0;
- } else {
- av_log(child_device_ctx, AV_LOG_ERROR, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
- ret = AVERROR_EXTERNAL;
- }
- IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle);
- if (ret < 0)
- return ret;
- res = amf_ctx->context->pVtbl->InitDX9(amf_ctx->context, device);
- IDirect3DDevice9_Release(device);
- if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
- if (res == AMF_NOT_SUPPORTED)
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n");
- else
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res);
- return AVERROR(ENODEV);
- }
- av_log(child_device_ctx, AV_LOG_INFO, "AMF via DXVA2.\n");
- return 0;
- }
- #endif
- #if CONFIG_D3D11VA
- static int amf_init_from_d3d11_device(AVAMFDeviceContext* amf_ctx, AVHWDeviceContext *child_device_ctx)
- {
- AMF_RESULT res;
- AVD3D11VADeviceContext *hwctx = child_device_ctx->hwctx;
- res = amf_ctx->context->pVtbl->InitDX11(amf_ctx->context, hwctx->device, AMF_DX11_1);
- if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
- if (res == AMF_NOT_SUPPORTED)
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D11 is not supported on the given device.\n");
- else
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D11 device: %d.\n", res);
- return AVERROR(ENODEV);
- }
- av_log(child_device_ctx, AV_LOG_INFO, "AMF via D3D11.\n");
- return 0;
- }
- #endif
- #if CONFIG_D3D12VA
- static int amf_init_from_d3d12_device(AVAMFDeviceContext* amf_ctx, AVHWDeviceContext *child_device_ctx)
- {
- AVD3D12VADeviceContext *hwctx = child_device_ctx->hwctx;
- AMF_RESULT res;
- AMFContext2 *context2 = NULL;
- AMFGuid guid = IID_AMFContext2();
- res = amf_ctx->context->pVtbl->QueryInterface(amf_ctx->context, &guid, (void**)&context2);
- AMF_RETURN_IF_FALSE(child_device_ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext2() failed with error %d\n", res);
- res = context2->pVtbl->InitDX12(context2, hwctx->device, AMF_DX12);
- context2->pVtbl->Release(context2);
- if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
- if (res == AMF_NOT_SUPPORTED)
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF via D3D12 is not supported on the given device.\n");
- else
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D12 device: %d.\n", res);
- return AVERROR(ENODEV);
- }
- av_log(child_device_ctx, AV_LOG_INFO, "AMF via D3D12.\n");
- return 0;
- }
- #endif
- static int amf_device_derive(AVHWDeviceContext *device_ctx,
- AVHWDeviceContext *child_device_ctx, AVDictionary *opts,
- int flags)
- {
- #if CONFIG_DXVA2 || CONFIG_D3D11VA
- AVAMFDeviceContext *amf_ctx = device_ctx->hwctx;
- #endif
- int ret;
- ret = amf_device_create(device_ctx, "", opts, flags);
- if(ret < 0)
- return ret;
- switch (child_device_ctx->type) {
- #if CONFIG_DXVA2
- case AV_HWDEVICE_TYPE_DXVA2: {
- return amf_init_from_dxva2_device(amf_ctx, child_device_ctx);
- }
- break;
- #endif
- #if CONFIG_D3D11VA
- case AV_HWDEVICE_TYPE_D3D11VA: {
- return amf_init_from_d3d11_device(amf_ctx, child_device_ctx);
- }
- break;
- #endif
- #if CONFIG_D3D12VA
- case AV_HWDEVICE_TYPE_D3D12VA: {
- return amf_init_from_d3d12_device(amf_ctx, child_device_ctx);
- }
- break;
- #endif
- default: {
- av_log(child_device_ctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n",
- av_hwdevice_get_type_name(child_device_ctx->type));
- return AVERROR(ENOSYS);
- }
- }
- return 0;
- }
- const HWContextType ff_hwcontext_type_amf = {
- .type = AV_HWDEVICE_TYPE_AMF,
- .name = "AMF",
- .device_hwctx_size = sizeof(AVAMFDeviceContext),
- .frames_hwctx_size = sizeof(AMFFramesContext),
- .device_create = amf_device_create,
- .device_derive = amf_device_derive,
- .device_init = amf_device_init,
- .device_uninit = amf_device_uninit,
- .frames_get_constraints = amf_frames_get_constraints,
- .frames_init = amf_frames_init,
- .frames_get_buffer = amf_get_buffer,
- .transfer_get_formats = amf_transfer_get_formats,
- .transfer_data_to = amf_transfer_data_to,
- .transfer_data_from = amf_transfer_data_from,
- .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_AMF_SURFACE, AV_PIX_FMT_NONE },
- };
|