summaryrefslogtreecommitdiffstats
path: root/libavcodec/amfenc.c
diff options
context:
space:
mode:
authorMark Thompson <sw@jkqxz.net>2018-04-14 15:45:55 +0100
committerMark Thompson <sw@jkqxz.net>2018-04-15 16:42:35 +0100
commitff1be6c9a694ee019608288fd25f1c869f7f51b7 (patch)
tree8683764e7c3e7919726c001e66b76c18a45327c9 /libavcodec/amfenc.c
parent9fd11e51882aad9000943a9962d10880cae6667a (diff)
downloadffmpeg-streaming-ff1be6c9a694ee019608288fd25f1c869f7f51b7.zip
ffmpeg-streaming-ff1be6c9a694ee019608288fd25f1c869f7f51b7.tar.gz
amfenc: Fail to open if the user-supplied device is not usable
If the user supplies a device or frames context then it is an error not to use it; this is consistent with other hardware components. Also factorise out the D3D11 initialisation and improve error messages.
Diffstat (limited to 'libavcodec/amfenc.c')
-rw-r--r--libavcodec/amfenc.c130
1 files changed, 81 insertions, 49 deletions
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index b9418b6..8a9d688 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -152,10 +152,30 @@ static int amf_load_library(AVCodecContext *avctx)
return 0;
}
+#if CONFIG_D3D11VA
+static int amf_init_from_d3d11_device(AVCodecContext *avctx, AVD3D11VADeviceContext *hwctx)
+{
+ AmfContext *ctx = avctx->priv_data;
+ AMF_RESULT res;
+
+ res = ctx->context->pVtbl->InitDX11(ctx->context, hwctx->device, AMF_DX11_1);
+ if (res != AMF_OK) {
+ if (res == AMF_NOT_SUPPORTED)
+ av_log(avctx, AV_LOG_ERROR, "AMF via D3D11 is not supported on the given device.\n");
+ else
+ av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D11 device: %d.\n", res);
+ return AVERROR(ENODEV);
+ }
+
+ return 0;
+}
+#endif
+
static int amf_init_context(AVCodecContext *avctx)
{
- AmfContext *ctx = avctx->priv_data;
- AMF_RESULT res = AMF_OK;
+ AmfContext *ctx = avctx->priv_data;
+ AMF_RESULT res;
+ av_unused int ret;
ctx->hwsurfaces_in_queue = 0;
ctx->hwsurfaces_in_queue_max = 16;
@@ -176,59 +196,71 @@ static int amf_init_context(AVCodecContext *avctx)
res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context);
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res);
- // try to reuse existing DX device
-#if CONFIG_D3D11VA
+
+ // If a device was passed to the encoder, try to initialise from that.
if (avctx->hw_frames_ctx) {
- AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
- if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
- if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) {
- if (device_ctx->device_ctx->hwctx) {
- AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx;
- res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
- if (res == AMF_OK) {
- ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
- if (!ctx->hw_frames_ctx) {
- return AVERROR(ENOMEM);
- }
- if (device_ctx->initial_pool_size > 0)
- ctx->hwsurfaces_in_queue_max = device_ctx->initial_pool_size - 1;
- } else {
- if(res == AMF_NOT_SUPPORTED)
- av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
- else
- av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n");
- }
- }
- } else {
- av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n");
- }
+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+
+ if (amf_av_to_amf_format(frames_ctx->sw_format) == AMF_SURFACE_UNKNOWN) {
+ av_log(avctx, AV_LOG_ERROR, "Format of input frames context (%s) is not supported by AMF.\n",
+ av_get_pix_fmt_name(frames_ctx->sw_format));
+ return AVERROR(EINVAL);
}
- } else if (avctx->hw_device_ctx) {
- AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
- if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
- if (device_ctx->hwctx) {
- AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx;
- res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
- if (res == AMF_OK) {
- ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx);
- if (!ctx->hw_device_ctx) {
- return AVERROR(ENOMEM);
- }
- } else {
- if (res == AMF_NOT_SUPPORTED)
- av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
- else
- av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n");
- }
- }
+
+ switch (frames_ctx->device_ctx->type) {
+#if CONFIG_D3D11VA
+ case AV_HWDEVICE_TYPE_D3D11VA:
+ ret = amf_init_from_d3d11_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));
+ return AVERROR(ENOSYS);
}
- }
+
+ ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
+ if (!ctx->hw_frames_ctx)
+ return AVERROR(ENOMEM);
+
+ if (frames_ctx->initial_pool_size > 0)
+ ctx->hwsurfaces_in_queue_max = frames_ctx->initial_pool_size - 1;
+
+ } else if (avctx->hw_device_ctx) {
+ AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data;
+
+ switch (device_ctx->type) {
+#if CONFIG_D3D11VA
+ case AV_HWDEVICE_TYPE_D3D11VA:
+ ret = amf_init_from_d3d11_device(avctx, device_ctx->hwctx);
+ if (ret < 0)
+ return ret;
+ break;
#endif
- if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) {
+ 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));
+ return AVERROR(ENOSYS);
+ }
+
+ ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx);
+ if (!ctx->hw_device_ctx)
+ return AVERROR(ENOMEM);
+
+ } else {
res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1);
- if (res != AMF_OK) {
+ 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);
- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res);
+ if (res == AMF_OK) {
+ av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n");
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res);
+ return AVERROR(ENOSYS);
+ }
}
}
return 0;
OpenPOWER on IntegriCloud