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 <stdatomic.h>
20 #include <stdint.h>
21 #include <string.h>
22
23 #include <mfxvideo.h>
24
25 #include "config.h"
26
27 #if HAVE_PTHREADS
28 #include <pthread.h>
29 #endif
30
32 #if CONFIG_VAAPI
34 #endif
35 #if CONFIG_D3D11VA
37 #endif
38 #if CONFIG_DXVA2
39 #include <initguid.h>
41 #endif
42
54
55 #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \
56 (MFX_VERSION_MAJOR > (MAJOR) || \
57 MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
58
59 #define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
60 ((MFX_VERSION.Major > (MAJOR)) || \
61 (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR)))
62
63 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
64 #define QSV_ONEVPL QSV_VERSION_ATLEAST(2, 0)
65 #define QSV_HAVE_OPAQUE !QSV_ONEVPL
66
67 #if QSV_ONEVPL
68 #include <mfxdispatcher.h>
69 #else
70 #define MFXUnload(a) do { } while(0)
71 #endif
72
76
78 /**
79 * The public AVQSVDeviceContext. See hwcontext_qsv.h for it.
80 */
82
87
91
93 /**
94 * The public AVQSVFramesContext. See hwcontext_qsv.h for it.
95 */
97
102 #if HAVE_PTHREADS
104 #endif
105
110
111 // used in the frame allocator for non-opaque surfaces
113 #if QSV_HAVE_OPAQUE
114 // used in the opaque alloc request for opaque surfaces
116
119 #endif
122
125
130
131 static const struct {
141 MFX_FOURCC_YUY2, 0 },
142 #if CONFIG_VAAPI
144 MFX_FOURCC_UYVY, 0 },
145 #endif
147 MFX_FOURCC_Y210, 1 },
148 // VUYX is used for VAAPI child device,
149 // the SDK only delares support for AYUV
151 MFX_FOURCC_AYUV, 0 },
152 // XV30 is used for VAAPI child device,
153 // the SDK only delares support for Y410
155 MFX_FOURCC_Y410, 0 },
156 #if QSV_VERSION_ATLEAST(1, 31)
157 // P012 is used for VAAPI child device,
158 // the SDK only delares support for P016
160 MFX_FOURCC_P016, 1 },
161 // Y212 is used for VAAPI child device,
162 // the SDK only delares support for Y216
164 MFX_FOURCC_Y216, 1 },
165 // XV36 is used for VAAPI child device,
166 // the SDK only delares support for Y416
168 MFX_FOURCC_Y416, 1 },
169 #endif
170 };
171
174 void **base_handle);
175
177
178 /**
179 * Caller needs to allocate enough space for base_handle pointer.
180 **/
183 void **base_handle)
184 {
185 mfxHDLPair *handle_pair;
186 handle_pair = surf->Data.MemId;
187 switch (base_dev_type) {
188 #if CONFIG_VAAPI
190 base_handle[0] = handle_pair->first;
191 return 0;
192 #endif
193 #if CONFIG_D3D11VA
195 base_handle[0] = handle_pair->first;
196 base_handle[1] = handle_pair->second;
197 return 0;
198 #endif
199 #if CONFIG_DXVA2
201 base_handle[0] = handle_pair->first;
202 return 0;
203 #endif
204 }
206 }
207
209 {
214 }
215 return 0;
216 }
217
219 {
223 }
224
225 return 0;
226 }
227
228 #if CONFIG_D3D11VA
229 static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
230 {
231 uint32_t bind_flags = 0;
232
233 if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
234 bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
235 else
236 bind_flags = D3D11_BIND_DECODER;
237
238 if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) || (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
239 bind_flags = D3D11_BIND_RENDER_TARGET;
240
241 return bind_flags;
242 }
243 #endif
244
246 {
248 int i, planes_nb = 0;
249 if (
dst->format !=
src->format)
251
253
254 for (
i = 0;
i <
desc->nb_components;
i++)
255 planes_nb =
FFMAX(planes_nb,
desc->comp[
i].plane + 1);
256
257 for (
i = 0;
i < planes_nb;
i++) {
258 int sheight, dheight, y;
266 if (swidth < 0 || dwidth < 0) {
269 }
270 sheight =
src->height;
271 dheight =
dst->height;
275 }
276 //fill right padding
277 for (y = 0; y < sheight; y++) {
278 void *line_ptr =
dst->data[
i] + y*
dst->linesize[
i] + swidth;
280 comp.depth > 8 ? 2 : 1,
281 dwidth - swidth);
282 }
283 //fill bottom padding
284 for (y = sheight; y < dheight; y++) {
285 memcpy(
dst->data[
i]+y*
dst->linesize[
i],
286 dst->data[
i]+(sheight-1)*
dst->linesize[
i],
287 dwidth);
288 }
289 }
290 return 0;
291 }
292
294 {
297 int hw_handle_supported = 0;
298 mfxHandleType handle_type;
301 mfxStatus err;
302
303 err = MFXQueryIMPL(hwctx->
session, &
s->impl);
304 if (err == MFX_ERR_NONE)
305 err = MFXQueryVersion(hwctx->
session, &
s->ver);
306 if (err != MFX_ERR_NONE) {
309 }
310
312 #if CONFIG_VAAPI
313 handle_type = MFX_HANDLE_VA_DISPLAY;
316 hw_handle_supported = 1;
317 #endif
319 #if CONFIG_D3D11VA
320 handle_type = MFX_HANDLE_D3D11_DEVICE;
323 hw_handle_supported = 1;
324 #endif
326 #if CONFIG_DXVA2
327 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
330 hw_handle_supported = 1;
331 #endif
332 }
333
334 if (hw_handle_supported) {
335 err = MFXVideoCORE_GetHandle(hwctx->
session, handle_type, &
s->handle);
336 if (err == MFX_ERR_NONE) {
337 s->handle_type = handle_type;
338 s->child_device_type = device_type;
340 }
341 }
344 "from the session\n");
345 }
346 return 0;
347 }
348
350 {
352
353 if (
s->session_download) {
354 MFXVideoVPP_Close(
s->session_download);
355 MFXClose(
s->session_download);
356 }
357 s->session_download =
NULL;
358 s->session_download_init = 0;
359
360 if (
s->session_upload) {
361 MFXVideoVPP_Close(
s->session_upload);
362 MFXClose(
s->session_upload);
363 }
364 s->session_upload =
NULL;
365 s->session_upload_init = 0;
366
367 #if HAVE_PTHREADS
369 #endif
370
372 #if QSV_HAVE_OPAQUE
374 #endif
380 }
381
383 {
384 }
385
387 {
391 mfxHDLPair *hdl_pair = (mfxHDLPair *)qsv_surface->
mfx_surface.Data.MemId;
393
394 if (!
s->child_frames_ref)
395 return;
396
398 if (!child_frames_ctx->device_ctx)
399 return;
400
401 #if CONFIG_VAAPI
404 #endif
405
409 }
410
412 {
416
418 s->nb_surfaces_used++;
421 }
422
424 }
425
427 {
432 mfxHDLPair *handle_pairs_internal =
NULL;
434
435 if (!
s->child_frames_ref)
437
441
442 #if CONFIG_DXVA2
445 "QSV on dxva2 requires a fixed frame pool size\n");
447 }
448 #endif
449
450 qsv_surface =
av_calloc(1,
sizeof(*qsv_surface));
451 if (!qsv_surface)
453
457
461
462 handle_pairs_internal =
av_calloc(1,
sizeof(*handle_pairs_internal));
463 if (!handle_pairs_internal)
465
469
470 #if CONFIG_VAAPI
472 VASurfaceID *surface_id_internal;
473
474 surface_id_internal =
av_calloc(1,
sizeof(*surface_id_internal));
475 if (!surface_id_internal)
477
478 *surface_id_internal = (VASurfaceID)(uintptr_t)qsv_surface->
child_frame->
data[3];
479 handle_pairs_internal->first = (mfxHDL)surface_id_internal;
480 handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
481 }
482 #endif
483
484 #if CONFIG_D3D11VA
487 handle_pairs_internal->first = (mfxMemId)qsv_surface->
child_frame->
data[0];
488
489 if (child_frames_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET)
490 handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
491 else
492 handle_pairs_internal->second = (mfxMemId)qsv_surface->
child_frame->
data[1];
493
494 }
495 #endif
496
497 qsv_surface->
mfx_surface.Data.MemId = (mfxMemId)handle_pairs_internal;
500
502 if (qsv_surface) {
504 }
505
508
510 }
511
513 {
516
519 } else {
521 }
522 }
523
525 {
529
532
535
537
538 if (!device_priv->
handle) {
540 "Cannot create a non-opaque internal surface pool without "
541 "a hardware handle\n");
543 }
544
546 if (!child_device_ref)
549
550 #if CONFIG_VAAPI
553 child_device_hwctx->
display = (VADisplay)device_priv->
handle;
554 }
555 #endif
556 #if CONFIG_D3D11VA
561 }
562 #endif
563 #if CONFIG_DXVA2
566 child_device_hwctx->
devmgr = (IDirect3DDeviceManager9*)device_priv->
handle;
567 }
568 #endif
569
574 }
575
577 if (!child_frames_ref) {
580 }
582
588
589 #if CONFIG_D3D11VA
593 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
594 if (hwctx->
frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
595 child_frames_hwctx->
MiscFlags = D3D11_RESOURCE_MISC_SHARED;
597 }
598 #endif
599 #if CONFIG_DXVA2
602 if (hwctx->
frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
603 child_frames_hwctx->
surface_type = DXVA2_VideoProcessorRenderTarget;
604 else
605 child_frames_hwctx->
surface_type = DXVA2_VideoDecoderRenderTarget;
606 }
607 #endif
608
613 }
614
615 #if CONFIG_VAAPI
618 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
619 s->handle_pairs_internal[
i].first = child_frames_hwctx->
surface_ids +
i;
620 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
621 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
622 }
623 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
624 }
625 #endif
626 #if CONFIG_D3D11VA
629 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
631 if(child_frames_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
632 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
633 } else {
635 }
636 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
637 }
638 if (child_frames_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
639 hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
640 } else {
641 hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
642 }
643 }
644 #endif
645 #if CONFIG_DXVA2
648 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
649 s->handle_pairs_internal[
i].first = (mfxMemId)child_frames_hwctx->
surfaces[
i];
650 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
651 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
652 }
653 if (child_frames_hwctx->
surface_type == DXVA2_VideoProcessorRenderTarget)
654 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
655 else
656 hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
657 }
658 #endif
659
660 s->child_frames_ref = child_frames_ref;
661 child_frames_ref =
NULL;
662
667 }
668
670 {
673
677
681
682 surf->Info.BitDepthLuma =
desc->comp[0].depth;
683 surf->Info.BitDepthChroma =
desc->comp[0].depth;
685
686 if (
desc->log2_chroma_w &&
desc->log2_chroma_h)
687 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
688 else if (
desc->log2_chroma_w)
689 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
690 else
691 surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
692
693 surf->Info.FourCC =
fourcc;
695 surf->Info.CropW =
ctx->width;
697 surf->Info.CropH =
ctx->height;
698 surf->Info.FrameRateExtN = 25;
699 surf->Info.FrameRateExtD = 1;
700 surf->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
701
702 return 0;
703 }
704
706 {
709
711
712 if (
ctx->initial_pool_size < 0) {
715 }
else if (
ctx->initial_pool_size == 0) {
716 mfxFrameSurface1 mfx_surf1;
717
721
726
727 memset(&mfx_surf1, 0, sizeof(mfx_surf1));
729 s->frame_info = mfx_surf1.Info;
730 frames_hwctx->
info = &
s->frame_info;
732
733 return 0;
734 }
735
737 sizeof(*
s->handle_pairs_internal));
738 if (!
s->handle_pairs_internal)
740
742 sizeof(*
s->surfaces_internal));
743 if (!
s->surfaces_internal)
745
746 for (
i = 0;
i <
ctx->initial_pool_size;
i++) {
750 }
751
752 #if QSV_HAVE_OPAQUE
753 if (!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
757 }
758 #else
762 #endif
763
768
769 frames_hwctx->
surfaces =
s->surfaces_internal;
771
772 return 0;
773 }
774
775 static mfxStatus
frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
776 mfxFrameAllocResponse *resp)
777 {
781 mfxFrameInfo *
i = &req->Info;
783
784 if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
785 !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
786 !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
787 return MFX_ERR_UNSUPPORTED;
788 if (
i->Width > i1->Width ||
i->Height > i1->Height ||
789 i->FourCC != i1->FourCC ||
i->ChromaFormat != i1->ChromaFormat) {
791 "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
792 i->Width,
i->Height,
i->FourCC,
i->ChromaFormat,
793 i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
794 return MFX_ERR_UNSUPPORTED;
795 }
796
797 resp->mids =
s->mem_ids;
799
800 return MFX_ERR_NONE;
801 }
802
803 static mfxStatus
frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
804 {
805 return MFX_ERR_NONE;
806 }
807
808 static mfxStatus
frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
809 {
810 return MFX_ERR_UNSUPPORTED;
811 }
812
813 static mfxStatus
frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
814 {
815 return MFX_ERR_UNSUPPORTED;
816 }
817
819 {
820 mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
821 mfxHDLPair *pair_src = (mfxHDLPair*)mid;
822
823 pair_dst->first = pair_src->first;
824
825 if (pair_src->second != (mfxMemId)MFX_INFINITE)
826 pair_dst->second = pair_src->second;
827 return MFX_ERR_NONE;
828 }
829
830 #if QSV_ONEVPL
831
832 static int qsv_d3d11_update_config(
void *
ctx, mfxHDL handle, mfxConfig cfg)
833 {
835 #if CONFIG_D3D11VA
836 mfxStatus sts;
837 IDXGIAdapter *pDXGIAdapter;
838 DXGI_ADAPTER_DESC adapterDesc;
839 IDXGIDevice *pDXGIDevice =
NULL;
840 HRESULT hr;
842 mfxVariant impl_value = {0};
843
844 hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void**)&pDXGIDevice);
845 if (SUCCEEDED(hr)) {
846 hr = IDXGIDevice_GetAdapter(pDXGIDevice, &pDXGIAdapter);
847 if (FAILED(hr)) {
849 IDXGIDevice_Release(pDXGIDevice);
851 }
852
853 hr = IDXGIAdapter_GetDesc(pDXGIAdapter, &adapterDesc);
854 if (FAILED(hr)) {
857 }
858 } else {
861 }
862
863 impl_value.Type = MFX_VARIANT_TYPE_U16;
864 impl_value.Data.U16 = adapterDesc.DeviceId;
865 sts = MFXSetConfigFilterProperty(cfg,
866 (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
867 if (sts != MFX_ERR_NONE) {
869 "DeviceID property: %d.\n", sts);
871 }
872
873 impl_value.Type = MFX_VARIANT_TYPE_PTR;
874 impl_value.Data.Ptr = &adapterDesc.AdapterLuid;
875 sts = MFXSetConfigFilterProperty(cfg,
876 (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
877 if (sts != MFX_ERR_NONE) {
879 "DeviceLUID property: %d.\n", sts);
881 }
882
883 impl_value.Type = MFX_VARIANT_TYPE_U32;
884 impl_value.Data.U32 = 0x0001;
885 sts = MFXSetConfigFilterProperty(cfg,
886 (const mfxU8 *)"mfxExtendedDeviceId.LUIDDeviceNodeMask", impl_value);
887 if (sts != MFX_ERR_NONE) {
889 "LUIDDeviceNodeMask property: %d.\n", sts);
891 }
892
894
896 IDXGIAdapter_Release(pDXGIAdapter);
897 IDXGIDevice_Release(pDXGIDevice);
898 #endif
900 }
901
902 static int qsv_d3d9_update_config(
void *
ctx, mfxHDL handle, mfxConfig cfg)
903 {
905 #if CONFIG_DXVA2
906 mfxStatus sts;
907 IDirect3DDeviceManager9* devmgr = handle;
908 IDirect3DDevice9 *device =
NULL;
909 IDirect3DDevice9Ex *device_ex =
NULL;
910 HANDLE device_handle = 0;
911 IDirect3D9Ex *d3d9ex =
NULL;
912 IDirect3D9 *d3d9 =
NULL;
913 LUID luid;
914 D3DDEVICE_CREATION_PARAMETERS params;
915 HRESULT hr;
916 mfxVariant impl_value = {0};
917
918 hr = IDirect3DDeviceManager9_OpenDeviceHandle(devmgr, &device_handle);
919 if (FAILED(hr)) {
922 }
923
924 hr = IDirect3DDeviceManager9_LockDevice(devmgr, device_handle, &device, TRUE);
925 if (FAILED(hr)) {
927 IDirect3DDeviceManager9_CloseDeviceHandle(devmgr, device_handle);
929 }
930 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **)&device_ex);
931 IDirect3DDevice9_Release(device);
932 if (FAILED(hr)) {
934 goto unlock;
935 }
936
937 hr = IDirect3DDevice9Ex_GetCreationParameters(device_ex, ¶ms);
938 if (FAILED(hr)) {
940 IDirect3DDevice9Ex_Release(device_ex);
941 goto unlock;
942 }
943
944 hr = IDirect3DDevice9Ex_GetDirect3D(device_ex, &d3d9);
945 if (FAILED(hr)) {
947 IDirect3DDevice9Ex_Release(device_ex);
948 goto unlock;
949 }
950 hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **)&d3d9ex);
951 IDirect3D9_Release(d3d9);
952 if (FAILED(hr)) {
954 IDirect3DDevice9Ex_Release(device_ex);
955 goto unlock;
956 }
957
958 hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, params.AdapterOrdinal, &luid);
959 if (FAILED(hr)) {
961 goto release;
962 }
963
964 impl_value.Type = MFX_VARIANT_TYPE_PTR;
965 impl_value.Data.Ptr = &luid;
966 sts = MFXSetConfigFilterProperty(cfg,
967 (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
968 if (sts != MFX_ERR_NONE) {
970 "DeviceLUID property: %d.\n", sts);
971 goto release;
972 }
973
975
976 release:
977 IDirect3D9Ex_Release(d3d9ex);
978 IDirect3DDevice9Ex_Release(device_ex);
979
980 unlock:
981 IDirect3DDeviceManager9_UnlockDevice(devmgr, device_handle, FALSE);
982 IDirect3DDeviceManager9_CloseDeviceHandle(devmgr, device_handle);
984 #endif
986 }
987
988 static int qsv_va_update_config(
void *
ctx, mfxHDL handle, mfxConfig cfg)
989 {
990 #if CONFIG_VAAPI
991 #if VA_CHECK_VERSION(1, 15, 0)
992 mfxStatus sts;
993 VADisplay dpy = handle;
994 VAStatus vas;
995 VADisplayAttribute attr = {
996 .type = VADisplayPCIID,
997 };
998 mfxVariant impl_value = {0};
999
1000 vas = vaGetDisplayAttributes(dpy, &attr, 1);
1001 if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
1002 impl_value.Type = MFX_VARIANT_TYPE_U16;
1003 impl_value.Data.U16 = (attr.value & 0xFFFF);
1004 sts = MFXSetConfigFilterProperty(cfg,
1005 (const mfxU8 *)"mfxImplDescription.mfxDeviceDescription.DeviceID", impl_value);
1006 if (sts != MFX_ERR_NONE) {
1008 "DeviceID property: %d.\n", sts);
1010 }
1011 } else {
1013 "consider to upgrade the driver to support VA-API 1.15.0\n");
1015 }
1016
1017 return 0;
1018
1020 #else
1022 "the device information from the driver. Please consider to upgrade libva to "
1023 "support VA-API 1.15.0\n");
1024 #endif
1025 #endif
1027 }
1028
1029 static int qsv_new_mfx_loader(
void *
ctx,
1030 mfxHDL handle,
1031 mfxHandleType handle_type,
1032 mfxIMPL implementation,
1033 mfxVersion *pver,
1034 void **ploader)
1035 {
1036 mfxStatus sts;
1037 mfxLoader loader =
NULL;
1038 mfxConfig cfg;
1039 mfxVariant impl_value = {0};
1040
1042 loader = MFXLoad();
1043 if (!loader) {
1046 }
1047
1048 /* Create configurations for implementation */
1049 cfg = MFXCreateConfig(loader);
1050 if (!cfg) {
1053 }
1054
1055 impl_value.Type = MFX_VARIANT_TYPE_U32;
1056 impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
1057 MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
1058 sts = MFXSetConfigFilterProperty(cfg,
1059 (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
1060 if (sts != MFX_ERR_NONE) {
1062 "property: %d.\n", sts);
1064 }
1065
1066 impl_value.Type = MFX_VARIANT_TYPE_U32;
1067 impl_value.Data.U32 = pver->Version;
1068 sts = MFXSetConfigFilterProperty(cfg,
1069 (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
1070 impl_value);
1071 if (sts != MFX_ERR_NONE) {
1073 "property: %d.\n", sts);
1075 }
1076
1077 impl_value.Type = MFX_VARIANT_TYPE_U32;
1078 impl_value.Data.U32 = 0x8086; // Intel device only
1079 sts = MFXSetConfigFilterProperty(cfg,
1080 (const mfxU8 *)"mfxImplDescription.VendorID", impl_value);
1081 if (sts != MFX_ERR_NONE) {
1083 "VendorID property: %d.\n", sts);
1085 }
1086
1087 if (MFX_HANDLE_VA_DISPLAY == handle_type) {
1088 if (handle && qsv_va_update_config(
ctx, handle, cfg))
1090
1091 impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_VAAPI;
1092 } else if (MFX_HANDLE_D3D9_DEVICE_MANAGER == handle_type) {
1093 if (handle && qsv_d3d9_update_config(
ctx, handle, cfg))
1095
1096 impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D9;
1097 } else {
1098 if (handle && qsv_d3d11_update_config(
ctx, handle, cfg))
1100
1101 impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D11;
1102 }
1103
1104 impl_value.Type = MFX_VARIANT_TYPE_U32;
1105 sts = MFXSetConfigFilterProperty(cfg,
1106 (const mfxU8 *)"mfxImplDescription.AccelerationMode", impl_value);
1107 if (sts != MFX_ERR_NONE) {
1109 "AccelerationMode property: %d.\n", sts);
1111 }
1112
1113 *ploader = loader;
1114
1115 return 0;
1116
1118 if (loader)
1120
1122 }
1123
1124 static int qsv_create_mfx_session_from_loader(
void *
ctx, mfxLoader loader, mfxSession *psession)
1125 {
1126 mfxStatus sts;
1127 mfxSession session =
NULL;
1128 uint32_t impl_idx = 0;
1129 mfxVersion ver;
1130
1131 while (1) {
1132 /* Enumerate all implementations */
1133 mfxImplDescription *impl_desc;
1134
1135 sts = MFXEnumImplementations(loader, impl_idx,
1136 MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
1137 (mfxHDL *)&impl_desc);
1138 /* Failed to find an available implementation */
1139 if (sts == MFX_ERR_NOT_FOUND)
1140 break;
1141 else if (sts != MFX_ERR_NONE) {
1142 impl_idx++;
1143 continue;
1144 }
1145
1146 sts = MFXCreateSession(loader, impl_idx, &session);
1147 MFXDispReleaseImplDescription(loader, impl_desc);
1148 if (sts == MFX_ERR_NONE)
1149 break;
1150
1151 impl_idx++;
1152 }
1153
1154 if (sts != MFX_ERR_NONE) {
1157 }
1158
1159 sts = MFXQueryVersion(session, &ver);
1160 if (sts != MFX_ERR_NONE) {
1163 }
1164
1166 "version is %d.%d\n", ver.Major, ver.Minor);
1167
1168 *psession = session;
1169
1170 return 0;
1171
1173 if (session)
1174 MFXClose(session);
1175
1177 }
1178
1180 mfxHDL handle,
1181 mfxHandleType handle_type,
1182 mfxIMPL implementation,
1183 mfxVersion *pver,
1184 mfxSession *psession,
1185 void **ploader)
1186 {
1187 mfxLoader loader =
NULL;
1188
1190 "Use Intel(R) oneVPL to create MFX session, API version is "
1191 "%d.%d, the required implementation version is %d.%d\n",
1192 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1193
1194 if (handle_type != MFX_HANDLE_VA_DISPLAY &&
1195 handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER &&
1196 handle_type != MFX_HANDLE_D3D11_DEVICE) {
1198 "Invalid MFX device handle type\n");
1200 }
1201
1203
1204 if (!*ploader) {
1205 if (qsv_new_mfx_loader(
ctx, handle, handle_type, implementation, pver, (
void **)&loader))
1207
1209 } else
1210 loader = *ploader; // Use the input mfxLoader to create mfx session
1211
1212 if (qsv_create_mfx_session_from_loader(
ctx, loader, psession))
1214
1215 if (!*ploader)
1216 *ploader = loader;
1217
1218 return 0;
1219
1221 if (!*ploader && loader)
1223
1225 }
1226
1227 #else
1228
1230 mfxHDL handle,
1231 mfxHandleType handle_type,
1232 mfxIMPL implementation,
1233 mfxVersion *pver,
1234 mfxSession *psession,
1235 void **ploader)
1236 {
1237 mfxVersion ver;
1238 mfxStatus sts;
1239 mfxSession session =
NULL;
1240
1242 "Use Intel(R) Media SDK to create MFX session, API version is "
1243 "%d.%d, the required implementation version is %d.%d\n",
1244 MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1245
1248 ver = *pver;
1249 sts = MFXInit(implementation, &ver, &session);
1250 if (sts != MFX_ERR_NONE) {
1252 "%d.\n", sts);
1254 }
1255
1256 sts = MFXQueryVersion(session, &ver);
1257 if (sts != MFX_ERR_NONE) {
1259 "%d.\n", sts);
1261 }
1262
1264 "version is %d.%d\n", ver.Major, ver.Minor);
1265
1266 MFXClose(session);
1267
1268 sts = MFXInit(implementation, &ver, &session);
1269 if (sts != MFX_ERR_NONE) {
1271 "%d.\n", sts);
1273 }
1274
1275 *psession = session;
1276
1277 return 0;
1278
1280 if (session)
1281 MFXClose(session);
1282
1284 }
1285
1286 #endif
1287
1289 mfxSession *session, int upload)
1290 {
1295 int opaque = 0;
1296
1297 mfxFrameAllocator frame_allocator = {
1304 };
1305
1306 mfxVideoParam par;
1307 mfxStatus err;
1309 /* hwctx->loader is non-NULL for oneVPL user and NULL for non-oneVPL user */
1310 void **loader = &hwctx->
loader;
1311 mfxSession parent_session = hwctx->
session;
1312 mfxIMPL impl;
1313 mfxVersion ver;
1314
1315 err = MFXQueryIMPL(parent_session, &impl);
1316 if (err == MFX_ERR_NONE)
1317 err = MFXQueryVersion(parent_session, &ver);
1318 if (err != MFX_ERR_NONE) {
1321 }
1322
1323 #if QSV_HAVE_OPAQUE
1324 opaque = !!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
1325 #endif
1326
1328 device_priv->
impl, &device_priv->
ver, session, loader);
1331
1332 if (device_priv->
handle) {
1333 err = MFXVideoCORE_SetHandle(*session, device_priv->
handle_type,
1335 if (err != MFX_ERR_NONE) {
1338 }
1339 }
1340
1342 err = MFXJoinSession(parent_session, *session);
1343 if (err != MFX_ERR_NONE) {
1347 }
1348 }
1349
1350 if (!opaque) {
1351 err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
1352 if (err != MFX_ERR_NONE) {
1355 }
1356 }
1357
1358 memset(&par, 0, sizeof(par));
1359
1360 if (!opaque) {
1361 par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
1362 MFX_IOPATTERN_IN_VIDEO_MEMORY;
1363 }
1364 #if QSV_HAVE_OPAQUE
1365 else {
1366 par.ExtParam =
s->ext_buffers;
1368 par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY :
1369 MFX_IOPATTERN_IN_OPAQUE_MEMORY;
1370 }
1371 #endif
1372
1373 par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY :
1374 MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
1375 par.AsyncDepth = 1;
1376
1378
1379 /* Apparently VPP requires the frame rate to be set to some value, otherwise
1380 * init will fail (probably for the framerate conversion filter). Since we
1381 * are only doing data upload/download here, we just invent an arbitrary
1382 * value */
1383 par.vpp.In.FrameRateExtN = 25;
1384 par.vpp.In.FrameRateExtD = 1;
1385 par.vpp.Out = par.vpp.In;
1386
1387 err = MFXVideoVPP_Init(*session, &par);
1388 if (err != MFX_ERR_NONE) {
1390 "Surface upload/download will not be possible\n");
1391
1394 }
1395
1396 return 0;
1397
1399 if (*session)
1400 MFXClose(*session);
1401
1403
1405 }
1406
1408 {
1411
1412 int opaque = 0;
1413
1416
1417 #if QSV_HAVE_OPAQUE
1418 opaque = !!(frames_hwctx->
frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
1419 #endif
1420
1425 }
1426
1432 }
1433 }
1434
1435 if (!opaque) {
1439
1441 s->mem_ids[
i] = frames_hwctx->
surfaces[
i].Data.MemId;
1442 }
1443 #if QSV_HAVE_OPAQUE
1444 else {
1446 sizeof(*
s->surface_ptrs));
1447 if (!
s->surface_ptrs)
1449
1452
1453 s->opaque_alloc.In.Surfaces =
s->surface_ptrs;
1454 s->opaque_alloc.In.NumSurface = frames_hwctx->
nb_surfaces;
1455 s->opaque_alloc.In.Type = frames_hwctx->
frame_type;
1456
1457 s->opaque_alloc.Out =
s->opaque_alloc.In;
1458
1459 s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
1460 s->opaque_alloc.Header.BufferSz =
sizeof(
s->opaque_alloc);
1461
1462 s->ext_buffers[0] = (mfxExtBuffer*)&
s->opaque_alloc;
1463 }
1464 #endif
1465
1466 s->session_download =
NULL;
1467 s->session_upload =
NULL;
1468
1469 s->session_download_init = 0;
1470 s->session_upload_init = 0;
1471
1472 #if HAVE_PTHREADS
1474 #endif
1475
1476 return 0;
1477 }
1478
1480 {
1484
1489
1490 return 0;
1491 }
1492
1496 {
1498
1500 if (!fmts)
1502
1503 fmts[0] =
ctx->sw_format;
1505
1507
1508 return 0;
1509 }
1510
1513 {
1516
1518 #if CONFIG_VAAPI
1520 {
1527 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
1528 dst_hwctx->
surface_ids[
i] = *(VASurfaceID*)pair->first;
1529 }
1531 }
1532 break;
1533 #endif
1534 #if CONFIG_D3D11VA
1536 {
1537 D3D11_TEXTURE2D_DESC texDesc;
1540 dst_hwctx = dst_ctx->
hwctx;
1545 if (src_hwctx->
frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
1546 dst_hwctx->
MiscFlags = D3D11_RESOURCE_MISC_SHARED;
1548 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
1550 dst_hwctx->
texture_infos[
i].
index = pair->second == (mfxMemId)MFX_INFINITE ? (intptr_t)0 : (intptr_t)pair->second;
1551 }
1554 dst_hwctx->
BindFlags = texDesc.BindFlags;
1555 } else
1557 }
1558 break;
1559 #endif
1560 #if CONFIG_DXVA2
1562 {
1569 mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->
surfaces[
i].Data.MemId;
1570 dst_hwctx->
surfaces[
i] = (IDirect3DSurface9*)pair->first;
1571 }
1573 if (src_hwctx->
frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
1574 dst_hwctx->
surface_type = DXVA2_VideoDecoderRenderTarget;
1575 else
1576 dst_hwctx->
surface_type = DXVA2_VideoProcessorRenderTarget;
1577 }
1578 break;
1579 #endif
1580 default:
1582 }
1583
1584 return 0;
1585 }
1586
1589 {
1591 mfxFrameSurface1 *surf = (mfxFrameSurface1*)
src->data[3];
1594 uint8_t *child_data;
1597
1598 if (!
s->child_frames_ref)
1601
1602 switch (child_frames_ctx->device_ctx->type) {
1603 #if CONFIG_VAAPI
1605 {
1606 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1607 /* pair->first is *VASurfaceID while data[3] in vaapi frame is VASurfaceID, so
1608 * we need this casting for vaapi.
1609 * Add intptr_t to force cast from VASurfaceID(uint) type to pointer(long) type
1610 * to avoid compile warning */
1611 child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)pair->first;
1612 break;
1613 }
1614 #endif
1615 #if CONFIG_D3D11VA
1617 {
1618 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1619 child_data = pair->first;
1620 break;
1621 }
1622 #endif
1623 #if CONFIG_DXVA2
1625 {
1626 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1627 child_data = pair->first;
1628 break;
1629 }
1630 #endif
1631 default:
1633 }
1634
1635 if (
dst->format == child_frames_ctx->format) {
1640
1642 dst->height =
src->height;
1643
1645 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1646 dst->data[0] = pair->first;
1647 dst->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second;
1648 } else {
1649 dst->data[3] = child_data;
1650 }
1651
1652 return 0;
1653 }
1654
1657 // This only supports mapping to software.
1659 }
1660
1664
1669
1670 dummy->format = child_frames_ctx->format;
1673
1675 mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1676 dummy->data[0] = pair->first;
1677 dummy->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second;
1678 } else {
1679 dummy->data[3] = child_data;
1680 }
1681
1683
1686
1688 }
1689
1692 {
1695 int download = !!
src->hw_frames_ctx;
1696 mfxFrameSurface1 *surf = (mfxFrameSurface1*)(download ?
src->data[3] :
dst->data[3]);
1697
1700
1704
1708 dummy->buf[0] = download ?
src->buf[0] :
dst->buf[0];
1709 dummy->data[3] = surf->Data.MemId;
1710 dummy->hw_frames_ctx =
s->child_frames_ref;
1711
1714
1718
1720
1722 }
1723
1725 {
1726 switch (
frame->format) {
1730 surface->Data.Y =
frame->data[0];
1731 surface->Data.UV =
frame->data[1];
1732 break;
1733
1735 surface->Data.Y =
frame->data[0];
1736 surface->Data.U =
frame->data[1];
1737 surface->Data.V =
frame->data[2];
1738 break;
1739
1741 surface->Data.B =
frame->data[0];
1742 surface->Data.G =
frame->data[0] + 1;
1743 surface->Data.R =
frame->data[0] + 2;
1744 surface->Data.A =
frame->data[0] + 3;
1745 break;
1747 surface->Data.Y =
frame->data[0];
1748 surface->Data.U =
frame->data[0] + 1;
1749 surface->Data.V =
frame->data[0] + 3;
1750 break;
1751
1754 surface->Data.Y16 = (mfxU16 *)
frame->data[0];
1755 surface->Data.U16 = (mfxU16 *)
frame->data[0] + 1;
1756 surface->Data.V16 = (mfxU16 *)
frame->data[0] + 3;
1757 break;
1759 surface->Data.V =
frame->data[0];
1760 surface->Data.U =
frame->data[0] + 1;
1761 surface->Data.Y =
frame->data[0] + 2;
1762 // Only set Data.A to a valid address, the SDK doesn't
1763 // use the value from the frame.
1764 surface->Data.A =
frame->data[0] + 3;
1765 break;
1767 surface->Data.U =
frame->data[0];
1768 break;
1770 surface->Data.U =
frame->data[0];
1771 surface->Data.Y =
frame->data[0] + 2;
1772 surface->Data.V =
frame->data[0] + 4;
1773 // Only set Data.A to a valid address, the SDK doesn't
1774 // use the value from the frame.
1775 surface->Data.A =
frame->data[0] + 6;
1776 break;
1777 #if CONFIG_VAAPI
1779 surface->Data.Y =
frame->data[0] + 1;
1780 surface->Data.U =
frame->data[0];
1781 surface->Data.V =
frame->data[0] + 2;
1782 break;
1783 #endif
1784 default:
1785 return MFX_ERR_UNSUPPORTED;
1786 }
1787 surface->Data.Pitch =
frame->linesize[0];
1788 surface->Data.TimeStamp =
frame->pts;
1789
1790 return 0;
1791 }
1792
1794 {
1796 atomic_int *inited = upload ? &
s->session_upload_init : &
s->session_download_init;
1797 mfxSession *session = upload ? &
s->session_upload : &
s->session_download;
1799
1801 return 0;
1802
1803 #if HAVE_PTHREADS
1805 #endif
1806
1810 }
1811
1812 #if HAVE_PTHREADS
1814 #endif
1815
1817 }
1818
1821 {
1823 mfxFrameSurface1
out = {{ 0 }};
1824 mfxFrameSurface1 *in = (mfxFrameSurface1*)
src->data[3];
1825
1826 mfxSyncPoint sync =
NULL;
1827 mfxStatus err;
1829 /* download to temp frame if the output is not padded as libmfx requires */
1830 AVFrame *tmp_frame = &
s->realigned_download_frame;
1832 int realigned = 0;
1833
1837
1838 /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1839 * Height must be a multiple of 16 for progressive frame sequence and a
1840 * multiple of 32 otherwise.", so allign all frames to 16 before downloading. */
1841 if (
dst->height & 15 ||
dst->linesize[0] & 15) {
1842 realigned = 1;
1843 if (tmp_frame->format !=
dst->format ||
1844 tmp_frame->width !=
FFALIGN(
dst->linesize[0], 16) ||
1845 tmp_frame->height !=
FFALIGN(
dst->height, 16)) {
1847
1848 tmp_frame->format =
dst->format;
1849 tmp_frame->width =
FFALIGN(
dst->linesize[0], 16);
1850 tmp_frame->height =
FFALIGN(
dst->height, 16);
1854 }
1855 }
1856
1857 dst_frame = realigned ? tmp_frame :
dst;
1858
1859 if (!
s->session_download) {
1860 if (
s->child_frames_ref)
1862
1865 }
1866
1867 out.Info = in->Info;
1869
1870 do {
1871 err = MFXVideoVPP_RunFrameVPPAsync(
s->session_download, in, &
out,
NULL, &sync);
1872 if (err == MFX_WRN_DEVICE_BUSY)
1874 } while (err == MFX_WRN_DEVICE_BUSY);
1875
1876 if (err < 0 || !sync) {
1879 }
1880
1881 do {
1882 err = MFXVideoCORE_SyncOperation(
s->session_download, sync, 1000);
1883 } while (err == MFX_WRN_IN_EXECUTION);
1884 if (err < 0) {
1887 }
1888
1889 if (realigned) {
1890 tmp_frame->width =
dst->width;
1891 tmp_frame->height =
dst->height;
1893 tmp_frame->width =
FFALIGN(
dst->linesize[0], 16);
1894 tmp_frame->height =
FFALIGN(
dst->height, 16);
1897 }
1898
1899 return 0;
1900 }
1901
1904 {
1906 mfxFrameSurface1 in = {{ 0 }};
1907 mfxFrameSurface1 *
out = (mfxFrameSurface1*)
dst->data[3];
1908 mfxFrameInfo tmp_info;
1909
1910 mfxSyncPoint sync =
NULL;
1911 mfxStatus err;
1913 /* make a copy if the input is not padded as libmfx requires */
1914 AVFrame *tmp_frame = &
s->realigned_upload_frame;
1916 int realigned = 0;
1917
1921
1922 /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1923 * Height must be a multiple of 16 for progressive frame sequence and a
1924 * multiple of 32 otherwise.", so allign all frames to 16 before uploading. */
1925 if (
src->height & 15 ||
src->linesize[0] & 15) {
1926 realigned = 1;
1927 if (tmp_frame->format !=
src->format ||
1928 tmp_frame->width !=
FFALIGN(
src->width, 16) ||
1929 tmp_frame->height !=
FFALIGN(
src->height, 16)) {
1931
1932 tmp_frame->format =
src->format;
1934 tmp_frame->height =
FFALIGN(
src->height, 16);
1938 }
1943 }
1948 }
1949
1950 tmp_info =
out->Info;
1951 out->Info.CropW =
FFMIN(
out->Info.Width, tmp_frame->width);
1952 out->Info.CropH =
FFMIN(
out->Info.Height, tmp_frame->height);
1953 }
1954
1955 src_frame = realigned ? tmp_frame :
src;
1956
1957 if (!
s->session_upload) {
1958 if (
s->child_frames_ref)
1960
1963 }
1964
1965 in.Info =
out->Info;
1967
1968 do {
1969 err = MFXVideoVPP_RunFrameVPPAsync(
s->session_upload, &in,
out,
NULL, &sync);
1970 if (err == MFX_WRN_DEVICE_BUSY)
1972 } while (err == MFX_WRN_DEVICE_BUSY);
1973
1974 if (err < 0 || !sync) {
1977 }
1978
1979 do {
1980 err = MFXVideoCORE_SyncOperation(
s->session_upload, sync, 1000);
1981 } while (err == MFX_WRN_IN_EXECUTION);
1982 if (err < 0) {
1985 }
1986
1987 if (realigned) {
1988 out->Info.CropW = tmp_info.CropW;
1989 out->Info.CropH = tmp_info.CropH;
1990 }
1991
1992 return 0;
1993 }
1994
1997 {
2000 mfxFrameSurface1 mfx_surf1;
2001
2003 #if CONFIG_VAAPI
2005 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
2006 break;
2007 #endif
2008
2009 #if CONFIG_D3D11VA
2011 {
2013
2014 if (src_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
2015 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
2016 } else {
2017 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
2018 }
2019 }
2020 break;
2021 #endif
2022
2023 default:
2025 }
2026
2027 memset(&mfx_surf1, 0, sizeof(mfx_surf1));
2029 s->frame_info = mfx_surf1.Info;
2030 dst_hwctx->
info = &
s->frame_info;
2032 return 0;
2033 }
2034
2037 {
2041
2043 #if CONFIG_VAAPI
2045 {
2048 sizeof(*
s->handle_pairs_internal));
2049 if (!
s->handle_pairs_internal)
2052 sizeof(*
s->surfaces_internal));
2053 if (!
s->surfaces_internal)
2058 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
2059 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
2060 }
2062 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
2063 }
2064 break;
2065 #endif
2066 #if CONFIG_D3D11VA
2068 {
2071 sizeof(*
s->handle_pairs_internal));
2072 if (!
s->handle_pairs_internal)
2075 sizeof(*
s->surfaces_internal));
2076 if (!
s->surfaces_internal)
2081 if (src_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
2082 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
2083 } else {
2085 }
2086 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
2087 }
2089 if (src_hwctx->
BindFlags & D3D11_BIND_RENDER_TARGET) {
2090 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
2091 } else {
2092 dst_hwctx->
frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
2093 }
2094 }
2095 break;
2096 #endif
2097 #if CONFIG_DXVA2
2099 {
2102 sizeof(*
s->handle_pairs_internal));
2103 if (!
s->handle_pairs_internal)
2106 sizeof(*
s->surfaces_internal));
2107 if (!
s->surfaces_internal)
2111 s->handle_pairs_internal[
i].first = (mfxMemId)src_hwctx->
surfaces[
i];
2112 s->handle_pairs_internal[
i].second = (mfxMemId)MFX_INFINITE;
2113 s->surfaces_internal[
i].Data.MemId = (mfxMemId)&
s->handle_pairs_internal[
i];
2114 }
2116 if (src_hwctx->
surface_type == DXVA2_VideoProcessorRenderTarget)
2117 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
2118 else
2119 dst_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
2120 }
2121 break;
2122 #endif
2123 default:
2125 }
2126
2127 dst_hwctx->
surfaces =
s->surfaces_internal;
2128
2129 return 0;
2130 }
2131
2134 {
2140 } else {
2142 }
2143 }
2144
2147 {
2150
2152 switch(
src->format) {
2153 #if CONFIG_VAAPI
2155 {
2156 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
2157 if (*(VASurfaceID*)pair->first == (VASurfaceID)(uintptr_t)
src->data[3]) {
2159 break;
2160 }
2161 }
2162 #endif
2163 #if CONFIG_D3D11VA
2165 {
2166 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
2167 if (pair->first ==
src->data[0]
2168 && (pair->second ==
src->data[1]
2169 || (pair->second == (mfxMemId)MFX_INFINITE &&
src->data[1] == (uint8_t *)0))) {
2171 break;
2172 }
2173 }
2174 #endif
2175 #if CONFIG_DXVA2
2177 {
2178 mfxHDLPair *pair = (mfxHDLPair*)hwctx->
surfaces[
i].Data.MemId;
2179 if (pair->first ==
src->data[3]) {
2181 break;
2182 }
2183 }
2184 #endif
2185 }
2186 }
2189 "is not in the mapped frames context.\n");
2191 }
2192
2195 if (err)
2196 return err;
2197
2199 dst->height =
src->height;
2201
2202 return 0;
2203 }
2204
2206 {
2207 mfxFrameSurface1 *surfaces_internal = (mfxFrameSurface1 *)hwmap->
priv;
2208 mfxHDLPair *handle_pairs_internal = (mfxHDLPair *)surfaces_internal->Data.MemId;
2210
2211 switch (src_ctx->
format) {
2212 #if CONFIG_VAAPI
2214 {
2215 av_freep(&handle_pairs_internal->first);
2216
2217 break;
2218 }
2219 #endif
2220
2221 #if CONFIG_D3D11VA
2223 {
2224 /* Do nothing */
2225 break;
2226 }
2227 #endif
2228 default:
2230 break;
2231 }
2232
2235 }
2236
2239 {
2240 mfxFrameSurface1 *surfaces_internal =
NULL;
2241 mfxHDLPair *handle_pairs_internal =
NULL;
2243
2244 surfaces_internal =
av_calloc(1,
sizeof(*surfaces_internal));
2245 if (!surfaces_internal) {
2248 }
2249
2250 handle_pairs_internal =
av_calloc(1,
sizeof(*handle_pairs_internal));
2251 if (!handle_pairs_internal) {
2254 }
2255
2259
2260 switch (
src->format) {
2261 #if CONFIG_VAAPI
2263 {
2264 VASurfaceID *surface_id_internal;
2265
2266 surface_id_internal =
av_calloc(1,
sizeof(*surface_id_internal));
2267 if (!surface_id_internal) {
2270 }
2271
2272 *surface_id_internal = (VASurfaceID)(uintptr_t)
src->data[3];
2273 handle_pairs_internal->first = (mfxHDL)surface_id_internal;
2274 handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
2275
2276 break;
2277 }
2278 #endif
2279
2280 #if CONFIG_D3D11VA
2282 {
2285
2286 handle_pairs_internal->first = (mfxMemId)
src->data[0];
2287
2288 if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
2289 handle_pairs_internal->second = (mfxMemId)MFX_INFINITE;
2290 } else {
2291 handle_pairs_internal->second = (mfxMemId)
src->data[1];
2292 }
2293
2294 break;
2295 }
2296 #endif
2297 default:
2300 }
2301
2302 surfaces_internal->Data.MemId = (mfxMemId)handle_pairs_internal;
2303
2308
2310 dst->height =
src->height;
2311 dst->data[3] = (uint8_t*)surfaces_internal;
2312
2313 return 0;
2314
2319 }
2320
2323 {
2325
2328 else
2330 }
2331
2333 const void *hwconfig,
2335 {
2337
2342
2346
2350
2353
2354 return 0;
2355 }
2356
2358 {
2361
2364
2369 }
2370
2372 {
2373 static const struct {
2375 mfxIMPL impl;
2376 } impl_map[] = {
2377 { "auto", MFX_IMPL_AUTO },
2378 { "sw", MFX_IMPL_SOFTWARE },
2379 { "hw", MFX_IMPL_HARDWARE },
2380 { "auto_any", MFX_IMPL_AUTO_ANY },
2381 { "hw_any", MFX_IMPL_HARDWARE_ANY },
2382 { "hw2", MFX_IMPL_HARDWARE2 },
2383 { "hw3", MFX_IMPL_HARDWARE3 },
2384 { "hw4", MFX_IMPL_HARDWARE4 },
2385 };
2386
2387 mfxIMPL impl = MFX_IMPL_AUTO_ANY;
2389
2390 if (device) {
2392 if (!strcmp(device, impl_map[
i].
name)) {
2393 impl = impl_map[
i].impl;
2394 break;
2395 }
2397 impl = strtol(device,
NULL, 0);
2398 }
2399
2400 if (impl != MFX_IMPL_SOFTWARE) {
2402 impl |= MFX_IMPL_VIA_D3D11;
2404 impl |= MFX_IMPL_VIA_D3D9;
2405 }
2406
2407 return impl;
2408 }
2409
2411 mfxIMPL implementation,
2414 {
2416
2417 mfxVersion ver = { { 3, 1 } };
2418 mfxHDL handle;
2419 mfxHandleType handle_type;
2420 mfxStatus err;
2422
2423 switch (child_device_ctx->
type) {
2424 #if CONFIG_VAAPI
2426 {
2428 handle_type = MFX_HANDLE_VA_DISPLAY;
2429 handle = (mfxHDL)child_device_hwctx->
display;
2430 }
2431 break;
2432 #endif
2433 #if CONFIG_D3D11VA
2435 {
2437 handle_type = MFX_HANDLE_D3D11_DEVICE;
2438 handle = (mfxHDL)child_device_hwctx->
device;
2439 }
2440 break;
2441 #endif
2442 #if CONFIG_DXVA2
2444 {
2446 handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
2447 handle = (mfxHDL)child_device_hwctx->
devmgr;
2448 }
2449 break;
2450 #endif
2451 default:
2454 }
2455
2460
2461 err = MFXVideoCORE_SetHandle(hwctx->
session, handle_type, handle);
2462 if (err != MFX_ERR_NONE) {
2464 "%d\n", err);
2467 }
2468
2469 return 0;
2470
2474
2477
2481 }
2482
2486 {
2487 mfxIMPL impl;
2489
2491 if (!priv)
2493
2494 ctx->user_opaque = priv;
2496
2499 child_device_ctx,
flags);
2500 }
2501
2504 {
2510
2511 mfxIMPL impl;
2513
2515 if (!priv)
2517
2518 ctx->user_opaque = priv;
2520
2522 if (e) {
2526 "\"%s\".\n", e->
value);
2528 }
2529 #if QSV_ONEVPL
2530 } else if (CONFIG_D3D11VA) { // Use D3D11 by default if d3d11va is enabled
2532 "Defaulting child_device_type to AV_HWDEVICE_TYPE_D3D11VA for oneVPL."
2533 "Please explicitly set child device type via \"-init_hw_device\" "
2534 "option if needed.\n");
2536 } else if (CONFIG_DXVA2) {
2538 #else
2539 } else if (CONFIG_DXVA2) {
2541 "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility "
2542 "with old commandlines. This behaviour will be removed "
2543 "in the future. Please explicitly set device type via \"-init_hw_device\" option.\n");
2545 } else if (CONFIG_D3D11VA) {
2547 #endif
2548 } else if (CONFIG_VAAPI) {
2550 } else {
2553 }
2554
2555 #if CONFIG_VAAPI && defined(_WIN32)
2556 /* AV_HWDEVICE_TYPE_VAAPI on Windows/Libva-win32 not supported */
2557 /* Reject user specified child_device_type or CONFIG_VAAPI on Windows */
2560 "\"%s\".\n", e->
value);
2562 }
2563 #endif
2564
2565 child_device_opts =
NULL;
2566 switch (child_device_type) {
2567 #if CONFIG_VAAPI
2569 {
2570 // libmfx does not actually implement VAAPI properly, rather it
2571 // depends on the specific behaviour of a matching iHD driver when
2572 // used on recent Intel hardware. Set options to the VAAPI device
2573 // creation so that we should pick a usable setup by default if
2574 // possible, even when multiple devices and drivers are available.
2575 av_dict_set(&child_device_opts,
"vendor_id",
"0x8086", 0);
2576 av_dict_set(&child_device_opts,
"driver",
"iHD", 0);
2577 }
2578 break;
2579 #endif
2580 #if CONFIG_D3D11VA
2582 {
2583 // Make sure the hardware vendor is Intel when multiple devices are
2584 // available, it will be ignored if user specifies the child device
2585 // explicitly
2586 av_dict_set(&child_device_opts,
"vendor_id",
"0x8086", 0);
2587 }
2588 break;
2589 #endif
2590 #if CONFIG_DXVA2
2592 #if QSV_ONEVPL
2593 {
2595 "d3d11va is not available or child device type is set to dxva2 "
2596 "explicitly for oneVPL.\n");
2597 }
2598 #endif
2599 break;
2600 #endif
2601 default:
2602 {
2605 }
2606 break;
2607 }
2608
2611 e ? e->
value :
NULL, child_device_opts, 0);
2612
2616
2618
2620
2622 }
2623
2626 .name = "QSV",
2627
2630
2645
2647 };