@@ -120,7 +120,7 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
}
}
-static int qsv_load_plugins(mfxSession session, const char *load_plugins,
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins,
void *logctx)
{
if (!load_plugins || !*load_plugins)
@@ -185,7 +185,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
return ff_qsv_error(ret);
}
- ret = qsv_load_plugins(*session, load_plugins, avctx);
+ ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
return ret;
@@ -329,7 +329,7 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession,
}
}
- ret = qsv_load_plugins(session, load_plugins, avctx);
+ ret = ff_qsv_load_plugins(session, load_plugins, avctx);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
return ret;
@@ -50,6 +50,10 @@ typedef struct QSVFrame {
struct QSVFrame *next;
} QSVFrame;
+typedef struct QSVDeviceContext {
+ AVBufferRef *hw_device_ctx;
+} QSVDeviceContext;
+
typedef struct QSVFramesContext {
AVBufferRef *hw_frames_ctx;
mfxFrameInfo info;
@@ -73,5 +77,6 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session,
QSVFramesContext *qsv_frames_ctx,
const char *load_plugins, int opaque);
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx);
#endif /* AVCODEC_QSV_INTERNAL_H */
@@ -41,6 +41,68 @@
#include "qsv_internal.h"
#include "qsvdec.h"
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+ QSVContext *q, const char *load_plugins)
+{
+ mfxIMPL impl = MFX_IMPL_AUTO_ANY;
+ mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+ const char *desc;
+ int ret;
+ AVHWDeviceContext *device_hw;
+ AVQSVDeviceContext *hwctx;
+ AVBufferRef *hw_device_ctx;
+ AVDictionary *dev_dict = NULL;
+
+ if(q->dev_name) {
+ ret = av_dict_set(&dev_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, dev_dict, 0);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+ av_dict_free(&dev_dict);
+ return ret;
+ }
+ av_dict_free(&dev_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 qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
AVBufferRef *hw_frames_ref)
{
@@ -70,13 +132,13 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
q->session = q->internal_session;
} else {
if (!q->internal_session) {
- 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;
+ /* the session will close when unref the hw_device_ctx */
+ // q->session = q->internal_session;
}
/* make sure the decoder is uninitialized */
@@ -428,6 +490,7 @@ int ff_qsv_decode_close(QSVContext *q)
MFXClose(q->internal_session);
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;
@@ -35,6 +35,10 @@
#include "avcodec.h"
#include "qsv_internal.h"
+#define QSV_COMMON_OPTS \
+ { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD }, \
+ { "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, VD },
+
typedef struct QSVContext {
// the session used for decoding
mfxSession session;
@@ -44,6 +48,7 @@ typedef struct QSVContext {
mfxSession internal_session;
QSVFramesContext frames_ctx;
+ QSVDeviceContext device_ctx;
/**
* a linked list of frames currently being used by QSV
@@ -62,6 +67,7 @@ typedef struct QSVContext {
// options set by the caller
int async_depth;
int iopattern;
+ char *dev_name;
char *load_plugins;
@@ -237,7 +237,7 @@ AVHWAccel ff_hevc_qsv_hwaccel = {
};
static const AVOption hevc_options[] = {
- { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+ QSV_COMMON_OPTS
{ "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" },
{ "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" },
@@ -284,7 +284,7 @@ AVHWAccel ff_h264_qsv_hwaccel = {
};
static const AVOption options[] = {
- { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+ QSV_COMMON_OPTS
{ NULL },
};
@@ -150,7 +150,7 @@ AVHWAccel ff_mpeg2_qsv_hwaccel = {
#define OFFSET(x) offsetof(QSVMPEG2Context, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
- { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+ QSV_COMMON_OPTS
{ NULL },
};
@@ -147,7 +147,7 @@ AVHWAccel ff_vc1_qsv_hwaccel = {
#define OFFSET(x) offsetof(QSVVC1Context, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
- { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+ QSV_COMMON_OPTS
{ NULL },
};