[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