mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
lavu/hwcontext_qsv: create dynamic frame pool if required
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@intel.com>
This commit is contained in:
parent
4c0bb7d4a9
commit
96db4a62e0
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user