21 #include <mfx/mfxvideo.h>
22 #include <mfx/mfxplugin.h>
23 #include <mfx/mfxjpeg.h>
39 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
41 #if QSV_VERSION_ATLEAST(1, 12)
42 #include "mfx/mfxvp8.h"
50 #if QSV_VERSION_ATLEAST(1, 8)
52 return MFX_CODEC_HEVC;
56 return MFX_CODEC_MPEG2;
59 #if QSV_VERSION_ATLEAST(1, 12)
64 return MFX_CODEC_JPEG;
65 #if QSV_VERSION_ATLEAST(1, 19)
69 #if QSV_VERSION_ATLEAST(1, 34)
85 {MFX_IOPATTERN_IN_VIDEO_MEMORY,
"input is video memory surface" },
86 {MFX_IOPATTERN_IN_SYSTEM_MEMORY,
"input is system memory surface" },
87 {MFX_IOPATTERN_IN_OPAQUE_MEMORY,
"input is opaque memory surface" },
88 {MFX_IOPATTERN_OUT_VIDEO_MEMORY,
"output is video memory surface" },
89 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY,
"output is system memory surface" },
90 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
"output is opaque memory surface" },
94 const char *extra_string)
104 desc =
"unknown iopattern";
110 static const struct {
115 { MFX_ERR_NONE, 0,
"success" },
117 { MFX_ERR_NULL_PTR,
AVERROR(EINVAL),
"NULL pointer" },
118 { MFX_ERR_UNSUPPORTED,
AVERROR(ENOSYS),
"unsupported" },
119 { MFX_ERR_MEMORY_ALLOC,
AVERROR(ENOMEM),
"failed to allocate memory" },
120 { MFX_ERR_NOT_ENOUGH_BUFFER,
AVERROR(ENOMEM),
"insufficient input/output buffer" },
121 { MFX_ERR_INVALID_HANDLE,
AVERROR(EINVAL),
"invalid handle" },
122 { MFX_ERR_LOCK_MEMORY,
AVERROR(EIO),
"failed to lock the memory block" },
123 { MFX_ERR_NOT_INITIALIZED,
AVERROR_BUG,
"not initialized" },
124 { MFX_ERR_NOT_FOUND,
AVERROR(ENOSYS),
"specified object was not found" },
128 { MFX_ERR_MORE_SURFACE,
AVERROR_UNKNOWN,
"expect more surface at output" },
129 { MFX_ERR_MORE_BITSTREAM,
AVERROR_UNKNOWN,
"expect more bitstream at output" },
131 { MFX_ERR_DEVICE_LOST,
AVERROR(EIO),
"device lost" },
132 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
AVERROR(EINVAL),
"incompatible video parameters" },
133 { MFX_ERR_INVALID_VIDEO_PARAM,
AVERROR(EINVAL),
"invalid video parameters" },
134 { MFX_ERR_UNDEFINED_BEHAVIOR,
AVERROR_BUG,
"undefined behavior" },
135 { MFX_ERR_DEVICE_FAILED,
AVERROR(EIO),
"device failed" },
136 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
137 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
139 { MFX_WRN_IN_EXECUTION, 0,
"operation in execution" },
140 { MFX_WRN_DEVICE_BUSY, 0,
"device busy" },
141 { MFX_WRN_VIDEO_PARAM_CHANGED, 0,
"video parameters changed" },
142 { MFX_WRN_PARTIAL_ACCELERATION, 0,
"partial acceleration" },
143 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0,
"incompatible video parameters" },
144 { MFX_WRN_VALUE_NOT_CHANGED, 0,
"value is saturated" },
145 { MFX_WRN_OUT_OF_RANGE, 0,
"value out of range" },
146 { MFX_WRN_FILTER_SKIPPED, 0,
"filter skipped" },
147 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0,
"incompatible audio parameters" },
164 *
desc =
"unknown error";
169 const char *error_string)
178 const char *warning_string)
194 #if QSV_VERSION_ATLEAST(1, 27)
208 *
fourcc = MFX_FOURCC_NV12;
212 *
fourcc = MFX_FOURCC_P010;
217 *
fourcc = MFX_FOURCC_YUY2;
219 #if QSV_VERSION_ATLEAST(1, 27)
222 *
fourcc = MFX_FOURCC_Y210;
234 for (
i = 0;
i <
ctx->nb_mids;
i++) {
236 mfxHDLPair *pair = (mfxHDLPair*)
frame->surface.Data.MemId;
247 switch (mfx_pic_struct & 0xF) {
248 case MFX_PICSTRUCT_PROGRESSIVE:
251 case MFX_PICSTRUCT_FIELD_TFF:
254 case MFX_PICSTRUCT_FIELD_BFF:
265 switch (mfx_pic_type & 0x7) {
266 case MFX_FRAMETYPE_I:
267 if (mfx_pic_type & MFX_FRAMETYPE_S)
272 case MFX_FRAMETYPE_B:
275 case MFX_FRAMETYPE_P:
276 if (mfx_pic_type & MFX_FRAMETYPE_S)
281 case MFX_FRAMETYPE_UNKNOWN:
294 if (!load_plugins || !*load_plugins)
297 while (*load_plugins) {
305 if (strlen(plugin) != 2 *
sizeof(
uid.Data)) {
308 goto load_plugin_fail;
311 for (
i = 0;
i <
sizeof(
uid.Data);
i++) {
312 err = sscanf(plugin + 2 *
i,
"%2hhx",
uid.Data +
i);
316 goto load_plugin_fail;
321 ret = MFXVideoUSER_Load(session, &
uid, 1);
324 snprintf(errorbuf,
sizeof(errorbuf),
325 "Could not load the requested plugin '%s'", plugin);
327 goto load_plugin_fail;
345 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
352 av_dict_set(&child_device_opts,
"kernel_driver",
"i915", 0);
353 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
362 hwctx = qs->va_device_ctx->hwctx;
365 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->
display);
373 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
376 const char *load_plugins,
int gpu_copy)
379 mfxIMPL impl = MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11;
381 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
384 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
389 #if QSV_VERSION_ATLEAST(1, 16)
390 init_par.GPUCopy = gpu_copy;
392 init_par.Implementation = impl;
393 init_par.Version = ver;
397 "Error initializing an internal MFX session");
399 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
400 ret = ff_qsv_set_display_handle(avctx, qs);
411 MFXQueryIMPL(qs->
session, &impl);
413 switch (MFX_IMPL_BASETYPE(impl)) {
414 case MFX_IMPL_SOFTWARE:
417 case MFX_IMPL_HARDWARE:
418 case MFX_IMPL_HARDWARE2:
419 case MFX_IMPL_HARDWARE3:
420 case MFX_IMPL_HARDWARE4:
421 desc =
"hardware accelerated";
428 "Initialized an internal MFX session using %s implementation\n",
445 int nb_surfaces = frames_hwctx->nb_surfaces;
455 mids =
av_calloc(nb_surfaces,
sizeof(*mids));
469 for (
i = 0;
i < nb_surfaces;
i++) {
471 mid->
handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[
i].Data.MemId;
484 int nb_surfaces = frames_hwctx->nb_surfaces;
490 resp->mids =
av_calloc(nb_surfaces + 2,
sizeof(*resp->mids));
494 for (
i = 0;
i < nb_surfaces;
i++)
495 resp->mids[
i] = &mids[
i];
496 resp->NumFrameActual = nb_surfaces;
498 resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
499 if (!resp->mids[resp->NumFrameActual]) {
504 resp->mids[resp->NumFrameActual + 1] =
av_buffer_ref(mids_buf);
505 if (!resp->mids[resp->NumFrameActual + 1]) {
515 mfxFrameAllocResponse *resp)
522 if (!(req->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET |
523 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ||
524 !(req->Type & (MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_ENCODE)))
525 return MFX_ERR_UNSUPPORTED;
527 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
531 mfxFrameInfo *
i = &req->Info;
532 mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info;
534 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
535 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
537 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
538 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
539 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
540 return MFX_ERR_UNSUPPORTED;
546 "Error filling an external frame allocation request\n");
547 return MFX_ERR_MEMORY_ALLOC;
549 }
else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
552 mfxFrameInfo *
i = &req->Info;
560 return MFX_ERR_MEMORY_ALLOC;
563 frames_hwctx = frames_ctx->hwctx;
567 frames_ctx->width =
i->Width;
568 frames_ctx->height =
i->Height;
569 frames_ctx->initial_pool_size = req->NumFrameSuggested;
571 frames_hwctx->frame_type = req->Type;
576 "Error initializing a frames context for an internal frame "
577 "allocation request\n");
579 return MFX_ERR_MEMORY_ALLOC;
585 return MFX_ERR_MEMORY_ALLOC;
593 "Error filling an internal frame allocation request\n");
594 return MFX_ERR_MEMORY_ALLOC;
597 return MFX_ERR_UNSUPPORTED;
619 return MFX_ERR_UNDEFINED_BEHAVIOR;
624 return MFX_ERR_MEMORY_ALLOC;
647 qsv_mid->
surf.Info = hw_frames_hwctx->surfaces[0].Info;
665 return MFX_ERR_MEMORY_ALLOC;
681 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
682 mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->
handle_pair;
684 pair_dst->first = pair_src->first;
686 if (pair_src->second != (mfxMemId)MFX_INFINITE)
687 pair_dst->second = pair_src->second;
697 mfxSession parent_session = device_hwctx->session;
698 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
699 mfxHDL handle =
NULL;
700 int hw_handle_supported = 0;
705 mfxHandleType handle_type;
709 err = MFXQueryIMPL(parent_session, &impl);
710 if (err == MFX_ERR_NONE)
711 err = MFXQueryVersion(parent_session, &ver);
712 if (err != MFX_ERR_NONE)
714 "Error querying the session attributes");
717 handle_type = MFX_HANDLE_VA_DISPLAY;
718 hw_handle_supported = 1;
720 handle_type = MFX_HANDLE_D3D11_DEVICE;
721 hw_handle_supported = 1;
723 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
724 hw_handle_supported = 1;
727 if (hw_handle_supported) {
728 err = MFXVideoCORE_GetHandle(parent_session, handle_type, &handle);
729 if (err != MFX_ERR_NONE) {
731 "Error getting handle session");
736 "from the session\n");
739 #if QSV_VERSION_ATLEAST(1, 16)
740 init_par.GPUCopy = gpu_copy;
742 init_par.Implementation = impl;
743 init_par.Version = ver;
744 err = MFXInitEx(init_par, &session);
745 if (err != MFX_ERR_NONE)
747 "Error initializing a child MFX session");
750 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
751 if (err != MFX_ERR_NONE)
753 "Error setting a HW handle");
757 err = MFXJoinSession(parent_session, session);
758 if (err != MFX_ERR_NONE)
760 "Error joining session");
775 const char *load_plugins,
int opaque,
int gpu_copy)
777 mfxFrameAllocator frame_allocator = {
778 .pthis = qsv_frames_ctx,
795 frames_ctx->
device_ref, load_plugins, gpu_copy);
800 qsv_frames_ctx->
logctx = avctx;
808 qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
810 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
811 if (err != MFX_ERR_NONE)
813 "Error setting a frame allocator");
826 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE