40 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
41 #define QSV_HAVE_USER_PLUGIN !QSV_ONEVPL
42 #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)
76 #if QSV_VERSION_ATLEAST(2, 11)
92 {MFX_IOPATTERN_IN_VIDEO_MEMORY,
"input is video memory surface" },
93 {MFX_IOPATTERN_IN_SYSTEM_MEMORY,
"input is system memory surface" },
95 {MFX_IOPATTERN_IN_OPAQUE_MEMORY,
"input is opaque memory surface" },
97 {MFX_IOPATTERN_OUT_VIDEO_MEMORY,
"output is video memory surface" },
98 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY,
"output is system memory surface" },
100 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
"output is opaque memory surface" },
105 const char *extra_string)
115 desc =
"unknown iopattern";
121 static const struct {
126 { MFX_ERR_NONE, 0,
"success" },
128 { MFX_ERR_NULL_PTR,
AVERROR(EINVAL),
"NULL pointer" },
129 { MFX_ERR_UNSUPPORTED,
AVERROR(ENOSYS),
"unsupported" },
130 { MFX_ERR_MEMORY_ALLOC,
AVERROR(ENOMEM),
"failed to allocate memory" },
131 { MFX_ERR_NOT_ENOUGH_BUFFER,
AVERROR(ENOMEM),
"insufficient input/output buffer" },
132 { MFX_ERR_INVALID_HANDLE,
AVERROR(EINVAL),
"invalid handle" },
133 { MFX_ERR_LOCK_MEMORY,
AVERROR(EIO),
"failed to lock the memory block" },
134 { MFX_ERR_NOT_INITIALIZED,
AVERROR_BUG,
"not initialized" },
135 { MFX_ERR_NOT_FOUND,
AVERROR(ENOSYS),
"specified object was not found" },
139 { MFX_ERR_MORE_SURFACE,
AVERROR_UNKNOWN,
"expect more surface at output" },
140 { MFX_ERR_MORE_BITSTREAM,
AVERROR_UNKNOWN,
"expect more bitstream at output" },
142 { MFX_ERR_DEVICE_LOST,
AVERROR(EIO),
"device lost" },
143 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
AVERROR(EINVAL),
"incompatible video parameters" },
144 { MFX_ERR_INVALID_VIDEO_PARAM,
AVERROR(EINVAL),
"invalid video parameters" },
145 { MFX_ERR_UNDEFINED_BEHAVIOR,
AVERROR_BUG,
"undefined behavior" },
146 { MFX_ERR_DEVICE_FAILED,
AVERROR(EIO),
"device failed" },
148 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
149 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
151 { MFX_ERR_GPU_HANG,
AVERROR(EIO),
"GPU Hang" },
152 { MFX_ERR_REALLOC_SURFACE,
AVERROR_UNKNOWN,
"need bigger surface for output" },
154 { MFX_WRN_IN_EXECUTION, 0,
"operation in execution" },
155 { MFX_WRN_DEVICE_BUSY, 0,
"device busy" },
156 { MFX_WRN_VIDEO_PARAM_CHANGED, 0,
"video parameters changed" },
157 { MFX_WRN_PARTIAL_ACCELERATION, 0,
"partial acceleration" },
158 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0,
"incompatible video parameters" },
159 { MFX_WRN_VALUE_NOT_CHANGED, 0,
"value is saturated" },
160 { MFX_WRN_OUT_OF_RANGE, 0,
"value out of range" },
161 { MFX_WRN_FILTER_SKIPPED, 0,
"filter skipped" },
163 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0,
"incompatible audio parameters" },
166 #if QSV_VERSION_ATLEAST(1, 31)
167 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0,
"partial output" },
185 *
desc =
"unknown error";
190 const char *error_string)
199 const char *warning_string)
219 #if QSV_VERSION_ATLEAST(1, 31)
234 *
fourcc = MFX_FOURCC_NV12;
239 *
fourcc = MFX_FOURCC_P010;
243 *
fourcc = MFX_FOURCC_A2RGB10;
247 *
fourcc = MFX_FOURCC_RGB4;
252 *
fourcc = MFX_FOURCC_YUY2;
257 *
fourcc = MFX_FOURCC_Y210;
261 *
fourcc = MFX_FOURCC_AYUV;
265 *
fourcc = MFX_FOURCC_Y410;
268 #if QSV_VERSION_ATLEAST(1, 31)
270 *
fourcc = MFX_FOURCC_P016;
274 *
fourcc = MFX_FOURCC_Y216;
278 *
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,
"vendor_id",
"0x8086", 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 = {0};
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)
686 MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11,
707 "supported, try next mfx implementation.\n");
710 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
711 ret = ff_qsv_set_display_handle(avctx, qs);
723 if (
ret != MFX_ERR_NONE)
725 "Error querying the session attributes");
727 switch (MFX_IMPL_BASETYPE(impl)) {
728 case MFX_IMPL_SOFTWARE:
731 case MFX_IMPL_HARDWARE:
732 case MFX_IMPL_HARDWARE2:
733 case MFX_IMPL_HARDWARE3:
734 case MFX_IMPL_HARDWARE4:
735 desc =
"hardware accelerated";
742 "Initialized an internal MFX session using %s implementation\n",
758 int nb_surfaces = frames_hwctx->nb_surfaces;
775 for (
i = 0;
i < nb_surfaces;
i++) {
777 mid->
handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[
i].Data.MemId;
789 int nb_surfaces = frames_hwctx->nb_surfaces;
795 resp->mids =
av_calloc(nb_surfaces + 2,
sizeof(*resp->mids));
799 for (
i = 0;
i < nb_surfaces;
i++)
800 resp->mids[
i] = &mids[
i];
801 resp->NumFrameActual = nb_surfaces;
803 resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
804 if (!resp->mids[resp->NumFrameActual]) {
815 mfxFrameAllocResponse *resp)
822 if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
823 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
824 !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
825 return MFX_ERR_UNSUPPORTED;
827 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
831 mfxFrameInfo *
i = &req->Info;
834 if (!frames_hwctx->nb_surfaces) {
836 "Dynamic frame pools, no frame is pre-allocated\n");
841 i1 = &frames_hwctx->surfaces[0].Info;
842 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
843 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
845 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
846 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
847 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
848 return MFX_ERR_UNSUPPORTED;
854 "Error filling an external frame allocation request\n");
855 return MFX_ERR_MEMORY_ALLOC;
857 }
else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
861 mfxFrameInfo *
i = &req->Info;
868 if (!ext_frames_hwctx->nb_surfaces)
869 return MFX_ERR_UNSUPPORTED;
873 return MFX_ERR_MEMORY_ALLOC;
876 frames_hwctx = frames_ctx->hwctx;
880 frames_ctx->width =
i->Width;
881 frames_ctx->height =
i->Height;
882 frames_ctx->initial_pool_size = req->NumFrameSuggested;
884 frames_hwctx->frame_type = req->Type;
889 "Error initializing a frames context for an internal frame "
890 "allocation request\n");
892 return MFX_ERR_MEMORY_ALLOC;
898 return MFX_ERR_MEMORY_ALLOC;
906 "Error filling an internal frame allocation request\n");
907 return MFX_ERR_MEMORY_ALLOC;
910 return MFX_ERR_UNSUPPORTED;
937 if (!frames_hwctx->nb_surfaces)
938 return MFX_ERR_UNSUPPORTED;
942 hw_frames_hwctx = hw_frames_ctx->hwctx;
943 if (qsv_mid->locked_frame)
944 return MFX_ERR_UNDEFINED_BEHAVIOR;
948 if (!qsv_mid->locked_frame)
949 return MFX_ERR_MEMORY_ALLOC;
950 qsv_mid->locked_frame->format = hw_frames_ctx->sw_format;
954 if (!qsv_mid->hw_frame)
957 qsv_mid->hw_frame->data[3] = (uint8_t*)&qsv_mid->surf;
962 if (!qsv_mid->hw_frame->buf[0])
965 qsv_mid->hw_frame->width = hw_frames_ctx->width;
966 qsv_mid->hw_frame->height = hw_frames_ctx->height;
968 qsv_mid->hw_frame->hw_frames_ctx =
av_buffer_ref(qsv_mid->hw_frames_ref);
969 if (!qsv_mid->hw_frame->hw_frames_ctx)
972 qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
973 qsv_mid->surf.Data.MemId = qsv_mid->handle_pair;
981 ptr->Pitch = qsv_mid->locked_frame->linesize[0];
982 ptr->Y = qsv_mid->locked_frame->data[0];
983 ptr->U = qsv_mid->locked_frame->data[1];
984 ptr->V = qsv_mid->locked_frame->data[1] + 1;
990 return MFX_ERR_MEMORY_ALLOC;
1000 if (!frames_hwctx->nb_surfaces)
1001 return MFX_ERR_UNSUPPORTED;
1007 return MFX_ERR_NONE;
1015 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
1016 mfxHDLPair *pair_src;
1018 if (frames_hwctx->nb_surfaces) {
1022 pair_src = (mfxHDLPair*)mid;
1025 pair_dst->first = pair_src->first;
1027 if (pair_src->second != (mfxMemId)MFX_INFINITE)
1028 pair_dst->second = pair_src->second;
1029 return MFX_ERR_NONE;
1033 AVBufferRef *device_ref,
const char *load_plugins,
1038 mfxSession parent_session = device_hwctx->session;
1039 void *loader = device_hwctx->loader;
1040 mfxHDL handle =
NULL;
1041 int hw_handle_supported = 0;
1046 mfxHandleType handle_type;
1050 err = MFXQueryIMPL(parent_session, &impl);
1051 if (err == MFX_ERR_NONE)
1052 err = MFXQueryVersion(parent_session, &ver);
1053 if (err != MFX_ERR_NONE)
1055 "Error querying the session attributes");
1058 handle_type = MFX_HANDLE_VA_DISPLAY;
1059 hw_handle_supported = 1;
1061 handle_type = MFX_HANDLE_D3D11_DEVICE;
1062 hw_handle_supported = 1;
1064 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1065 hw_handle_supported = 1;
1068 if (hw_handle_supported) {
1069 err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
1070 if (err != MFX_ERR_NONE) {
1072 "Error getting handle session");
1077 "from the session\n");
1086 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
1087 if (err != MFX_ERR_NONE)
1089 "Error setting a HW handle");
1093 err = MFXJoinSession(parent_session, session);
1094 if (err != MFX_ERR_NONE)
1096 "Error joining session");
1105 *psession = session;
1111 const char *load_plugins,
int opaque,
int gpu_copy)
1113 mfxFrameAllocator frame_allocator = {
1114 .pthis = qsv_frames_ctx,
1131 frames_ctx->
device_ref, load_plugins, gpu_copy);
1136 qsv_frames_ctx->
logctx = avctx;
1141 if (frames_hwctx->nb_surfaces) {
1144 if (!qsv_frames_ctx->
mids)
1146 qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
1149 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
1150 if (err != MFX_ERR_NONE)
1152 "Error setting a frame allocator");
1155 *psession = session;
1171 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
1178 mfxExtBuffer * param)
1182 for (
i = 0;
i <
frame->num_ext_params;
i++) {
1183 mfxExtBuffer *ext_buffer =
frame->ext_param[
i];
1185 if (ext_buffer->BufferId == param->BufferId) {
1193 frame->ext_param[
frame->num_ext_params] = param;
1194 frame->num_ext_params++;
1195 frame->surface.Data.NumExtParam =
frame->num_ext_params;
1198 "have enough space\n");