case AV_CODEC_ID_VP9:
return MFX_CODEC_VP9;
#endif
+#if QSV_VERSION_ATLEAST(1, 34)
+ case AV_CODEC_ID_AV1:
+ return MFX_CODEC_AV1;
+#endif
default:
break;
return AVERROR(ENOSYS);
}
-
-static const struct {
- enum AVCodecID codec_id;
- int codec_profile;
- int mfx_profile;
-} qsv_profile_map[] = {
-#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, MFX_PROFILE_ ## v }
- MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2_SIMPLE ),
- MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2_MAIN ),
- MAP(MPEG2VIDEO, MPEG2_HIGH, MPEG2_HIGH ),
-
- MAP(H264, H264_BASELINE, AVC_BASELINE ),
- MAP(H264, H264_CONSTRAINED_BASELINE, AVC_BASELINE),
-#if QSV_VERSION_ATLEAST(1, 3)
- MAP(H264, H264_EXTENDED, AVC_EXTENDED ),
-#endif
- MAP(H264, H264_MAIN, AVC_MAIN ),
- MAP(H264, H264_HIGH, AVC_HIGH ),
- MAP(H264, H264_HIGH_422, AVC_HIGH_422 ),
-
-#if QSV_VERSION_ATLEAST(1, 8)
- MAP(HEVC, HEVC_MAIN, HEVC_MAIN ),
- MAP(HEVC, HEVC_MAIN_10, HEVC_MAIN10 ),
- MAP(HEVC, HEVC_MAIN_STILL_PICTURE, HEVC_MAINSP ),
-#endif
-#if QSV_VERSION_ATLEAST(1, 16)
- MAP(HEVC, HEVC_REXT, HEVC_REXT ),
-#endif
-
- MAP(VC1, VC1_SIMPLE, VC1_SIMPLE ),
- MAP(VC1, VC1_MAIN, VC1_MAIN ),
- MAP(VC1, VC1_COMPLEX, VC1_ADVANCED ),
- MAP(VC1, VC1_ADVANCED, VC1_ADVANCED ),
-#undef MAP
-};
-
-int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile)
-{
- int i;
- if (profile == FF_PROFILE_UNKNOWN)
- return MFX_PROFILE_UNKNOWN;
-
- for (i = 0; i < FF_ARRAY_ELEMS(qsv_profile_map); i++) {
- if (qsv_profile_map[i].codec_id != codec_id)
- continue;
- if (qsv_profile_map[i].codec_profile == profile)
- return qsv_profile_map[i].mfx_profile;
- }
-
- return MFX_PROFILE_UNKNOWN;
-}
-
int ff_qsv_level_to_mfx(enum AVCodecID codec_id, int level)
{
if (level == FF_LEVEL_UNKNOWN)
}
}
+static const struct {
+ int mfx_iopattern;
+ const char *desc;
+} qsv_iopatterns[] = {
+ {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
+ {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
+ {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
+ {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
+ {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
+ {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
+};
+
+int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern,
+ const char *extra_string)
+{
+ const char *desc = NULL;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) {
+ if (qsv_iopatterns[i].mfx_iopattern == mfx_iopattern) {
+ desc = qsv_iopatterns[i].desc;
+ }
+ }
+ if (!desc)
+ desc = "unknown iopattern";
+
+ av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc);
+ return 0;
+}
+
static const struct {
mfxStatus mfxerr;
int averr;
case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12;
case MFX_FOURCC_P010: return AV_PIX_FMT_P010;
case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8;
+#if CONFIG_VAAPI
+ case MFX_FOURCC_YUY2: return AV_PIX_FMT_YUYV422;
+#if QSV_VERSION_ATLEAST(1, 27)
+ case MFX_FOURCC_Y210: return AV_PIX_FMT_Y210;
+#endif
+#endif
}
return AV_PIX_FMT_NONE;
}
case AV_PIX_FMT_P010:
*fourcc = MFX_FOURCC_P010;
return AV_PIX_FMT_P010;
+#if CONFIG_VAAPI
+ case AV_PIX_FMT_YUV422P:
+ case AV_PIX_FMT_YUYV422:
+ *fourcc = MFX_FOURCC_YUY2;
+ return AV_PIX_FMT_YUYV422;
+#if QSV_VERSION_ATLEAST(1, 27)
+ case AV_PIX_FMT_YUV422P10:
+ case AV_PIX_FMT_Y210:
+ *fourcc = MFX_FOURCC_Y210;
+ return AV_PIX_FMT_Y210;
+#endif
+#endif
default:
return AVERROR(ENOSYS);
}
}
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
- const char *load_plugins)
+//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);
+ av_dict_free(&child_device_opts);
+ 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");
+ }
+ }
+
+ return 0;
+}
+#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
+
+int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
+ const char *load_plugins, int gpu_copy)
{
- mfxIMPL impl = MFX_IMPL_AUTO_ANY;
- mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+ mfxIMPL impl = MFX_IMPL_AUTO_ANY;
+ mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+ mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
const char *desc;
int ret;
- ret = MFXInit(impl, &ver, session);
+#if QSV_VERSION_ATLEAST(1, 16)
+ init_par.GPUCopy = gpu_copy;
+#endif
+ init_par.Implementation = impl;
+ init_par.Version = ver;
+ ret = MFXInitEx(init_par, &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:
}
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
- AVBufferRef *device_ref, const char *load_plugins)
+ AVBufferRef *device_ref, const char *load_plugins,
+ int gpu_copy)
{
static const mfxHandleType handle_types[] = {
MFX_HANDLE_VA_DISPLAY,
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data;
AVQSVDeviceContext *device_hwctx = device_ctx->hwctx;
mfxSession parent_session = device_hwctx->session;
+ mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
+ mfxHDL handle = NULL;
mfxSession session;
mfxVersion ver;
mfxIMPL impl;
- mfxHDL handle = NULL;
mfxHandleType handle_type;
mfxStatus err;
"from the session\n");
}
- err = MFXInit(impl, &ver, &session);
+#if QSV_VERSION_ATLEAST(1, 16)
+ init_par.GPUCopy = gpu_copy;
+#endif
+ init_par.Implementation = impl;
+ init_par.Version = ver;
+ err = MFXInitEx(init_par, &session);
if (err != MFX_ERR_NONE)
return ff_qsv_print_error(avctx, err,
"Error initializing a child MFX session");
int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
QSVFramesContext *qsv_frames_ctx,
- const char *load_plugins, int opaque)
+ const char *load_plugins, int opaque, int gpu_copy)
{
mfxFrameAllocator frame_allocator = {
.pthis = qsv_frames_ctx,
int ret;
ret = ff_qsv_init_session_device(avctx, &session,
- frames_ctx->device_ref, load_plugins);
+ frames_ctx->device_ref, load_plugins, gpu_copy);
if (ret < 0)
return ret;
*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
+ av_buffer_unref(&qs->va_device_ref);
+#endif
+ return 0;
+}