MSDK does not create internal acceleration device on Linux, So MFXVideoCORE_SetHandle() is necessary. It has been added for ff_qsv_init_session_device(). But missed for ff_qsv_init_internal_session() due to committags/n4.31f26a23overwrited commitdb89f45Fix #7030 Signed-off-by: Zhong Li <zhong.li@intel.com>
| @@ -348,7 +348,41 @@ load_plugin_fail: | |||
| } | |||
| int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, | |||
| //This code is only required for Linux since a display handle is required. | |||
| //For Windows the session is complete and ready to use. | |||
| #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs) | |||
| { | |||
| AVDictionary *child_device_opts = NULL; | |||
| AVVAAPIDeviceContext *hwctx; | |||
| int ret; | |||
| av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); | |||
| av_dict_set(&child_device_opts, "driver", "iHD", 0); | |||
| ret = av_hwdevice_ctx_create(&qs->va_device_ref, AV_HWDEVICE_TYPE_VAAPI, NULL, child_device_opts, 0); | |||
| if (ret < 0) { | |||
| av_log(avctx, AV_LOG_ERROR, "Failed to create a VAAPI device.\n"); | |||
| return ret; | |||
| } else { | |||
| qs->va_device_ctx = (AVHWDeviceContext*)qs->va_device_ref->data; | |||
| hwctx = qs->va_device_ctx->hwctx; | |||
| ret = MFXVideoCORE_SetHandle(qs->session, | |||
| (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->display); | |||
| if (ret < 0) { | |||
| return ff_qsv_print_error(avctx, ret, "Error during set display handle\n"); | |||
| } | |||
| } | |||
| av_dict_free(&child_device_opts); | |||
| return 0; | |||
| } | |||
| #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, | |||
| const char *load_plugins) | |||
| { | |||
| mfxIMPL impl = MFX_IMPL_AUTO_ANY; | |||
| @@ -357,18 +391,24 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, | |||
| const char *desc; | |||
| int ret; | |||
| ret = MFXInit(impl, &ver, session); | |||
| ret = MFXInit(impl, &ver, &qs->session); | |||
| if (ret < 0) | |||
| return ff_qsv_print_error(avctx, ret, | |||
| "Error initializing an internal MFX session"); | |||
| ret = qsv_load_plugins(*session, load_plugins, avctx); | |||
| #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| ret = ff_qsv_set_display_handle(avctx, qs); | |||
| if (ret < 0) | |||
| return ret; | |||
| #endif | |||
| ret = qsv_load_plugins(qs->session, load_plugins, avctx); | |||
| if (ret < 0) { | |||
| av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); | |||
| return ret; | |||
| } | |||
| MFXQueryIMPL(*session, &impl); | |||
| MFXQueryIMPL(qs->session, &impl); | |||
| switch (MFX_IMPL_BASETYPE(impl)) { | |||
| case MFX_IMPL_SOFTWARE: | |||
| @@ -758,3 +798,17 @@ int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, | |||
| *psession = session; | |||
| 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_device_ctx) { | |||
| qs->va_device_ctx->free(qs->va_device_ctx); | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -21,6 +21,22 @@ | |||
| #ifndef AVCODEC_QSV_INTERNAL_H | |||
| #define AVCODEC_QSV_INTERNAL_H | |||
| #if CONFIG_VAAPI | |||
| #define AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| #endif //CONFIG_VAAPI | |||
| #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #if HAVE_UNISTD_H | |||
| #include <unistd.h> | |||
| #endif | |||
| #include <fcntl.h> | |||
| #include <va/va.h> | |||
| #include <va/va_drm.h> | |||
| #include "libavutil/hwcontext_vaapi.h" | |||
| #endif | |||
| #include <mfx/mfxvideo.h> | |||
| #include "libavutil/frame.h" | |||
| @@ -64,6 +80,14 @@ typedef struct QSVFrame { | |||
| struct QSVFrame *next; | |||
| } QSVFrame; | |||
| typedef struct QSVSession { | |||
| mfxSession session; | |||
| #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE | |||
| AVBufferRef *va_device_ref; | |||
| AVHWDeviceContext *va_device_ctx; | |||
| #endif | |||
| } QSVSession; | |||
| typedef struct QSVFramesContext { | |||
| AVBufferRef *hw_frames_ctx; | |||
| void *logctx; | |||
| @@ -99,9 +123,11 @@ enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type); | |||
| enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct); | |||
| int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, | |||
| int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, | |||
| const char *load_plugins); | |||
| int ff_qsv_close_internal_session(QSVSession *qs); | |||
| int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, | |||
| AVBufferRef *device_ref, const char *load_plugins); | |||
| @@ -62,9 +62,9 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses | |||
| if (session) { | |||
| q->session = session; | |||
| } else if (hw_frames_ref) { | |||
| if (q->internal_session) { | |||
| MFXClose(q->internal_session); | |||
| q->internal_session = NULL; | |||
| if (q->internal_qs.session) { | |||
| MFXClose(q->internal_qs.session); | |||
| q->internal_qs.session = NULL; | |||
| } | |||
| av_buffer_unref(&q->frames_ctx.hw_frames_ctx); | |||
| @@ -72,7 +72,7 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses | |||
| if (!q->frames_ctx.hw_frames_ctx) | |||
| return AVERROR(ENOMEM); | |||
| ret = ff_qsv_init_session_frames(avctx, &q->internal_session, | |||
| ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, | |||
| &q->frames_ctx, q->load_plugins, | |||
| q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); | |||
| if (ret < 0) { | |||
| @@ -80,28 +80,28 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses | |||
| return ret; | |||
| } | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } else if (hw_device_ref) { | |||
| if (q->internal_session) { | |||
| MFXClose(q->internal_session); | |||
| q->internal_session = NULL; | |||
| if (q->internal_qs.session) { | |||
| MFXClose(q->internal_qs.session); | |||
| q->internal_qs.session = NULL; | |||
| } | |||
| ret = ff_qsv_init_session_device(avctx, &q->internal_session, | |||
| ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, | |||
| hw_device_ref, q->load_plugins); | |||
| if (ret < 0) | |||
| return ret; | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } else { | |||
| if (!q->internal_session) { | |||
| ret = ff_qsv_init_internal_session(avctx, &q->internal_session, | |||
| if (!q->internal_qs.session) { | |||
| ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, | |||
| q->load_plugins); | |||
| if (ret < 0) | |||
| return ret; | |||
| } | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } | |||
| /* make sure the decoder is uninitialized */ | |||
| @@ -529,8 +529,7 @@ int ff_qsv_decode_close(QSVContext *q) | |||
| av_fifo_free(q->async_fifo); | |||
| q->async_fifo = NULL; | |||
| if (q->internal_session) | |||
| MFXClose(q->internal_session); | |||
| ff_qsv_close_internal_session(&q->internal_qs); | |||
| av_buffer_unref(&q->frames_ctx.hw_frames_ctx); | |||
| av_buffer_unref(&q->frames_ctx.mids_buf); | |||
| @@ -42,7 +42,7 @@ typedef struct QSVContext { | |||
| // the session we allocated internally, in case the caller did not provide | |||
| // one | |||
| mfxSession internal_session; | |||
| QSVSession internal_qs; | |||
| QSVFramesContext frames_ctx; | |||
| @@ -954,7 +954,7 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) | |||
| if (!q->frames_ctx.hw_frames_ctx) | |||
| return AVERROR(ENOMEM); | |||
| ret = ff_qsv_init_session_frames(avctx, &q->internal_session, | |||
| ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, | |||
| &q->frames_ctx, q->load_plugins, | |||
| q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY); | |||
| if (ret < 0) { | |||
| @@ -962,21 +962,21 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) | |||
| return ret; | |||
| } | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } else if (avctx->hw_device_ctx) { | |||
| ret = ff_qsv_init_session_device(avctx, &q->internal_session, | |||
| ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, | |||
| avctx->hw_device_ctx, q->load_plugins); | |||
| if (ret < 0) | |||
| return ret; | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } else { | |||
| ret = ff_qsv_init_internal_session(avctx, &q->internal_session, | |||
| ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, | |||
| q->load_plugins); | |||
| if (ret < 0) | |||
| return ret; | |||
| q->session = q->internal_session; | |||
| q->session = q->internal_qs.session; | |||
| } | |||
| return 0; | |||
| @@ -1507,10 +1507,9 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) | |||
| if (q->session) | |||
| MFXVideoENCODE_Close(q->session); | |||
| if (q->internal_session) | |||
| MFXClose(q->internal_session); | |||
| q->session = NULL; | |||
| q->internal_session = NULL; | |||
| ff_qsv_close_internal_session(&q->internal_qs); | |||
| av_buffer_unref(&q->frames_ctx.hw_frames_ctx); | |||
| av_buffer_unref(&q->frames_ctx.mids_buf); | |||
| @@ -102,7 +102,7 @@ typedef struct QSVEncContext { | |||
| QSVFrame *work_frames; | |||
| mfxSession session; | |||
| mfxSession internal_session; | |||
| QSVSession internal_qs; | |||
| int packet_size; | |||
| int width_align; | |||