[FFmpeg-devel] [PATCH] libavcodec/amfenc.h: Added engine selection support for AMFContext initialisation.
OvchinnikovDmitrii
ovchinnikov.dmitrii at gmail.com
Tue Oct 29 15:57:45 EET 2019
---
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
More information about the ffmpeg-devel
mailing list