38 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
39 #define QSV_HAVE_USER_PLUGIN !QSV_ONEVPL
40 #define QSV_HAVE_AUDIO !QSV_ONEVPL
44 #if QSV_HAVE_USER_PLUGIN
45 #include <mfxplugin.h>
49 #include <mfxdispatcher.h>
51 #define MFXUnload(a) do { } while(0)
60 return MFX_CODEC_HEVC;
63 return MFX_CODEC_MPEG2;
69 return MFX_CODEC_JPEG;
72 #if QSV_VERSION_ATLEAST(1, 34)
88 {MFX_IOPATTERN_IN_VIDEO_MEMORY,
"input is video memory surface" },
89 {MFX_IOPATTERN_IN_SYSTEM_MEMORY,
"input is system memory surface" },
91 {MFX_IOPATTERN_IN_OPAQUE_MEMORY,
"input is opaque memory surface" },
93 {MFX_IOPATTERN_OUT_VIDEO_MEMORY,
"output is video memory surface" },
94 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY,
"output is system memory surface" },
96 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
"output is opaque memory surface" },
101 const char *extra_string)
111 desc =
"unknown iopattern";
117 static const struct {
122 { MFX_ERR_NONE, 0,
"success" },
124 { MFX_ERR_NULL_PTR,
AVERROR(EINVAL),
"NULL pointer" },
125 { MFX_ERR_UNSUPPORTED,
AVERROR(ENOSYS),
"unsupported" },
126 { MFX_ERR_MEMORY_ALLOC,
AVERROR(ENOMEM),
"failed to allocate memory" },
127 { MFX_ERR_NOT_ENOUGH_BUFFER,
AVERROR(ENOMEM),
"insufficient input/output buffer" },
128 { MFX_ERR_INVALID_HANDLE,
AVERROR(EINVAL),
"invalid handle" },
129 { MFX_ERR_LOCK_MEMORY,
AVERROR(EIO),
"failed to lock the memory block" },
130 { MFX_ERR_NOT_INITIALIZED,
AVERROR_BUG,
"not initialized" },
131 { MFX_ERR_NOT_FOUND,
AVERROR(ENOSYS),
"specified object was not found" },
135 { MFX_ERR_MORE_SURFACE,
AVERROR_UNKNOWN,
"expect more surface at output" },
136 { MFX_ERR_MORE_BITSTREAM,
AVERROR_UNKNOWN,
"expect more bitstream at output" },
138 { MFX_ERR_DEVICE_LOST,
AVERROR(EIO),
"device lost" },
139 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
AVERROR(EINVAL),
"incompatible video parameters" },
140 { MFX_ERR_INVALID_VIDEO_PARAM,
AVERROR(EINVAL),
"invalid video parameters" },
141 { MFX_ERR_UNDEFINED_BEHAVIOR,
AVERROR_BUG,
"undefined behavior" },
142 { MFX_ERR_DEVICE_FAILED,
AVERROR(EIO),
"device failed" },
144 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
145 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
147 { MFX_ERR_GPU_HANG,
AVERROR(EIO),
"GPU Hang" },
148 { MFX_ERR_REALLOC_SURFACE,
AVERROR_UNKNOWN,
"need bigger surface for output" },
150 { MFX_WRN_IN_EXECUTION, 0,
"operation in execution" },
151 { MFX_WRN_DEVICE_BUSY, 0,
"device busy" },
152 { MFX_WRN_VIDEO_PARAM_CHANGED, 0,
"video parameters changed" },
153 { MFX_WRN_PARTIAL_ACCELERATION, 0,
"partial acceleration" },
154 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0,
"incompatible video parameters" },
155 { MFX_WRN_VALUE_NOT_CHANGED, 0,
"value is saturated" },
156 { MFX_WRN_OUT_OF_RANGE, 0,
"value out of range" },
157 { MFX_WRN_FILTER_SKIPPED, 0,
"filter skipped" },
159 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0,
"incompatible audio parameters" },
162 #if QSV_VERSION_ATLEAST(1, 31)
163 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0,
"partial output" },
181 *
desc =
"unknown error";
186 const char *error_string)
195 const char *warning_string)
215 #if QSV_VERSION_ATLEAST(1, 31)
230 *
fourcc = MFX_FOURCC_NV12;
235 *
fourcc = MFX_FOURCC_P010;
239 *
fourcc = MFX_FOURCC_A2RGB10;
243 *
fourcc = MFX_FOURCC_RGB4;
248 *
fourcc = MFX_FOURCC_YUY2;
253 *
fourcc = MFX_FOURCC_Y210;
257 *
fourcc = MFX_FOURCC_AYUV;
261 *
fourcc = MFX_FOURCC_Y410;
264 #if QSV_VERSION_ATLEAST(1, 31)
266 *
fourcc = MFX_FOURCC_P016;
270 *
fourcc = MFX_FOURCC_Y216;
274 *
fourcc = MFX_FOURCC_Y416;
292 surface->Data.V = surface->Data.UV + 1;
309 surface->Data.Y16 = (mfxU16 *)
frame->
data[0];
310 surface->Data.U16 = (mfxU16 *)
frame->
data[0] + 1;
311 surface->Data.V16 = (mfxU16 *)
frame->
data[0] + 3;
347 for (
i = 0;
i <
ctx->nb_mids;
i++) {
349 mfxHDLPair *pair = (mfxHDLPair*)
frame->surface.Data.MemId;
360 switch (mfx_pic_struct & 0xF) {
361 case MFX_PICSTRUCT_PROGRESSIVE:
364 case MFX_PICSTRUCT_FIELD_TFF:
367 case MFX_PICSTRUCT_FIELD_BFF:
378 switch (mfx_pic_type & 0x7) {
379 case MFX_FRAMETYPE_I:
380 if (mfx_pic_type & MFX_FRAMETYPE_S)
385 case MFX_FRAMETYPE_B:
388 case MFX_FRAMETYPE_P:
389 if (mfx_pic_type & MFX_FRAMETYPE_S)
394 case MFX_FRAMETYPE_UNKNOWN:
407 #if QSV_HAVE_USER_PLUGIN
408 if (!load_plugins || !*load_plugins)
411 while (*load_plugins) {
419 if (strlen(plugin) != 2 *
sizeof(
uid.Data)) {
422 goto load_plugin_fail;
425 for (
i = 0;
i <
sizeof(
uid.Data);
i++) {
426 err = sscanf(plugin + 2 *
i,
"%2hhx",
uid.Data +
i);
430 goto load_plugin_fail;
435 ret = MFXVideoUSER_Load(session, &
uid, 1);
438 snprintf(errorbuf,
sizeof(errorbuf),
439 "Could not load the requested plugin '%s'", plugin);
441 goto load_plugin_fail;
460 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
467 av_dict_set(&child_device_opts,
"kernel_driver",
"i915", 0);
468 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
477 hwctx = qs->va_device_ctx->hwctx;
480 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->
display);
488 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
492 mfxIMPL implementation,
497 mfxLoader loader =
NULL;
499 mfxVariant impl_value;
508 cfg = MFXCreateConfig(loader);
514 impl_value.Type = MFX_VARIANT_TYPE_U32;
515 impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
516 MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
517 sts = MFXSetConfigFilterProperty(cfg,
518 (
const mfxU8 *)
"mfxImplDescription.Impl", impl_value);
519 if (sts != MFX_ERR_NONE) {
521 "property: %d\n", sts);
525 impl_value.Type = MFX_VARIANT_TYPE_U32;
526 impl_value.Data.U32 = pver->Version;
527 sts = MFXSetConfigFilterProperty(cfg,
528 (
const mfxU8 *)
"mfxImplDescription.ApiVersion.Version",
530 if (sts != MFX_ERR_NONE) {
532 "property: %d\n", sts);
548 static int qsv_create_mfx_session_from_loader(
void *
ctx, mfxLoader loader, mfxSession *psession)
551 mfxSession session =
NULL;
552 uint32_t impl_idx = 0;
556 mfxImplDescription *impl_desc;
558 sts = MFXEnumImplementations(loader, impl_idx,
559 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
560 (mfxHDL *)&impl_desc);
562 if (sts == MFX_ERR_NOT_FOUND)
564 else if (sts != MFX_ERR_NONE) {
569 sts = MFXCreateSession(loader, impl_idx, &session);
570 MFXDispReleaseImplDescription(loader, impl_desc);
571 if (sts == MFX_ERR_NONE)
577 if (sts != MFX_ERR_NONE) {
595 mfxIMPL implementation,
598 mfxSession *psession,
601 mfxLoader loader =
NULL;
604 if (*ploader ==
NULL) {
606 "Use Intel(R) oneVPL to create MFX session, the required "
607 "implementation version is %d.%d\n",
608 pver->Major, pver->Minor);
610 if (qsv_new_mfx_loader(avctx, implementation, pver, (
void **)&loader))
616 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
621 if (qsv_create_mfx_session_from_loader(avctx, loader, psession))
630 if (!*ploader && loader)
639 mfxIMPL implementation,
642 mfxSession *psession,
645 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
646 mfxSession session =
NULL;
650 "Use Intel(R) Media SDK to create MFX session, the required "
651 "implementation version is %d.%d\n",
652 pver->Major, pver->Minor);
657 init_par.GPUCopy = gpu_copy;
658 init_par.Implementation = implementation;
659 init_par.Version = *pver;
660 sts = MFXInitEx(init_par, &session);
663 "Error initializing a MFX session");
666 "Warning in MFX initialization");
678 const char *load_plugins,
int gpu_copy)
682 MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11,
703 "supported, try next mfx implementation.\n");
706 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
707 ret = ff_qsv_set_display_handle(avctx, qs);
719 if (
ret != MFX_ERR_NONE)
721 "Error querying the session attributes");
723 switch (MFX_IMPL_BASETYPE(impl)) {
724 case MFX_IMPL_SOFTWARE:
727 case MFX_IMPL_HARDWARE:
728 case MFX_IMPL_HARDWARE2:
729 case MFX_IMPL_HARDWARE3:
730 case MFX_IMPL_HARDWARE4:
731 desc =
"hardware accelerated";
738 "Initialized an internal MFX session using %s implementation\n",
755 int nb_surfaces = frames_hwctx->nb_surfaces;
765 mids =
av_calloc(nb_surfaces,
sizeof(*mids));
779 for (
i = 0;
i < nb_surfaces;
i++) {
781 mid->
handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[
i].Data.MemId;
794 int nb_surfaces = frames_hwctx->nb_surfaces;
800 resp->mids =
av_calloc(nb_surfaces + 2,
sizeof(*resp->mids));
804 for (
i = 0;
i < nb_surfaces;
i++)
805 resp->mids[
i] = &mids[
i];
806 resp->NumFrameActual = nb_surfaces;
808 resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
809 if (!resp->mids[resp->NumFrameActual]) {
814 resp->mids[resp->NumFrameActual + 1] =
av_buffer_ref(mids_buf);
815 if (!resp->mids[resp->NumFrameActual + 1]) {
825 mfxFrameAllocResponse *resp)
832 if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
833 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
834 !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
835 return MFX_ERR_UNSUPPORTED;
837 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
841 mfxFrameInfo *
i = &req->Info;
842 mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info;
844 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
845 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
847 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
848 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
849 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
850 return MFX_ERR_UNSUPPORTED;
856 "Error filling an external frame allocation request\n");
857 return MFX_ERR_MEMORY_ALLOC;
859 }
else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
862 mfxFrameInfo *
i = &req->Info;
870 return MFX_ERR_MEMORY_ALLOC;
873 frames_hwctx = frames_ctx->hwctx;
877 frames_ctx->width =
i->Width;
878 frames_ctx->height =
i->Height;
879 frames_ctx->initial_pool_size = req->NumFrameSuggested;
881 frames_hwctx->frame_type = req->Type;
886 "Error initializing a frames context for an internal frame "
887 "allocation request\n");
889 return MFX_ERR_MEMORY_ALLOC;
895 return MFX_ERR_MEMORY_ALLOC;
903 "Error filling an internal frame allocation request\n");
904 return MFX_ERR_MEMORY_ALLOC;
907 return MFX_ERR_UNSUPPORTED;
929 return MFX_ERR_UNDEFINED_BEHAVIOR;
934 return MFX_ERR_MEMORY_ALLOC;
957 qsv_mid->
surf.Info = hw_frames_hwctx->surfaces[0].Info;
975 return MFX_ERR_MEMORY_ALLOC;
991 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
992 mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->
handle_pair;
994 pair_dst->first = pair_src->first;
996 if (pair_src->second != (mfxMemId)MFX_INFINITE)
997 pair_dst->second = pair_src->second;
1002 AVBufferRef *device_ref,
const char *load_plugins,
1007 mfxSession parent_session = device_hwctx->session;
1008 void *loader = device_hwctx->loader;
1009 mfxHDL handle =
NULL;
1010 int hw_handle_supported = 0;
1015 mfxHandleType handle_type;
1019 err = MFXQueryIMPL(parent_session, &impl);
1020 if (err == MFX_ERR_NONE)
1021 err = MFXQueryVersion(parent_session, &ver);
1022 if (err != MFX_ERR_NONE)
1024 "Error querying the session attributes");
1027 handle_type = MFX_HANDLE_VA_DISPLAY;
1028 hw_handle_supported = 1;
1030 handle_type = MFX_HANDLE_D3D11_DEVICE;
1031 hw_handle_supported = 1;
1033 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1034 hw_handle_supported = 1;
1037 if (hw_handle_supported) {
1038 err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
1039 if (err != MFX_ERR_NONE) {
1041 "Error getting handle session");
1046 "from the session\n");
1055 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
1056 if (err != MFX_ERR_NONE)
1058 "Error setting a HW handle");
1062 err = MFXJoinSession(parent_session, session);
1063 if (err != MFX_ERR_NONE)
1065 "Error joining session");
1074 *psession = session;
1080 const char *load_plugins,
int opaque,
int gpu_copy)
1082 mfxFrameAllocator frame_allocator = {
1083 .pthis = qsv_frames_ctx,
1100 frames_ctx->
device_ref, load_plugins, gpu_copy);
1105 qsv_frames_ctx->
logctx = avctx;
1113 qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
1115 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
1116 if (err != MFX_ERR_NONE)
1118 "Error setting a frame allocator");
1121 *psession = session;
1137 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
1144 mfxExtBuffer * param)
1148 for (
i = 0;
i <
frame->num_ext_params;
i++) {
1149 mfxExtBuffer *ext_buffer =
frame->ext_param[
i];
1151 if (ext_buffer->BufferId == param->BufferId) {
1159 frame->ext_param[
frame->num_ext_params] = param;
1160 frame->num_ext_params++;
1161 frame->surface.Data.NumExtParam =
frame->num_ext_params;
1164 "have enough space\n");