From 95ebc0ad912447ba83cacb197f506b881f82179e Mon Sep 17 00:00:00 2001 From: 21pages Date: Tue, 10 Dec 2024 15:29:21 +0800 Subject: [PATCH 1/2] dlopen libva Signed-off-by: 21pages --- 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 #endif +#include #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 +#include +#include +#include + + +//////////////////////////////////////////////////////////// +/// 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