[FFmpeg-devel] [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when using system memory
Huang, Zhengxu
zhengxu.maxwell at gmail.com
Mon Jan 9 04:05:23 EET 2017
-------------- next part --------------
From 37629f14294125c7396e5e12970d75e895b1caba Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxwell at gmail.com>
Date: Mon, 19 Dec 2016 01:27:06 -0500
Subject: [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when
using system memory
Description: ./ffmpeg -c:v h264_qsv -i in -c:v h264 output.h264 does not
work because the qsv decode will failed.
Root cuase: when using the system rather than the hwaccel,ff_qsv_init_internal_session
does not set the vaDisplay handle for the session. The qsv decode will failed.
Solution: when creating the internal session , call the HwContext API to get session and
release all resource when close the decoder.
Signed-off-by: ChaoX A Liu <chaox.a.liu at gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxwell at gmail.com>
Signed-off-by: Andrew, Zhang <huazh407 at gmail.com>
---
libavcodec/qsv.c | 6 ++---
libavcodec/qsv_internal.h | 5 ++++
libavcodec/qsvdec.c | 59 ++++++++++++++++++++++++++++++++++++++++++++---
libavcodec/qsvdec.h | 1 +
4 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index aac6ce6..a932fc3 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -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;
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 5d2a216..13f23ef 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -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 */
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 258042d..ccd5e26 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -41,6 +41,58 @@
#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;
+
+ ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, NULL, 0);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+ return ret;
+ }
+ 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 +122,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 +480,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;
diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h
index 41fb716..ae810bc 100644
--- a/libavcodec/qsvdec.h
+++ b/libavcodec/qsvdec.h
@@ -44,6 +44,7 @@ typedef struct QSVContext {
mfxSession internal_session;
QSVFramesContext frames_ctx;
+ QSVDeviceContext device_ctx;
/**
* a linked list of frames currently being used by QSV
--
1.8.3.1
More information about the ffmpeg-devel
mailing list