[FFmpeg-devel,2/2,V2] libavcodec/qsvenc: Fix the encode part hwaccle issue when using system memory

Submitted by Huang, Zhengxu on Jan. 17, 2017, 6:57 a.m.

Details

Message ID d02ec4ab-0198-e3fa-9bc8-99cfb2aabb5d@gmail.com
State New
Headers show

Commit Message

Huang, Zhengxu Jan. 17, 2017, 6:57 a.m.
在 2017/1/9 10:10, Huang, Zhengxu 写道:
>
From 8466186d4622f760194edd62f7779a0ab8a230d2 Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxwell@gmail.com>
Date: Mon, 19 Dec 2016 03:39:39 -0500
Subject: [PATCH 2/2] libavcodec/qsvenc: Fix the encode part hwaccle issue when
 using system memory

Description: when using system memory the encode actually uses the
PARTIAL_ACCELERATION which means the SW encoder of MSDK. And the performance
will quite poor compared with the HW MSDK.
eg: ./ffmpeg -c:v h264 -i in -c:v h264_qsv  output.h264

Fix: Use the HWContext to get the vaDisplay and configure the encode to HW
mode. The performance will be improved significantly

Signed-off-by: ChaoX A Liu <chaox.a.liu@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxwell@gmail.com>
Signed-off-by: Andrew, Zhang <huazh407@gmail.com>
---
 libavcodec/qsvenc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 libavcodec/qsvenc.h |  4 +++-
 2 files changed, 66 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ac443c1..f61aad7 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -651,6 +651,66 @@  static int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q)
     return 0;
 }
 
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+                                 QSVEncContext *q, const char *load_plugins)
+{
+    mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+    const char *desc;
+    int ret;
+    AVHWDeviceContext *device_hw;
+    AVQSVDeviceContext *hwctx;
+    AVBufferRef *hw_device_ctx;
+    AVDictionary *dict = NULL;
+
+    if (q->dev_name) {
+        ret = av_dict_set(&dict, "child_device", q->dev_name, 0);
+        if (ret < 0)
+            return ret;
+    }
+
+    ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, dict, 0);
+    if (ret < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+        av_dict_free(&dict);
+        return ret;
+    }
+    av_dict_free(&dict);
+
+    device_hw = (AVHWDeviceContext*)hw_device_ctx->data;
+    hwctx = device_hw->hwctx;
+
+    *session = hwctx->session;
+
+    q->device_ctx.hw_device_ctx = hw_device_ctx;
+
+    ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
+        return ret;
+    }
+    MFXQueryIMPL(*session, &impl);
+
+    switch (MFX_IMPL_BASETYPE(impl)) {
+    case MFX_IMPL_SOFTWARE:
+        desc = "software";
+        break;
+    case MFX_IMPL_HARDWARE:
+    case MFX_IMPL_HARDWARE2:
+    case MFX_IMPL_HARDWARE3:
+    case MFX_IMPL_HARDWARE4:
+        desc = "hardware accelerated";
+        break;
+    default:
+        desc = "unknown";
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE,
+           "Initialized an internal MFX session using %s implementation\n",
+           desc);
+
+    return 0;
+}
+
 static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 {
     int ret;
@@ -673,12 +733,12 @@  static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 
         q->session = q->internal_session;
     } else {
-        ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
+        ret = qsv_init_internal_session(avctx, &q->session, q,
                                            q->load_plugins);
         if (ret < 0)
             return ret;
 
-        q->session = q->internal_session;
+       // q->session = q->internal_session;
     }
 
     return 0;
@@ -1088,6 +1148,7 @@  int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
     q->internal_session = NULL;
 
     av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
+    av_buffer_unref(&q->device_ctx.hw_device_ctx);
     av_freep(&q->frames_ctx.mids);
     q->frames_ctx.nb_mids = 0;
 
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 361d933..42d3ed5 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -71,6 +71,7 @@ 
 { "adaptive_b",     "Adaptive B-frame placement",             OFFSET(qsv.adaptive_b),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 { "b_strategy",     "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),    AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 { "cavlc",          "Enable CAVLC",                           OFFSET(qsv.cavlc),          AV_OPT_TYPE_INT, { .i64 = 0 },   0,          1, VE },                         \
+{ "qsv_dev",        "Set QSV hardware device (DirectX adapter index, DRM path or X11 display name)", OFFSET(qsv.dev_name), AV_OPT_TYPE_STRING, { .str = "" }, 0, 128, VE }, \
 
 typedef int SetEncodeCtrlCB (AVCodecContext *avctx,
                              const AVFrame *frame, mfxEncodeCtrl* enc_ctrl);
@@ -105,7 +106,7 @@  typedef struct QSVEncContext {
     AVFifoBuffer *async_fifo;
 
     QSVFramesContext frames_ctx;
-
+    QSVDeviceContext device_ctx;
     // options set by the caller
     int async_depth;
     int idr_interval;
@@ -141,6 +142,7 @@  typedef struct QSVEncContext {
 
     int a53_cc;
     char *load_plugins;
+    char *dev_name;
     SetEncodeCtrlCB *set_encode_ctrl_cb;
 } QSVEncContext;