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)
216 #if QSV_VERSION_ATLEAST(1, 31)
232 *
fourcc = MFX_FOURCC_NV12;
237 *
fourcc = MFX_FOURCC_P010;
241 *
fourcc = MFX_FOURCC_A2RGB10;
245 *
fourcc = MFX_FOURCC_RGB4;
251 *
fourcc = MFX_FOURCC_YUY2;
256 *
fourcc = MFX_FOURCC_Y210;
260 *
fourcc = MFX_FOURCC_AYUV;
264 *
fourcc = MFX_FOURCC_Y410;
267 #if QSV_VERSION_ATLEAST(1, 31)
269 *
fourcc = MFX_FOURCC_P016;
273 *
fourcc = MFX_FOURCC_Y216;
277 *
fourcc = MFX_FOURCC_Y416;
289 switch (
frame->format) {
293 surface->Data.Y =
frame->data[0];
294 surface->Data.UV =
frame->data[1];
296 surface->Data.V = surface->Data.UV + 1;
300 surface->Data.B =
frame->data[0];
301 surface->Data.G =
frame->data[0] + 1;
302 surface->Data.R =
frame->data[0] + 2;
303 surface->Data.A =
frame->data[0] + 3;
306 surface->Data.Y =
frame->data[0];
307 surface->Data.U =
frame->data[0] + 1;
308 surface->Data.V =
frame->data[0] + 3;
313 surface->Data.Y16 = (mfxU16 *)
frame->data[0];
314 surface->Data.U16 = (mfxU16 *)
frame->data[0] + 1;
315 surface->Data.V16 = (mfxU16 *)
frame->data[0] + 3;
319 surface->Data.V =
frame->data[0];
320 surface->Data.U =
frame->data[0] + 1;
321 surface->Data.Y =
frame->data[0] + 2;
324 surface->Data.A =
frame->data[0] + 3;
328 surface->Data.U =
frame->data[0];
332 surface->Data.U =
frame->data[0];
333 surface->Data.Y =
frame->data[0] + 2;
334 surface->Data.V =
frame->data[0] + 4;
337 surface->Data.A =
frame->data[0] + 6;
343 surface->Data.PitchLow =
frame->linesize[0];
351 for (
i = 0;
i <
ctx->nb_mids;
i++) {
353 mfxHDLPair *pair = (mfxHDLPair*)
frame->surface.Data.MemId;
364 switch (mfx_pic_struct & 0xF) {
365 case MFX_PICSTRUCT_PROGRESSIVE:
368 case MFX_PICSTRUCT_FIELD_TFF:
371 case MFX_PICSTRUCT_FIELD_BFF:
382 switch (mfx_pic_type & 0x7) {
383 case MFX_FRAMETYPE_I:
384 if (mfx_pic_type & MFX_FRAMETYPE_S)
389 case MFX_FRAMETYPE_B:
392 case MFX_FRAMETYPE_P:
393 if (mfx_pic_type & MFX_FRAMETYPE_S)
398 case MFX_FRAMETYPE_UNKNOWN:
411 #if QSV_HAVE_USER_PLUGIN
412 if (!load_plugins || !*load_plugins)
415 while (*load_plugins) {
423 if (strlen(plugin) != 2 *
sizeof(
uid.Data)) {
426 goto load_plugin_fail;
429 for (
i = 0;
i <
sizeof(
uid.Data);
i++) {
430 err = sscanf(plugin + 2 *
i,
"%2hhx",
uid.Data +
i);
434 goto load_plugin_fail;
439 ret = MFXVideoUSER_Load(session, &
uid, 1);
442 snprintf(errorbuf,
sizeof(errorbuf),
443 "Could not load the requested plugin '%s'", plugin);
445 goto load_plugin_fail;
464 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
471 av_dict_set(&child_device_opts,
"kernel_driver",
"i915", 0);
472 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
481 hwctx = qs->va_device_ctx->hwctx;
484 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->
display);
492 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
496 mfxIMPL implementation,
501 mfxLoader loader =
NULL;
503 mfxVariant impl_value;
512 cfg = MFXCreateConfig(loader);
518 impl_value.Type = MFX_VARIANT_TYPE_U32;
519 impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
520 MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
521 sts = MFXSetConfigFilterProperty(cfg,
522 (
const mfxU8 *)
"mfxImplDescription.Impl", impl_value);
523 if (sts != MFX_ERR_NONE) {
525 "property: %d\n", sts);
529 impl_value.Type = MFX_VARIANT_TYPE_U32;
530 impl_value.Data.U32 = pver->Version;
531 sts = MFXSetConfigFilterProperty(cfg,
532 (
const mfxU8 *)
"mfxImplDescription.ApiVersion.Version",
534 if (sts != MFX_ERR_NONE) {
536 "property: %d\n", sts);
552 static int qsv_create_mfx_session_from_loader(
void *
ctx, mfxLoader loader, mfxSession *psession)
555 mfxSession session =
NULL;
556 uint32_t impl_idx = 0;
560 mfxImplDescription *impl_desc;
562 sts = MFXEnumImplementations(loader, impl_idx,
563 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
564 (mfxHDL *)&impl_desc);
566 if (sts == MFX_ERR_NOT_FOUND)
568 else if (sts != MFX_ERR_NONE) {
573 sts = MFXCreateSession(loader, impl_idx, &session);
574 MFXDispReleaseImplDescription(loader, impl_desc);
575 if (sts == MFX_ERR_NONE)
581 if (sts != MFX_ERR_NONE) {
599 mfxIMPL implementation,
602 mfxSession *psession,
605 mfxLoader loader =
NULL;
608 if (*ploader ==
NULL) {
610 "Use Intel(R) oneVPL to create MFX session, the required "
611 "implementation version is %d.%d\n",
612 pver->Major, pver->Minor);
614 if (qsv_new_mfx_loader(avctx, implementation, pver, (
void **)&loader))
620 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
625 if (qsv_create_mfx_session_from_loader(avctx, loader, psession))
634 if (!*ploader && loader)
643 mfxIMPL implementation,
646 mfxSession *psession,
649 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
650 mfxSession session =
NULL;
654 "Use Intel(R) Media SDK to create MFX session, the required "
655 "implementation version is %d.%d\n",
656 pver->Major, pver->Minor);
661 init_par.GPUCopy = gpu_copy;
662 init_par.Implementation = implementation;
663 init_par.Version = *pver;
664 sts = MFXInitEx(init_par, &session);
667 "Error initializing a MFX session");
670 "Warning in MFX initialization");
682 const char *load_plugins,
int gpu_copy)
685 mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11;
687 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
697 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
698 ret = ff_qsv_set_display_handle(avctx, qs);
710 if (
ret != MFX_ERR_NONE)
712 "Error querying the session attributes");
714 switch (MFX_IMPL_BASETYPE(impl)) {
715 case MFX_IMPL_SOFTWARE:
718 case MFX_IMPL_HARDWARE:
719 case MFX_IMPL_HARDWARE2:
720 case MFX_IMPL_HARDWARE3:
721 case MFX_IMPL_HARDWARE4:
722 desc =
"hardware accelerated";
729 "Initialized an internal MFX session using %s implementation\n",
746 int nb_surfaces = frames_hwctx->nb_surfaces;
756 mids =
av_calloc(nb_surfaces,
sizeof(*mids));
770 for (
i = 0;
i < nb_surfaces;
i++) {
772 mid->
handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[
i].Data.MemId;
785 int nb_surfaces = frames_hwctx->nb_surfaces;
791 resp->mids =
av_calloc(nb_surfaces + 2,
sizeof(*resp->mids));
795 for (
i = 0;
i < nb_surfaces;
i++)
796 resp->mids[
i] = &mids[
i];
797 resp->NumFrameActual = nb_surfaces;
799 resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
800 if (!resp->mids[resp->NumFrameActual]) {
805 resp->mids[resp->NumFrameActual + 1] =
av_buffer_ref(mids_buf);
806 if (!resp->mids[resp->NumFrameActual + 1]) {
816 mfxFrameAllocResponse *resp)
823 if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
824 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
825 !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
826 return MFX_ERR_UNSUPPORTED;
828 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
832 mfxFrameInfo *
i = &req->Info;
833 mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info;
835 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
836 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
838 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
839 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
840 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
841 return MFX_ERR_UNSUPPORTED;
847 "Error filling an external frame allocation request\n");
848 return MFX_ERR_MEMORY_ALLOC;
850 }
else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
853 mfxFrameInfo *
i = &req->Info;
861 return MFX_ERR_MEMORY_ALLOC;
864 frames_hwctx = frames_ctx->hwctx;
868 frames_ctx->width =
i->Width;
869 frames_ctx->height =
i->Height;
870 frames_ctx->initial_pool_size = req->NumFrameSuggested;
872 frames_hwctx->frame_type = req->Type;
877 "Error initializing a frames context for an internal frame "
878 "allocation request\n");
880 return MFX_ERR_MEMORY_ALLOC;
886 return MFX_ERR_MEMORY_ALLOC;
894 "Error filling an internal frame allocation request\n");
895 return MFX_ERR_MEMORY_ALLOC;
898 return MFX_ERR_UNSUPPORTED;
920 return MFX_ERR_UNDEFINED_BEHAVIOR;
925 return MFX_ERR_MEMORY_ALLOC;
948 qsv_mid->
surf.Info = hw_frames_hwctx->surfaces[0].Info;
966 return MFX_ERR_MEMORY_ALLOC;
982 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
983 mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->
handle_pair;
985 pair_dst->first = pair_src->first;
987 if (pair_src->second != (mfxMemId)MFX_INFINITE)
988 pair_dst->second = pair_src->second;
998 mfxSession parent_session = device_hwctx->session;
999 void *loader = device_hwctx->loader;
1000 mfxHDL handle =
NULL;
1001 int hw_handle_supported = 0;
1006 mfxHandleType handle_type;
1010 err = MFXQueryIMPL(parent_session, &impl);
1011 if (err == MFX_ERR_NONE)
1012 err = MFXQueryVersion(parent_session, &ver);
1013 if (err != MFX_ERR_NONE)
1015 "Error querying the session attributes");
1018 handle_type = MFX_HANDLE_VA_DISPLAY;
1019 hw_handle_supported = 1;
1021 handle_type = MFX_HANDLE_D3D11_DEVICE;
1022 hw_handle_supported = 1;
1024 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1025 hw_handle_supported = 1;
1028 if (hw_handle_supported) {
1029 err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
1030 if (err != MFX_ERR_NONE) {
1032 "Error getting handle session");
1037 "from the session\n");
1046 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
1047 if (err != MFX_ERR_NONE)
1049 "Error setting a HW handle");
1053 err = MFXJoinSession(parent_session, session);
1054 if (err != MFX_ERR_NONE)
1056 "Error joining session");
1065 *psession = session;
1071 const char *load_plugins,
int opaque,
int gpu_copy)
1073 mfxFrameAllocator frame_allocator = {
1074 .pthis = qsv_frames_ctx,
1091 frames_ctx->
device_ref, load_plugins, gpu_copy);
1096 qsv_frames_ctx->
logctx = avctx;
1104 qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
1106 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
1107 if (err != MFX_ERR_NONE)
1109 "Error setting a frame allocator");
1112 *psession = session;
1128 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
1135 mfxExtBuffer * param)
1139 for (
i = 0;
i <
frame->num_ext_params;
i++) {
1140 mfxExtBuffer *ext_buffer =
frame->ext_param[
i];
1142 if (ext_buffer->BufferId == param->BufferId) {
1150 frame->ext_param[
frame->num_ext_params] = param;
1151 frame->num_ext_params++;
1152 frame->surface.Data.NumExtParam =
frame->num_ext_params;
1155 "have enough space\n");