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 #include <stdint.h>
20 #include <string.h>
21
22 #include <mfx/mfxvideo.h>
23
24 #include "config.h"
25
26 #if HAVE_PTHREADS
27 #include <pthread.h>
28 #endif
29
31 #if CONFIG_VAAPI
33 #endif
34 #if CONFIG_D3D11VA
36 #endif
37 #if CONFIG_DXVA2
39 #endif
40
51
52 #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \
53 (MFX_VERSION_MAJOR > (MAJOR) || \
54 MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
55
56 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
57
61
67
71
77 #if HAVE_PTHREADS
80 #endif
81
86
87 // used in the frame allocator for non-opaque surfaces
89 // used in the opaque alloc request for opaque surfaces
91
96
97 static const struct {
105 #if CONFIG_VAAPI
107 MFX_FOURCC_YUY2 },
108 #if QSV_VERSION_ATLEAST(1, 27)
110 MFX_FOURCC_Y210 },
111 #endif
112 #endif
113 };
114
116 {
121 }
122 return 0;
123 }
124
125 #if CONFIG_D3D11VA
126 static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
127 {
128 uint32_t bind_flags = 0;
129
130 if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
131 bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
132 else
133 bind_flags = D3D11_BIND_DECODER;
134
135 if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) || (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
136 bind_flags = D3D11_BIND_RENDER_TARGET;
137
138 return bind_flags;
139 }
140 #endif
141
143 {
145 int i, planes_nb = 0;
148
150
151 for (
i = 0;
i <
desc->nb_components;
i++)
152 planes_nb =
FFMAX(planes_nb,
desc->comp[
i].plane + 1);
153
154 for (
i = 0;
i < planes_nb;
i++) {
155 int sheight, dheight, y;
163 if (swidth < 0 || dwidth < 0) {
166 }
167 sheight =
src->height;
172 }
173 //fill right padding
174 for (y = 0; y < sheight; y++) {
177 comp.depth > 8 ? 2 : 1,
178 dwidth - swidth);
179 }
180 //fill bottom padding
181 for (y = sheight; y < dheight; y++) {
184 dwidth);
185 }
186 }
187 return 0;
188 }
189
191 {
194 int hw_handle_supported = 0;
195 mfxHandleType handle_type;
198 mfxStatus err;
199
200 err = MFXQueryIMPL(hwctx->
session, &
s->impl);
201 if (err == MFX_ERR_NONE)
202 err = MFXQueryVersion(hwctx->
session, &
s->ver);
203 if (err != MFX_ERR_NONE) {
206 }
207
209 #if CONFIG_VAAPI
210 handle_type = MFX_HANDLE_VA_DISPLAY;
213 hw_handle_supported = 1;
214 #endif
216 #if CONFIG_D3D11VA
217 handle_type = MFX_HANDLE_D3D11_DEVICE;
220 hw_handle_supported = 1;
221 #endif
223 #if CONFIG_DXVA2
224 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
227 hw_handle_supported = 1;
228 #endif
229 }
230
231 if (hw_handle_supported) {
232 err = MFXVideoCORE_GetHandle(hwctx->
session, handle_type, &
s->handle);
233 if (err == MFX_ERR_NONE) {
234 s->handle_type = handle_type;
235 s->child_device_type = device_type;
237 }
238 }
241 "from the session\n");
242 }
243 return 0;
244 }
245
247 {
249
250 if (
s->session_download) {
251 MFXVideoVPP_Close(
s->session_download);
252 MFXClose(
s->session_download);
253 }
254 s->session_download =
NULL;
255 s->session_download_init = 0;
256
257 if (
s->session_upload) {
258 MFXVideoVPP_Close(
s->session_upload);
259 MFXClose(
s->session_upload);
260 }
261 s->session_upload =
NULL;
262 s->session_upload_init = 0;
263
264 #if HAVE_PTHREADS
267 #endif
268
275 }
276
278 {
279 }
280
282 {
286
288 s->nb_surfaces_used++;
291 }
292
294 }
295
297 {
301
304
307
309
310 if (!device_priv->
handle) {
312 "Cannot create a non-opaque internal surface pool without "
313 "a hardware handle\n");
315 }
316
318 if (!child_device_ref)
321
322 #if CONFIG_VAAPI
325 child_device_hwctx->
display = (VADisplay)device_priv->
handle;
326 }
327 #endif
328 #if CONFIG_D3D11VA
333 }
334 #endif
335 #if CONFIG_DXVA2
338 child_device_hwctx->
devmgr = (IDirect3DDeviceManager9*)device_priv->
handle;
339 }
340 #endif
341
346 }
347
349 if (!child_frames_ref) {
352 }
354
360
361 #if CONFIG_D3D11VA
365 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
366 if (hwctx->
frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
367 child_frames_hwctx->
MiscFlags = D3D11_RESOURCE_MISC_SHARED;
369 }
370 #endif
371 #if CONFIG_DXVA2
374 if (hwctx->
frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
375 child_frames_hwctx->
surface_type = DXVA2_VideoProcessorRenderTarget;
376 else
377 child_frames_hwctx->
surface_type = DXVA2_VideoDecoderRenderTarget;
378 }
379 #endif
380
385 }
386
387 #if CONFIG_VAAPI
390 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
391 s->handle_pairs_internal[
i].first = child_frames_hwctx->
surface_ids +
i;
392 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
393 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
394 }
395 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
396 }
397 #endif
398 #if CONFIG_D3D11VA
401 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
403 if(child_frames_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
404 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
405 } else {
407 }
408 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
409 }
410 if (child_frames_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
411 hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
412 } else {
413 hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
414 }
415 }
416 #endif
417 #if CONFIG_DXVA2
420 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
421 s->handle_pairs_internal[
i].first = (mfxMemId)child_frames_hwctx->
surfaces[
i];
422 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
423 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
424 }
425 if (child_frames_hwctx->
surface_type == DXVA2_VideoProcessorRenderTarget)
426 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
427 else
428 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
429 }
430 #endif
431
432 s->child_frames_ref = child_frames_ref;
433 child_frames_ref =
NULL;
434
439 }
440
442 {
445
449
453
454 surf->Info.BitDepthLuma =
desc->comp[0].depth;
455 surf->Info.BitDepthChroma =
desc->comp[0].depth;
456 surf->Info.Shift =
desc->comp[0].depth > 8;
457
458 if (
desc->log2_chroma_w &&
desc->log2_chroma_h)
459 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
460 else if (
desc->log2_chroma_w)
461 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
462 else
463 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
464
465 surf->Info.FourCC =
fourcc;
467 surf->Info.CropW =
ctx->width;
469 surf->Info.CropH =
ctx->height;
470 surf->Info.FrameRateExtN = 25;
471 surf->Info.FrameRateExtD = 1;
472 surf->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
473
474 return 0;
475 }
476
478 {
481
483
484 if (
ctx->initial_pool_size <= 0) {
487 }
488
490 sizeof(*
s->handle_pairs_internal));
491 if (!
s->handle_pairs_internal)
493
495 sizeof(*
s->surfaces_internal));
496 if (!
s->surfaces_internal)
498
499 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
503 }
504
505 if (!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
509 }
510
513 if (!
ctx->internal->pool_internal)
515
516 frames_hwctx->
surfaces =
s->surfaces_internal;
518
519 return 0;
520 }
521
522 static mfxStatus
frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
523 mfxFrameAllocResponse *resp)
524 {
528 mfxFrameInfo *
i = &req->Info;
529 mfxFrameInfo *i1 = &hwctx->
surfaces[0].Info;
530
531 if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
532 !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
533 !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
534 return MFX_ERR_UNSUPPORTED;
535 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
536 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
538 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
539 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
540 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
541 return MFX_ERR_UNSUPPORTED;
542 }
543
544 resp->mids =
s->mem_ids;
546
547 return MFX_ERR_NONE;
548 }
549
550 static mfxStatus
frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
551 {
552 return MFX_ERR_NONE;
553 }
554
555 static mfxStatus
frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
556 {
557 return MFX_ERR_UNSUPPORTED;
558 }
559
560 static mfxStatus
frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
561 {
562 return MFX_ERR_UNSUPPORTED;
563 }
564
566 {
567 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
568 mfxHDLPair *pair_src = (mfxHDLPair*)mid;
569
570 pair_dst->first = pair_src->first;
571
572 if (pair_src->second != (mfxMemId)MFX_INFINITE)
573 pair_dst->second = pair_src->second;
574 return MFX_ERR_NONE;
575 }
576
578 mfxSession *session, int upload)
579 {
583 int opaque = !!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
584
585 mfxFrameAllocator frame_allocator = {
592 };
593
594 mfxVideoParam par;
595 mfxStatus err;
596
597 err = MFXInit(device_priv->
impl, &device_priv->
ver, session);
598 if (err != MFX_ERR_NONE) {
601 }
602
603 if (device_priv->
handle) {
604 err = MFXVideoCORE_SetHandle(*session, device_priv->
handle_type,
606 if (err != MFX_ERR_NONE)
608 }
609
610 if (!opaque) {
611 err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
612 if (err != MFX_ERR_NONE)
614 }
615
616 memset(&par, 0, sizeof(par));
617
618 if (opaque) {
619 par.ExtParam =
s->ext_buffers;
621 par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY :
622 MFX_IOPATTERN_IN_OPAQUE_MEMORY;
623 } else {
624 par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
625 MFX_IOPATTERN_IN_VIDEO_MEMORY;
626 }
627
628 par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY :
629 MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
630 par.AsyncDepth = 1;
631
632 par.vpp.In = frames_hwctx->
surfaces[0].Info;
633
634 /* Apparently VPP requires the frame rate to be set to some value, otherwise
635 * init will fail (probably for the framerate conversion filter). Since we
636 * are only doing data upload/download here, we just invent an arbitrary
637 * value */
638 par.vpp.In.FrameRateExtN = 25;
639 par.vpp.In.FrameRateExtD = 1;
640 par.vpp.Out = par.vpp.In;
641
642 err = MFXVideoVPP_Init(*session, &par);
643 if (err != MFX_ERR_NONE) {
645 "Surface upload/download will not be possible\n");
646 MFXClose(*session);
648 }
649
650 return 0;
651 }
652
654 {
657
658 int opaque = !!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
659
662
667 }
668
674 }
675 }
676
677 if (opaque) {
679 sizeof(*
s->surface_ptrs));
680 if (!
s->surface_ptrs)
682
685
686 s->opaque_alloc.In.Surfaces =
s->surface_ptrs;
687 s->opaque_alloc.In.NumSurface = frames_hwctx->
nb_surfaces;
688 s->opaque_alloc.In.Type = frames_hwctx->
frame_type;
689
690 s->opaque_alloc.Out =
s->opaque_alloc.In;
691
692 s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
693 s->opaque_alloc.Header.BufferSz =
sizeof(
s->opaque_alloc);
694
695 s->ext_buffers[0] = (mfxExtBuffer*)&
s->opaque_alloc;
696 } else {
700
702 s->mem_ids[
i] = frames_hwctx->
surfaces[
i].Data.MemId;
703 }
704
705 s->session_download =
NULL;
706 s->session_upload =
NULL;
707
708 s->session_download_init = 0;
709 s->session_upload_init = 0;
710
711 #if HAVE_PTHREADS
714 #endif
715
716 return 0;
717 }
718
720 {
724
729
730 return 0;
731 }
732
736 {
738
740 if (!fmts)
742
743 fmts[0] =
ctx->sw_format;
745
747
748 return 0;
749 }
750
753 {
756
758 #if CONFIG_VAAPI
760 {
767 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
769 }
771 }
772 break;
773 #endif
774 #if CONFIG_D3D11VA
776 {
778 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
779 dst_hwctx->
texture = (ID3D11Texture2D*)pair->first;
780 if (src_hwctx->
frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
781 dst_hwctx->
MiscFlags = D3D11_RESOURCE_MISC_SHARED;
783 }
784 break;
785 #endif
786 #if CONFIG_DXVA2
788 {
795 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
796 dst_hwctx->
surfaces[
i] = (IDirect3DSurface9*)pair->first;
797 }
799 if (src_hwctx->
frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
800 dst_hwctx->
surface_type = DXVA2_VideoDecoderRenderTarget;
801 else
802 dst_hwctx->
surface_type = DXVA2_VideoProcessorRenderTarget;
803 }
804 break;
805 #endif
806 default:
808 }
809
810 return 0;
811 }
812
815 {
817 mfxFrameSurface1 *surf = (mfxFrameSurface1*)
src->data[3];
820 uint8_t *child_data;
823
824 if (!
s->child_frames_ref)
827
828 switch (child_frames_ctx->device_ctx->type) {
829 #if CONFIG_VAAPI
831 {
832 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
833 /* pair->first is *VASurfaceID while data[3] in vaapi frame is VASurfaceID, so
834 * we need this casting for vaapi.
835 * Add intptr_t to force cast from VASurfaceID(uint) type to pointer(long) type
836 * to avoid compile warning */
837 child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)pair->first;
838 break;
839 }
840 #endif
841 #if CONFIG_D3D11VA
843 {
844 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
845 child_data = pair->first;
846 break;
847 }
848 #endif
849 #if CONFIG_DXVA2
851 {
852 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
853 child_data = pair->first;
854 break;
855 }
856 #endif
857 default:
859 }
860
861 if (dst->
format == child_frames_ctx->format) {
866
869
871 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
872 dst->
data[0] = pair->first;
873 dst->
data[1] = pair->second;
874 } else {
875 dst->
data[3] = child_data;
876 }
877
878 return 0;
879 }
880
883 // This only supports mapping to software.
885 }
886
890
895
896 dummy->format = child_frames_ctx->format;
899
901 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
902 dummy->data[0] = pair->first;
903 dummy->data[1] = pair->second;
904 } else {
905 dummy->data[3] = child_data;
906 }
907
909
912
914 }
915
918 {
921 int download = !!
src->hw_frames_ctx;
922 mfxFrameSurface1 *surf = (mfxFrameSurface1*)(download ?
src->data[3] : dst->
data[3]);
923
926
930
934 dummy->buf[0] = download ?
src->buf[0] : dst->
buf[0];
935 dummy->data[3] = surf->Data.MemId;
936 dummy->hw_frames_ctx =
s->child_frames_ref;
937
940
944
946
948 }
949
951 {
952 switch (
frame->format) {
955 surface->Data.Y =
frame->data[0];
956 surface->Data.UV =
frame->data[1];
957 break;
958
960 surface->Data.Y =
frame->data[0];
961 surface->Data.U =
frame->data[1];
962 surface->Data.V =
frame->data[2];
963 break;
964
966 surface->Data.B =
frame->data[0];
967 surface->Data.G =
frame->data[0] + 1;
968 surface->Data.R =
frame->data[0] + 2;
969 surface->Data.A =
frame->data[0] + 3;
970 break;
971 #if CONFIG_VAAPI
973 surface->Data.Y =
frame->data[0];
974 surface->Data.U =
frame->data[0] + 1;
975 surface->Data.V =
frame->data[0] + 3;
976 break;
977
979 surface->Data.Y16 = (mfxU16 *)
frame->data[0];
980 surface->Data.U16 = (mfxU16 *)
frame->data[0] + 1;
981 surface->Data.V16 = (mfxU16 *)
frame->data[0] + 3;
982 break;
983 #endif
984 default:
985 return MFX_ERR_UNSUPPORTED;
986 }
987 surface->Data.Pitch =
frame->linesize[0];
988 surface->Data.TimeStamp =
frame->pts;
989
990 return 0;
991 }
992
995 {
997 mfxFrameSurface1
out = {{ 0 }};
998 mfxFrameSurface1 *in = (mfxFrameSurface1*)
src->data[3];
999
1000 mfxSyncPoint sync =
NULL;
1001 mfxStatus err;
1003
1004 while (!
s->session_download_init && !
s->session_download && !
ret) {
1005 #if HAVE_PTHREADS
1006 if (pthread_mutex_trylock(&
s->session_lock) == 0) {
1007 #endif
1008 if (!
s->session_download_init) {
1010 if (
s->session_download)
1011 s->session_download_init = 1;
1012 }
1013 #if HAVE_PTHREADS
1016 } else {
1018 while (!
s->session_download_init && !
s->session_download) {
1020 }
1022 }
1023 #endif
1024 }
1025
1028
1029 if (!
s->session_download) {
1030 if (
s->child_frames_ref)
1032
1035 }
1036
1037 out.Info = in->Info;
1039
1040 do {
1041 err = MFXVideoVPP_RunFrameVPPAsync(
s->session_download, in, &
out,
NULL, &sync);
1042 if (err == MFX_WRN_DEVICE_BUSY)
1044 } while (err == MFX_WRN_DEVICE_BUSY);
1045
1046 if (err < 0 || !sync) {
1049 }
1050
1051 do {
1052 err = MFXVideoCORE_SyncOperation(
s->session_download, sync, 1000);
1053 } while (err == MFX_WRN_IN_EXECUTION);
1054 if (err < 0) {
1057 }
1058
1059 return 0;
1060 }
1061
1064 {
1066 mfxFrameSurface1 in = {{ 0 }};
1067 mfxFrameSurface1 *
out = (mfxFrameSurface1*)dst->
data[3];
1068 mfxFrameInfo tmp_info;
1069
1070 mfxSyncPoint sync =
NULL;
1071 mfxStatus err;
1073 /* make a copy if the input is not padded as libmfx requires */
1074 AVFrame *tmp_frame = &
s->realigned_tmp_frame;
1076 int realigned = 0;
1077
1078
1079 while (!
s->session_upload_init && !
s->session_upload && !
ret) {
1080 #if HAVE_PTHREADS
1081 if (pthread_mutex_trylock(&
s->session_lock) == 0) {
1082 #endif
1083 if (!
s->session_upload_init) {
1085 if (
s->session_upload)
1086 s->session_upload_init = 1;
1087 }
1088 #if HAVE_PTHREADS
1091 } else {
1093 while (!
s->session_upload_init && !
s->session_upload) {
1095 }
1097 }
1098 #endif
1099 }
1102
1103 /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1104 * Height must be a multiple of 16 for progressive frame sequence and a
1105 * multiple of 32 otherwise.", so allign all frames to 16 before uploading. */
1106 if (
src->height & 15 ||
src->linesize[0] & 15) {
1107 realigned = 1;
1108 if (tmp_frame->format !=
src->format ||
1109 tmp_frame->width !=
FFALIGN(
src->width, 16) ||
1110 tmp_frame->height !=
FFALIGN(
src->height, 16)) {
1112
1113 tmp_frame->format =
src->format;
1115 tmp_frame->height =
FFALIGN(
src->height, 16);
1119 }
1124 }
1129 }
1130
1131 tmp_info =
out->Info;
1132 out->Info.CropW =
FFMIN(
out->Info.Width, tmp_frame->width);
1133 out->Info.CropH =
FFMIN(
out->Info.Height, tmp_frame->height);
1134 }
1135
1136 src_frame = realigned ? tmp_frame :
src;
1137
1138 if (!
s->session_upload) {
1139 if (
s->child_frames_ref)
1141
1144 }
1145
1146 in.Info =
out->Info;
1148
1149 do {
1150 err = MFXVideoVPP_RunFrameVPPAsync(
s->session_upload, &in,
out,
NULL, &sync);
1151 if (err == MFX_WRN_DEVICE_BUSY)
1153 } while (err == MFX_WRN_DEVICE_BUSY);
1154
1155 if (err < 0 || !sync) {
1158 }
1159
1160 do {
1161 err = MFXVideoCORE_SyncOperation(
s->session_upload, sync, 1000);
1162 } while (err == MFX_WRN_IN_EXECUTION);
1163 if (err < 0) {
1166 }
1167
1168 if (realigned) {
1169 out->Info.CropW = tmp_info.CropW;
1170 out->Info.CropH = tmp_info.CropH;
1171 }
1172
1173 return 0;
1174 }
1175
1178 {
1182
1185 "mapped to QSV frames.\n");
1187 }
1188
1190 #if CONFIG_VAAPI
1192 {
1195 sizeof(*
s->handle_pairs_internal));
1196 if (!
s->handle_pairs_internal)
1199 sizeof(*
s->surfaces_internal));
1200 if (!
s->surfaces_internal)
1205 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
1206 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
1207 }
1209 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1210 }
1211 break;
1212 #endif
1213 #if CONFIG_D3D11VA
1215 {
1218 sizeof(*
s->handle_pairs_internal));
1219 if (!
s->handle_pairs_internal)
1222 sizeof(*
s->surfaces_internal));
1223 if (!
s->surfaces_internal)
1228 if (src_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
1229 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
1230 } else {
1232 }
1233 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
1234 }
1236 if (src_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
1237 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1238 } else {
1239 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1240 }
1241 }
1242 break;
1243 #endif
1244 #if CONFIG_DXVA2
1246 {
1249 sizeof(*
s->handle_pairs_internal));
1250 if (!
s->handle_pairs_internal)
1253 sizeof(*
s->surfaces_internal));
1254 if (!
s->surfaces_internal)
1258 s->handle_pairs_internal[
i].first = (mfxMemId)src_hwctx->
surfaces[
i];
1259 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
1260 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
1261 }
1263 if (src_hwctx->
surface_type == DXVA2_VideoProcessorRenderTarget)
1264 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1265 else
1266 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1267 }
1268 break;
1269 #endif
1270 default:
1272 }
1273
1274 dst_hwctx->
surfaces =
s->surfaces_internal;
1275
1276 return 0;
1277 }
1278
1281 {
1284
1286 switch(
src->format) {
1287 #if CONFIG_VAAPI
1289 {
1290 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
1291 if (*(VASurfaceID*)pair->first == (VASurfaceID)
src->data[3]) {
1293 break;
1294 }
1295 }
1296 #endif
1297 #if CONFIG_D3D11VA
1299 {
1300 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
1301 if (pair->first ==
src->data[0]
1302 && pair->second ==
src->data[1]) {
1304 break;
1305 }
1306 }
1307 #endif
1308 #if CONFIG_DXVA2
1310 {
1311 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
1312 if (pair->first ==
src->data[3]) {
1314 break;
1315 }
1316 }
1317 #endif
1318 }
1319 }
1322 "is not in the mapped frames context.\n");
1324 }
1325
1328 if (err)
1329 return err;
1330
1334
1335 return 0;
1336 }
1337
1339 const void *hwconfig,
1341 {
1343
1348
1352
1356
1359
1360 return 0;
1361 }
1362
1364 {
1367
1370
1373 }
1374
1376 {
1377 static const struct {
1379 mfxIMPL impl;
1380 } impl_map[] = {
1381 { "auto", MFX_IMPL_AUTO },
1382 { "sw", MFX_IMPL_SOFTWARE },
1383 { "hw", MFX_IMPL_HARDWARE },
1384 { "auto_any", MFX_IMPL_AUTO_ANY },
1385 { "hw_any", MFX_IMPL_HARDWARE_ANY },
1386 { "hw2", MFX_IMPL_HARDWARE2 },
1387 { "hw3", MFX_IMPL_HARDWARE3 },
1388 { "hw4", MFX_IMPL_HARDWARE4 },
1389 };
1390
1391 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
1393
1394 if (device) {
1396 if (!strcmp(device, impl_map[
i].
name)) {
1397 impl = impl_map[
i].impl;
1398 break;
1399 }
1401 impl = strtol(device,
NULL, 0);
1402 }
1403
1404 if (impl != MFX_IMPL_SOFTWARE) {
1406 impl |= MFX_IMPL_VIA_D3D11;
1408 impl |= MFX_IMPL_VIA_D3D9;
1409 }
1410
1411 return impl;
1412 }
1413
1415 mfxIMPL implementation,
1418 {
1420
1421 mfxVersion ver = { { 3, 1 } };
1422 mfxHDL handle;
1423 mfxHandleType handle_type;
1424 mfxStatus err;
1426
1427 switch (child_device_ctx->
type) {
1428 #if CONFIG_VAAPI
1430 {
1432 handle_type = MFX_HANDLE_VA_DISPLAY;
1433 handle = (mfxHDL)child_device_hwctx->
display;
1434 }
1435 break;
1436 #endif
1437 #if CONFIG_D3D11VA
1439 {
1441 handle_type = MFX_HANDLE_D3D11_DEVICE;
1442 handle = (mfxHDL)child_device_hwctx->
device;
1443 }
1444 break;
1445 #endif
1446 #if CONFIG_DXVA2
1448 {
1450 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1451 handle = (mfxHDL)child_device_hwctx->
devmgr;
1452 }
1453 break;
1454 #endif
1455 default:
1458 }
1459
1460 err = MFXInit(implementation, &ver, &hwctx->
session);
1461 if (err != MFX_ERR_NONE) {
1463 "%d.\n", err);
1466 }
1467
1468 err = MFXQueryVersion(hwctx->
session, &ver);
1469 if (err != MFX_ERR_NONE) {
1473 }
1474
1476 "Initialize MFX session: API version is %d.%d, implementation version is %d.%d\n",
1477 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
1478
1480
1481 err = MFXInit(implementation, &ver, &hwctx->
session);
1482 if (err != MFX_ERR_NONE) {
1484 "Error initializing an MFX session: %d.\n", err);
1487 }
1488
1489 err = MFXVideoCORE_SetHandle(hwctx->
session, handle_type, handle);
1490 if (err != MFX_ERR_NONE) {
1492 "%d\n", err);
1495 }
1496
1497 return 0;
1498
1503 }
1504
1508 {
1509 mfxIMPL impl;
1512 child_device_ctx,
flags);
1513 }
1514
1517 {
1523
1524 mfxIMPL impl;
1526
1528 if (!priv)
1530
1531 ctx->user_opaque = priv;
1533
1535 if (e) {
1539 "\"%s\".\n", e->
value);
1541 }
1542 } else if (CONFIG_VAAPI) {
1544 } else if (CONFIG_DXVA2) {
1546 "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility "
1547 "with old commandlines. This behaviour will be removed "
1548 "in the future. Please explicitly set device type via \"-init_hw_device\" option.\n");
1550 } else if (CONFIG_D3D11VA) {
1552 } else {
1555 }
1556
1557 child_device_opts =
NULL;
1558 switch (child_device_type) {
1559 #if CONFIG_VAAPI
1561 {
1562 // libmfx does not actually implement VAAPI properly, rather it
1563 // depends on the specific behaviour of a matching iHD driver when
1564 // used on recent Intel hardware. Set options to the VAAPI device
1565 // creation so that we should pick a usable setup by default if
1566 // possible, even when multiple devices and drivers are available.
1567 av_dict_set(&child_device_opts,
"kernel_driver",
"i915", 0);
1568 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
1569 }
1570 break;
1571 #endif
1572 #if CONFIG_D3D11VA
1574 break;
1575 #endif
1576 #if CONFIG_DXVA2
1578 break;
1579 #endif
1580 default:
1581 {
1584 }
1585 break;
1586 }
1587
1590 e ? e->
value :
NULL, child_device_opts, 0);
1591
1595
1597
1599
1601 }
1602
1605 .name = "QSV",
1606
1611
1626
1628 };