]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/qsv.c
Cosmetics: Reindent after last commit.
[ffmpeg] / libavcodec / qsv.c
index 714c7948cbfee98e88b56a4ed4ea8d9fffb1a91e..697af872a68b6ca1c5dec12352e32c5905fddf15 100644 (file)
  */
 
 #include <mfx/mfxvideo.h>
+#include <mfx/mfxplugin.h>
 
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/avstring.h"
 #include "libavutil/error.h"
 
 #include "avcodec.h"
@@ -30,6 +35,10 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
     switch (codec_id) {
     case AV_CODEC_ID_H264:
         return MFX_CODEC_AVC;
+#if QSV_VERSION_ATLEAST(1, 8)
+    case AV_CODEC_ID_HEVC:
+        return MFX_CODEC_HEVC;
+#endif
     case AV_CODEC_ID_MPEG1VIDEO:
     case AV_CODEC_ID_MPEG2VIDEO:
         return MFX_CODEC_MPEG2;
@@ -76,41 +85,13 @@ int ff_qsv_error(int mfx_err)
         return AVERROR_UNKNOWN;
     }
 }
-
-/**
- * @brief Initialize a MSDK session
- *
- * Media SDK is based on sessions, so this is the prerequisite
- * initialization for HW acceleration.  For Windows the session is
- * complete and ready to use, for Linux a display handle is
- * required.  For releases of Media Server Studio >= 2015 R4 the
- * render nodes interface is preferred (/dev/dri/renderD).
- * Using Media Server Studio 2015 R4 or newer is recommended
- * but the older /dev/dri/card interface is also searched
- * for broader compatibility.
- *
- * @param avctx    ffmpeg metadata for this codec context
- * @param session  the MSDK session used
- */
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session)
+static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
 {
-    mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
-    mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
-
-    const char *desc;
-    int ret;
-
-    ret = MFXInit(impl, &ver, session);
-    if (ret < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
-        return ff_qsv_error(ret);
-    }
-
-
     // this code is only required for Linux.  It searches for a valid
     // display handle.  First in /dev/dri/renderD then in /dev/dri/card
 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
     // VAAPI display handle
+    int ret = 0;
     VADisplay va_dpy = NULL;
     VAStatus va_res = VA_STATUS_SUCCESS;
     int major_version = 0, minor_version = 0;
@@ -154,12 +135,52 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session)
         } else {
             av_log(avctx, AV_LOG_VERBOSE,
             "mfx initialization: %s vaInitialize successful\n",adapterpath);
+            ret = MFXVideoCORE_SetHandle(session,
+                  (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR,
+                "Error %d during set display handle\n", ret);
+                return ff_qsv_error(ret);
+            }
             break;
         }
     }
-    MFXVideoCORE_SetHandle((*session), (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
-
 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
+    return 0;
+}
+/**
+ * @brief Initialize a MSDK session
+ *
+ * Media SDK is based on sessions, so this is the prerequisite
+ * initialization for HW acceleration.  For Windows the session is
+ * complete and ready to use, for Linux a display handle is
+ * required.  For releases of Media Server Studio >= 2015 R4 the
+ * render nodes interface is preferred (/dev/dri/renderD).
+ * Using Media Server Studio 2015 R4 or newer is recommended
+ * but the older /dev/dri/card interface is also searched
+ * for broader compatibility.
+ *
+ * @param avctx    ffmpeg metadata for this codec context
+ * @param session  the MSDK session used
+ */
+int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+                                 const char *load_plugins)
+{
+    mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+    mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+    const char *desc;
+    int ret;
+
+    ret = MFXInit(impl, &ver, session);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
+        return ff_qsv_error(ret);
+    }
+
+    ret = ff_qsv_set_display_handle(avctx, *session);
+    if (ret < 0)
+        return ret;
 
     MFXQueryIMPL(*session, &impl);
 
@@ -177,6 +198,45 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session)
         desc = "unknown";
     }
 
+    if (load_plugins && *load_plugins) {
+        while (*load_plugins) {
+            mfxPluginUID uid;
+            int i, err = 0;
+
+            char *plugin = av_get_token(&load_plugins, ":");
+            if (!plugin)
+                return AVERROR(ENOMEM);
+            if (strlen(plugin) != 2 * sizeof(uid.Data)) {
+                av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
+                err = AVERROR(EINVAL);
+                goto load_plugin_fail;
+            }
+
+            for (i = 0; i < sizeof(uid.Data); i++) {
+                err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
+                if (err != 1) {
+                    av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID\n");
+                    err = AVERROR(EINVAL);
+                    goto load_plugin_fail;
+                }
+
+            }
+
+            ret = MFXVideoUSER_Load(*session, &uid, 1);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
+                       plugin);
+                err = ff_qsv_error(ret);
+                goto load_plugin_fail;
+            }
+
+load_plugin_fail:
+            av_freep(&plugin);
+            if (err < 0)
+                return err;
+        }
+    }
+
     av_log(avctx, AV_LOG_VERBOSE,
            "Initialized an internal MFX session using %s implementation\n",
            desc);