Commit 74915453 authored by Haihao Xiang's avatar Haihao Xiang

lavfi/qsv: use QSVVPPContext as base context in vf_vpp_qsv/vf_overlay_qsv

The same members between QSVVPPContext and VPPContext are removed from
VPPContext, and async_depth is moved from QSVVPPParam to QSVVPPContext
so that all QSV filters using QSVVPPContext may support async depth.

In addition, we may use QSVVPPContext as base context in other QSV
filters in the future so that we may re-use functions defined in
qsvvpp.c for other QSV filters.

This commit shouldn't change the functionality of vpp_qsv / overlay_qsv.
Signed-off-by: 's avatarHaihao Xiang <haihao.xiang@intel.com>
parent 3763635e
...@@ -687,15 +687,11 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) ...@@ -687,15 +687,11 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
return 0; return 0;
} }
int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param) int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param)
{ {
int i; int i;
int ret; int ret;
QSVVPPContext *s; QSVVPPContext *s = avctx->priv;
s = av_mallocz(sizeof(*s));
if (!s)
return AVERROR(ENOMEM);
s->filter_frame = param->filter_frame; s->filter_frame = param->filter_frame;
if (!s->filter_frame) if (!s->filter_frame)
...@@ -767,14 +763,13 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p ...@@ -767,14 +763,13 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
s->got_frame = 0; s->got_frame = 0;
/** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */ /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
s->async_fifo = av_fifo_alloc2(param->async_depth + 1, sizeof(QSVAsyncFrame), 0); s->async_fifo = av_fifo_alloc2(s->async_depth + 1, sizeof(QSVAsyncFrame), 0);
s->async_depth = param->async_depth;
if (!s->async_fifo) { if (!s->async_fifo) {
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto failed; goto failed;
} }
s->vpp_param.AsyncDepth = param->async_depth; s->vpp_param.AsyncDepth = s->async_depth;
if (IS_SYSTEM_MEMORY(s->in_mem_mode)) if (IS_SYSTEM_MEMORY(s->in_mem_mode))
s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY; s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
...@@ -805,25 +800,22 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p ...@@ -805,25 +800,22 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p
} else if (ret > 0) } else if (ret > 0)
ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp"); ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp");
*vpp = s;
return 0; return 0;
failed: failed:
ff_qsvvpp_free(&s); ff_qsvvpp_close(avctx);
return ret; return ret;
} }
int ff_qsvvpp_free(QSVVPPContext **vpp) int ff_qsvvpp_close(AVFilterContext *avctx)
{ {
QSVVPPContext *s = *vpp; QSVVPPContext *s = avctx->priv;
if (!s)
return 0;
if (s->session) { if (s->session) {
MFXVideoVPP_Close(s->session); MFXVideoVPP_Close(s->session);
MFXClose(s->session); MFXClose(s->session);
s->session = NULL;
} }
/* release all the resources */ /* release all the resources */
...@@ -836,7 +828,6 @@ int ff_qsvvpp_free(QSVVPPContext **vpp) ...@@ -836,7 +828,6 @@ int ff_qsvvpp_free(QSVVPPContext **vpp)
#endif #endif
av_freep(&s->frame_infos); av_freep(&s->frame_infos);
av_fifo_freep2(&s->async_fifo); av_fifo_freep2(&s->async_fifo);
av_freep(vpp);
return 0; return 0;
} }
......
...@@ -53,6 +53,8 @@ typedef struct QSVFrame { ...@@ -53,6 +53,8 @@ typedef struct QSVFrame {
} QSVFrame; } QSVFrame;
typedef struct QSVVPPContext { typedef struct QSVVPPContext {
const AVClass *class;
mfxSession session; mfxSession session;
int (*filter_frame) (AVFilterLink *outlink, AVFrame *frame); /**< callback */ int (*filter_frame) (AVFilterLink *outlink, AVFrame *frame); /**< callback */
enum AVPixelFormat out_sw_format; /**< Real output format */ enum AVPixelFormat out_sw_format; /**< Real output format */
...@@ -102,15 +104,13 @@ typedef struct QSVVPPParam { ...@@ -102,15 +104,13 @@ typedef struct QSVVPPParam {
/* Crop information for each input, if needed */ /* Crop information for each input, if needed */
int num_crop; int num_crop;
QSVVPPCrop *crop; QSVVPPCrop *crop;
int async_depth;
} QSVVPPParam; } QSVVPPParam;
/* create and initialize the QSV session */ /* create and initialize the QSV session */
int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param); int ff_qsvvpp_init(AVFilterContext *avctx, QSVVPPParam *param);
/* release the resources (eg.surfaces) */ /* release the resources (eg.surfaces) */
int ff_qsvvpp_free(QSVVPPContext **vpp); int ff_qsvvpp_close(AVFilterContext *avctx);
/* vpp filter frame and call the cb if needed */ /* vpp filter frame and call the cb if needed */
int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame); int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame);
......
...@@ -57,10 +57,9 @@ enum var_name { ...@@ -57,10 +57,9 @@ enum var_name {
}; };
typedef struct QSVOverlayContext { typedef struct QSVOverlayContext {
const AVClass *class; QSVVPPContext qsv;
FFFrameSync fs; FFFrameSync fs;
QSVVPPContext *qsv;
QSVVPPParam qsv_param; QSVVPPParam qsv_param;
mfxExtVPPComposite comp_conf; mfxExtVPPComposite comp_conf;
double var_values[VAR_VARS_NB]; double var_values[VAR_VARS_NB];
...@@ -230,14 +229,14 @@ static int config_overlay_input(AVFilterLink *inlink) ...@@ -230,14 +229,14 @@ static int config_overlay_input(AVFilterLink *inlink)
static int process_frame(FFFrameSync *fs) static int process_frame(FFFrameSync *fs)
{ {
AVFilterContext *ctx = fs->parent; AVFilterContext *ctx = fs->parent;
QSVOverlayContext *s = fs->opaque; QSVVPPContext *qsv = fs->opaque;
AVFrame *frame = NULL; AVFrame *frame = NULL;
int ret = 0, i; int ret = 0, i;
for (i = 0; i < ctx->nb_inputs; i++) { for (i = 0; i < ctx->nb_inputs; i++) {
ret = ff_framesync_get_frame(fs, i, &frame, 0); ret = ff_framesync_get_frame(fs, i, &frame, 0);
if (ret == 0) if (ret == 0)
ret = ff_qsvvpp_filter_frame(s->qsv, ctx->inputs[i], frame); ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame);
if (ret < 0 && ret != AVERROR(EAGAIN)) if (ret < 0 && ret != AVERROR(EAGAIN))
break; break;
} }
...@@ -301,7 +300,7 @@ static int config_output(AVFilterLink *outlink) ...@@ -301,7 +300,7 @@ static int config_output(AVFilterLink *outlink)
if (ret < 0) if (ret < 0)
return ret; return ret;
return ff_qsvvpp_create(ctx, &vpp->qsv, &vpp->qsv_param); return ff_qsvvpp_init(ctx, &vpp->qsv_param);
} }
/* /*
...@@ -350,7 +349,7 @@ static av_cold void overlay_qsv_uninit(AVFilterContext *ctx) ...@@ -350,7 +349,7 @@ static av_cold void overlay_qsv_uninit(AVFilterContext *ctx)
{ {
QSVOverlayContext *vpp = ctx->priv; QSVOverlayContext *vpp = ctx->priv;
ff_qsvvpp_free(&vpp->qsv); ff_qsvvpp_close(ctx);
ff_framesync_uninit(&vpp->fs); ff_framesync_uninit(&vpp->fs);
av_freep(&vpp->comp_conf.InputStream); av_freep(&vpp->comp_conf.InputStream);
av_freep(&vpp->qsv_param.ext_buf); av_freep(&vpp->qsv_param.ext_buf);
......
...@@ -45,9 +45,7 @@ ...@@ -45,9 +45,7 @@
#define ENH_FILTERS_COUNT (8) #define ENH_FILTERS_COUNT (8)
typedef struct VPPContext{ typedef struct VPPContext{
const AVClass *class; QSVVPPContext qsv;
QSVVPPContext *qsv;
/* Video Enhancement Algorithms */ /* Video Enhancement Algorithms */
mfxExtVPPDeinterlacing deinterlace_conf; mfxExtVPPDeinterlacing deinterlace_conf;
...@@ -100,8 +98,6 @@ typedef struct VPPContext{ ...@@ -100,8 +98,6 @@ typedef struct VPPContext{
char *ow, *oh; char *ow, *oh;
char *output_format_str; char *output_format_str;
int async_depth;
int eof;
int has_passthrough; /* apply pass through mode if possible */ int has_passthrough; /* apply pass through mode if possible */
} VPPContext; } VPPContext;
...@@ -138,7 +134,7 @@ static const AVOption options[] = { ...@@ -138,7 +134,7 @@ static const AVOption options[] = {
{ "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS },
{ "height", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "height", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS },
{ "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
{ "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS },
{ "scale_mode", "scale & format conversion mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" }, { "scale_mode", "scale & format conversion mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" },
{ "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "auto", "auto mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_DEFAULT}, INT_MIN, INT_MAX, FLAGS, "scale mode"},
{ "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"}, { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "scale mode"},
...@@ -401,7 +397,6 @@ static int config_output(AVFilterLink *outlink) ...@@ -401,7 +397,6 @@ static int config_output(AVFilterLink *outlink)
param.filter_frame = NULL; param.filter_frame = NULL;
param.num_ext_buf = 0; param.num_ext_buf = 0;
param.ext_buf = ext_buf; param.ext_buf = ext_buf;
param.async_depth = vpp->async_depth;
if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) { if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n"); av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
...@@ -557,8 +552,9 @@ static int config_output(AVFilterLink *outlink) ...@@ -557,8 +552,9 @@ static int config_output(AVFilterLink *outlink)
vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip ||
inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format || inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format ||
!vpp->has_passthrough) !vpp->has_passthrough)
return ff_qsvvpp_create(ctx, &vpp->qsv, &param); return ff_qsvvpp_init(ctx, &param);
else { else {
/* No MFX session is created in this case */
av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n"); av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n");
if (inlink->hw_frames_ctx) if (inlink->hw_frames_ctx)
outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
...@@ -571,29 +567,27 @@ static int activate(AVFilterContext *ctx) ...@@ -571,29 +567,27 @@ static int activate(AVFilterContext *ctx)
{ {
AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *outlink = ctx->outputs[0];
VPPContext *s =ctx->priv; QSVVPPContext *qsv = ctx->priv;
QSVVPPContext *qsv = s->qsv;
AVFrame *in = NULL; AVFrame *in = NULL;
int ret, status = 0; int ret, status = 0;
int64_t pts = AV_NOPTS_VALUE; int64_t pts = AV_NOPTS_VALUE;
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
if (!s->eof) { if (!qsv->eof) {
ret = ff_inlink_consume_frame(inlink, &in); ret = ff_inlink_consume_frame(inlink, &in);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
if (status == AVERROR_EOF) { if (status == AVERROR_EOF) {
s->eof = 1; qsv->eof = 1;
} }
} }
} }
if (qsv) { if (qsv->session) {
if (in || s->eof) { if (in || qsv->eof) {
qsv->eof = s->eof;
ret = ff_qsvvpp_filter_frame(qsv, inlink, in); ret = ff_qsvvpp_filter_frame(qsv, inlink, in);
av_frame_free(&in); av_frame_free(&in);
if (ret == AVERROR(EAGAIN)) if (ret == AVERROR(EAGAIN))
...@@ -601,7 +595,7 @@ static int activate(AVFilterContext *ctx) ...@@ -601,7 +595,7 @@ static int activate(AVFilterContext *ctx)
else if (ret < 0) else if (ret < 0)
return ret; return ret;
if (s->eof) if (qsv->eof)
goto eof; goto eof;
if (qsv->got_frame) { if (qsv->got_frame) {
...@@ -610,6 +604,7 @@ static int activate(AVFilterContext *ctx) ...@@ -610,6 +604,7 @@ static int activate(AVFilterContext *ctx)
} }
} }
} else { } else {
/* No MFX session is created in pass-through mode */
if (in) { if (in) {
if (in->pts != AV_NOPTS_VALUE) if (in->pts != AV_NOPTS_VALUE)
in->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); in->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base);
...@@ -618,7 +613,7 @@ static int activate(AVFilterContext *ctx) ...@@ -618,7 +613,7 @@ static int activate(AVFilterContext *ctx)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (s->eof) if (qsv->eof)
goto eof; goto eof;
return 0; return 0;
...@@ -626,7 +621,7 @@ static int activate(AVFilterContext *ctx) ...@@ -626,7 +621,7 @@ static int activate(AVFilterContext *ctx)
} }
not_ready: not_ready:
if (s->eof) if (qsv->eof)
goto eof; goto eof;
FF_FILTER_FORWARD_WANTED(outlink, inlink); FF_FILTER_FORWARD_WANTED(outlink, inlink);
...@@ -667,9 +662,7 @@ static int query_formats(AVFilterContext *ctx) ...@@ -667,9 +662,7 @@ static int query_formats(AVFilterContext *ctx)
static av_cold void vpp_uninit(AVFilterContext *ctx) static av_cold void vpp_uninit(AVFilterContext *ctx)
{ {
VPPContext *vpp = ctx->priv; ff_qsvvpp_close(ctx);
ff_qsvvpp_free(&vpp->qsv);
} }
static const AVClass vpp_class = { static const AVClass vpp_class = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment