1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * Intel Quick Sync Video VPP base function
22 */
23
29
33
34 #if QSV_ONEVPL
35 #include <mfxdispatcher.h>
36 #else
37 #define MFXUnload(a) do { } while(0)
38 #endif
39
40 #define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
41 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
42 #if QSV_HAVE_OPAQUE
43 #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
44 #endif
45 #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
46 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
47
48 #define QSV_HAVE_AUDIO !QSV_ONEVPL
49
51
56
57 static const struct {
61 {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
62 {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
63 #if QSV_HAVE_OPAQUE
64 {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
65 #endif
66 {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
67 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
68 #if QSV_HAVE_OPAQUE
69 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
70 #endif
71 };
72
74 const char *extra_string)
75 {
77
81 }
82 }
84 desc =
"unknown iopattern";
85
87 return 0;
88 }
89
90 static const struct {
95 { MFX_ERR_NONE, 0, "success" },
97 { MFX_ERR_NULL_PTR,
AVERROR(EINVAL),
"NULL pointer" },
98 { MFX_ERR_UNSUPPORTED,
AVERROR(ENOSYS),
"unsupported" },
99 { MFX_ERR_MEMORY_ALLOC,
AVERROR(ENOMEM),
"failed to allocate memory" },
100 { MFX_ERR_NOT_ENOUGH_BUFFER,
AVERROR(ENOMEM),
"insufficient input/output buffer" },
101 { MFX_ERR_INVALID_HANDLE,
AVERROR(EINVAL),
"invalid handle" },
102 { MFX_ERR_LOCK_MEMORY,
AVERROR(EIO),
"failed to lock the memory block" },
103 { MFX_ERR_NOT_INITIALIZED,
AVERROR_BUG,
"not initialized" },
104 { MFX_ERR_NOT_FOUND,
AVERROR(ENOSYS),
"specified object was not found" },
105 /* the following 3 errors should always be handled explicitly, so those "mappings"
106 * are for completeness only */
108 { MFX_ERR_MORE_SURFACE,
AVERROR_UNKNOWN,
"expect more surface at output" },
109 { MFX_ERR_MORE_BITSTREAM,
AVERROR_UNKNOWN,
"expect more bitstream at output" },
111 { MFX_ERR_DEVICE_LOST,
AVERROR(EIO),
"device lost" },
112 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
AVERROR(EINVAL),
"incompatible video parameters" },
113 { MFX_ERR_INVALID_VIDEO_PARAM,
AVERROR(EINVAL),
"invalid video parameters" },
114 { MFX_ERR_UNDEFINED_BEHAVIOR,
AVERROR_BUG,
"undefined behavior" },
115 { MFX_ERR_DEVICE_FAILED,
AVERROR(EIO),
"device failed" },
116 #if QSV_HAVE_AUDIO
117 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
118 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
119 #endif
120 { MFX_ERR_GPU_HANG,
AVERROR(EIO),
"GPU Hang" },
121 { MFX_ERR_REALLOC_SURFACE,
AVERROR_UNKNOWN,
"need bigger surface for output" },
122
123 { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
124 { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
125 { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
126 { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
127 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
128 { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
129 { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
130 { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
131 #if QSV_HAVE_AUDIO
132 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
133 #endif
134
135 #if QSV_VERSION_ATLEAST(1, 31)
136 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
137 #endif
138 };
139
141 {
148 }
149 }
151 *
desc =
"unknown error";
153 }
154
156 const char *error_string)
157 {
163 }
164
166 const char *warning_string)
167 {
173 }
174
175 /* functions for frameAlloc */
176 static mfxStatus
frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
177 mfxFrameAllocResponse *resp)
178 {
181
182 if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
183 !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
184 !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
185 return MFX_ERR_UNSUPPORTED;
186
187 if (req->Type & MFX_MEMTYPE_FROM_VPPIN) {
188 resp->mids =
av_mallocz(
s->nb_surface_ptrs_in *
sizeof(*resp->mids));
189 if (!resp->mids)
191
192 for (
i = 0;
i <
s->nb_surface_ptrs_in;
i++)
193 resp->mids[
i] =
s->surface_ptrs_in[
i]->Data.MemId;
194
195 resp->NumFrameActual =
s->nb_surface_ptrs_in;
196 } else {
197 resp->mids =
av_mallocz(
s->nb_surface_ptrs_out *
sizeof(*resp->mids));
198 if (!resp->mids)
200
201 for (
i = 0;
i <
s->nb_surface_ptrs_out;
i++)
202 resp->mids[
i] =
s->surface_ptrs_out[
i]->Data.MemId;
203
204 resp->NumFrameActual =
s->nb_surface_ptrs_out;
205 }
206
207 return MFX_ERR_NONE;
208 }
209
210 static mfxStatus
frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
211 {
213 return MFX_ERR_NONE;
214 }
215
216 static mfxStatus
frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
217 {
218 return MFX_ERR_UNSUPPORTED;
219 }
220
221 static mfxStatus
frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
222 {
223 return MFX_ERR_UNSUPPORTED;
224 }
225
227 {
228 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
229 mfxHDLPair *pair_src = (mfxHDLPair*)mid;
230
231 pair_dst->first = pair_src->first;
232
233 if (pair_src->second != (mfxMemId)MFX_INFINITE)
234 pair_dst->second = pair_src->second;
235 return MFX_ERR_NONE;
236 }
237
239 {
242 return MFX_FOURCC_YV12;
244 return MFX_FOURCC_NV12;
246 return MFX_FOURCC_YUY2;
248 return MFX_FOURCC_RGB4;
250 return MFX_FOURCC_P010;
251 #if CONFIG_VAAPI
253 return MFX_FOURCC_UYVY;
254 #endif
255 }
256
257 return MFX_FOURCC_NV12;
258 }
259
261 {
262 switch (
frame->format) {
265 surface->Data.Y =
frame->data[0];
266 surface->Data.UV =
frame->data[1];
267 break;
269 surface->Data.Y =
frame->data[0];
270 surface->Data.U =
frame->data[1];
271 surface->Data.V =
frame->data[2];
272 break;
274 surface->Data.Y =
frame->data[0];
275 surface->Data.U =
frame->data[0] + 1;
276 surface->Data.V =
frame->data[0] + 3;
277 break;
279 surface->Data.B =
frame->data[0];
280 surface->Data.G =
frame->data[0] + 1;
281 surface->Data.R =
frame->data[0] + 2;
282 surface->Data.A =
frame->data[0] + 3;
283 break;
285 surface->Data.Y =
frame->data[0] + 1;
286 surface->Data.U =
frame->data[0];
287 surface->Data.V =
frame->data[0] + 2;
288 break;
289 default:
290 return MFX_ERR_UNSUPPORTED;
291 }
292 surface->Data.Pitch =
frame->linesize[0];
293
294 return 0;
295 }
296
297 /* fill the surface info */
299 {
305
309
311 frames_hwctx = frames_ctx->
hwctx;
313 } else {
318
319 frameinfo->CropX = 0;
320 frameinfo->CropY = 0;
323 frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
325 frameinfo->BitDepthLuma =
desc->comp[0].depth;
326 frameinfo->BitDepthChroma =
desc->comp[0].depth;
327 frameinfo->Shift =
desc->comp[0].depth > 8;
328 if (
desc->log2_chroma_w &&
desc->log2_chroma_h)
329 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
330 else if (
desc->log2_chroma_w)
331 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
332 else
333 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
334 }
335
336 frameinfo->CropW =
link->w;
337 frameinfo->CropH =
link->h;
340
341 /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
342 * init will fail */
343 if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
344 frameinfo->FrameRateExtN = 25;
345 frameinfo->FrameRateExtD = 1;
346 }
347
350
351 return 0;
352 }
353
355 {
357 /* list->queued==1 means the frame is not cached in VPP
358 * process any more, it can be released to pool. */
359 if ((
list->queued == 1) && !
list->surface.Data.Locked) {
362 }
364 }
365 }
366
368 {
371
373 *
list = (*list)->next;
376 }
377 }
378
380 {
382
386 break;
387 }
388 }
389
395 }
399 }
400
402 }
403
404 /* get the input surface */
406 {
409
411
413 if (!qsv_frame)
415
416 /* Turn AVFrame into mfxFrameSurface1.
417 * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
418 * mfxFrameSurface1 is stored in AVFrame->data[3];
419 * for system memory mode, raw video data is stored in
420 * AVFrame, we should map it into mfxFrameSurface1.
421 */
426 }
429 } else {
430 /* make a copy if the input is not padded as libmfx requires */
435 if (!qsv_frame->
frame)
437
440
444 }
445 } else
447
452 }
453 }
454
458
459 qsv_frame->
surface.Info.PicStruct =
462 MFX_PICSTRUCT_FIELD_BFF);
464 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
466 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
468 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
469
470 return qsv_frame;
471 }
472
473 /* get the output surface */
475 {
480
482
484 if (!out_frame)
486
487 /* For video memory, get a hw frame;
488 * For system memory, get a sw frame and map it into a mfx_surface. */
491 if (!out_frame->
frame)
493
498 }
499
501 } else {
502 /* Get a frame with aligned dimensions.
503 * Libmfx need system memory being 128x64 aligned */
507 if (!out_frame->
frame)
509
514 }
515
518 else
520
523 out_frame->
surface.Info =
s->vpp_param.vpp.Out;
524
525 for (
int i = 0;
i <
s->vpp_param.NumExtParam;
i++) {
526 mfxExtBuffer *extbuf =
s->vpp_param.ExtParam[
i];
527
528 if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) {
529 #if FF_API_INTERLACED_FRAME
533 #endif
535 break;
536 }
537 }
538
539 out_frame->
surface.Info.PicStruct =
542 MFX_PICSTRUCT_FIELD_BFF);
543
544 return out_frame;
545 }
546
547 /* create the QSV session */
549 {
556
560 mfxHDL handle;
561 mfxHandleType handle_type;
562 mfxVersion ver;
563 mfxIMPL impl;
565
568
570 in_frames_hwctx = frames_ctx->
hwctx;
571
573
575 sizeof(*
s->surface_ptrs_in));
576 if (!
s->surface_ptrs_in)
578
580 s->surface_ptrs_in[
i] = in_frames_hwctx->
surfaces +
i;
581
585 s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
586 } else {
589 }
590
592 device_hwctx = device_ctx->
hwctx;
593
594 /* extract the properties of the "master" session given to us */
595 ret = MFXQueryIMPL(device_hwctx->
session, &impl);
596 if (
ret == MFX_ERR_NONE)
597 ret = MFXQueryVersion(device_hwctx->
session, &ver);
598 if (
ret != MFX_ERR_NONE) {
601 }
602
604 handle_type = MFX_HANDLE_VA_DISPLAY;
606 handle_type = MFX_HANDLE_D3D11_DEVICE;
608 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
609 } else {
612 }
613
617 if (!out_frames_ref)
619
620 #if QSV_HAVE_OPAQUE
622 MFX_MEMTYPE_OPAQUE_FRAME :
623 MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
624 #else
625 s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
626 #endif
627
629 out_frames_hwctx = out_frames_ctx->
hwctx;
630
635
638 else {
642 }
643
645
651 }
652
654 sizeof(*
s->surface_ptrs_out));
655 if (!
s->surface_ptrs_out) {
658 }
659
661 s->surface_ptrs_out[
i] = out_frames_hwctx->
surfaces +
i;
663
666 } else
667 s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
668
669 ret = MFXVideoCORE_GetHandle(device_hwctx->
session, handle_type, &handle);
675 }
676
677 /* create a "slave" session with those same properties, to be used for vpp */
682
683 ret = MFXQueryVersion(
s->session, &
s->ver);
684 if (
ret != MFX_ERR_NONE) {
687 }
688
689 if (handle) {
690 ret = MFXVideoCORE_SetHandle(
s->session, handle_type, handle);
691 if (
ret != MFX_ERR_NONE)
693 }
694
696 ret = MFXJoinSession(device_hwctx->
session,
s->session);
697 if (
ret != MFX_ERR_NONE)
699 }
700
701 #if QSV_HAVE_OPAQUE
703 s->opaque_alloc.In.Surfaces =
s->surface_ptrs_in;
704 s->opaque_alloc.In.NumSurface =
s->nb_surface_ptrs_in;
705 s->opaque_alloc.In.Type =
s->in_mem_mode;
706
707 s->opaque_alloc.Out.Surfaces =
s->surface_ptrs_out;
708 s->opaque_alloc.Out.NumSurface =
s->nb_surface_ptrs_out;
709 s->opaque_alloc.Out.Type =
s->out_mem_mode;
710
711 s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
712 s->opaque_alloc.Header.BufferSz =
sizeof(
s->opaque_alloc);
713 } else
714 #endif
716 mfxFrameAllocator frame_allocator = {
723 };
724
725 ret = MFXVideoCORE_SetFrameAllocator(
s->session, &frame_allocator);
726 if (
ret != MFX_ERR_NONE)
728 }
729
730 return 0;
731 }
732
734 {
735 return 0;
736 }
737
739 {
743
745 if (!
s->filter_frame)
748
750 if (!
s->set_frame_ext_params)
752
753 /* create the vpp session */
756 goto failed;
757
759 if (!
s->frame_infos) {
761 goto failed;
762 }
763
764 /* Init each input's information */
768 goto failed;
769 }
770
771 /* Update input's frame info according to crop */
776 goto failed;
777 }
778 s->frame_infos[crop->
in_idx].CropX = crop->
x;
779 s->frame_infos[crop->
in_idx].CropY = crop->
y;
780 s->frame_infos[crop->
in_idx].CropW = crop->
w;
781 s->frame_infos[crop->
in_idx].CropH = crop->
h;
782 }
783
784 s->vpp_param.vpp.In =
s->frame_infos[0];
785
789 goto failed;
790 }
791
793 #if QSV_HAVE_OPAQUE
796 #endif
797
798 if (
s->nb_seq_buffers) {
799 s->seq_buffers =
av_calloc(
s->nb_seq_buffers,
sizeof(*
s->seq_buffers));
800 if (!
s->seq_buffers) {
802 goto failed;
803 }
804
807
810 s->seq_buffers[
i] = (mfxExtBuffer *)&
s->opaque_alloc;
811 #endif
812
813 s->nb_ext_buffers =
s->nb_seq_buffers;
814 s->ext_buffers =
av_calloc(
s->nb_ext_buffers,
sizeof(*
s->ext_buffers));
815 if (!
s->ext_buffers) {
817 goto failed;
818 }
819
820 memcpy(
s->ext_buffers,
s->seq_buffers,
s->nb_seq_buffers *
sizeof(*
s->seq_buffers));
821 }
822
823 s->vpp_param.ExtParam =
s->ext_buffers;
824 s->vpp_param.NumExtParam =
s->nb_ext_buffers;
825
827
828 /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
830 if (!
s->async_fifo) {
832 goto failed;
833 }
834
835 s->vpp_param.AsyncDepth =
s->async_depth;
836
838 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
840 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
841 #if QSV_HAVE_OPAQUE
843 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
844 #endif
845
847 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
849 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
850 #if QSV_HAVE_OPAQUE
852 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
853 #endif
854
855 /* Print input memory mode */
857 /* Print output memory mode */
859
860 /* Validate VPP params, but don't initial VPP session here */
861 ret = MFXVideoVPP_Query(
s->session, &
s->vpp_param, &
s->vpp_param);
864 goto failed;
867
868 return 0;
869
870 failed:
872
874 }
875
877 {
881
882 ret =
s->set_frame_ext_params(avctx, in->
frame,
out->frame, &fp);
885
889
890 s->ext_buffers =
av_calloc(
s->nb_ext_buffers,
sizeof(*
s->ext_buffers));
893
894 memcpy(&
s->ext_buffers[0],
s->seq_buffers,
s->nb_seq_buffers *
sizeof(*
s->seq_buffers));
896 s->vpp_param.ExtParam =
s->ext_buffers;
897 s->vpp_param.NumExtParam =
s->nb_ext_buffers;
898 }
899
900 if (!
s->vpp_initted) {
901 s->vpp_param.vpp.In.PicStruct = in->
surface.Info.PicStruct;
902 s->vpp_param.vpp.Out.PicStruct =
out->surface.Info.PicStruct;
903
904 /* Query VPP params again, including params for frame */
905 ret = MFXVideoVPP_Query(
s->session, &
s->vpp_param, &
s->vpp_param);
910
911 ret = MFXVideoVPP_Init(
s->session, &
s->vpp_param);
916
919 ret = MFXVideoVPP_Reset(
s->session, &
s->vpp_param);
925 }
926
927 return 0;
928 }
929
931 {
933
935 MFXVideoVPP_Close(
s->session);
936 MFXClose(
s->session);
939 }
940
941 /* release all the resources */
950
951 return 0;
952 }
953
955 {
959 mfxSyncPoint sync;
961 int ret, ret1, filter_ret;
962
964 if (MFXVideoCORE_SyncOperation(
s->session, aframe.
sync, 1000) < 0)
966
967 filter_ret =
s->filter_frame(outlink, aframe.
frame->
frame);
968 if (filter_ret < 0) {
970 return filter_ret;
971 }
975 };
976
977 if (!picref)
978 return 0;
979
981 if (!in_frame) {
985 }
986
987 do {
989 if (!out_frame) {
992 }
993
997
998 do {
999 ret = MFXVideoVPP_RunFrameVPPAsync(
s->session, &in_frame->
surface,
1001 if (
ret == MFX_WRN_DEVICE_BUSY)
1003 }
while (
ret == MFX_WRN_DEVICE_BUSY);
1004
1005 if (
ret < 0 &&
ret != MFX_ERR_MORE_SURFACE) {
1006 /* Ignore more_data error */
1007 if (
ret == MFX_ERR_MORE_DATA)
1009 break;
1010 }
1011
1012 if (propref) {
1014 if (ret1 < 0) {
1017 return ret1;
1018 }
1019 }
1020
1023
1027
1030
1031 do {
1032 ret1 = MFXVideoCORE_SyncOperation(
s->session, aframe.
sync, 1000);
1033 } while (ret1 == MFX_WRN_IN_EXECUTION);
1034
1035 if (ret1 < 0) {
1037 break;
1038 }
1039
1040 filter_ret =
s->filter_frame(outlink, aframe.
frame->
frame);
1041 if (filter_ret < 0) {
1043 return filter_ret;
1044 }
1045
1049 }
1050 }
while(
ret == MFX_ERR_MORE_SURFACE);
1051
1056
1057 return 0;
1058 }
1059
1060 #if QSV_ONEVPL
1061
1063 void *loader,
1064 mfxIMPL implementation,
1065 mfxVersion *pver,
1066 mfxSession *psession)
1067 {
1068 mfxStatus sts;
1069 mfxSession session =
NULL;
1070 uint32_t impl_idx = 0;
1071
1073 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
1074
1075 if (!loader) {
1078 }
1079
1080 while (1) {
1081 /* Enumerate all implementations */
1082 mfxImplDescription *impl_desc;
1083
1084 sts = MFXEnumImplementations(loader, impl_idx,
1085 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
1086 (mfxHDL *)&impl_desc);
1087 /* Failed to find an available implementation */
1088 if (sts == MFX_ERR_NOT_FOUND)
1089 break;
1090 else if (sts != MFX_ERR_NONE) {
1091 impl_idx++;
1092 continue;
1093 }
1094
1095 sts = MFXCreateSession(loader, impl_idx, &session);
1096 MFXDispReleaseImplDescription(loader, impl_desc);
1097 if (sts == MFX_ERR_NONE)
1098 break;
1099
1100 impl_idx++;
1101 }
1102
1103 if (sts < 0)
1105 "Error creating a MFX session");
1106
1107 *psession = session;
1108
1109 return 0;
1110 }
1111
1112 #else
1113
1115 void *loader,
1116 mfxIMPL implementation,
1117 mfxVersion *pver,
1118 mfxSession *psession)
1119 {
1120 mfxSession session =
NULL;
1121 mfxStatus sts;
1122
1124 "Use Intel(R) Media SDK to create MFX session, API version is "
1125 "%d.%d, the required implementation version is %d.%d\n",
1126 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1127
1129 sts = MFXInit(implementation, pver, &session);
1130 if (sts < 0)
1132 "Error initializing an MFX session");
1133 else if (sts > 0) {
1136 }
1137
1138 *psession = session;
1139
1140 return 0;
1141 }
1142
1143 #endif
1144
1146 {
1147 /* When process YUV420 frames, FFmpeg uses same alignment on Y/U/V
1148 * planes. VPL and MSDK use Y plane's pitch / 2 as U/V planes's
1149 * pitch, which makes U/V planes 16-bytes aligned. We need to set a
1150 * separate alignment to meet runtime's behaviour.
1151 */
1155 16);
1156 }