From 00aeedd84105a17f414185bd33ecadebeddb3a27 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 10 Aug 2016 08:29:23 +0200 Subject: qsv{dec,enc}: use a struct as a memory id with internal memory allocator This will allow implementing the allocator more fully, which is needed by the HEVC encoder plugin with video memory input. Signed-off-by: Maxym Dmytrychenko --- libavcodec/qsv.c | 26 +++++++++++++++++++++++--- libavcodec/qsv_internal.h | 10 ++++++++-- libavcodec/qsvdec.c | 8 ++++++++ libavcodec/qsvenc.c | 8 ++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 91195865bc..f433b8bf6d 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -144,6 +144,17 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc) } } +int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame) +{ + int i; + for (i = 0; i < ctx->nb_mids; i++) { + QSVMid *mid = &ctx->mids[i]; + if (mid->handle == frame->surface.Data.MemId) + return i; + } + return AVERROR_BUG; +} + static int qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx) { @@ -244,6 +255,7 @@ static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, QSVFramesContext *ctx = pthis; mfxFrameInfo *i = &req->Info; mfxFrameInfo *i1 = &ctx->info; + int j; if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) || !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)) || @@ -258,7 +270,13 @@ static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, return MFX_ERR_UNSUPPORTED; } - resp->mids = ctx->mids; + resp->mids = av_mallocz_array(ctx->nb_mids, sizeof(*resp->mids)); + if (!resp->mids) + return MFX_ERR_MEMORY_ALLOC; + + for (j = 0; j < ctx->nb_mids; j++) + resp->mids[j] = &ctx->mids[j]; + resp->NumFrameActual = ctx->nb_mids; return MFX_ERR_NONE; @@ -266,6 +284,7 @@ static mfxStatus qsv_frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) { + av_freep(&resp->mids); return MFX_ERR_NONE; } @@ -281,7 +300,8 @@ static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) { - *hdl = mid; + QSVMid *qsv_mid = (QSVMid*)mid; + *hdl = qsv_mid->handle; return MFX_ERR_NONE; } @@ -365,7 +385,7 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession, qsv_frames_ctx->info = frames_hwctx->surfaces[0].Info; qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces; for (i = 0; i < frames_hwctx->nb_surfaces; i++) - qsv_frames_ctx->mids[i] = frames_hwctx->surfaces[i].Data.MemId; + qsv_frames_ctx->mids[i].handle = frames_hwctx->surfaces[i].Data.MemId; err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator); if (err != MFX_ERR_NONE) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 5b015a619d..8b69891aa6 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -36,6 +36,10 @@ (MFX_VERSION_MAJOR > (MAJOR) || \ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) +typedef struct QSVMid { + mfxHDL handle; +} QSVMid; + typedef struct QSVFrame { AVFrame *frame; mfxFrameSurface1 surface; @@ -49,8 +53,8 @@ typedef struct QSVFrame { typedef struct QSVFramesContext { AVBufferRef *hw_frames_ctx; mfxFrameInfo info; - mfxMemId *mids; - int nb_mids; + QSVMid *mids; + int nb_mids; } QSVFramesContext; /** @@ -75,4 +79,6 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session, QSVFramesContext *qsv_frames_ctx, const char *load_plugins, int opaque); +int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame); + #endif /* AVCODEC_QSV_INTERNAL_H */ diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8353d252d2..398c319b30 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -188,6 +188,14 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) frame->surface.Data.UV = frame->frame->data[1]; } + if (q->frames_ctx.mids) { + ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame); + if (ret < 0) + return ret; + + frame->surface.Data.MemId = &q->frames_ctx.mids[ret]; + } + frame->used = 1; return 0; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 3d99e846e3..be8cbee884 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -872,6 +872,14 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, return ret; qf->surface = *(mfxFrameSurface1*)qf->frame->data[3]; + + if (q->frames_ctx.mids) { + ret = ff_qsv_find_surface_idx(&q->frames_ctx, qf); + if (ret < 0) + return ret; + + qf->surface.Data.MemId = &q->frames_ctx.mids[ret]; + } } else { /* make a copy if the input is not padded as libmfx requires */ if (frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) { -- cgit v1.2.3