diff options
author | Alexander Kravchenko <akravchenko188@gmail.com> | 2018-04-14 15:46:10 +0100 |
---|---|---|
committer | Mark Thompson <sw@jkqxz.net> | 2018-04-15 16:46:17 +0100 |
commit | 2c6ca2b54968ad3d2c947cdc16f92b6867f29f3a (patch) | |
tree | 6e6a17088cef75dd00b2af045ca3375850d7e64e | |
parent | ab7eed13a789b3f709a8964b0337bc69f152a9d7 (diff) | |
download | ffmpeg-2c6ca2b54968ad3d2c947cdc16f92b6867f29f3a.tar.gz |
amfenc: Add DXVA2 hardware frame input support
Adds support for AMF initialisation from a DXVA2 (Direct3D9) device, and
then allows passing DXVA2 surfaces into an AMF encoder.
Signed-off-by: Mark Thompson <sw@jkqxz.net>
-rw-r--r-- | libavcodec/amfenc.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index 1ac4ebf456..2a8c76069b 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -24,6 +24,10 @@ #if CONFIG_D3D11VA #include "libavutil/hwcontext_d3d11va.h" #endif +#if CONFIG_DXVA2 +#define COBJMACROS +#include "libavutil/hwcontext_dxva2.h" +#endif #include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "libavutil/time.h" @@ -51,6 +55,9 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { #if CONFIG_D3D11VA AV_PIX_FMT_D3D11, #endif +#if CONFIG_DXVA2 + AV_PIX_FMT_DXVA2_VLD, +#endif AV_PIX_FMT_NONE }; @@ -162,6 +169,52 @@ static int amf_init_from_d3d11_device(AVCodecContext *avctx, AVD3D11VADeviceCont } #endif +#if CONFIG_DXVA2 +static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContext *hwctx) +{ + AmfContext *ctx = avctx->priv_data; + HANDLE device_handle; + IDirect3DDevice9 *device; + HRESULT hr; + AMF_RESULT res; + int ret; + + hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle); + if (FAILED(hr)) { + av_log(avctx, 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(avctx, 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 = ctx->context->pVtbl->InitDX9(ctx->context, device); + + IDirect3DDevice9_Release(device); + + if (res != AMF_OK) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res); + return AVERROR(ENODEV); + } + + return 0; +} +#endif + static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; @@ -206,6 +259,13 @@ static int amf_init_context(AVCodecContext *avctx) return ret; break; #endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + ret = amf_init_from_dxva2_device(avctx, frames_ctx->device_ctx->hwctx); + if (ret < 0) + return ret; + break; +#endif default: av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s frames context is not supported.\n", av_hwdevice_get_type_name(frames_ctx->device_ctx->type)); @@ -230,6 +290,13 @@ static int amf_init_context(AVCodecContext *avctx) return ret; break; #endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + ret = amf_init_from_dxva2_device(avctx, device_ctx->hwctx); + if (ret < 0) + return ret; + break; +#endif default: av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n", av_hwdevice_get_type_name(device_ctx->type)); @@ -581,6 +648,18 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) } break; #endif +#if CONFIG_DXVA2 + case AV_PIX_FMT_DXVA2_VLD: + { + IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture + + res = ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res); + + hw_surface = 1; + } + break; +#endif default: { res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); |