[FFmpeg-cvslog] qsv: adding Multi Frame Encode support
Maxym Dmytrychenko
git at videolan.org
Sat Apr 14 02:38:14 EEST 2018
ffmpeg | branch: master | Maxym Dmytrychenko <maxim.d33 at gmail.com> | Mon Apr 2 15:17:23 2018 +0200| [cca5e4f040971db6de0bfe6968f00c021d8a9c42] | committer: Maxym Dmytrychenko
qsv: adding Multi Frame Encode support
Starting from API 1.25 helps to improve performance of the simultaneous
encode, 1:N scenario, like:
./avconv -y -hwaccel qsv -c:v h264_qsv -r 30000/1001 -i
~/bbb_sunflower_1080p_60fps_normal.mp4 -vframes 600 -an \
-filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1];
[s2]scale_qsv=960:540[o2]" \
-map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f
rawvideo /tmp/3200a.264 \
-map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f
rawvideo /tmp/1750a.264
Signed-off-by: Maxym Dmytrychenko <maxim.d33 at gmail.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=cca5e4f040971db6de0bfe6968f00c021d8a9c42
---
libavcodec/qsv.c | 10 ++++++----
libavcodec/qsv_internal.h | 4 ++++
libavcodec/qsvenc.c | 16 +++++++++++++++-
libavcodec/qsvenc.h | 12 ++++++++++--
libavcodec/qsvenc_h264.c | 4 ++++
libavfilter/qsvvpp.c | 9 ++++++---
libavfilter/qsvvpp.h | 8 ++++++++
libavfilter/vf_deinterlace_qsv.c | 7 +++++++
libavfilter/vf_scale_qsv.c | 7 +++++++
libavutil/hwcontext_qsv.c | 5 +++++
10 files changed, 72 insertions(+), 10 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index e578ab15f5..a9b3c59f3a 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -617,10 +617,12 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
"Error setting a HW handle");
}
- err = MFXJoinSession(parent_session, session);
- if (err != MFX_ERR_NONE)
- return ff_qsv_print_error(avctx, err,
- "Error joining session");
+ if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+ err = MFXJoinSession(parent_session, session);
+ if (err != MFX_ERR_NONE)
+ return ff_qsv_print_error(avctx, err,
+ "Error joining session");
+ }
ret = qsv_load_plugins(session, load_plugins, avctx);
if (ret < 0) {
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 07ddc59044..3cd8f1872b 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))
+#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+ (MFX_VERSION.Major > (MAJOR)) || \
+ (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
+
typedef struct QSVMid {
AVBufferRef *hw_frames_ref;
mfxHDL handle;
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index f6b1a0d676..a8b446c5bd 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -135,7 +135,7 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
#if QSV_HAVE_CO2
mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
#endif
-#if QSV_HAVE_CO3
+#if QSV_HAVE_CO3 && QSV_HAVE_QVBR
mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
#endif
@@ -657,6 +657,20 @@ FF_ENABLE_DEPRECATION_WARNINGS
q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
}
#endif
+#if QSV_HAVE_MF
+ if (avctx->codec_id == AV_CODEC_ID_H264) {
+ mfxVersion ver;
+ ret = MFXQueryVersion(q->session,&ver);
+ if (ret >= MFX_ERR_NONE && QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+ q->extmfp.Header.BufferId = MFX_EXTBUFF_MULTI_FRAME_PARAM;
+ q->extmfp.Header.BufferSz = sizeof(q->extmfp);
+
+ q->extmfp.MFMode = q->mfmode;
+ av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode);
+ q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmfp;
+ }
+ }
+#endif
}
if (!check_enc_param(avctx,q)) {
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index ab55795950..a7fc57bb48 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -50,11 +50,13 @@
#define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 8)
#define QSV_HAVE_VCM QSV_VERSION_ATLEAST(1, 8)
#define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11)
+#define QSV_HAVE_MF 0
#else
#define QSV_HAVE_AVBR 0
#define QSV_HAVE_ICQ 0
#define QSV_HAVE_VCM 0
#define QSV_HAVE_QVBR 0
+#define QSV_HAVE_MF QSV_VERSION_ATLEAST(1, 25)
#endif
#if !QSV_HAVE_LA_DS
@@ -109,12 +111,15 @@ typedef struct QSVEncContext {
#if QSV_HAVE_CO2
mfxExtCodingOption2 extco2;
#endif
-
+#if QSV_HAVE_MF
+ mfxExtMultiFrameParam extmfp;
+ mfxExtMultiFrameControl extmfc;
+#endif
mfxExtOpaqueSurfaceAlloc opaque_alloc;
mfxFrameSurface1 **opaque_surfaces;
AVBufferRef *opaque_alloc_buf;
- mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2];
+ mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + (QSV_HAVE_MF * 2)];
int nb_extparam_internal;
mfxExtBuffer **extparam;
@@ -156,6 +161,9 @@ typedef struct QSVEncContext {
int int_ref_qp_delta;
int recovery_point_sei;
+#if QSV_HAVE_MF
+ int mfmode;
+#endif
char *load_plugins;
} QSVEncContext;
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 634a7d3f91..ae00ff8d54 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -93,6 +93,10 @@ static const AVOption options[] = {
{ "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE},
+#if QSV_HAVE_MF
+ { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, 0, INT_MAX, VE },
+#endif
+
{ NULL },
};
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index a96cfa65de..f704517aee 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -515,9 +515,12 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
if (ret != MFX_ERR_NONE)
return AVERROR_UNKNOWN;
}
- ret = MFXJoinSession(device_hwctx->session, s->session);
- if (ret != MFX_ERR_NONE)
- return AVERROR_UNKNOWN;
+
+ if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+ ret = MFXJoinSession(device_hwctx->session, s->session);
+ if (ret != MFX_ERR_NONE)
+ return AVERROR_UNKNOWN;
+ }
if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
s->opaque_alloc.In.Surfaces = s->surface_ptrs_in;
diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h
index 082c0a8994..d25ea69e5c 100644
--- a/libavfilter/qsvvpp.h
+++ b/libavfilter/qsvvpp.h
@@ -31,6 +31,14 @@
#define FF_INLINK_IDX(link) ((int)((link)->dstpad - (link)->dst->input_pads))
#define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads))
+#define QSV_VERSION_ATLEAST(MAJOR, MINOR) \
+ (MFX_VERSION_MAJOR > (MAJOR) || \
+ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
+
+#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+ (MFX_VERSION.Major > (MAJOR)) || \
+ (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
+
typedef struct QSVVPPContext QSVVPPContext;
typedef struct QSVVPPCrop {
diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
index 2360491d3f..bb26a4dbfe 100644
--- a/libavfilter/vf_deinterlace_qsv.c
+++ b/libavfilter/vf_deinterlace_qsv.c
@@ -35,6 +35,7 @@
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/time.h"
+#include "libavfilter/qsvvpp.h"
#include "avfilter.h"
#include "formats.h"
@@ -214,6 +215,12 @@ static int init_out_session(AVFilterContext *ctx)
return AVERROR_UNKNOWN;
}
+ if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+ err = MFXJoinSession(device_hwctx->session, s->session);
+ if (err != MFX_ERR_NONE)
+ return AVERROR_UNKNOWN;
+ }
+
memset(&par, 0, sizeof(par));
s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index c568e96259..381844cdc4 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -36,6 +36,7 @@
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/time.h"
+#include "libavfilter/qsvvpp.h"
#include "avfilter.h"
#include "formats.h"
@@ -313,6 +314,12 @@ static int init_out_session(AVFilterContext *ctx)
return AVERROR_UNKNOWN;
}
+ if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+ err = MFXJoinSession(device_hwctx->session, s->session);
+ if (err != MFX_ERR_NONE)
+ return AVERROR_UNKNOWN;
+ }
+
memset(&par, 0, sizeof(par));
if (opaque) {
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index f5d78d0595..b3eb4a3ea6 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -1058,6 +1058,11 @@ static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
goto fail;
}
+ ret = MFXQueryVersion(hwctx->session,&ver);
+ if (ret == MFX_ERR_NONE) {
+ av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime API: %d.%d/%d.%d\n",
+ MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
+ }
return 0;
fail:
More information about the ffmpeg-cvslog
mailing list