1 /*
2 * Intel MediaSDK QSV encoder/decoder shared code
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <mfxvideo.h>
22 #include <mfxjpeg.h>
23 #include <mfxvp8.h>
24
25 #include <stdio.h>
26 #include <string.h>
27
35
39
40 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
41 #define QSV_HAVE_USER_PLUGIN !QSV_ONEVPL
42 #define QSV_HAVE_AUDIO !QSV_ONEVPL
43
44 #if QSV_HAVE_USER_PLUGIN
45 #include <mfxplugin.h>
46 #endif
47
48 #if QSV_ONEVPL
49 #include <mfxdispatcher.h>
50 #else
51 #define MFXUnload(a) do { } while(0)
52 #endif
53
55 {
58 return MFX_CODEC_AVC;
60 return MFX_CODEC_HEVC;
63 return MFX_CODEC_MPEG2;
65 return MFX_CODEC_VC1;
67 return MFX_CODEC_VP8;
69 return MFX_CODEC_JPEG;
71 return MFX_CODEC_VP9;
72 #if QSV_VERSION_ATLEAST(1, 34)
74 return MFX_CODEC_AV1;
75 #endif
76 #if QSV_VERSION_ATLEAST(2, 11)
78 return MFX_CODEC_VVC;
79 #endif
80
81 default:
82 break;
83 }
84
86 }
87
88 static const struct {
92 {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
93 {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
94 #if QSV_HAVE_OPAQUE
95 {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
96 #endif
97 {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
98 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
99 #if QSV_HAVE_OPAQUE
100 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
101 #endif
102 };
103
105 const char *extra_string)
106 {
108
112 }
113 }
115 desc =
"unknown iopattern";
116
118 return 0;
119 }
120
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" },
136 /* the following 3 errors should always be handled explicitly, so those "mappings"
137 * are for completeness only */
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" },
147 #if QSV_HAVE_AUDIO
148 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
149 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
150 #endif
151 { MFX_ERR_GPU_HANG,
AVERROR(EIO),
"GPU Hang" },
152 { MFX_ERR_REALLOC_SURFACE,
AVERROR_UNKNOWN,
"need bigger surface for output" },
153
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" },
162 #if QSV_HAVE_AUDIO
163 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
164 #endif
165
166 #if QSV_VERSION_ATLEAST(1, 31)
167 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
168 #endif
169 };
170
171 /**
172 * Convert a libmfx error code into an FFmpeg error code.
173 */
175 {
182 }
183 }
185 *
desc =
"unknown error";
187 }
188
190 const char *error_string)
191 {
196 }
197
199 const char *warning_string)
200 {
205 }
206
208 {
219 #if QSV_VERSION_ATLEAST(1, 31)
223 #endif
224 }
226 }
227
229 {
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;
281 #endif
282 default:
284 }
285 }
286
288 {
289 switch (
frame->format) {
293 surface->Data.Y =
frame->data[0];
294 surface->Data.UV =
frame->data[1];
295 /* The SDK checks Data.V when using system memory for VP9 encoding */
296 surface->Data.V = surface->Data.UV + 1;
297 break;
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;
304 break;
306 surface->Data.Y =
frame->data[0];
307 surface->Data.U =
frame->data[0] + 1;
308 surface->Data.V =
frame->data[0] + 3;
309 break;
310
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;
316 break;
317
319 surface->Data.V =
frame->data[0];
320 surface->Data.U =
frame->data[0] + 1;
321 surface->Data.Y =
frame->data[0] + 2;
322 // Only set Data.A to a valid address, the SDK doesn't
323 // use the value from the frame.
324 surface->Data.A =
frame->data[0] + 3;
325 break;
326
328 surface->Data.U =
frame->data[0];
329 break;
330
332 surface->Data.U =
frame->data[0];
333 surface->Data.Y =
frame->data[0] + 2;
334 surface->Data.V =
frame->data[0] + 4;
335 // Only set Data.A to a valid address, the SDK doesn't
336 // use the value from the frame.
337 surface->Data.A =
frame->data[0] + 6;
338 break;
339
340 default:
342 }
343 surface->Data.PitchLow =
frame->linesize[0];
344
345 return 0;
346 }
347
349 {
351 for (
i = 0;
i <
ctx->nb_mids;
i++) {
353 mfxHDLPair *pair = (mfxHDLPair*)
frame->surface.Data.MemId;
357 }
359 }
360
362 {
364 switch (mfx_pic_struct & 0xF) {
365 case MFX_PICSTRUCT_PROGRESSIVE:
367 break;
368 case MFX_PICSTRUCT_FIELD_TFF:
370 break;
371 case MFX_PICSTRUCT_FIELD_BFF:
373 break;
374 }
375
377 }
378
380 {
382 switch (mfx_pic_type & 0x7) {
383 case MFX_FRAMETYPE_I:
384 if (mfx_pic_type & MFX_FRAMETYPE_S)
386 else
388 break;
389 case MFX_FRAMETYPE_B:
391 break;
392 case MFX_FRAMETYPE_P:
393 if (mfx_pic_type & MFX_FRAMETYPE_S)
395 else
397 break;
398 case MFX_FRAMETYPE_UNKNOWN:
400 break;
401 default:
403 }
404
406 }
407
409 void *logctx)
410 {
411 #if QSV_HAVE_USER_PLUGIN
412 if (!load_plugins || !*load_plugins)
413 return 0;
414
415 while (*load_plugins) {
419
421 if (!plugin)
423 if (strlen(plugin) != 2 *
sizeof(
uid.Data)) {
426 goto load_plugin_fail;
427 }
428
429 for (
i = 0;
i <
sizeof(
uid.Data);
i++) {
430 err = sscanf(plugin + 2 *
i,
"%2hhx",
uid.Data +
i);
431 if (err != 1) {
434 goto load_plugin_fail;
435 }
436
437 }
438
439 ret = MFXVideoUSER_Load(session, &
uid, 1);
441 char errorbuf[128];
442 snprintf(errorbuf,
sizeof(errorbuf),
443 "Could not load the requested plugin '%s'", plugin);
445 goto load_plugin_fail;
446 }
447
448 if (*load_plugins)
449 load_plugins++;
450 load_plugin_fail:
452 if (err < 0)
453 return err;
454 }
455 #endif
456
457 return 0;
458
459 }
460
461 //This code is only required for Linux since a display handle is required.
462 //For Windows the session is complete and ready to use.
463
464 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
466 {
470
471 av_dict_set(&child_device_opts,
"vendor_id",
"0x8086", 0);
472 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
473
479 } else {
481 hwctx = qs->va_device_ctx->hwctx;
482
484 (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->
display);
487 }
488 }
489
490 return 0;
491 }
492 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
493
494 #if QSV_ONEVPL
496 mfxIMPL implementation,
497 mfxVersion *pver,
498 void **ploader)
499 {
500 mfxStatus sts;
501 mfxLoader loader =
NULL;
502 mfxConfig cfg;
503 mfxVariant impl_value = {0};
504
505 loader = MFXLoad();
506 if (!loader) {
509 }
510
511 /* Create configurations for implementation */
512 cfg = MFXCreateConfig(loader);
513 if (!cfg) {
516 }
517
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);
527 }
528
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",
533 impl_value);
534 if (sts != MFX_ERR_NONE) {
536 "property: %d\n", sts);
538 }
539
540 *ploader = loader;
541
542 return 0;
543
545 if (loader)
547
550 }
551
552 static int qsv_create_mfx_session_from_loader(
void *
ctx, mfxLoader loader, mfxSession *psession)
553 {
554 mfxStatus sts;
555 mfxSession session =
NULL;
556 uint32_t impl_idx = 0;
557
558 while (1) {
559 /* Enumerate all implementations */
560 mfxImplDescription *impl_desc;
561
562 sts = MFXEnumImplementations(loader, impl_idx,
563 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
564 (mfxHDL *)&impl_desc);
565 /* Failed to find an available implementation */
566 if (sts == MFX_ERR_NOT_FOUND)
567 break;
568 else if (sts != MFX_ERR_NONE) {
569 impl_idx++;
570 continue;
571 }
572
573 sts = MFXCreateSession(loader, impl_idx, &session);
574 MFXDispReleaseImplDescription(loader, impl_desc);
575 if (sts == MFX_ERR_NONE)
576 break;
577
578 impl_idx++;
579 }
580
581 if (sts != MFX_ERR_NONE) {
584 }
585
586 *psession = session;
587
588 return 0;
589
591 if (session)
592 MFXClose(session);
593
596 }
597
599 mfxIMPL implementation,
600 mfxVersion *pver,
601 int gpu_copy,
602 mfxSession *psession,
603 void **ploader)
604 {
605 mfxLoader loader =
NULL;
606
607 /* Don't create a new MFX loader if the input loader is valid */
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);
613
614 if (qsv_new_mfx_loader(avctx, implementation, pver, (void **)&loader))
616
618 } else {
620 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
621
622 loader = *ploader;
623 }
624
625 if (qsv_create_mfx_session_from_loader(avctx, loader, psession))
627
628 if (!*ploader)
629 *ploader = loader;
630
631 return 0;
632
634 if (!*ploader && loader)
636
638 }
639
640 #else
641
643 mfxIMPL implementation,
644 mfxVersion *pver,
645 int gpu_copy,
646 mfxSession *psession,
647 void **ploader)
648 {
649 mfxInitParam init_par = { MFX_IMPL_AUTO_ANY };
650 mfxSession session =
NULL;
651 mfxStatus sts;
652
654 "Use Intel(R) Media SDK to create MFX session, the required "
655 "implementation version is %d.%d\n",
656 pver->Major, pver->Minor);
657
660
661 init_par.GPUCopy = gpu_copy;
662 init_par.Implementation = implementation;
663 init_par.Version = *pver;
664 sts = MFXInitEx(init_par, &session);
665 if (sts < 0)
667 "Error initializing a MFX session");
668 else if (sts > 0) {
670 "Warning in MFX initialization");
672 }
673
674 *psession = session;
675
676 return 0;
677 }
678
679 #endif
680
682 const char *load_plugins, int gpu_copy)
683 {
684 mfxIMPL impls[] = {
685 #if CONFIG_D3D11VA
686 MFX_IMPL_AUTO_ANY | MFX_IMPL_VIA_D3D11,
687 #endif
688 MFX_IMPL_AUTO_ANY
689 };
690 mfxIMPL impl;
692
695
699
701 break;
702
705 else
707 "supported, try next mfx implementation.\n");
708 }
709
710 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
711 ret = ff_qsv_set_display_handle(avctx, qs);
714 #endif
715
720 }
721
723 if (
ret != MFX_ERR_NONE)
725 "Error querying the session attributes");
726
727 switch (MFX_IMPL_BASETYPE(impl)) {
728 case MFX_IMPL_SOFTWARE:
730 break;
731 case MFX_IMPL_HARDWARE:
732 case MFX_IMPL_HARDWARE2:
733 case MFX_IMPL_HARDWARE3:
734 case MFX_IMPL_HARDWARE4:
735 desc =
"hardware accelerated";
736 break;
737 default:
739 }
740
742 "Initialized an internal MFX session using %s implementation\n",
744
745 return 0;
746 }
747
749 {
752 }
753
755 {
758 int nb_surfaces = frames_hwctx->nb_surfaces;
759
763
765 if (!hw_frames_ref1)
767
770 if (!mids) {
773 }
774
775 for (
i = 0;
i < nb_surfaces;
i++) {
777 mid->
handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[
i].Data.MemId;
779 }
780
781 return mids;
782 }
783
786 {
789 int nb_surfaces = frames_hwctx->nb_surfaces;
791
792 // the allocated size of the array is two larger than the number of
793 // surfaces, we store the references to the frames context and the
794 // QSVMid array there
795 resp->mids =
av_calloc(nb_surfaces + 2,
sizeof(*resp->mids));
796 if (!resp->mids)
798
799 for (
i = 0;
i < nb_surfaces;
i++)
800 resp->mids[
i] = &mids[
i];
801 resp->NumFrameActual = nb_surfaces;
802
803 resp->mids[resp->NumFrameActual] = (mfxMemId)
av_buffer_ref(hw_frames_ref);
804 if (!resp->mids[resp->NumFrameActual]) {
807 }
808
810
811 return 0;
812 }
813
815 mfxFrameAllocResponse *resp)
816 {
819
820 /* this should only be called from an encoder or decoder and
821 * only allocates video memory frames */
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;
826
827 if (req->Type & MFX_MEMTYPE_EXTERNAL_FRAME) {
828 /* external frames -- fill from the caller-supplied frames context */
831 mfxFrameInfo *
i = &req->Info;
832 mfxFrameInfo *i1;
833
834 if (!frames_hwctx->nb_surfaces) {
836 "Dynamic frame pools, no frame is pre-allocated\n");
837
838 return MFX_ERR_NONE;
839 }
840
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;
849 }
850
854 "Error filling an external frame allocation request\n");
855 return MFX_ERR_MEMORY_ALLOC;
856 }
857 } else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) {
858 /* internal frames -- allocate a new hw frames context */
861 mfxFrameInfo *
i = &req->Info;
862
867
868 if (!ext_frames_hwctx->nb_surfaces)
869 return MFX_ERR_UNSUPPORTED;
870
872 if (!frames_ref)
873 return MFX_ERR_MEMORY_ALLOC;
874
876 frames_hwctx = frames_ctx->hwctx;
877
880 frames_ctx->width =
i->Width;
881 frames_ctx->height =
i->Height;
882 frames_ctx->initial_pool_size = req->NumFrameSuggested;
883
884 frames_hwctx->frame_type = req->Type;
885
889 "Error initializing a frames context for an internal frame "
890 "allocation request\n");
892 return MFX_ERR_MEMORY_ALLOC;
893 }
894
896 if (!mids) {
898 return MFX_ERR_MEMORY_ALLOC;
899 }
900
906 "Error filling an internal frame allocation request\n");
907 return MFX_ERR_MEMORY_ALLOC;
908 }
909 } else {
910 return MFX_ERR_UNSUPPORTED;
911 }
912
913 return MFX_ERR_NONE;
914 }
915
917 {
918 if (!resp->mids)
919 return MFX_ERR_NONE;
920
924 return MFX_ERR_NONE;
925 }
926
928 {
936
937 if (!frames_hwctx->nb_surfaces)
938 return MFX_ERR_UNSUPPORTED;
939
940 qsv_mid = mid;
942 hw_frames_hwctx = hw_frames_ctx->hwctx;
943 if (qsv_mid->locked_frame)
944 return MFX_ERR_UNDEFINED_BEHAVIOR;
945
946 /* Allocate a system memory frame that will hold the mapped data. */
948 if (!qsv_mid->locked_frame)
949 return MFX_ERR_MEMORY_ALLOC;
950 qsv_mid->locked_frame->format = hw_frames_ctx->sw_format;
951
952 /* wrap the provided handle in a hwaccel AVFrame */
954 if (!qsv_mid->hw_frame)
956
957 qsv_mid->hw_frame->data[3] = (uint8_t*)&qsv_mid->surf;
959
960 // doesn't really matter what buffer is used here
962 if (!qsv_mid->hw_frame->buf[0])
964
965 qsv_mid->hw_frame->width = hw_frames_ctx->width;
966 qsv_mid->hw_frame->height = hw_frames_ctx->height;
967
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)
971
972 qsv_mid->surf.Info = hw_frames_hwctx->surfaces[0].Info;
973 qsv_mid->surf.Data.MemId = qsv_mid->handle_pair;
974
975 /* map the data to the system memory */
980
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;
985
986 return MFX_ERR_NONE;
990 return MFX_ERR_MEMORY_ALLOC;
991 }
992
994 {
999
1000 if (!frames_hwctx->nb_surfaces)
1001 return MFX_ERR_UNSUPPORTED;
1002
1003 qsv_mid = mid;
1006
1007 return MFX_ERR_NONE;
1008 }
1009
1011 {
1015 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
1016 mfxHDLPair *pair_src;
1017
1018 if (frames_hwctx->nb_surfaces) {
1021 } else {
1022 pair_src = (mfxHDLPair*)mid;
1023 }
1024
1025 pair_dst->first = pair_src->first;
1026
1027 if (pair_src->second != (mfxMemId)MFX_INFINITE)
1028 pair_dst->second = pair_src->second;
1029 return MFX_ERR_NONE;
1030 }
1031
1033 AVBufferRef *device_ref,
const char *load_plugins,
1034 int gpu_copy)
1035 {
1038 mfxSession parent_session = device_hwctx->session;
1039 void *loader = device_hwctx->loader;
1040 mfxHDL handle =
NULL;
1041 int hw_handle_supported = 0;
1042
1043 mfxSession session;
1044 mfxVersion ver;
1045 mfxIMPL impl;
1046 mfxHandleType handle_type;
1047 mfxStatus err;
1049
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");
1056
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;
1066 }
1067
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");
1073 }
1074 }
1075 if (!handle) {
1077 "from the session\n");
1078 }
1079
1081 &loader);
1084
1085 if (handle) {
1086 err = MFXVideoCORE_SetHandle(session, handle_type, handle);
1087 if (err != MFX_ERR_NONE)
1089 "Error setting a HW handle");
1090 }
1091
1093 err = MFXJoinSession(parent_session, session);
1094 if (err != MFX_ERR_NONE)
1096 "Error joining session");
1097 }
1098
1103 }
1104
1105 *psession = session;
1106 return 0;
1107 }
1108
1111 const char *load_plugins, int opaque, int gpu_copy)
1112 {
1113 mfxFrameAllocator frame_allocator = {
1114 .pthis = qsv_frames_ctx,
1120 };
1121
1124
1125 mfxSession session;
1126 mfxStatus err;
1127
1129
1131 frames_ctx->
device_ref, load_plugins, gpu_copy);
1134
1135 if (!opaque) {
1136 qsv_frames_ctx->
logctx = avctx;
1139
1140 /* allocate the memory ids for the external frames */
1141 if (frames_hwctx->nb_surfaces) {
1144 if (!qsv_frames_ctx->
mids)
1146 qsv_frames_ctx->
nb_mids = frames_hwctx->nb_surfaces;
1147 }
1148
1149 err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator);
1150 if (err != MFX_ERR_NONE)
1152 "Error setting a frame allocator");
1153 }
1154
1155 *psession = session;
1156 return 0;
1157 }
1158
1160 {
1164 }
1165
1169 }
1170
1171 #ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
1173 #endif
1174 return 0;
1175 }
1176
1178 mfxExtBuffer * param)
1179 {
1181
1182 for (
i = 0;
i <
frame->num_ext_params;
i++) {
1183 mfxExtBuffer *ext_buffer =
frame->ext_param[
i];
1184
1185 if (ext_buffer->BufferId == param->BufferId) {
1187 "added\n");
1188 return;
1189 }
1190 }
1191
1193 frame->ext_param[
frame->num_ext_params] = param;
1194 frame->num_ext_params++;
1195 frame->surface.Data.NumExtParam =
frame->num_ext_params;
1196 } else {
1198 "have enough space\n");
1199 }
1200
1201
1202 }