mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-05-18 23:36:57 +02:00
1. version changes: * vcpkg: 2024.07.12 -> 2024.11.16 * aom (except linux sciter): 3.9.1 -> 3.11.0 * libvpx: 1.14.1 -> 1.15.0 * libyuv: not update because compiled failed on arm64, and didn't apply different version on different archs * opus: already the latest version * ffmpeg: 7.0.2 -> 7.1 2. other changes: * android 5.0 required, otherwise crash when start, because FFmpeg 7.1 link to mediandk directly 3. Tests: * Except arm, arm64, linux amf, ios, all the other codecs are tested * Compile on arm32 linux is not tested, ci is failed before vcpkg install * Tested windows FFmpeg qsv, still no memory leak Signed-off-by: 21pages <sunboeasy@gmail.com>
1883 lines
81 KiB
Diff
1883 lines
81 KiB
Diff
From 95ebc0ad912447ba83cacb197f506b881f82179e Mon Sep 17 00:00:00 2001
|
|
From: 21pages <sunboeasy@gmail.com>
|
|
Date: Tue, 10 Dec 2024 15:29:21 +0800
|
|
Subject: [PATCH 1/2] dlopen libva
|
|
|
|
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
|
---
|
|
libavcodec/vaapi_decode.c | 96 ++++++-----
|
|
libavcodec/vaapi_encode.c | 173 ++++++++++---------
|
|
libavcodec/vaapi_encode_h264.c | 3 +-
|
|
libavcodec/vaapi_encode_h265.c | 6 +-
|
|
libavutil/hwcontext_vaapi.c | 292 ++++++++++++++++++++++++---------
|
|
libavutil/hwcontext_vaapi.h | 96 +++++++++++
|
|
6 files changed, 477 insertions(+), 189 deletions(-)
|
|
|
|
diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
|
|
index a59194340f..e202b673f4 100644
|
|
--- a/libavcodec/vaapi_decode.c
|
|
+++ b/libavcodec/vaapi_decode.c
|
|
@@ -38,17 +38,18 @@ int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx,
|
|
size_t size)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VABufferID buffer;
|
|
|
|
av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS);
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
type, size, 1, (void*)data, &buffer);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create parameter "
|
|
"buffer (type %d): %d (%s).\n",
|
|
- type, vas, vaErrorStr(vas));
|
|
+ type, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
|
|
@@ -69,6 +70,7 @@ int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx,
|
|
size_t slice_size)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
int index;
|
|
|
|
@@ -88,13 +90,13 @@ int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx,
|
|
|
|
index = 2 * pic->nb_slices;
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
VASliceParameterBufferType,
|
|
params_size, nb_params, (void*)params_data,
|
|
&pic->slice_buffers[index]);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
|
|
- "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "parameter buffer: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
|
|
@@ -102,15 +104,15 @@ int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx,
|
|
"is %#x.\n", pic->nb_slices, params_size,
|
|
pic->slice_buffers[index]);
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
VASliceDataBufferType,
|
|
slice_size, 1, (void*)slice_data,
|
|
&pic->slice_buffers[index + 1]);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
|
|
"data buffer (size %zu): %d (%s).\n",
|
|
- slice_size, vas, vaErrorStr(vas));
|
|
- vaDestroyBuffer(ctx->hwctx->display,
|
|
+ slice_size, vas, vaf->vaErrorStr(vas));
|
|
+ vaf->vaDestroyBuffer(ctx->hwctx->display,
|
|
pic->slice_buffers[index]);
|
|
return AVERROR(EIO);
|
|
}
|
|
@@ -127,26 +129,27 @@ static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx,
|
|
VAAPIDecodePicture *pic)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
int i;
|
|
|
|
for (i = 0; i < pic->nb_param_buffers; i++) {
|
|
- vas = vaDestroyBuffer(ctx->hwctx->display,
|
|
+ vas = vaf->vaDestroyBuffer(ctx->hwctx->display,
|
|
pic->param_buffers[i]);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
|
|
"parameter buffer %#x: %d (%s).\n",
|
|
- pic->param_buffers[i], vas, vaErrorStr(vas));
|
|
+ pic->param_buffers[i], vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2 * pic->nb_slices; i++) {
|
|
- vas = vaDestroyBuffer(ctx->hwctx->display,
|
|
+ vas = vaf->vaDestroyBuffer(ctx->hwctx->display,
|
|
pic->slice_buffers[i]);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice "
|
|
"slice buffer %#x: %d (%s).\n",
|
|
- pic->slice_buffers[i], vas, vaErrorStr(vas));
|
|
+ pic->slice_buffers[i], vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
}
|
|
@@ -155,6 +158,7 @@ int ff_vaapi_decode_issue(AVCodecContext *avctx,
|
|
VAAPIDecodePicture *pic)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
int err;
|
|
|
|
@@ -166,37 +170,37 @@ int ff_vaapi_decode_issue(AVCodecContext *avctx,
|
|
av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n",
|
|
pic->output_surface);
|
|
|
|
- vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaBeginPicture(ctx->hwctx->display, ctx->va_context,
|
|
pic->output_surface);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode "
|
|
- "issue: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "issue: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_with_picture;
|
|
}
|
|
|
|
- vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
pic->param_buffers, pic->nb_param_buffers);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to upload decode "
|
|
- "parameters: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "parameters: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_with_picture;
|
|
}
|
|
|
|
- vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
pic->slice_buffers, 2 * pic->nb_slices);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_with_picture;
|
|
}
|
|
|
|
- vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
+ vas = vaf->vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
|
|
- "issue: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "issue: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
|
|
AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
|
|
@@ -213,10 +217,10 @@ int ff_vaapi_decode_issue(AVCodecContext *avctx,
|
|
goto exit;
|
|
|
|
fail_with_picture:
|
|
- vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
+ vas = vaf->vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode "
|
|
- "after error: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "after error: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
}
|
|
fail:
|
|
ff_vaapi_decode_destroy_buffers(avctx, pic);
|
|
@@ -304,6 +308,7 @@ static int vaapi_decode_find_best_format(AVCodecContext *avctx,
|
|
AVHWFramesContext *frames)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = device->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VAStatus vas;
|
|
VASurfaceAttrib *attr;
|
|
enum AVPixelFormat source_format, best_format, format;
|
|
@@ -313,11 +318,11 @@ static int vaapi_decode_find_best_format(AVCodecContext *avctx,
|
|
source_format = avctx->sw_pix_fmt;
|
|
av_assert0(source_format != AV_PIX_FMT_NONE);
|
|
|
|
- vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
|
|
+ vas = vaf->vaQuerySurfaceAttributes(hwctx->display, config_id,
|
|
NULL, &nb_attr);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(ENOSYS);
|
|
}
|
|
|
|
@@ -325,11 +330,11 @@ static int vaapi_decode_find_best_format(AVCodecContext *avctx,
|
|
if (!attr)
|
|
return AVERROR(ENOMEM);
|
|
|
|
- vas = vaQuerySurfaceAttributes(hwctx->display, config_id,
|
|
+ vas = vaf->vaQuerySurfaceAttributes(hwctx->display, config_id,
|
|
attr, &nb_attr);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
av_freep(&attr);
|
|
return AVERROR(ENOSYS);
|
|
}
|
|
@@ -471,6 +476,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
|
|
|
|
AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data;
|
|
AVVAAPIDeviceContext *hwctx = device->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
|
|
codec_desc = avcodec_descriptor_get(avctx->codec_id);
|
|
if (!codec_desc) {
|
|
@@ -478,7 +484,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
|
|
goto fail;
|
|
}
|
|
|
|
- profile_count = vaMaxNumProfiles(hwctx->display);
|
|
+ profile_count = vaf->vaMaxNumProfiles(hwctx->display);
|
|
profile_list = av_malloc_array(profile_count,
|
|
sizeof(VAProfile));
|
|
if (!profile_list) {
|
|
@@ -486,11 +492,11 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
|
|
goto fail;
|
|
}
|
|
|
|
- vas = vaQueryConfigProfiles(hwctx->display,
|
|
+ vas = vaf->vaQueryConfigProfiles(hwctx->display,
|
|
profile_list, &profile_count);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(ENOSYS);
|
|
goto fail;
|
|
}
|
|
@@ -550,12 +556,12 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
|
|
}
|
|
}
|
|
|
|
- vas = vaCreateConfig(hwctx->display, matched_va_profile,
|
|
+ vas = vaf->vaCreateConfig(hwctx->display, matched_va_profile,
|
|
VAEntrypointVLD, NULL, 0,
|
|
va_config);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
|
|
- "configuration: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "configuration: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -638,7 +644,7 @@ fail:
|
|
av_hwframe_constraints_free(&constraints);
|
|
av_freep(&hwconfig);
|
|
if (*va_config != VA_INVALID_ID) {
|
|
- vaDestroyConfig(hwctx->display, *va_config);
|
|
+ vaf->vaDestroyConfig(hwctx->display, *va_config);
|
|
*va_config = VA_INVALID_ID;
|
|
}
|
|
av_freep(&profile_list);
|
|
@@ -651,12 +657,14 @@ int ff_vaapi_common_frame_params(AVCodecContext *avctx,
|
|
AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data;
|
|
AVHWDeviceContext *device_ctx = hw_frames->device_ctx;
|
|
AVVAAPIDeviceContext *hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf;
|
|
VAConfigID va_config = VA_INVALID_ID;
|
|
int err;
|
|
|
|
if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI)
|
|
return AVERROR(EINVAL);
|
|
hwctx = device_ctx->hwctx;
|
|
+ vaf = hwctx->funcs;
|
|
|
|
err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config,
|
|
hw_frames_ctx);
|
|
@@ -664,7 +672,7 @@ int ff_vaapi_common_frame_params(AVCodecContext *avctx,
|
|
return err;
|
|
|
|
if (va_config != VA_INVALID_ID)
|
|
- vaDestroyConfig(hwctx->display, va_config);
|
|
+ vaf->vaDestroyConfig(hwctx->display, va_config);
|
|
|
|
return 0;
|
|
}
|
|
@@ -672,6 +680,7 @@ int ff_vaapi_common_frame_params(AVCodecContext *avctx,
|
|
int ff_vaapi_decode_init(AVCodecContext *avctx)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf;
|
|
VAStatus vas;
|
|
int err;
|
|
|
|
@@ -686,13 +695,18 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
|
|
ctx->hwfc = ctx->frames->hwctx;
|
|
ctx->device = ctx->frames->device_ctx;
|
|
ctx->hwctx = ctx->device->hwctx;
|
|
+ if (!ctx->hwctx || !ctx->hwctx->funcs) {
|
|
+ err = AVERROR(EINVAL);
|
|
+ goto fail;
|
|
+ }
|
|
+ vaf = ctx->hwctx->funcs;
|
|
|
|
err = vaapi_decode_make_config(avctx, ctx->frames->device_ref,
|
|
&ctx->va_config, NULL);
|
|
if (err)
|
|
goto fail;
|
|
|
|
- vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
|
|
+ vas = vaf->vaCreateContext(ctx->hwctx->display, ctx->va_config,
|
|
avctx->coded_width, avctx->coded_height,
|
|
VA_PROGRESSIVE,
|
|
ctx->hwfc->surface_ids,
|
|
@@ -700,7 +714,7 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
|
|
&ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
|
|
- "context: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "context: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -718,22 +732,28 @@ fail:
|
|
int ff_vaapi_decode_uninit(AVCodecContext *avctx)
|
|
{
|
|
VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = NULL;
|
|
VAStatus vas;
|
|
|
|
+ if (ctx->hwctx && ctx->hwctx->funcs)
|
|
+ vaf = ctx->hwctx->funcs;
|
|
+ if (!vaf)
|
|
+ return 0;
|
|
+
|
|
if (ctx->va_context != VA_INVALID_ID) {
|
|
- vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context);
|
|
+ vas = vaf->vaDestroyContext(ctx->hwctx->display, ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
|
|
"context %#x: %d (%s).\n",
|
|
- ctx->va_context, vas, vaErrorStr(vas));
|
|
+ ctx->va_context, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
if (ctx->va_config != VA_INVALID_ID) {
|
|
- vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
|
|
+ vas = vaf->vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode "
|
|
"configuration %#x: %d (%s).\n",
|
|
- ctx->va_config, vas, vaErrorStr(vas));
|
|
+ ctx->va_config, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
|
|
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
|
|
index 16a9a364f0..ccf6fa59d6 100644
|
|
--- a/libavcodec/vaapi_encode.c
|
|
+++ b/libavcodec/vaapi_encode.c
|
|
@@ -43,6 +43,7 @@ static int vaapi_encode_make_packed_header(AVCodecContext *avctx,
|
|
int type, char *data, size_t bit_len)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VABufferID param_buffer, data_buffer;
|
|
VABufferID *tmp;
|
|
@@ -57,24 +58,24 @@ static int vaapi_encode_make_packed_header(AVCodecContext *avctx,
|
|
return AVERROR(ENOMEM);
|
|
pic->param_buffers = tmp;
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
VAEncPackedHeaderParameterBufferType,
|
|
sizeof(params), 1, ¶ms, ¶m_buffer);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
|
|
"for packed header (type %d): %d (%s).\n",
|
|
- type, vas, vaErrorStr(vas));
|
|
+ type, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
pic->param_buffers[pic->nb_param_buffers++] = param_buffer;
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
VAEncPackedHeaderDataBufferType,
|
|
(bit_len + 7) / 8, 1, data, &data_buffer);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create data buffer "
|
|
"for packed header (type %d): %d (%s).\n",
|
|
- type, vas, vaErrorStr(vas));
|
|
+ type, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
pic->param_buffers[pic->nb_param_buffers++] = data_buffer;
|
|
@@ -89,6 +90,7 @@ static int vaapi_encode_make_param_buffer(AVCodecContext *avctx,
|
|
int type, char *data, size_t len)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VABufferID *tmp;
|
|
VABufferID buffer;
|
|
@@ -98,11 +100,11 @@ static int vaapi_encode_make_param_buffer(AVCodecContext *avctx,
|
|
return AVERROR(ENOMEM);
|
|
pic->param_buffers = tmp;
|
|
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
type, len, 1, data, &buffer);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
|
|
- "(type %d): %d (%s).\n", type, vas, vaErrorStr(vas));
|
|
+ "(type %d): %d (%s).\n", type, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
pic->param_buffers[pic->nb_param_buffers++] = buffer;
|
|
@@ -141,6 +143,7 @@ static int vaapi_encode_wait(AVCodecContext *avctx, FFHWBaseEncodePicture *base_
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
#endif
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAAPIEncodePicture *pic = base_pic->priv;
|
|
VAStatus vas;
|
|
|
|
@@ -156,22 +159,22 @@ static int vaapi_encode_wait(AVCodecContext *avctx, FFHWBaseEncodePicture *base_
|
|
base_pic->encode_order, pic->input_surface);
|
|
|
|
#if VA_CHECK_VERSION(1, 9, 0)
|
|
- if (base_ctx->async_encode) {
|
|
- vas = vaSyncBuffer(ctx->hwctx->display,
|
|
+ if (base_ctx->async_encode && vaf->vaSyncBuffer) {
|
|
+ vas = vaf->vaSyncBuffer(ctx->hwctx->display,
|
|
pic->output_buffer,
|
|
VA_TIMEOUT_INFINITE);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer completion: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
} else
|
|
#endif
|
|
{ // If vaSyncBuffer is not implemented, try old version API.
|
|
- vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
|
|
+ vas = vaf->vaSyncSurface(ctx->hwctx->display, pic->input_surface);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
}
|
|
@@ -270,6 +273,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAAPIEncodePicture *pic = base_pic->priv;
|
|
VAAPIEncodeSlice *slice;
|
|
VAStatus vas;
|
|
@@ -587,28 +591,28 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
|
}
|
|
#endif
|
|
|
|
- vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaBeginPicture(ctx->hwctx->display, ctx->va_context,
|
|
pic->input_surface);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_with_picture;
|
|
}
|
|
|
|
- vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaRenderPicture(ctx->hwctx->display, ctx->va_context,
|
|
pic->param_buffers, pic->nb_param_buffers);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_with_picture;
|
|
}
|
|
|
|
- vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
+ vas = vaf->vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
// vaRenderPicture() has been called here, so we should not destroy
|
|
// the parameter buffers unless separate destruction is required.
|
|
@@ -622,12 +626,12 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
|
if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
|
|
AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) {
|
|
for (i = 0; i < pic->nb_param_buffers; i++) {
|
|
- vas = vaDestroyBuffer(ctx->hwctx->display,
|
|
+ vas = vaf->vaDestroyBuffer(ctx->hwctx->display,
|
|
pic->param_buffers[i]);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
|
|
"param buffer %#x: %d (%s).\n",
|
|
- pic->param_buffers[i], vas, vaErrorStr(vas));
|
|
+ pic->param_buffers[i], vas, vaf->vaErrorStr(vas));
|
|
// And ignore.
|
|
}
|
|
}
|
|
@@ -636,10 +640,10 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
|
return 0;
|
|
|
|
fail_with_picture:
|
|
- vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
+ vaf->vaEndPicture(ctx->hwctx->display, ctx->va_context);
|
|
fail:
|
|
for(i = 0; i < pic->nb_param_buffers; i++)
|
|
- vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
|
|
+ vaf->vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
|
|
if (pic->slices) {
|
|
for (i = 0; i < pic->nb_slices; i++)
|
|
av_freep(&pic->slices[i].codec_slice_params);
|
|
@@ -657,16 +661,17 @@ fail_at_end:
|
|
static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VACodedBufferSegment *buf_list, *buf;
|
|
int size = 0;
|
|
VAStatus vas;
|
|
int err;
|
|
|
|
- vas = vaMapBuffer(ctx->hwctx->display, buf_id,
|
|
+ vas = vaf->vaMapBuffer(ctx->hwctx->display, buf_id,
|
|
(void**)&buf_list);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
return err;
|
|
}
|
|
@@ -674,10 +679,10 @@ static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID
|
|
for (buf = buf_list; buf; buf = buf->next)
|
|
size += buf->size;
|
|
|
|
- vas = vaUnmapBuffer(ctx->hwctx->display, buf_id);
|
|
+ vas = vaf->vaUnmapBuffer(ctx->hwctx->display, buf_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
return err;
|
|
}
|
|
@@ -689,15 +694,16 @@ static int vaapi_encode_get_coded_buffer_data(AVCodecContext *avctx,
|
|
VABufferID buf_id, uint8_t **dst)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VACodedBufferSegment *buf_list, *buf;
|
|
VAStatus vas;
|
|
int err;
|
|
|
|
- vas = vaMapBuffer(ctx->hwctx->display, buf_id,
|
|
+ vas = vaf->vaMapBuffer(ctx->hwctx->display, buf_id,
|
|
(void**)&buf_list);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
return err;
|
|
}
|
|
@@ -710,10 +716,10 @@ static int vaapi_encode_get_coded_buffer_data(AVCodecContext *avctx,
|
|
*dst += buf->size;
|
|
}
|
|
|
|
- vas = vaUnmapBuffer(ctx->hwctx->display, buf_id);
|
|
+ vas = vaf->vaUnmapBuffer(ctx->hwctx->display, buf_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
return err;
|
|
}
|
|
@@ -936,6 +942,7 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAProfile *va_profiles = NULL;
|
|
VAEntrypoint *va_entrypoints = NULL;
|
|
VAStatus vas;
|
|
@@ -977,16 +984,16 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
|
|
desc->name);
|
|
|
|
- n = vaMaxNumProfiles(ctx->hwctx->display);
|
|
+ n = vaf->vaMaxNumProfiles(ctx->hwctx->display);
|
|
va_profiles = av_malloc_array(n, sizeof(VAProfile));
|
|
if (!va_profiles) {
|
|
err = AVERROR(ENOMEM);
|
|
goto fail;
|
|
}
|
|
- vas = vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
|
|
+ vas = vaf->vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
|
|
- vas, vaErrorStr(vas));
|
|
+ vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR_EXTERNAL;
|
|
goto fail;
|
|
}
|
|
@@ -1007,7 +1014,7 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
continue;
|
|
|
|
#if VA_CHECK_VERSION(1, 0, 0)
|
|
- profile_string = vaProfileStr(profile->va_profile);
|
|
+ profile_string = vaf->vaProfileStr(profile->va_profile);
|
|
#else
|
|
profile_string = "(no profile names)";
|
|
#endif
|
|
@@ -1037,18 +1044,18 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n",
|
|
profile_string, ctx->va_profile);
|
|
|
|
- n = vaMaxNumEntrypoints(ctx->hwctx->display);
|
|
+ n = vaf->vaMaxNumEntrypoints(ctx->hwctx->display);
|
|
va_entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
|
|
if (!va_entrypoints) {
|
|
err = AVERROR(ENOMEM);
|
|
goto fail;
|
|
}
|
|
- vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
|
|
+ vas = vaf->vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
|
|
va_entrypoints, &n);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for "
|
|
"profile %s (%d): %d (%s).\n", profile_string,
|
|
- ctx->va_profile, vas, vaErrorStr(vas));
|
|
+ ctx->va_profile, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR_EXTERNAL;
|
|
goto fail;
|
|
}
|
|
@@ -1070,7 +1077,7 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
|
|
ctx->va_entrypoint = va_entrypoints[i];
|
|
#if VA_CHECK_VERSION(1, 0, 0)
|
|
- entrypoint_string = vaEntrypointStr(ctx->va_entrypoint);
|
|
+ entrypoint_string = vaf->vaEntrypointStr(ctx->va_entrypoint);
|
|
#else
|
|
entrypoint_string = "(no entrypoint names)";
|
|
#endif
|
|
@@ -1095,12 +1102,12 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
|
|
}
|
|
|
|
rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile, ctx->va_entrypoint,
|
|
&rt_format_attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query RT format "
|
|
- "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "config attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR_EXTERNAL;
|
|
goto fail;
|
|
}
|
|
@@ -1157,6 +1164,7 @@ static const VAAPIEncodeRCMode vaapi_encode_rc_modes[] = {
|
|
static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
uint32_t supported_va_rc_modes;
|
|
const VAAPIEncodeRCMode *rc_mode;
|
|
int64_t rc_bits_per_second;
|
|
@@ -1170,12 +1178,12 @@ static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
|
|
VAStatus vas;
|
|
char supported_rc_modes_string[64];
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile, ctx->va_entrypoint,
|
|
&rc_attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query rate control "
|
|
- "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "config attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
|
|
@@ -1516,6 +1524,7 @@ static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
|
|
{
|
|
#if VA_CHECK_VERSION(1, 5, 0)
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
|
|
VAStatus vas;
|
|
|
|
@@ -1526,14 +1535,14 @@ static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
|
|
return AVERROR(EINVAL);
|
|
}
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
ctx->max_frame_size = 0;
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size "
|
|
- "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "config attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
|
|
@@ -1573,18 +1582,19 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
|
|
uint32_t ref_l0, ref_l1;
|
|
int prediction_pre_only, err;
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query reference frames "
|
|
- "attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
|
|
@@ -1602,13 +1612,13 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
|
|
if (!(ctx->codec->flags & FF_HW_FLAG_INTRA_ONLY ||
|
|
avctx->gop_size <= 1)) {
|
|
attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection };
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_WARNING, "Failed to query prediction direction "
|
|
- "attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
} else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
|
|
av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any additional "
|
|
@@ -1758,6 +1768,7 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
|
|
{ VAConfigAttribEncSliceStructure },
|
|
#if VA_CHECK_VERSION(1, 1, 0)
|
|
@@ -1789,13 +1800,13 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
|
return 0;
|
|
}
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
attr, FF_ARRAY_ELEMS(attr));
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query slice "
|
|
- "attributes: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "attributes: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
max_slices = attr[0].value;
|
|
@@ -1849,16 +1860,17 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
|
|
static av_cold int vaapi_encode_init_packed_headers(AVCodecContext *avctx)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query packed headers "
|
|
- "attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
|
|
@@ -1910,17 +1922,18 @@ static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
|
|
{
|
|
#if VA_CHECK_VERSION(0, 36, 0)
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
|
|
int quality = avctx->compression_level;
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query quality "
|
|
- "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "config attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
|
|
@@ -1958,16 +1971,17 @@ static av_cold int vaapi_encode_init_roi(AVCodecContext *avctx)
|
|
#if VA_CHECK_VERSION(1, 0, 0)
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAStatus vas;
|
|
VAConfigAttrib attr = { VAConfigAttribEncROI };
|
|
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display,
|
|
ctx->va_profile,
|
|
ctx->va_entrypoint,
|
|
&attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query ROI "
|
|
- "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "config attribute: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
|
|
@@ -1992,10 +2006,11 @@ static void vaapi_encode_free_output_buffer(FFRefStructOpaque opaque,
|
|
{
|
|
AVCodecContext *avctx = opaque.nc;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VABufferID *buffer_id_ref = obj;
|
|
VABufferID buffer_id = *buffer_id_ref;
|
|
|
|
- vaDestroyBuffer(ctx->hwctx->display, buffer_id);
|
|
+ vaf->vaDestroyBuffer(ctx->hwctx->display, buffer_id);
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id);
|
|
}
|
|
@@ -2005,6 +2020,7 @@ static int vaapi_encode_alloc_output_buffer(FFRefStructOpaque opaque, void *obj)
|
|
AVCodecContext *avctx = opaque.nc;
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VABufferID *buffer_id = obj;
|
|
VAStatus vas;
|
|
|
|
@@ -2012,13 +2028,13 @@ static int vaapi_encode_alloc_output_buffer(FFRefStructOpaque opaque, void *obj)
|
|
// to hold the largest possible compressed frame. We assume here
|
|
// that the uncompressed frame plus some header data is an upper
|
|
// bound on that.
|
|
- vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
+ vas = vaf->vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
|
|
VAEncCodedBufferType,
|
|
3 * base_ctx->surface_width * base_ctx->surface_height +
|
|
(1 << 16), 1, 0, buffer_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
|
|
- "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "output buffer: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
@@ -2092,6 +2108,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = NULL;
|
|
AVVAAPIFramesContext *recon_hwctx = NULL;
|
|
VAStatus vas;
|
|
int err;
|
|
@@ -2107,6 +2124,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
|
|
ctx->hwctx = base_ctx->device->hwctx;
|
|
|
|
+ if (!ctx->hwctx || !ctx->hwctx->funcs) {
|
|
+ err = AVERROR(EINVAL);
|
|
+ goto fail;
|
|
+ }
|
|
+ vaf = ctx->hwctx->funcs;
|
|
+
|
|
err = vaapi_encode_profile_entrypoint(avctx);
|
|
if (err < 0)
|
|
goto fail;
|
|
@@ -2157,13 +2180,13 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
goto fail;
|
|
}
|
|
|
|
- vas = vaCreateConfig(ctx->hwctx->display,
|
|
+ vas = vaf->vaCreateConfig(ctx->hwctx->display,
|
|
ctx->va_profile, ctx->va_entrypoint,
|
|
ctx->config_attributes, ctx->nb_config_attributes,
|
|
&ctx->va_config);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
|
|
- "configuration: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "configuration: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -2173,7 +2196,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
goto fail;
|
|
|
|
recon_hwctx = base_ctx->recon_frames->hwctx;
|
|
- vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
|
|
+ vas = vaf->vaCreateContext(ctx->hwctx->display, ctx->va_config,
|
|
base_ctx->surface_width, base_ctx->surface_height,
|
|
VA_PROGRESSIVE,
|
|
recon_hwctx->surface_ids,
|
|
@@ -2181,7 +2204,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
&ctx->va_context);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
|
|
- "context: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "context: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -2255,14 +2278,16 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
|
|
|
|
#if VA_CHECK_VERSION(1, 9, 0)
|
|
// check vaSyncBuffer function
|
|
- vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0);
|
|
- if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
|
|
- base_ctx->async_encode = 1;
|
|
- base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
|
|
- sizeof(VAAPIEncodePicture*),
|
|
- 0);
|
|
- if (!base_ctx->encode_fifo)
|
|
- return AVERROR(ENOMEM);
|
|
+ if (vaf->vaSyncBuffer) {
|
|
+ vas = vaf->vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0);
|
|
+ if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
|
|
+ base_ctx->async_encode = 1;
|
|
+ base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
|
|
+ sizeof(VAAPIEncodePicture*),
|
|
+ 0);
|
|
+ if (!base_ctx->encode_fifo)
|
|
+ return AVERROR(ENOMEM);
|
|
+ }
|
|
}
|
|
#endif
|
|
|
|
@@ -2291,14 +2316,14 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
|
|
ff_refstruct_pool_uninit(&ctx->output_buffer_pool);
|
|
|
|
if (ctx->va_context != VA_INVALID_ID) {
|
|
- if (ctx->hwctx)
|
|
- vaDestroyContext(ctx->hwctx->display, ctx->va_context);
|
|
+ if (ctx->hwctx && ctx->hwctx->funcs)
|
|
+ ctx->hwctx->funcs->vaDestroyContext(ctx->hwctx->display, ctx->va_context);
|
|
ctx->va_context = VA_INVALID_ID;
|
|
}
|
|
|
|
if (ctx->va_config != VA_INVALID_ID) {
|
|
- if (ctx->hwctx)
|
|
- vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
|
|
+ if (ctx->hwctx && ctx->hwctx->funcs)
|
|
+ ctx->hwctx->funcs->vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
|
|
ctx->va_config = VA_INVALID_ID;
|
|
}
|
|
|
|
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
|
|
index fb87b68bec..6d4ce630ce 100644
|
|
--- a/libavcodec/vaapi_encode_h264.c
|
|
+++ b/libavcodec/vaapi_encode_h264.c
|
|
@@ -868,6 +868,7 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
|
|
static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
|
|
{
|
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAAPIEncodeH264Context *priv = avctx->priv_data;
|
|
int err;
|
|
|
|
@@ -919,7 +920,7 @@ static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
|
|
vaapi_encode_h264_sei_identifier_uuid,
|
|
sizeof(priv->sei_identifier.uuid_iso_iec_11578));
|
|
|
|
- driver = vaQueryVendorString(ctx->hwctx->display);
|
|
+ driver = vaf->vaQueryVendorString(ctx->hwctx->display);
|
|
if (!driver)
|
|
driver = "unknown driver";
|
|
|
|
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
|
|
index 2283bcc0b4..7c624f99a9 100644
|
|
--- a/libavcodec/vaapi_encode_h265.c
|
|
+++ b/libavcodec/vaapi_encode_h265.c
|
|
@@ -899,6 +899,8 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
|
static av_cold int vaapi_encode_h265_get_encoder_caps(AVCodecContext *avctx)
|
|
{
|
|
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
|
|
+ VAAPIEncodeContext *ctx = avctx->priv_data;
|
|
+ VAAPIDynLoadFunctions *vaf = ctx->hwctx->funcs;
|
|
VAAPIEncodeH265Context *priv = avctx->priv_data;
|
|
|
|
#if VA_CHECK_VERSION(1, 13, 0)
|
|
@@ -909,7 +911,7 @@ static av_cold int vaapi_encode_h265_get_encoder_caps(AVCodecContext *avctx)
|
|
VAStatus vas;
|
|
|
|
attr.type = VAConfigAttribEncHEVCFeatures;
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile,
|
|
ctx->va_entrypoint, &attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query encoder "
|
|
@@ -923,7 +925,7 @@ static av_cold int vaapi_encode_h265_get_encoder_caps(AVCodecContext *avctx)
|
|
}
|
|
|
|
attr.type = VAConfigAttribEncHEVCBlockSizes;
|
|
- vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile,
|
|
+ vas = vaf->vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile,
|
|
ctx->va_entrypoint, &attr, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Failed to query encoder "
|
|
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
|
|
index 95aa38d9d2..13451e8ad7 100644
|
|
--- a/libavutil/hwcontext_vaapi.c
|
|
+++ b/libavutil/hwcontext_vaapi.c
|
|
@@ -48,6 +48,7 @@ typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
+#include <dlfcn.h>
|
|
|
|
#include "avassert.h"
|
|
#include "buffer.h"
|
|
@@ -60,6 +61,128 @@ typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory)
|
|
#include "pixdesc.h"
|
|
#include "pixfmt.h"
|
|
|
|
+////////////////////////////////////////////////////////////
|
|
+/// dynamic load functions
|
|
+////////////////////////////////////////////////////////////
|
|
+
|
|
+#define LOAD_SYMBOL(name) do { \
|
|
+ funcs->name = dlsym(funcs->handle_va, #name); \
|
|
+ if (!funcs->name) { \
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load %s\n", #name); \
|
|
+ goto fail; \
|
|
+ } \
|
|
+} while(0)
|
|
+
|
|
+static void vaapi_free_functions(VAAPIDynLoadFunctions *funcs)
|
|
+{
|
|
+ if (!funcs)
|
|
+ return;
|
|
+
|
|
+ if (funcs->handle_va_x11)
|
|
+ dlclose(funcs->handle_va_x11);
|
|
+ if (funcs->handle_va_drm)
|
|
+ dlclose(funcs->handle_va_drm);
|
|
+ if (funcs->handle_va)
|
|
+ dlclose(funcs->handle_va);
|
|
+ av_free(funcs);
|
|
+}
|
|
+
|
|
+static VAAPIDynLoadFunctions *vaapi_load_functions(void)
|
|
+{
|
|
+ VAAPIDynLoadFunctions *funcs = av_mallocz(sizeof(*funcs));
|
|
+ if (!funcs)
|
|
+ return NULL;
|
|
+
|
|
+ // Load libva.so
|
|
+ funcs->handle_va = dlopen("libva.so.2", RTLD_NOW | RTLD_LOCAL);
|
|
+ if (!funcs->handle_va) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load libva: %s\n", dlerror());
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // Load core functions
|
|
+ LOAD_SYMBOL(vaInitialize);
|
|
+ LOAD_SYMBOL(vaTerminate);
|
|
+ LOAD_SYMBOL(vaCreateConfig);
|
|
+ LOAD_SYMBOL(vaDestroyConfig);
|
|
+ LOAD_SYMBOL(vaCreateContext);
|
|
+ LOAD_SYMBOL(vaDestroyContext);
|
|
+ LOAD_SYMBOL(vaCreateBuffer);
|
|
+ LOAD_SYMBOL(vaDestroyBuffer);
|
|
+ LOAD_SYMBOL(vaMapBuffer);
|
|
+ LOAD_SYMBOL(vaUnmapBuffer);
|
|
+ LOAD_SYMBOL(vaSyncSurface);
|
|
+ LOAD_SYMBOL(vaGetConfigAttributes);
|
|
+ LOAD_SYMBOL(vaCreateSurfaces);
|
|
+ LOAD_SYMBOL(vaDestroySurfaces);
|
|
+ LOAD_SYMBOL(vaBeginPicture);
|
|
+ LOAD_SYMBOL(vaRenderPicture);
|
|
+ LOAD_SYMBOL(vaEndPicture);
|
|
+ LOAD_SYMBOL(vaQueryConfigEntrypoints);
|
|
+ LOAD_SYMBOL(vaQueryConfigProfiles);
|
|
+ LOAD_SYMBOL(vaGetDisplayAttributes);
|
|
+ LOAD_SYMBOL(vaErrorStr);
|
|
+ LOAD_SYMBOL(vaMaxNumEntrypoints);
|
|
+ LOAD_SYMBOL(vaMaxNumProfiles);
|
|
+ LOAD_SYMBOL(vaQueryVendorString);
|
|
+ LOAD_SYMBOL(vaQuerySurfaceAttributes);
|
|
+ LOAD_SYMBOL(vaDestroyImage);
|
|
+ LOAD_SYMBOL(vaDeriveImage);
|
|
+ LOAD_SYMBOL(vaPutImage);
|
|
+ LOAD_SYMBOL(vaCreateImage);
|
|
+ LOAD_SYMBOL(vaGetImage);
|
|
+ LOAD_SYMBOL(vaExportSurfaceHandle);
|
|
+ LOAD_SYMBOL(vaReleaseBufferHandle);
|
|
+ LOAD_SYMBOL(vaAcquireBufferHandle);
|
|
+ LOAD_SYMBOL(vaSetErrorCallback);
|
|
+ LOAD_SYMBOL(vaSetInfoCallback);
|
|
+ LOAD_SYMBOL(vaSetDriverName);
|
|
+ LOAD_SYMBOL(vaEntrypointStr);
|
|
+ LOAD_SYMBOL(vaQueryImageFormats);
|
|
+ LOAD_SYMBOL(vaMaxNumImageFormats);
|
|
+ LOAD_SYMBOL(vaProfileStr);
|
|
+
|
|
+ // Load libva-x11.so
|
|
+ funcs->handle_va_x11 = dlopen("libva-x11.so.2", RTLD_NOW | RTLD_LOCAL);
|
|
+ if (!funcs->handle_va_x11) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load libva-x11: %s\n", dlerror());
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ funcs->vaGetDisplay = dlsym(funcs->handle_va_x11, "vaGetDisplay");
|
|
+ if (!funcs->vaGetDisplay) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load vaGetDisplay\n");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // Load libva-drm.so
|
|
+ funcs->handle_va_drm = dlopen("libva-drm.so.2", RTLD_NOW | RTLD_LOCAL);
|
|
+ if (!funcs->handle_va_drm) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load libva-drm: %s\n", dlerror());
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ funcs->vaGetDisplayDRM = dlsym(funcs->handle_va_drm, "vaGetDisplayDRM");
|
|
+ if (!funcs->vaGetDisplayDRM) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load vaGetDisplayDRM\n");
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
+ // Optional functions
|
|
+ funcs->vaSyncBuffer = dlsym(funcs->handle_va, "vaSyncBuffer");
|
|
+ av_log(NULL, AV_LOG_DEBUG, "vaSyncBuffer:%p.\n", funcs->vaSyncBuffer);
|
|
+
|
|
+ return funcs;
|
|
+
|
|
+fail:
|
|
+ vaapi_free_functions(funcs);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+////////////////////////////////////////////////////////////
|
|
+/// VAAPI API end
|
|
+////////////////////////////////////////////////////////////
|
|
+
|
|
|
|
typedef struct VAAPIDevicePriv {
|
|
#if HAVE_VAAPI_X11
|
|
@@ -236,6 +359,7 @@ static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev,
|
|
{
|
|
VAAPIDeviceContext *ctx = hwdev->hwctx;
|
|
AVVAAPIDeviceContext *hwctx = &ctx->p;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
const AVVAAPIHWConfig *config = hwconfig;
|
|
VASurfaceAttrib *attr_list = NULL;
|
|
VAStatus vas;
|
|
@@ -246,11 +370,11 @@ static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev,
|
|
if (config &&
|
|
!(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES)) {
|
|
attr_count = 0;
|
|
- vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
|
|
+ vas = vaf->vaQuerySurfaceAttributes(hwctx->display, config->config_id,
|
|
0, &attr_count);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(ENOSYS);
|
|
goto fail;
|
|
}
|
|
@@ -261,11 +385,11 @@ static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev,
|
|
goto fail;
|
|
}
|
|
|
|
- vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
|
|
+ vas = vaf->vaQuerySurfaceAttributes(hwctx->display, config->config_id,
|
|
attr_list, &attr_count);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(ENOSYS);
|
|
goto fail;
|
|
}
|
|
@@ -396,6 +520,7 @@ static int vaapi_device_init(AVHWDeviceContext *hwdev)
|
|
{
|
|
VAAPIDeviceContext *ctx = hwdev->hwctx;
|
|
AVVAAPIDeviceContext *hwctx = &ctx->p;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VAImageFormat *image_list = NULL;
|
|
VAStatus vas;
|
|
const char *vendor_string;
|
|
@@ -403,7 +528,7 @@ static int vaapi_device_init(AVHWDeviceContext *hwdev)
|
|
enum AVPixelFormat pix_fmt;
|
|
unsigned int fourcc;
|
|
|
|
- image_count = vaMaxNumImageFormats(hwctx->display);
|
|
+ image_count = vaf->vaMaxNumImageFormats(hwctx->display);
|
|
if (image_count <= 0) {
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
@@ -413,7 +538,7 @@ static int vaapi_device_init(AVHWDeviceContext *hwdev)
|
|
err = AVERROR(ENOMEM);
|
|
goto fail;
|
|
}
|
|
- vas = vaQueryImageFormats(hwctx->display, image_list, &image_count);
|
|
+ vas = vaf->vaQueryImageFormats(hwctx->display, image_list, &image_count);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
@@ -440,7 +565,7 @@ static int vaapi_device_init(AVHWDeviceContext *hwdev)
|
|
}
|
|
}
|
|
|
|
- vendor_string = vaQueryVendorString(hwctx->display);
|
|
+ vendor_string = vaf->vaQueryVendorString(hwctx->display);
|
|
if (vendor_string)
|
|
av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string);
|
|
|
|
@@ -493,15 +618,16 @@ static void vaapi_buffer_free(void *opaque, uint8_t *data)
|
|
{
|
|
AVHWFramesContext *hwfc = opaque;
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)data;
|
|
|
|
- vas = vaDestroySurfaces(hwctx->display, &surface_id, 1);
|
|
+ vas = vaf->vaDestroySurfaces(hwctx->display, &surface_id, 1);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: "
|
|
- "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
|
|
@@ -511,6 +637,7 @@ static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
|
|
VAAPIFramesContext *ctx = hwfc->hwctx;
|
|
AVVAAPIFramesContext *avfc = &ctx->p;
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
AVBufferRef *ref;
|
|
@@ -519,13 +646,13 @@ static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
|
|
avfc->nb_surfaces >= hwfc->initial_pool_size)
|
|
return NULL;
|
|
|
|
- vas = vaCreateSurfaces(hwctx->display, ctx->rt_format,
|
|
+ vas = vaf->vaCreateSurfaces(hwctx->display, ctx->rt_format,
|
|
hwfc->width, hwfc->height,
|
|
&surface_id, 1,
|
|
ctx->attributes, ctx->nb_attributes);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return NULL;
|
|
}
|
|
av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id);
|
|
@@ -534,7 +661,7 @@ static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
|
|
sizeof(surface_id), &vaapi_buffer_free,
|
|
hwfc, AV_BUFFER_FLAG_READONLY);
|
|
if (!ref) {
|
|
- vaDestroySurfaces(hwctx->display, &surface_id, 1);
|
|
+ vaf->vaDestroySurfaces(hwctx->display, &surface_id, 1);
|
|
return NULL;
|
|
}
|
|
|
|
@@ -554,6 +681,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|
VAAPIFramesContext *ctx = hwfc->hwctx;
|
|
AVVAAPIFramesContext *avfc = &ctx->p;
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
const VAAPIFormatDescriptor *desc;
|
|
VAImageFormat *expected_format;
|
|
AVBufferRef *test_surface = NULL;
|
|
@@ -669,7 +797,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|
err = vaapi_get_image_format(hwfc->device_ctx,
|
|
hwfc->sw_format, &expected_format);
|
|
if (err == 0) {
|
|
- vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image);
|
|
+ vas = vaf->vaDeriveImage(hwctx->display, test_surface_id, &test_image);
|
|
if (vas == VA_STATUS_SUCCESS) {
|
|
if (expected_format->fourcc == test_image.format.fourcc) {
|
|
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
|
|
@@ -680,11 +808,11 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|
"expected format %08x.\n",
|
|
expected_format->fourcc, test_image.format.fourcc);
|
|
}
|
|
- vaDestroyImage(hwctx->display, test_image.image_id);
|
|
+ vaf->vaDestroyImage(hwctx->display, test_image.image_id);
|
|
} else {
|
|
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
|
|
"deriving image does not work: "
|
|
- "%d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
}
|
|
} else {
|
|
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
|
|
@@ -765,33 +893,34 @@ static void vaapi_unmap_frame(AVHWFramesContext *hwfc,
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
VAAPIMapping *map = hwmap->priv;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
|
|
surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
|
|
av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id);
|
|
|
|
- vas = vaUnmapBuffer(hwctx->display, map->image.buf);
|
|
+ vas = vaf->vaUnmapBuffer(hwctx->display, map->image.buf);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
|
|
if ((map->flags & AV_HWFRAME_MAP_WRITE) &&
|
|
!(map->flags & AV_HWFRAME_MAP_DIRECT)) {
|
|
- vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
|
|
+ vas = vaf->vaPutImage(hwctx->display, surface_id, map->image.image_id,
|
|
0, 0, hwfc->width, hwfc->height,
|
|
0, 0, hwfc->width, hwfc->height);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
}
|
|
|
|
- vas = vaDestroyImage(hwctx->display, map->image.image_id);
|
|
+ vas = vaf->vaDestroyImage(hwctx->display, map->image.image_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
|
|
av_free(map);
|
|
@@ -801,6 +930,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|
AVFrame *dst, const AVFrame *src, int flags)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VAAPIFramesContext *ctx = hwfc->hwctx;
|
|
VASurfaceID surface_id;
|
|
const VAAPIFormatDescriptor *desc;
|
|
@@ -839,10 +969,10 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|
map->flags = flags;
|
|
map->image.image_id = VA_INVALID_ID;
|
|
|
|
- vas = vaSyncSurface(hwctx->display, surface_id);
|
|
+ vas = vaf->vaSyncSurface(hwctx->display, surface_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -856,11 +986,11 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|
// prefer not to be given direct-mapped memory if they request read access.
|
|
if (ctx->derive_works && dst->format == hwfc->sw_format &&
|
|
((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) {
|
|
- vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
|
|
+ vas = vaf->vaDeriveImage(hwctx->display, surface_id, &map->image);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
|
|
"surface %#x: %d (%s).\n",
|
|
- surface_id, vas, vaErrorStr(vas));
|
|
+ surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -873,41 +1003,32 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|
}
|
|
map->flags |= AV_HWFRAME_MAP_DIRECT;
|
|
} else {
|
|
- vas = vaCreateImage(hwctx->display, image_format,
|
|
+ vas = vaf->vaCreateImage(hwctx->display, image_format,
|
|
hwfc->width, hwfc->height, &map->image);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
|
|
"surface %#x: %d (%s).\n",
|
|
- surface_id, vas, vaErrorStr(vas));
|
|
+ surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) {
|
|
- vas = vaGetImage(hwctx->display, surface_id, 0, 0,
|
|
+ vas = vaf->vaGetImage(hwctx->display, surface_id, 0, 0,
|
|
hwfc->width, hwfc->height, map->image.image_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
|
|
"surface %#x: %d (%s).\n",
|
|
- surface_id, vas, vaErrorStr(vas));
|
|
+ surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
}
|
|
}
|
|
|
|
-#if VA_CHECK_VERSION(1, 21, 0)
|
|
- if (flags & AV_HWFRAME_MAP_READ)
|
|
- vaflags |= VA_MAPBUFFER_FLAG_READ;
|
|
- if (flags & AV_HWFRAME_MAP_WRITE)
|
|
- vaflags |= VA_MAPBUFFER_FLAG_WRITE;
|
|
- // On drivers not implementing vaMapBuffer2 libva calls vaMapBuffer instead.
|
|
- vas = vaMapBuffer2(hwctx->display, map->image.buf, &address, vaflags);
|
|
-#else
|
|
- vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
|
|
-#endif
|
|
+ vas = vaf->vaMapBuffer(hwctx->display, map->image.buf, &address);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -936,9 +1057,9 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|
fail:
|
|
if (map) {
|
|
if (address)
|
|
- vaUnmapBuffer(hwctx->display, map->image.buf);
|
|
+ vaf->vaUnmapBuffer(hwctx->display, map->image.buf);
|
|
if (map->image.image_id != VA_INVALID_ID)
|
|
- vaDestroyImage(hwctx->display, map->image.image_id);
|
|
+ vaf->vaDestroyImage(hwctx->display, map->image.image_id);
|
|
av_free(map);
|
|
}
|
|
return err;
|
|
@@ -1080,12 +1201,12 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc,
|
|
HWMapDescriptor *hwmap)
|
|
{
|
|
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
|
|
-
|
|
+ VAAPIDynLoadFunctions *vaf = dst_dev->funcs;
|
|
VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->priv;
|
|
|
|
av_log(dst_fc, AV_LOG_DEBUG, "Destroy surface %#x.\n", surface_id);
|
|
|
|
- vaDestroySurfaces(dst_dev->display, &surface_id, 1);
|
|
+ vaf->vaDestroySurfaces(dst_dev->display, &surface_id, 1);
|
|
}
|
|
|
|
static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|
@@ -1100,6 +1221,7 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|
AVHWFramesContext *dst_fc =
|
|
(AVHWFramesContext*)dst->hw_frames_ctx->data;
|
|
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = dst_dev->funcs;
|
|
const AVDRMFrameDescriptor *desc;
|
|
const VAAPIFormatDescriptor *format_desc;
|
|
VASurfaceID surface_id;
|
|
@@ -1216,7 +1338,7 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|
* Gallium seem to do the correct error checks, so lets just try the
|
|
* PRIME_2 import first.
|
|
*/
|
|
- vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
+ vas = vaf->vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
src->width, src->height, &surface_id, 1,
|
|
prime_attrs, FF_ARRAY_ELEMS(prime_attrs));
|
|
if (vas != VA_STATUS_SUCCESS)
|
|
@@ -1267,7 +1389,7 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|
FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
|
|
}
|
|
|
|
- vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
+ vas = vaf->vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
src->width, src->height,
|
|
&surface_id, 1,
|
|
buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs));
|
|
@@ -1298,14 +1420,14 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|
FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
|
|
}
|
|
|
|
- vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
+ vas = vaf->vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
|
src->width, src->height,
|
|
&surface_id, 1,
|
|
attrs, FF_ARRAY_ELEMS(attrs));
|
|
#endif
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM "
|
|
- "object: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "object: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id);
|
|
@@ -1343,6 +1465,7 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
const AVFrame *src, int flags)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
VADRMPRIMESurfaceDescriptor va_desc;
|
|
@@ -1356,10 +1479,10 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
if (flags & AV_HWFRAME_MAP_READ) {
|
|
export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
|
|
|
|
- vas = vaSyncSurface(hwctx->display, surface_id);
|
|
+ vas = vaf->vaSyncSurface(hwctx->display, surface_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
|
|
- "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%#x: %d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
}
|
|
@@ -1367,14 +1490,14 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
if (flags & AV_HWFRAME_MAP_WRITE)
|
|
export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
|
|
|
|
- vas = vaExportSurfaceHandle(hwctx->display, surface_id,
|
|
+ vas = vaf->vaExportSurfaceHandle(hwctx->display, surface_id,
|
|
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
|
export_flags, &va_desc);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
|
|
return AVERROR(ENOSYS);
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: "
|
|
- "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
|
|
+ "%d (%s).\n", surface_id, vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
|
|
@@ -1437,6 +1560,7 @@ static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
|
|
HWMapDescriptor *hwmap)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VAAPIDRMImageBufferMapping *mapping = hwmap->priv;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
@@ -1448,19 +1572,19 @@ static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
|
|
// DRM PRIME file descriptors are closed by vaReleaseBufferHandle(),
|
|
// so we shouldn't close them separately.
|
|
|
|
- vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
|
|
+ vas = vaf->vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer "
|
|
"handle of image %#x (derived from surface %#x): "
|
|
"%d (%s).\n", mapping->image.buf, surface_id,
|
|
- vas, vaErrorStr(vas));
|
|
+ vas, vaf->vaErrorStr(vas));
|
|
}
|
|
|
|
- vas = vaDestroyImage(hwctx->display, mapping->image.image_id);
|
|
+ vas = vaf->vaDestroyImage(hwctx->display, mapping->image.image_id);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image "
|
|
"derived from surface %#x: %d (%s).\n",
|
|
- surface_id, vas, vaErrorStr(vas));
|
|
+ surface_id, vas, vaf->vaErrorStr(vas));
|
|
}
|
|
|
|
av_free(mapping);
|
|
@@ -1470,6 +1594,7 @@ static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
const AVFrame *src, int flags)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
VAAPIDRMImageBufferMapping *mapping = NULL;
|
|
VASurfaceID surface_id;
|
|
VAStatus vas;
|
|
@@ -1483,12 +1608,12 @@ static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
if (!mapping)
|
|
return AVERROR(ENOMEM);
|
|
|
|
- vas = vaDeriveImage(hwctx->display, surface_id,
|
|
+ vas = vaf->vaDeriveImage(hwctx->display, surface_id,
|
|
&mapping->image);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
|
|
"surface %#x: %d (%s).\n",
|
|
- surface_id, vas, vaErrorStr(vas));
|
|
+ surface_id, vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail;
|
|
}
|
|
@@ -1543,13 +1668,13 @@ static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
}
|
|
}
|
|
|
|
- vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
|
|
+ vas = vaf->vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
|
|
&mapping->buffer_info);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer "
|
|
"handle from image %#x (derived from surface %#x): "
|
|
"%d (%s).\n", mapping->image.buf, surface_id,
|
|
- vas, vaErrorStr(vas));
|
|
+ vas, vaf->vaErrorStr(vas));
|
|
err = AVERROR(EIO);
|
|
goto fail_derived;
|
|
}
|
|
@@ -1578,9 +1703,9 @@ static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
|
|
return 0;
|
|
|
|
fail_mapped:
|
|
- vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
|
|
+ vaf->vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
|
|
fail_derived:
|
|
- vaDestroyImage(hwctx->display, mapping->image.image_id);
|
|
+ vaf->vaDestroyImage(hwctx->display, mapping->image.image_id);
|
|
fail:
|
|
av_freep(&mapping);
|
|
return err;
|
|
@@ -1634,9 +1759,15 @@ static void vaapi_device_free(AVHWDeviceContext *ctx)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = ctx->hwctx;
|
|
VAAPIDevicePriv *priv = ctx->user_opaque;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
|
|
- if (hwctx->display)
|
|
- vaTerminate(hwctx->display);
|
|
+ if (hwctx && hwctx->display && vaf && vaf->vaTerminate)
|
|
+ vaf->vaTerminate(hwctx->display);
|
|
+
|
|
+ if (hwctx && hwctx->funcs) {
|
|
+ vaapi_free_functions(hwctx->funcs);
|
|
+ hwctx->funcs = NULL;
|
|
+ }
|
|
|
|
#if HAVE_VAAPI_X11
|
|
if (priv->x11_display)
|
|
@@ -1669,20 +1800,21 @@ static int vaapi_device_connect(AVHWDeviceContext *ctx,
|
|
VADisplay display)
|
|
{
|
|
AVVAAPIDeviceContext *hwctx = ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->funcs;
|
|
int major, minor;
|
|
VAStatus vas;
|
|
|
|
#if CONFIG_VAAPI_1
|
|
- vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
|
|
- vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
|
|
+ vaf->vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
|
|
+ vaf->vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
|
|
#endif
|
|
|
|
hwctx->display = display;
|
|
|
|
- vas = vaInitialize(display, &major, &minor);
|
|
+ vas = vaf->vaInitialize(display, &major, &minor);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
|
|
- "connection: %d (%s).\n", vas, vaErrorStr(vas));
|
|
+ "connection: %d (%s).\n", vas, vaf->vaErrorStr(vas));
|
|
return AVERROR(EIO);
|
|
}
|
|
av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
|
|
@@ -1698,6 +1830,16 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
|
|
VADisplay display = NULL;
|
|
const AVDictionaryEntry *ent;
|
|
int try_drm, try_x11, try_win32, try_all;
|
|
+ VAAPIDeviceContext *hwctx = ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf;
|
|
+
|
|
+ hwctx->p.funcs = vaapi_load_functions();
|
|
+ if (!hwctx->p.funcs) {
|
|
+ av_log(NULL, AV_LOG_ERROR, "Failed to load libva: %s\n", dlerror());
|
|
+ return AVERROR_EXTERNAL;
|
|
+ }
|
|
+
|
|
+ vaf = hwctx->p.funcs;
|
|
|
|
priv = av_mallocz(sizeof(*priv));
|
|
if (!priv)
|
|
@@ -1843,7 +1985,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
|
|
break;
|
|
}
|
|
|
|
- display = vaGetDisplayDRM(priv->drm_fd);
|
|
+ display = vaf->vaGetDisplayDRM(priv->drm_fd);
|
|
if (!display) {
|
|
av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display "
|
|
"from DRM device %s.\n", device);
|
|
@@ -1861,7 +2003,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
|
|
av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
|
|
"%s.\n", XDisplayName(device));
|
|
} else {
|
|
- display = vaGetDisplay(priv->x11_display);
|
|
+ display = vaf->vaGetDisplay(priv->x11_display);
|
|
if (!display) {
|
|
av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
|
|
"from X11 display %s.\n", XDisplayName(device));
|
|
@@ -1950,11 +2092,11 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
|
|
if (ent) {
|
|
#if VA_CHECK_VERSION(0, 38, 0)
|
|
VAStatus vas;
|
|
- vas = vaSetDriverName(display, ent->value);
|
|
+ vas = vaf->vaSetDriverName(display, ent->value);
|
|
if (vas != VA_STATUS_SUCCESS) {
|
|
av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
|
|
- "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas));
|
|
- vaTerminate(display);
|
|
+ "%s: %d (%s).\n", ent->value, vas, vaf->vaErrorStr(vas));
|
|
+ vaf->vaTerminate(display);
|
|
return AVERROR_EXTERNAL;
|
|
}
|
|
#else
|
|
@@ -1970,6 +2112,8 @@ static int vaapi_device_derive(AVHWDeviceContext *ctx,
|
|
AVHWDeviceContext *src_ctx,
|
|
AVDictionary *opts, int flags)
|
|
{
|
|
+ VAAPIDeviceContext *hwctx = ctx->hwctx;
|
|
+ VAAPIDynLoadFunctions *vaf = hwctx->p.funcs;
|
|
#if HAVE_VAAPI_DRM
|
|
if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
|
|
AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
|
|
@@ -2041,7 +2185,7 @@ static int vaapi_device_derive(AVHWDeviceContext *ctx,
|
|
ctx->user_opaque = priv;
|
|
ctx->free = &vaapi_device_free;
|
|
|
|
- display = vaGetDisplayDRM(fd);
|
|
+ display = vaf->vaGetDisplayDRM(fd);
|
|
if (!display) {
|
|
av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
|
|
"DRM device.\n");
|
|
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
|
|
index 0b2e071cb3..2c51223d45 100644
|
|
--- a/libavutil/hwcontext_vaapi.h
|
|
+++ b/libavutil/hwcontext_vaapi.h
|
|
@@ -20,6 +20,100 @@
|
|
#define AVUTIL_HWCONTEXT_VAAPI_H
|
|
|
|
#include <va/va.h>
|
|
+#include <va/va_x11.h>
|
|
+#include <va/va_drm.h>
|
|
+#include <va/va_str.h>
|
|
+
|
|
+
|
|
+////////////////////////////////////////////////////////////
|
|
+/// VAAPI dynamic load functions start
|
|
+////////////////////////////////////////////////////////////
|
|
+
|
|
+typedef struct VAAPIDynLoadFunctions {
|
|
+ // Core VA functions
|
|
+ VAStatus (*vaInitialize)(VADisplay dpy, int *major_version, int *minor_version);
|
|
+ VAStatus (*vaTerminate)(VADisplay dpy);
|
|
+ VAStatus (*vaCreateConfig)(VADisplay dpy, VAProfile profile, VAEntrypoint entrypoint,
|
|
+ VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id);
|
|
+ VAStatus (*vaDestroyConfig)(VADisplay dpy, VAConfigID config_id);
|
|
+ VAStatus (*vaCreateContext)(VADisplay dpy, VAConfigID config_id, int picture_width,
|
|
+ int picture_height, int flag, VASurfaceID *render_targets,
|
|
+ int num_render_targets, VAContextID *context);
|
|
+ VAStatus (*vaDestroyContext)(VADisplay dpy, VAContextID context);
|
|
+ VAStatus (*vaCreateBuffer)(VADisplay dpy, VAContextID context, VABufferType type,
|
|
+ unsigned int size, unsigned int num_elements, void *data,
|
|
+ VABufferID *buf_id);
|
|
+ VAStatus (*vaDestroyBuffer)(VADisplay dpy, VABufferID buf_id);
|
|
+ VAStatus (*vaMapBuffer)(VADisplay dpy, VABufferID buf_id, void **pbuf);
|
|
+ VAStatus (*vaUnmapBuffer)(VADisplay dpy, VABufferID buf_id);
|
|
+ VAStatus (*vaSyncSurface)(VADisplay dpy, VASurfaceID render_target);
|
|
+ VAStatus (*vaGetConfigAttributes)(VADisplay dpy, VAProfile profile,
|
|
+ VAEntrypoint entrypoint, VAConfigAttrib *attrib_list,
|
|
+ int num_attribs);
|
|
+ VAStatus (*vaCreateSurfaces)(VADisplay dpy, unsigned int format,
|
|
+ unsigned int width, unsigned int height,
|
|
+ VASurfaceID *surfaces, unsigned int num_surfaces,
|
|
+ VASurfaceAttrib *attrib_list, unsigned int num_attribs);
|
|
+ VAStatus (*vaDestroySurfaces)(VADisplay dpy, VASurfaceID *surfaces, int num_surfaces);
|
|
+ VAStatus (*vaBeginPicture)(VADisplay dpy, VAContextID context, VASurfaceID render_target);
|
|
+ VAStatus (*vaRenderPicture)(VADisplay dpy, VAContextID context,
|
|
+ VABufferID *buffers, int num_buffers);
|
|
+ VAStatus (*vaEndPicture)(VADisplay dpy, VAContextID context);
|
|
+ VAStatus (*vaQueryConfigEntrypoints)(VADisplay dpy, VAProfile profile,
|
|
+ VAEntrypoint *entrypoint_list, int *num_entrypoints);
|
|
+ VAStatus (*vaQueryConfigProfiles)(VADisplay dpy, VAProfile *profile_list, int *num_profiles);
|
|
+ VAStatus (*vaGetDisplayAttributes)(VADisplay dpy, VADisplayAttribute *attr_list, int num_attributes);
|
|
+ const char *(*vaErrorStr)(VAStatus error_status);
|
|
+ int (*vaMaxNumEntrypoints)(VADisplay dpy);
|
|
+ int (*vaMaxNumProfiles)(VADisplay dpy);
|
|
+ const char *(*vaQueryVendorString)(VADisplay dpy);
|
|
+ VAStatus (*vaQuerySurfaceAttributes)(VADisplay dpy, VAConfigID config_id,
|
|
+ VASurfaceAttrib *attrib_list, int *num_attribs);
|
|
+ VAStatus (*vaDestroyImage)(VADisplay dpy, VAImageID image);
|
|
+ VAStatus (*vaDeriveImage)(VADisplay dpy, VASurfaceID surface, VAImage *image);
|
|
+ VAStatus (*vaPutImage)(VADisplay dpy, VASurfaceID surface, VAImageID image,
|
|
+ int src_x, int src_y, unsigned int src_width, unsigned int src_height,
|
|
+ int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height);
|
|
+ VAStatus (*vaCreateImage)(VADisplay dpy, VAImageFormat *format, int width, int height, VAImage *image);
|
|
+ VAStatus (*vaGetImage)(VADisplay dpy, VASurfaceID surface,
|
|
+ int x, int y, unsigned int width, unsigned int height,
|
|
+ VAImageID image);
|
|
+ VAStatus (*vaExportSurfaceHandle)(VADisplay dpy, VASurfaceID surface_id,
|
|
+ uint32_t mem_type, uint32_t flags,
|
|
+ void *descriptor);
|
|
+ VAStatus (*vaReleaseBufferHandle)(VADisplay dpy, VABufferID buf_id);
|
|
+ VAStatus (*vaAcquireBufferHandle)(VADisplay dpy, VABufferID buf_id,
|
|
+ VABufferInfo *buf_info);
|
|
+ VAStatus (*vaSetErrorCallback)(VADisplay dpy, VAMessageCallback callback, void *user_context);
|
|
+ VAStatus (*vaSetInfoCallback)(VADisplay dpy, VAMessageCallback callback, void *user_context);
|
|
+ VAStatus (*vaSetDriverName)(VADisplay dpy, const char *driver_name);
|
|
+ const char *(*vaEntrypointStr)(VAEntrypoint entrypoint);
|
|
+ VAStatus (*vaQueryImageFormats)(VADisplay dpy, VAImageFormat *format_list, int *num_formats);
|
|
+ int (*vaMaxNumImageFormats)(VADisplay dpy);
|
|
+ const char *(*vaProfileStr)(VAProfile profile);
|
|
+
|
|
+
|
|
+ // Optional functions
|
|
+ VAStatus (*vaSyncBuffer)(VADisplay dpy, VABufferID buf_id, uint64_t timeout_ns);
|
|
+
|
|
+ // X11 specific functions
|
|
+ VADisplay (*vaGetDisplay)(Display *dpy);
|
|
+
|
|
+ // DRM specific functions
|
|
+ VADisplay (*vaGetDisplayDRM)(int fd);
|
|
+
|
|
+
|
|
+
|
|
+ // Library handles
|
|
+ void *handle_va;
|
|
+ void *handle_va_drm;
|
|
+ void *handle_va_x11;
|
|
+} VAAPIDynLoadFunctions;
|
|
+
|
|
+
|
|
+////////////////////////////////////////////////////////////
|
|
+/// VAAPI API end
|
|
+////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @file
|
|
@@ -78,6 +172,8 @@ typedef struct AVVAAPIDeviceContext {
|
|
* operations using VAAPI with the same VADisplay.
|
|
*/
|
|
unsigned int driver_quirks;
|
|
+
|
|
+ VAAPIDynLoadFunctions *funcs;
|
|
} AVVAAPIDeviceContext;
|
|
|
|
/**
|
|
--
|
|
2.34.1
|
|
|