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
28
32
33 #if QSV_ONEVPL
34 #include <mfxdispatcher.h>
35 #else
36 #define MFXUnload(a) do { } while(0)
37 #endif
38
39 #define IS_VIDEO_MEMORY(mode) (mode & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | \
40 MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET))
41 #if QSV_HAVE_OPAQUE
42 #define IS_OPAQUE_MEMORY(mode) (mode & MFX_MEMTYPE_OPAQUE_FRAME)
43 #endif
44 #define IS_SYSTEM_MEMORY(mode) (mode & MFX_MEMTYPE_SYSTEM_MEMORY)
45 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
46
47 #define QSV_HAVE_AUDIO !QSV_ONEVPL
48
50
55
56 static const struct {
60 {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" },
61 {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" },
62 #if QSV_HAVE_OPAQUE
63 {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" },
64 #endif
65 {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" },
66 {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" },
67 #if QSV_HAVE_OPAQUE
68 {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" },
69 #endif
70 };
71
73 const char *extra_string)
74 {
76
80 }
81 }
83 desc =
"unknown iopattern";
84
86 return 0;
87 }
88
89 static const struct {
94 { MFX_ERR_NONE, 0, "success" },
96 { MFX_ERR_NULL_PTR,
AVERROR(EINVAL),
"NULL pointer" },
97 { MFX_ERR_UNSUPPORTED,
AVERROR(ENOSYS),
"unsupported" },
98 { MFX_ERR_MEMORY_ALLOC,
AVERROR(ENOMEM),
"failed to allocate memory" },
99 { MFX_ERR_NOT_ENOUGH_BUFFER,
AVERROR(ENOMEM),
"insufficient input/output buffer" },
100 { MFX_ERR_INVALID_HANDLE,
AVERROR(EINVAL),
"invalid handle" },
101 { MFX_ERR_LOCK_MEMORY,
AVERROR(EIO),
"failed to lock the memory block" },
102 { MFX_ERR_NOT_INITIALIZED,
AVERROR_BUG,
"not initialized" },
103 { MFX_ERR_NOT_FOUND,
AVERROR(ENOSYS),
"specified object was not found" },
104 /* the following 3 errors should always be handled explicitly, so those "mappings"
105 * are for completeness only */
107 { MFX_ERR_MORE_SURFACE,
AVERROR_UNKNOWN,
"expect more surface at output" },
108 { MFX_ERR_MORE_BITSTREAM,
AVERROR_UNKNOWN,
"expect more bitstream at output" },
110 { MFX_ERR_DEVICE_LOST,
AVERROR(EIO),
"device lost" },
111 { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM,
AVERROR(EINVAL),
"incompatible video parameters" },
112 { MFX_ERR_INVALID_VIDEO_PARAM,
AVERROR(EINVAL),
"invalid video parameters" },
113 { MFX_ERR_UNDEFINED_BEHAVIOR,
AVERROR_BUG,
"undefined behavior" },
114 { MFX_ERR_DEVICE_FAILED,
AVERROR(EIO),
"device failed" },
115 #if QSV_HAVE_AUDIO
116 { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM,
AVERROR(EINVAL),
"incompatible audio parameters" },
117 { MFX_ERR_INVALID_AUDIO_PARAM,
AVERROR(EINVAL),
"invalid audio parameters" },
118 #endif
119 { MFX_ERR_GPU_HANG,
AVERROR(EIO),
"GPU Hang" },
120 { MFX_ERR_REALLOC_SURFACE,
AVERROR_UNKNOWN,
"need bigger surface for output" },
121
122 { MFX_WRN_IN_EXECUTION, 0, "operation in execution" },
123 { MFX_WRN_DEVICE_BUSY, 0, "device busy" },
124 { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" },
125 { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" },
126 { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" },
127 { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" },
128 { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" },
129 { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" },
130 #if QSV_HAVE_AUDIO
131 { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" },
132 #endif
133
134 #if QSV_VERSION_ATLEAST(1, 31)
135 { MFX_ERR_NONE_PARTIAL_OUTPUT, 0, "partial output" },
136 #endif
137 };
138
140 {
147 }
148 }
150 *
desc =
"unknown error";
152 }
153
155 const char *error_string)
156 {
162 }
163
165 const char *warning_string)
166 {
172 }
173
174 /* functions for frameAlloc */
175 static mfxStatus
frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
176 mfxFrameAllocResponse *resp)
177 {
180
181 if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
182 !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
183 !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
184 return MFX_ERR_UNSUPPORTED;
185
186 if (req->Type & MFX_MEMTYPE_FROM_VPPIN) {
187 resp->mids =
av_mallocz(
s->nb_surface_ptrs_in *
sizeof(*resp->mids));
188 if (!resp->mids)
190
191 for (
i = 0;
i <
s->nb_surface_ptrs_in;
i++)
192 resp->mids[
i] =
s->surface_ptrs_in[
i]->Data.MemId;
193
194 resp->NumFrameActual =
s->nb_surface_ptrs_in;
195 } else {
196 resp->mids =
av_mallocz(
s->nb_surface_ptrs_out *
sizeof(*resp->mids));
197 if (!resp->mids)
199
200 for (
i = 0;
i <
s->nb_surface_ptrs_out;
i++)
201 resp->mids[
i] =
s->surface_ptrs_out[
i]->Data.MemId;
202
203 resp->NumFrameActual =
s->nb_surface_ptrs_out;
204 }
205
206 return MFX_ERR_NONE;
207 }
208
209 static mfxStatus
frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
210 {
212 return MFX_ERR_NONE;
213 }
214
215 static mfxStatus
frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
216 {
217 return MFX_ERR_UNSUPPORTED;
218 }
219
220 static mfxStatus
frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
221 {
222 return MFX_ERR_UNSUPPORTED;
223 }
224
226 {
227 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
228 mfxHDLPair *pair_src = (mfxHDLPair*)mid;
229
230 pair_dst->first = pair_src->first;
231
232 if (pair_src->second != (mfxMemId)MFX_INFINITE)
233 pair_dst->second = pair_src->second;
234 return MFX_ERR_NONE;
235 }
236
238 {
241 return MFX_FOURCC_YV12;
243 return MFX_FOURCC_NV12;
245 return MFX_FOURCC_YUY2;
247 return MFX_FOURCC_RGB4;
249 return MFX_FOURCC_P010;
250 #if CONFIG_VAAPI
252 return MFX_FOURCC_UYVY;
253 #endif
254 }
255
256 return MFX_FOURCC_NV12;
257 }
258
260 {
266 break;
271 break;
276 break;
282 break;
287 break;
288 default:
289 return MFX_ERR_UNSUPPORTED;
290 }
292
293 return 0;
294 }
295
296 /* fill the surface info */
298 {
303
307
309 frames_hwctx = frames_ctx->
hwctx;
310 *frameinfo = frames_hwctx->
surfaces[0].Info;
311 } else {
316
317 frameinfo->CropX = 0;
318 frameinfo->CropY = 0;
321 frameinfo->PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
323 frameinfo->BitDepthLuma =
desc->comp[0].depth;
324 frameinfo->BitDepthChroma =
desc->comp[0].depth;
325 frameinfo->Shift =
desc->comp[0].depth > 8;
326 if (
desc->log2_chroma_w &&
desc->log2_chroma_h)
327 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV420;
328 else if (
desc->log2_chroma_w)
329 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV422;
330 else
331 frameinfo->ChromaFormat = MFX_CHROMAFORMAT_YUV444;
332 }
333
334 frameinfo->CropW =
link->w;
335 frameinfo->CropH =
link->h;
336 frameinfo->FrameRateExtN =
link->frame_rate.num;
337 frameinfo->FrameRateExtD =
link->frame_rate.den;
338
339 /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
340 * init will fail */
341 if (frameinfo->FrameRateExtD == 0 || frameinfo->FrameRateExtN == 0) {
342 frameinfo->FrameRateExtN = 25;
343 frameinfo->FrameRateExtD = 1;
344 }
345
348
349 return 0;
350 }
351
353 {
355 /* list->queued==1 means the frame is not cached in VPP
356 * process any more, it can be released to pool. */
357 if ((
list->queued == 1) && !
list->surface.Data.Locked) {
360 }
362 }
363 }
364
366 {
369
371 *
list = (*list)->next;
374 }
375 }
376
378 {
380
384 break;
385 }
386 }
387
393 }
397 }
398
400 }
401
402 /* get the input surface */
404 {
407
409
411 if (!qsv_frame)
413
414 /* Turn AVFrame into mfxFrameSurface1.
415 * For video/opaque memory mode, pix_fmt is AV_PIX_FMT_QSV, and
416 * mfxFrameSurface1 is stored in AVFrame->data[3];
417 * for system memory mode, raw video data is stored in
418 * AVFrame, we should map it into mfxFrameSurface1.
419 */
424 }
427 } else {
428 /* make a copy if the input is not padded as libmfx requires */
433 if (!qsv_frame->
frame)
435
438
442 }
443
447 }
448 } else
450
455 }
456 }
457
461
462 qsv_frame->
surface.Info.PicStruct =
465 MFX_PICSTRUCT_FIELD_BFF);
467 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
469 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
471 qsv_frame->
surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
472
473 return qsv_frame;
474 }
475
476 /* get the output surface */
478 {
482
484
486 if (!out_frame)
488
489 /* For video memory, get a hw frame;
490 * For system memory, get a sw frame and map it into a mfx_surface. */
493 if (!out_frame->
frame)
495
500 }
501
506 }
507
509 } else {
510 /* Get a frame with aligned dimensions.
511 * Libmfx need system memory being 128x64 aligned */
515 if (!out_frame->
frame)
517
522 }
523
528 }
529
532 else
534
537 out_frame->
surface.Info =
s->vpp_param.vpp.Out;
538
539 for (
int i = 0;
i <
s->vpp_param.NumExtParam;
i++) {
540 mfxExtBuffer *extbuf =
s->vpp_param.ExtParam[
i];
541
542 if (extbuf->BufferId == MFX_EXTBUFF_VPP_DEINTERLACING) {
543 #if FF_API_INTERLACED_FRAME
547 #endif
549 break;
550 }
551 }
552
553 out_frame->
surface.Info.PicStruct =
556 MFX_PICSTRUCT_FIELD_BFF);
557
558 return out_frame;
559 }
560
561 /* create the QSV session */
563 {
568
572 mfxHDL handle;
573 mfxHandleType handle_type;
574 mfxVersion ver;
575 mfxIMPL impl;
577
578 if (
inlink->hw_frames_ctx) {
580
582 in_frames_hwctx = frames_ctx->
hwctx;
583
585
587 sizeof(*
s->surface_ptrs_in));
588 if (!
s->surface_ptrs_in)
590
592 s->surface_ptrs_in[
i] = in_frames_hwctx->
surfaces +
i;
593
597 s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
598 } else {
601 }
602
604 device_hwctx = device_ctx->
hwctx;
605
609 if (!out_frames_ref)
611
612 #if QSV_HAVE_OPAQUE
614 MFX_MEMTYPE_OPAQUE_FRAME :
615 MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
616 #else
617 s->out_mem_mode = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_FROM_VPPOUT;
618 #endif
619
621 out_frames_hwctx = out_frames_ctx->
hwctx;
622
631
637 }
638
640 sizeof(*
s->surface_ptrs_out));
641 if (!
s->surface_ptrs_out) {
644 }
645
647 s->surface_ptrs_out[
i] = out_frames_hwctx->
surfaces +
i;
649
652 } else
653 s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
654
655 /* extract the properties of the "master" session given to us */
656 ret = MFXQueryIMPL(device_hwctx->
session, &impl);
657 if (
ret == MFX_ERR_NONE)
658 ret = MFXQueryVersion(device_hwctx->
session, &ver);
659 if (
ret != MFX_ERR_NONE) {
662 }
663
665 handle_type = MFX_HANDLE_VA_DISPLAY;
667 handle_type = MFX_HANDLE_D3D11_DEVICE;
669 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
670 } else {
673 }
674
675 ret = MFXVideoCORE_GetHandle(device_hwctx->
session, handle_type, &handle);
681 }
682
683 /* create a "slave" session with those same properties, to be used for vpp */
688
689 ret = MFXQueryVersion(
s->session, &
s->ver);
690 if (
ret != MFX_ERR_NONE) {
693 }
694
695 if (handle) {
696 ret = MFXVideoCORE_SetHandle(
s->session, handle_type, handle);
697 if (
ret != MFX_ERR_NONE)
699 }
700
702 ret = MFXJoinSession(device_hwctx->
session,
s->session);
703 if (
ret != MFX_ERR_NONE)
705 }
706
707 #if QSV_HAVE_OPAQUE
709 s->opaque_alloc.In.Surfaces =
s->surface_ptrs_in;
710 s->opaque_alloc.In.NumSurface =
s->nb_surface_ptrs_in;
711 s->opaque_alloc.In.Type =
s->in_mem_mode;
712
713 s->opaque_alloc.Out.Surfaces =
s->surface_ptrs_out;
714 s->opaque_alloc.Out.NumSurface =
s->nb_surface_ptrs_out;
715 s->opaque_alloc.Out.Type =
s->out_mem_mode;
716
717 s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
718 s->opaque_alloc.Header.BufferSz =
sizeof(
s->opaque_alloc);
719 } else
720 #endif
722 mfxFrameAllocator frame_allocator = {
729 };
730
731 ret = MFXVideoCORE_SetFrameAllocator(
s->session, &frame_allocator);
732 if (
ret != MFX_ERR_NONE)
734 }
735
736 return 0;
737 }
738
740 {
741 return 0;
742 }
743
745 {
749
751 if (!
s->filter_frame)
754
756 if (!
s->set_frame_ext_params)
758
759 /* create the vpp session */
762 goto failed;
763
765 if (!
s->frame_infos) {
767 goto failed;
768 }
769
770 /* Init each input's information */
774 goto failed;
775 }
776
777 /* Update input's frame info according to crop */
782 goto failed;
783 }
784 s->frame_infos[crop->
in_idx].CropX = crop->
x;
785 s->frame_infos[crop->
in_idx].CropY = crop->
y;
786 s->frame_infos[crop->
in_idx].CropW = crop->
w;
787 s->frame_infos[crop->
in_idx].CropH = crop->
h;
788 }
789
790 s->vpp_param.vpp.In =
s->frame_infos[0];
791
795 goto failed;
796 }
797
799 #if QSV_HAVE_OPAQUE
802 #endif
803
804 if (
s->nb_seq_buffers) {
805 s->seq_buffers =
av_calloc(
s->nb_seq_buffers,
sizeof(*
s->seq_buffers));
806 if (!
s->seq_buffers) {
808 goto failed;
809 }
810
813
816 s->seq_buffers[
i] = (mfxExtBuffer *)&
s->opaque_alloc;
817 #endif
818
819 s->nb_ext_buffers =
s->nb_seq_buffers;
820 s->ext_buffers =
av_calloc(
s->nb_ext_buffers,
sizeof(*
s->ext_buffers));
821 if (!
s->ext_buffers) {
823 goto failed;
824 }
825
826 memcpy(
s->ext_buffers,
s->seq_buffers,
s->nb_seq_buffers *
sizeof(*
s->seq_buffers));
827 }
828
829 s->vpp_param.ExtParam =
s->ext_buffers;
830 s->vpp_param.NumExtParam =
s->nb_ext_buffers;
831
833
834 /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */
836 if (!
s->async_fifo) {
838 goto failed;
839 }
840
841 s->vpp_param.AsyncDepth =
s->async_depth;
842
844 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_SYSTEM_MEMORY;
846 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_VIDEO_MEMORY;
847 #if QSV_HAVE_OPAQUE
849 s->vpp_param.IOPattern |= MFX_IOPATTERN_IN_OPAQUE_MEMORY;
850 #endif
851
853 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
855 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_VIDEO_MEMORY;
856 #if QSV_HAVE_OPAQUE
858 s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
859 #endif
860
861 /* Print input memory mode */
863 /* Print output memory mode */
865
866 /* Validate VPP params, but don't initial VPP session here */
867 ret = MFXVideoVPP_Query(
s->session, &
s->vpp_param, &
s->vpp_param);
870 goto failed;
873
874 return 0;
875
876 failed:
878
880 }
881
883 {
887
891
892 if (
fp.num_ext_buf) {
894 s->nb_ext_buffers =
s->nb_seq_buffers +
fp.num_ext_buf;
895
896 s->ext_buffers =
av_calloc(
s->nb_ext_buffers,
sizeof(*
s->ext_buffers));
899
900 memcpy(&
s->ext_buffers[0],
s->seq_buffers,
s->nb_seq_buffers *
sizeof(*
s->seq_buffers));
901 memcpy(&
s->ext_buffers[
s->nb_seq_buffers],
fp.ext_buf,
fp.num_ext_buf *
sizeof(*
fp.ext_buf));
902 s->vpp_param.ExtParam =
s->ext_buffers;
903 s->vpp_param.NumExtParam =
s->nb_ext_buffers;
904 }
905
906 if (!
s->vpp_initted) {
907 s->vpp_param.vpp.In.PicStruct = in->
surface.Info.PicStruct;
908 s->vpp_param.vpp.Out.PicStruct =
out->surface.Info.PicStruct;
909
910 /* Query VPP params again, including params for frame */
911 ret = MFXVideoVPP_Query(
s->session, &
s->vpp_param, &
s->vpp_param);
916
917 ret = MFXVideoVPP_Init(
s->session, &
s->vpp_param);
922
924 }
else if (
fp.num_ext_buf) {
925 ret = MFXVideoVPP_Reset(
s->session, &
s->vpp_param);
931 }
932
933 return 0;
934 }
935
937 {
939
941 MFXVideoVPP_Close(
s->session);
942 MFXClose(
s->session);
945 }
946
947 /* release all the resources */
956
957 return 0;
958 }
959
961 {
965 mfxSyncPoint sync;
967 int ret, ret1, filter_ret;
968
970 if (MFXVideoCORE_SyncOperation(
s->session, aframe.
sync, 1000) < 0)
972
973 filter_ret =
s->filter_frame(outlink, aframe.
frame->
frame);
974 if (filter_ret < 0) {
976 return filter_ret;
977 }
981 };
982
983 if (!picref)
984 return 0;
985
987 if (!in_frame) {
991 }
992
993 do {
995 if (!out_frame) {
998 }
999
1003
1004 do {
1005 ret = MFXVideoVPP_RunFrameVPPAsync(
s->session, &in_frame->
surface,
1007 if (
ret == MFX_WRN_DEVICE_BUSY)
1009 }
while (
ret == MFX_WRN_DEVICE_BUSY);
1010
1011 if (
ret < 0 &&
ret != MFX_ERR_MORE_SURFACE) {
1012 /* Ignore more_data error */
1013 if (
ret == MFX_ERR_MORE_DATA)
1015 break;
1016 }
1019
1023
1026
1027 do {
1028 ret1 = MFXVideoCORE_SyncOperation(
s->session, aframe.
sync, 1000);
1029 } while (ret1 == MFX_WRN_IN_EXECUTION);
1030
1031 if (ret1 < 0) {
1033 break;
1034 }
1035
1036 filter_ret =
s->filter_frame(outlink, aframe.
frame->
frame);
1037 if (filter_ret < 0) {
1039 return filter_ret;
1040 }
1041
1045 }
1046 }
while(
ret == MFX_ERR_MORE_SURFACE);
1047
1052
1053 return 0;
1054 }
1055
1056 #if QSV_ONEVPL
1057
1059 void *loader,
1060 mfxIMPL implementation,
1061 mfxVersion *pver,
1062 mfxSession *psession)
1063 {
1064 mfxStatus sts;
1065 mfxSession session =
NULL;
1066 uint32_t impl_idx = 0;
1067
1069 "Use Intel(R) oneVPL to create MFX session with the specified MFX loader\n");
1070
1071 if (!loader) {
1074 }
1075
1076 while (1) {
1077 /* Enumerate all implementations */
1078 mfxImplDescription *impl_desc;
1079
1080 sts = MFXEnumImplementations(loader, impl_idx,
1081 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
1082 (mfxHDL *)&impl_desc);
1083 /* Failed to find an available implementation */
1084 if (sts == MFX_ERR_NOT_FOUND)
1085 break;
1086 else if (sts != MFX_ERR_NONE) {
1087 impl_idx++;
1088 continue;
1089 }
1090
1091 sts = MFXCreateSession(loader, impl_idx, &session);
1092 MFXDispReleaseImplDescription(loader, impl_desc);
1093 if (sts == MFX_ERR_NONE)
1094 break;
1095
1096 impl_idx++;
1097 }
1098
1099 if (sts < 0)
1101 "Error creating a MFX session");
1102 else if (sts > 0) {
1104 "Warning in MFX session creation");
1106 }
1107
1108 *psession = session;
1109
1110 return 0;
1111 }
1112
1113 #else
1114
1116 void *loader,
1117 mfxIMPL implementation,
1118 mfxVersion *pver,
1119 mfxSession *psession)
1120 {
1121 mfxSession session =
NULL;
1122 mfxStatus sts;
1123
1125 "Use Intel(R) Media SDK to create MFX session, API version is "
1126 "%d.%d, the required implementation version is %d.%d\n",
1127 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1128
1130 sts = MFXInit(implementation, pver, &session);
1131 if (sts < 0)
1133 "Error initializing an MFX session");
1134 else if (sts > 0) {
1137 }
1138
1139 *psession = session;
1140
1141 return 0;
1142 }
1143
1144 #endif
1145
1147 {
1148 /* When process YUV420 frames, FFmpeg uses same alignment on Y/U/V
1149 * planes. VPL and MSDK use Y plane's pitch / 2 as U/V planes's
1150 * pitch, which makes U/V planes 16-bytes aligned. We need to set a
1151 * separate alignment to meet runtime's behaviour.
1152 */
1156 16);
1157 }