[FFmpeg-devel] [PATCH 2/9] lavu/hwcontext_qsv: create dynamic frame pool if required
Xiang, Haihao
haihao.xiang at intel.com
Sun Apr 28 10:39:04 EEST 2024
From: Haihao Xiang <haihao.xiang at intel.com>
When AVHWFramesContext.initial_pool_size is 0, a dynamic frame pool is
required. We may support this under certain conditions, e.g. oneVPL 2.9+
support dynamic frame allocation, we needn't provide a fixed frame pool
in the mfxFrameAllocator.Alloc callback.
Signed-off-by: Haihao Xiang <haihao.xiang at intel.com>
---
libavutil/hwcontext_qsv.c | 157 +++++++++++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 3 deletions(-)
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index f552811346..01bd273a08 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -118,8 +118,15 @@ typedef struct QSVFramesContext {
#endif
AVFrame realigned_upload_frame;
AVFrame realigned_download_frame;
+
+ mfxFrameInfo frame_info;
} QSVFramesContext;
+typedef struct QSVSurface {
+ mfxFrameSurface1 mfx_surface;
+ AVFrame *child_frame;
+} QSVSurface;
+
static const struct {
enum AVPixelFormat pix_fmt;
uint32_t fourcc;
@@ -165,6 +172,8 @@ extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf,
enum AVHWDeviceType base_dev_type,
void **base_handle);
+static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf);
+
/**
* Caller needs to allocate enough space for base_handle pointer.
**/
@@ -373,7 +382,32 @@ static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
{
}
-static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size)
+static void qsv_pool_release(void *opaque, uint8_t *data)
+{
+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
+ QSVFramesContext *s = ctx->hwctx;
+ QSVSurface *qsv_surface = (QSVSurface *)data;
+ mfxHDLPair *hdl_pair = (mfxHDLPair *)qsv_surface->mfx_surface.Data.MemId;
+ AVHWFramesContext *child_frames_ctx;
+
+ if (!s->child_frames_ref)
+ return;
+
+ child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
+ if (!child_frames_ctx->device_ctx)
+ return;
+
+#if CONFIG_VAAPI
+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_VAAPI)
+ av_freep(&hdl_pair->first);
+#endif
+
+ av_freep(&hdl_pair);
+ av_frame_free(&qsv_surface->child_frame);
+ av_freep(&qsv_surface);
+}
+
+static AVBufferRef *qsv_fixed_pool_alloc(void *opaque, size_t size)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
QSVFramesContext *s = ctx->hwctx;
@@ -388,6 +422,104 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size)
return NULL;
}
+static AVBufferRef *qsv_dynamic_pool_alloc(void *opaque, size_t size)
+{
+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
+ QSVFramesContext *s = ctx->hwctx;
+ AVHWFramesContext *child_frames_ctx;
+ QSVSurface *qsv_surface = NULL;
+ mfxHDLPair *handle_pairs_internal = NULL;
+ int ret;
+
+ if (!s->child_frames_ref)
+ goto fail;
+
+ child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
+ if (!child_frames_ctx->device_ctx)
+ goto fail;
+
+#if CONFIG_DXVA2
+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
+ av_log(ctx, AV_LOG_ERROR,
+ "QSV on dxva2 requires a fixed frame pool size\n");
+ goto fail;
+ }
+#endif
+
+ qsv_surface = av_calloc(1, sizeof(*qsv_surface));
+ if (!qsv_surface)
+ goto fail;
+
+ qsv_surface->child_frame = av_frame_alloc();
+ if (!qsv_surface->child_frame)
+ goto fail;
+
+ ret = av_hwframe_get_buffer(s->child_frames_ref, qsv_surface->child_frame, 0);
+ if (ret < 0)
+ goto fail;
+
+ handle_pairs_internal = av_calloc(1, sizeof(*handle_pairs_internal));
+ if (!handle_pairs_internal)
+ goto fail;
+
+ ret = qsv_init_surface(ctx, &qsv_surface->mfx_surface);
+ if (ret < 0)
+ goto fail;
+
+#if CONFIG_VAAPI
+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
+ VASurfaceID *surface_id_internal;
+
+ surface_id_internal = av_calloc(1, sizeof(*surface_id_internal));
+ if (!surface_id_internal)
+ goto fail;
+
+ *surface_id_internal = (VASurfaceID)(uintptr_t)qsv_surface->child_frame->data[3];
+ handle_pairs_internal->first = (mfxHDL)surface_id_internal;
+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
+ }
+#endif
+
+#if CONFIG_D3D11VA
+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
+ AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
+ handle_pairs_internal->first = (mfxMemId)qsv_surface->child_frame->data[0];
+
+ if (child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET)
+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
+ else
+ handle_pairs_internal->second = (mfxMemId)qsv_surface->child_frame->data[1];
+
+ }
+#endif
+
+ qsv_surface->mfx_surface.Data.MemId = (mfxMemId)handle_pairs_internal;
+ return av_buffer_create((uint8_t *)qsv_surface, sizeof(*qsv_surface),
+ qsv_pool_release, ctx, 0);
+
+fail:
+ if (qsv_surface) {
+ av_frame_free(&qsv_surface->child_frame);
+ }
+
+ av_freep(&qsv_surface);
+ av_freep(&handle_pairs_internal);
+
+ return NULL;
+}
+
+static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size)
+{
+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
+ AVQSVFramesContext *hwctx = ctx->hwctx;
+
+ if (hwctx->nb_surfaces == 0) {
+ return qsv_dynamic_pool_alloc(opaque, size);
+ } else {
+ return qsv_fixed_pool_alloc(opaque, size);
+ }
+}
+
static int qsv_init_child_ctx(AVHWFramesContext *ctx)
{
QSVDeviceContext *device_priv = ctx->device_ctx->hwctx;
@@ -576,9 +708,28 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
int i, ret = 0;
- if (ctx->initial_pool_size <= 0) {
- av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n");
+ if (ctx->initial_pool_size < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid frame pool size\n");
return AVERROR(EINVAL);
+ } else if (ctx->initial_pool_size == 0) {
+ mfxFrameSurface1 mfx_surf1;
+
+ ret = qsv_init_child_ctx(ctx);
+ if (ret < 0)
+ return ret;
+
+ ffhwframesctx(ctx)->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1),
+ ctx, qsv_pool_alloc, NULL);
+ if (!ffhwframesctx(ctx)->pool_internal)
+ return AVERROR(ENOMEM);
+
+ memset(&mfx_surf1, 0, sizeof(mfx_surf1));
+ qsv_init_surface(ctx, &mfx_surf1);
+ s->frame_info = mfx_surf1.Info;
+ frames_hwctx->info = &s->frame_info;
+ frames_hwctx->nb_surfaces = 0;
+
+ return 0;
}
s->handle_pairs_internal = av_calloc(ctx->initial_pool_size,
--
2.34.1
More information about the ffmpeg-devel
mailing list