--- libavcodec/amfenc.c | 93 +++++++++++++++++++++++++++++++--------- libavcodec/amfenc.h | 8 ++++ libavcodec/amfenc_h264.c | 6 +++ libavcodec/amfenc_hevc.c | 6 +++ 4 files changed, 93 insertions(+), 20 deletions(-)
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index f66b95645e..a89e14f6cd 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -210,10 +210,54 @@ static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContex } #endif -static int amf_init_context(AVCodecContext *avctx) +static AMF_RESULT amf_context_init_d3d11(AVCodecContext *avctx) { + AMF_RESULT res; + AmfContext *ctx = avctx->priv_data; + res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); + if (res == AMF_OK) { + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n"); + } + return res; +} + +static AMF_RESULT amf_context_init_dxva2(AVCodecContext *avctx) +{ + AMF_RESULT res; + AmfContext *ctx = avctx->priv_data; + res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); + if (res == AMF_OK) { + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via dxva2.\n"); + } + return res; +} + +static AMF_RESULT amf_context_init_vulkan(AVCodecContext *avctx) +{ + AMF_RESULT res; AmfContext *ctx = avctx->priv_data; AMFContext1 *context1 = NULL; + AMFGuid guid = IID_AMFContext1(); + + res = ctx->context->pVtbl->QueryInterface(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) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); + return AMF_FAIL; + } + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); + return res; +} + +static int amf_init_context(AVCodecContext *avctx) +{ + AmfContext *ctx = avctx->priv_data; AMF_RESULT res; av_unused int ret; @@ -304,30 +348,39 @@ static int amf_init_context(AVCodecContext *avctx) return AVERROR(ENOMEM); } else { - res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); - if (res == AMF_OK) { - av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n"); - } else { - res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); - if (res == AMF_OK) { - av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); - } else { - AMFGuid guid = IID_AMFContext1(); - res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); + res = AMF_FAIL; + switch (ctx->engine) { + case AMF_VIDEO_ENCODER_ENGINE_D3D11: + res = amf_context_init_d3d11(avctx); + break; + case AMF_VIDEO_ENCODER_ENGINE_DXVA2: + res = amf_context_init_dxva2(avctx); + break; + case AMF_VIDEO_ENCODER_ENGINE_VULKAN: + res = amf_context_init_vulkan(avctx); + break; + default: + break; + } + if (res != AMF_OK) { + if (ctx->engine != AMF_VIDEO_ENCODER_ENGINE_DEFAULT) + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise via preffered engine\n"); + + if (ctx->engine != AMF_VIDEO_ENCODER_ENGINE_D3D11) + res = amf_context_init_d3d11(avctx); - res = context1->pVtbl->InitVulkan(context1, NULL); - context1->pVtbl->Release(context1); + if (res != AMF_OK) { + if (ctx->engine != AMF_VIDEO_ENCODER_ENGINE_DXVA2) + res = amf_context_init_dxva2(avctx); if (res != AMF_OK) { - if (res == AMF_NOT_SUPPORTED) - av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); - else - av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); - return AVERROR(ENOSYS); + if (ctx->engine != AMF_VIDEO_ENCODER_ENGINE_VULKAN) + res = amf_context_init_vulkan(avctx); } - av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); } } + if (res != AMF_OK) { + return AVERROR(ENOSYS); + } } return 0; } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index b1361842bd..8cfb4776cf 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -28,6 +28,13 @@ #include "avcodec.h" +enum AMF_VIDEO_ENCODER_PREFFERED_ENGINE +{ + AMF_VIDEO_ENCODER_ENGINE_DEFAULT = 0, + AMF_VIDEO_ENCODER_ENGINE_DXVA2, + AMF_VIDEO_ENCODER_ENGINE_D3D11, + AMF_VIDEO_ENCODER_ENGINE_VULKAN +}; /** * AMF trace writer callback class @@ -86,6 +93,7 @@ typedef struct AmfContext { int quality; int b_frame_delta_qp; int ref_b_frame_delta_qp; + int engine; // Dynamic options, can be set after Init() call diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index 7f2817f115..79431942f6 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -71,6 +71,12 @@ static const AVOption options[] = { { "balanced", "Balanced", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" }, { "quality", "Prefer Quality", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + /// Preffered engine + { "engine", "Preffered engine", OFFSET(engine), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_ENGINE_DEFAULT}, AMF_VIDEO_ENCODER_ENGINE_DEFAULT, AMF_VIDEO_ENCODER_ENGINE_VULKAN, VE, "engine" }, + { "dxva2", "DirectX Video Acceleration 2", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_DXVA2 }, 0, 0, VE, "engine" }, + { "d3d11", "Direct3D11", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_D3D11 }, 0, 0, VE, "engine" }, + { "vulkan", "Vulkan", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_VULKAN }, 0, 0, VE, "engine" }, + // Dynamic /// Rate Control Method { "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" }, diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 7c9a33ab33..d42a9b6ff9 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -58,6 +58,12 @@ static const AVOption options[] = { { "speed", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" }, { "quality", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" }, + /// Preffered engine + { "engine", "Preffered engine", OFFSET(engine), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_ENGINE_DEFAULT}, AMF_VIDEO_ENCODER_ENGINE_DEFAULT, AMF_VIDEO_ENCODER_ENGINE_VULKAN, VE, "engine" }, + { "dxva2", "DirectX Video Acceleration 2", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_DXVA2 }, 0, 0, VE, "engine" }, + { "d3d11", "Direct3D11", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_D3D11 }, 0, 0, VE, "engine" }, + { "vulkan", "Vulkan", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_ENGINE_VULKAN }, 0, 0, VE, "engine" }, + { "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" }, { "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" }, { "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" }, -- 2.19.1.windows.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".