libavcodec/qsv.c: Issue fixed: QSV engine does not release display handler under linux platform.
Reviewed-by: Gwenole Beauchesne <gb.devel@gmail.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
96e1cc3f8b
commit
ce91bab70f
@ -85,7 +85,7 @@ int ff_qsv_error(int mfx_err)
|
|||||||
return AVERROR_UNKNOWN;
|
return AVERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
|
static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
|
||||||
{
|
{
|
||||||
// this code is only required for Linux. It searches for a valid
|
// this code is only required for Linux. It searches for a valid
|
||||||
// display handle. First in /dev/dri/renderD then in /dev/dri/card
|
// display handle. First in /dev/dri/renderD then in /dev/dri/card
|
||||||
@ -99,6 +99,9 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
|
|||||||
char adapterpath[256];
|
char adapterpath[256];
|
||||||
int adapter_num;
|
int adapter_num;
|
||||||
|
|
||||||
|
qs->fd_display = -1;
|
||||||
|
qs->va_display = NULL;
|
||||||
|
|
||||||
//search for valid graphics device
|
//search for valid graphics device
|
||||||
for (adapter_num = 0;adapter_num < 6;adapter_num++) {
|
for (adapter_num = 0;adapter_num < 6;adapter_num++) {
|
||||||
|
|
||||||
@ -135,7 +138,9 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
|
|||||||
} else {
|
} else {
|
||||||
av_log(avctx, AV_LOG_VERBOSE,
|
av_log(avctx, AV_LOG_VERBOSE,
|
||||||
"mfx initialization: %s vaInitialize successful\n",adapterpath);
|
"mfx initialization: %s vaInitialize successful\n",adapterpath);
|
||||||
ret = MFXVideoCORE_SetHandle(session,
|
qs->fd_display = fd;
|
||||||
|
qs->va_display = va_dpy;
|
||||||
|
ret = MFXVideoCORE_SetHandle(qs->session,
|
||||||
(mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
|
(mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
@ -163,7 +168,7 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
|
|||||||
* @param avctx ffmpeg metadata for this codec context
|
* @param avctx ffmpeg metadata for this codec context
|
||||||
* @param session the MSDK session used
|
* @param session the MSDK session used
|
||||||
*/
|
*/
|
||||||
int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
|
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
|
||||||
const char *load_plugins)
|
const char *load_plugins)
|
||||||
{
|
{
|
||||||
mfxIMPL impl = MFX_IMPL_AUTO_ANY;
|
mfxIMPL impl = MFX_IMPL_AUTO_ANY;
|
||||||
@ -172,17 +177,17 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
|
|||||||
const char *desc;
|
const char *desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = MFXInit(impl, &ver, session);
|
ret = MFXInit(impl, &ver, &qs->session);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
|
av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
|
||||||
return ff_qsv_error(ret);
|
return ff_qsv_error(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ff_qsv_set_display_handle(avctx, *session);
|
ret = ff_qsv_set_display_handle(avctx, qs);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
MFXQueryIMPL(*session, &impl);
|
MFXQueryIMPL(qs->session, &impl);
|
||||||
|
|
||||||
switch (MFX_IMPL_BASETYPE(impl)) {
|
switch (MFX_IMPL_BASETYPE(impl)) {
|
||||||
case MFX_IMPL_SOFTWARE:
|
case MFX_IMPL_SOFTWARE:
|
||||||
@ -222,7 +227,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = MFXVideoUSER_Load(*session, &uid, 1);
|
ret = MFXVideoUSER_Load(qs->session, &uid, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
|
av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
|
||||||
plugin);
|
plugin);
|
||||||
@ -243,3 +248,22 @@ load_plugin_fail:
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_qsv_close_internal_session(QSVSession *qs)
|
||||||
|
{
|
||||||
|
if (qs->session) {
|
||||||
|
MFXClose(qs->session);
|
||||||
|
qs->session = NULL;
|
||||||
|
}
|
||||||
|
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
|
||||||
|
if (qs->va_display) {
|
||||||
|
vaTerminate(qs->va_display);
|
||||||
|
qs->va_display = NULL;
|
||||||
|
}
|
||||||
|
if (qs->fd_display > 0) {
|
||||||
|
close(qs->fd_display);
|
||||||
|
qs->fd_display = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -58,6 +58,14 @@ typedef struct QSVFrame {
|
|||||||
struct QSVFrame *next;
|
struct QSVFrame *next;
|
||||||
} QSVFrame;
|
} QSVFrame;
|
||||||
|
|
||||||
|
typedef struct QSVSession {
|
||||||
|
mfxSession session;
|
||||||
|
#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
|
||||||
|
int fd_display;
|
||||||
|
VADisplay va_display;
|
||||||
|
#endif
|
||||||
|
} QSVSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a libmfx error code into a ffmpeg error code.
|
* Convert a libmfx error code into a ffmpeg error code.
|
||||||
*/
|
*/
|
||||||
@ -65,7 +73,8 @@ int ff_qsv_error(int mfx_err);
|
|||||||
|
|
||||||
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id);
|
int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id);
|
||||||
|
|
||||||
int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
|
int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
|
||||||
const char *load_plugins);
|
const char *load_plugins);
|
||||||
|
int ff_qsv_close_internal_session(QSVSession *qs);
|
||||||
|
|
||||||
#endif /* AVCODEC_QSV_INTERNAL_H */
|
#endif /* AVCODEC_QSV_INTERNAL_H */
|
||||||
|
@ -51,13 +51,13 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format)
|
|||||||
static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session)
|
static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session)
|
||||||
{
|
{
|
||||||
if (!session) {
|
if (!session) {
|
||||||
if (!q->internal_session) {
|
if (!q->internal_qs.session) {
|
||||||
int ret = ff_qsv_init_internal_session(avctx, &q->internal_session, NULL);
|
int ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->session = q->internal_session;
|
q->session = q->internal_qs.session;
|
||||||
} else {
|
} else {
|
||||||
q->session = session;
|
q->session = session;
|
||||||
}
|
}
|
||||||
@ -282,9 +282,7 @@ int ff_qsv_decode_close(QSVContext *q)
|
|||||||
av_freep(&cur);
|
av_freep(&cur);
|
||||||
cur = q->work_frames;
|
cur = q->work_frames;
|
||||||
}
|
}
|
||||||
|
ff_qsv_close_internal_session(&q->internal_qs);
|
||||||
if (q->internal_session)
|
|
||||||
MFXClose(q->internal_session);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ typedef struct QSVContext {
|
|||||||
|
|
||||||
// the session we allocated internally, in case the caller did not provide
|
// the session we allocated internally, in case the caller did not provide
|
||||||
// one
|
// one
|
||||||
mfxSession internal_session;
|
QSVSession internal_qs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a linked list of frames currently being used by QSV
|
* a linked list of frames currently being used by QSV
|
||||||
|
@ -217,12 +217,12 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!q->session) {
|
if (!q->session) {
|
||||||
ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
|
ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
|
||||||
q->load_plugins);
|
q->load_plugins);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
q->session = q->internal_session;
|
q->session = q->internal_qs.session;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = init_video_param(avctx, q);
|
ret = init_video_param(avctx, q);
|
||||||
@ -460,10 +460,9 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
|
|||||||
QSVFrame *cur;
|
QSVFrame *cur;
|
||||||
|
|
||||||
MFXVideoENCODE_Close(q->session);
|
MFXVideoENCODE_Close(q->session);
|
||||||
if (q->internal_session)
|
q->session = NULL;
|
||||||
MFXClose(q->internal_session);
|
|
||||||
q->session = NULL;
|
ff_qsv_close_internal_session(&q->internal_qs);
|
||||||
q->internal_session = NULL;
|
|
||||||
|
|
||||||
cur = q->work_frames;
|
cur = q->work_frames;
|
||||||
while (cur) {
|
while (cur) {
|
||||||
|
@ -39,7 +39,7 @@ typedef struct QSVEncContext {
|
|||||||
QSVFrame *work_frames;
|
QSVFrame *work_frames;
|
||||||
|
|
||||||
mfxSession session;
|
mfxSession session;
|
||||||
mfxSession internal_session;
|
QSVSession internal_qs;
|
||||||
|
|
||||||
int packet_size;
|
int packet_size;
|
||||||
int width_align;
|
int width_align;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user