Browse Source

lavf/qsv_scale: add scaling modes support

low_power mode will use a fixed HW engine (SFC), thus can offload EU usage.
high quality mode will take EU usage (AVS sampler).

Performance and EU usage (Render usage) comparsion on Intel(R) Xeon(R) CPU E3-1225 v5 @ 3.30GHz:

High quality mode : ffmpeg -hwaccel qsv -c:v h264_qsv -i bbb_sunflower_1080p_30fps_normal_2000frames.h264 \
-vf scale_qsv=w=1280:h=736:mode=hq -f null -
fps=389
RENDER usage: 28.10 (provided by MSDK metrics_monitor)

Low Power mode: ffmpeg -hwaccel qsv -c:v h264_qsv -i ~/bbb_sunflower_1080p_30fps_normal_2000frames.h264 \
-vf scale_qsv=w=1280:h=736:mode=low_power -f null -
fps=343
RENDER usage: 0.00

Low power mode (SFC) may be disabled if not supported by
MSDK/Driver/HW, and replaced by AVS mode interanlly.

Signed-off-by: Zhong Li <zhong.li@intel.com>
tags/n4.2
Zhong Li 5 years ago
parent
commit
dd662bbdd2
1 changed files with 35 additions and 5 deletions
  1. +35
    -5
      libavfilter/vf_scale_qsv.c

+ 35
- 5
libavfilter/vf_scale_qsv.c View File

@@ -69,6 +69,8 @@ enum var_name {
VARS_NB
};

#define QSV_HAVE_SCALING_CONFIG QSV_VERSION_ATLEAST(1, 19)

typedef struct QSVScaleContext {
const AVClass *class;

@@ -88,7 +90,14 @@ typedef struct QSVScaleContext {
int nb_surface_ptrs_out;

mfxExtOpaqueSurfaceAlloc opaque_alloc;
mfxExtBuffer *ext_buffers[1];

#if QSV_HAVE_SCALING_CONFIG
mfxExtVPPScaling scale_conf;
#endif
int mode;

mfxExtBuffer *ext_buffers[1 + QSV_HAVE_SCALING_CONFIG];
int num_ext_buf;

int shift_width, shift_height;

@@ -285,6 +294,8 @@ static int init_out_session(AVFilterContext *ctx)
mfxStatus err;
int i;

s->num_ext_buf = 0;

/* extract the properties of the "master" session given to us */
err = MFXQueryIMPL(device_hwctx->session, &impl);
if (err == MFX_ERR_NONE)
@@ -357,10 +368,7 @@ static int init_out_session(AVFilterContext *ctx)
s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);

s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc;

par.ExtParam = s->ext_buffers;
par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers);
s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->opaque_alloc;

par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
} else {
@@ -396,6 +404,18 @@ static int init_out_session(AVFilterContext *ctx)
par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY;
}

#if QSV_HAVE_SCALING_CONFIG
memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling));
s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING;
s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling);
s->scale_conf.ScalingMode = s->mode;
s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf;
av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %"PRIu16"\n", s->mode);
#endif

par.ExtParam = s->ext_buffers;
par.NumExtParam = s->num_ext_buf;

par.AsyncDepth = 1; // TODO async

par.vpp.In = in_frames_hwctx->surfaces[0].Info;
@@ -595,6 +615,16 @@ static const AVOption options[] = {
{ "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS },
{ "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },

#if QSV_HAVE_SCALING_CONFIG
{ "mode", "set scaling mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"},
{ "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"},
{ "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"},
#else
{ "mode", "(not supported)", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT_MAX, FLAGS, "mode"},
{ "low_power", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, FLAGS, "mode"},
{ "hq", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, FLAGS, "mode"},
#endif

{ NULL },
};



Loading…
Cancel
Save