/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include"config.h"
#if HAVE_VAAPI_WIN32 # include <windows.h> #define COBJMACROS # include <initguid.h> # include <dxgi1_2.h> # include "compat/w32dlfcn.h" # include <va/va_win32.h> typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); #endif #if HAVE_VAAPI_X11 # include <va/va_x11.h> #endif #if HAVE_VAAPI_DRM # include <va/va_drm.h> #endif
#if CONFIG_LIBDRM # include <va/va_drmcommon.h> # include <xf86drm.h> # include <drm_fourcc.h> # ifndef DRM_FORMAT_MOD_INVALID # define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) # endif #endif
#include <fcntl.h> #if HAVE_UNISTD_H # include <unistd.h> #endif
typedefstruct VAAPIDeviceContext { /** * The public AVVAAPIDeviceContext. See hwcontext_vaapi.h for it.
*/
AVVAAPIDeviceContext p;
// Surface formats which can be used with this device.
VAAPISurfaceFormat *formats; int nb_formats;
} VAAPIDeviceContext;
typedefstruct VAAPIFramesContext { /** * The public AVVAAPIFramesContext. See hwcontext_vaapi.h for it.
*/
AVVAAPIFramesContext p;
// Surface attributes set at create time.
VASurfaceAttrib *attributes; int nb_attributes; // RT format of the underlying surface (Intel driver ignores this anyway). unsignedint rt_format; // Whether vaDeriveImage works. int derive_works; // Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for // surface imports. int prime_2_import_unsupported;
} VAAPIFramesContext;
typedefstruct VAAPIMapping { // Handle to the derived or copied image which is mapped.
VAImage image; // The mapping flags actually used. int flags;
} VAAPIMapping;
#define MAP(va, rt, av, swap_uv) { \
VA_FOURCC_ ## va, \
VA_RT_FORMAT_ ## rt, \
AV_PIX_FMT_ ## av, \
swap_uv, \
} // The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V // plane swap cases. The frame handling below tries to hide these. staticconst VAAPIFormatDescriptor vaapi_format_map[] = {
MAP(NV12, YUV420, NV12, 0), #ifdef VA_FOURCC_I420
MAP(I420, YUV420, YUV420P, 0), #endif
MAP(YV12, YUV420, YUV420P, 1),
MAP(IYUV, YUV420, YUV420P, 0),
MAP(422H, YUV422, YUV422P, 0), #ifdef VA_FOURCC_YV16
MAP(YV16, YUV422, YUV422P, 1), #endif
MAP(UYVY, YUV422, UYVY422, 0),
MAP(YUY2, YUV422, YUYV422, 0), #ifdef VA_FOURCC_Y210
MAP(Y210, YUV422_10, Y210, 0), #endif #ifdef VA_FOURCC_Y212
MAP(Y212, YUV422_12, Y212, 0), #endif
MAP(411P, YUV411, YUV411P, 0),
MAP(422V, YUV422, YUV440P, 0),
MAP(444P, YUV444, YUV444P, 0), #ifdef VA_FOURCC_XYUV
MAP(XYUV, YUV444, VUYX, 0), #endif
MAP(Y800, YUV400, GRAY8, 0), #ifdef VA_FOURCC_P010
MAP(P010, YUV420_10BPP, P010, 0), #endif #ifdef VA_FOURCC_P012
MAP(P012, YUV420_12, P012, 0), #endif
MAP(BGRA, RGB32, BGRA, 0),
MAP(BGRX, RGB32, BGR0, 0),
MAP(RGBA, RGB32, RGBA, 0),
MAP(RGBX, RGB32, RGB0, 0), #ifdef VA_FOURCC_ABGR
MAP(ABGR, RGB32, ABGR, 0),
MAP(XBGR, RGB32, 0BGR, 0), #endif
MAP(ARGB, RGB32, ARGB, 0),
MAP(XRGB, RGB32, 0RGB, 0), #ifdef VA_FOURCC_X2R10G10B10
MAP(X2R10G10B10, RGB32_10, X2RGB10, 0), #endif #ifdef VA_FOURCC_Y410 // libva doesn't include a fourcc for XV30 and the driver only declares // support for Y410, so we must fudge the mapping here.
MAP(Y410, YUV444_10, XV30, 0), #endif #ifdef VA_FOURCC_Y412 // libva doesn't include a fourcc for XV36 and the driver only declares // support for Y412, so we must fudge the mapping here.
MAP(Y412, YUV444_12, XV36, 0), #endif
}; #undef MAP
staticconst VAAPIFormatDescriptor *
vaapi_format_from_fourcc(unsignedint fourcc)
{ int i; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) if (vaapi_format_map[i].fourcc == fourcc) return &vaapi_format_map[i]; return NULL;
}
staticconst VAAPIFormatDescriptor *
vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
{ int i; for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) if (vaapi_format_map[i].pix_fmt == pix_fmt) return &vaapi_format_map[i]; return NULL;
}
for (k = 0; k < j; k++) { if (constraints->valid_sw_formats[k] == pix_fmt) break;
}
if (k == j)
constraints->valid_sw_formats[j++] = pix_fmt;
}
constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
}
} else { // No configuration supplied. // Return the full set of image formats known by the implementation.
constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1, sizeof(pix_fmt)); if (!constraints->valid_sw_formats) {
err = AVERROR(ENOMEM); goto fail;
} for (i = j = 0; i < ctx->nb_formats; i++) { int k;
for (k = 0; k < j; k++) { if (constraints->valid_sw_formats[k] == ctx->formats[i].pix_fmt) break;
}
if (k == j)
constraints->valid_sw_formats[j++] = ctx->formats[i].pix_fmt;
}
if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) {
av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n",
hwctx->driver_quirks);
} else { // Detect the driver in use and set quirk flags if necessary.
hwctx->driver_quirks = 0; if (vendor_string) { for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) { if (strstr(vendor_string,
vaapi_driver_quirks_table[i].match_string)) {
av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string " "as known nonstandard driver \"%s\", setting " "quirks (%#x).\n",
vaapi_driver_quirks_table[i].friendly_name,
vaapi_driver_quirks_table[i].quirks);
hwctx->driver_quirks |=
vaapi_driver_quirks_table[i].quirks; break;
}
} if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) {
av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known " "nonstandard list, using standard behaviour.\n");
}
} else {
av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, " "assuming standard behaviour.\n");
}
}
if (hwfc->initial_pool_size > 0) { // This is a fixed-size pool, so we must still be in the initial // allocation sequence.
av_assert0(avfc->nb_surfaces < hwfc->initial_pool_size);
avfc->surface_ids[avfc->nb_surfaces] = surface_id;
++avfc->nb_surfaces;
}
if (hwfc->initial_pool_size > 0) { // This pool will be usable as a render target, so we need to store // all of the surface IDs somewhere that vaCreateContext() calls // will be able to access them.
avfc->nb_surfaces = 0;
avfc->surface_ids = av_malloc(hwfc->initial_pool_size * sizeof(*avfc->surface_ids)); if (!avfc->surface_ids) {
err = AVERROR(ENOMEM); goto fail;
}
} else { // This pool allows dynamic sizing, and will not be usable as a // render target.
avfc->nb_surfaces = 0;
avfc->surface_ids = NULL;
}
// Allocate a single surface to test whether vaDeriveImage() is going // to work for the specific configuration. if (hwfc->pool) {
test_surface = av_buffer_pool_get(hwfc->pool); if (!test_surface) {
av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " "user-configured buffer pool.\n");
err = AVERROR(ENOMEM); goto fail;
}
} else {
test_surface = av_buffer_pool_get(ffhwframesctx(hwfc)->pool_internal); if (!test_surface) {
av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from " "internal buffer pool.\n");
err = AVERROR(ENOMEM); goto fail;
}
}
test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data;
ctx->derive_works = 0;
err = vaapi_get_image_format(hwfc->device_ctx,
hwfc->sw_format, &expected_format); if (err == 0) {
vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image); if (vas == VA_STATUS_SUCCESS) { if (expected_format->fourcc == test_image.format.fourcc) {
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
ctx->derive_works = 1;
} else {
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "derived image format %08x does not match " "expected format %08x.\n",
expected_format->fourcc, test_image.format.fourcc);
}
vaDestroyImage(hwctx->display, test_image.image_id);
} else {
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "deriving image does not work: " "%d (%s).\n", vas, vaErrorStr(vas));
}
} else {
av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: " "image format is not supported.\n");
}
vas = vaUnmapBuffer(hwctx->display, map->image.buf); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
}
if ((map->flags & AV_HWFRAME_MAP_WRITE) &&
!(map->flags & AV_HWFRAME_MAP_DIRECT)) {
vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
0, 0, hwfc->width, hwfc->height,
0, 0, hwfc->width, hwfc->height); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
}
}
vas = vaDestroyImage(hwctx->display, map->image.image_id); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
}
if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) { // Requested direct mapping but it is not possible. return AVERROR(EINVAL);
} if (dst->format == AV_PIX_FMT_NONE)
dst->format = hwfc->sw_format; if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) { // Requested direct mapping but the formats do not match. return AVERROR(EINVAL);
}
err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format); if (err < 0) { // Requested format is not a valid output format. return err;
}
vas = vaSyncSurface(hwctx->display, surface_id); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
}
// The memory which we map using derive need not be connected to the CPU // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the // memory is mappable but not cached, so normal memcpy()-like access is // very slow to read it (but writing is ok). It is possible to read much // faster with a copy routine which is aware of the limitation, but we // assume for now that the user is not aware of that and would therefore // prefer not to be given direct-mapped memory if they request read access. if (ctx->derive_works && dst->format == hwfc->sw_format &&
((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) {
vas = vaDeriveImage(hwctx->display, surface_id, &map->image); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " "surface %#x: %d (%s).\n",
surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
} if (map->image.format.fourcc != image_format->fourcc) {
av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x " "is in wrong format: expected %#08x, got %#08x.\n",
surface_id, image_format->fourcc, map->image.format.fourcc);
err = AVERROR(EIO); goto fail;
}
map->flags |= AV_HWFRAME_MAP_DIRECT;
} else {
vas = vaCreateImage(hwctx->display, image_format,
hwfc->width, hwfc->height, &map->image); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to create image for " "surface %#x: %d (%s).\n",
surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
} if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) {
vas = vaGetImage(hwctx->display, surface_id, 0, 0,
hwfc->width, hwfc->height, map->image.image_id); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to read image from " "surface %#x: %d (%s).\n",
surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
}
}
}
#if VA_CHECK_VERSION(1, 21, 0) if (flags & AV_HWFRAME_MAP_READ)
vaflags |= VA_MAPBUFFER_FLAG_READ; if (flags & AV_HWFRAME_MAP_WRITE)
vaflags |= VA_MAPBUFFER_FLAG_WRITE; // On drivers not implementing vaMapBuffer2 libva calls vaMapBuffer instead.
vas = vaMapBuffer2(hwctx->display, map->image.buf, &address, vaflags); #else
vas = vaMapBuffer(hwctx->display, map->image.buf, &address); #endif if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface " "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
}
for (i = 0; i < map->image.num_planes; i++) {
dst->data[i] = (uint8_t*)address + map->image.offsets[i];
dst->linesize[i] = map->image.pitches[i];
}
desc = vaapi_format_from_fourcc(map->image.format.fourcc); if (desc && desc->chroma_planes_swapped) { // Chroma planes are YVU rather than YUV, so swap them.
FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
}
return 0;
fail: if (map) { if (address)
vaUnmapBuffer(hwctx->display, map->image.buf); if (map->image.image_id != VA_INVALID_ID)
vaDestroyImage(hwctx->display, map->image.image_id);
av_free(map);
} return err;
}
/* * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that * that needs the config_id which we don't have here . Both Intel and * Gallium seem to do the correct error checks, so lets just try the * PRIME_2 import first.
*/
vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
src->width, src->height, &surface_id, 1,
prime_attrs, FF_ARRAY_ELEMS(prime_attrs)); if (vas != VA_STATUS_SUCCESS)
src_vafc->prime_2_import_unsupported = 1;
}
mapping = av_mallocz(sizeof(*mapping)); if (!mapping) return AVERROR(ENOMEM);
vas = vaDeriveImage(hwctx->display, surface_id,
&mapping->image); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from " "surface %#x: %d (%s).\n",
surface_id, vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail;
}
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) { if (vaapi_drm_format_map[i].va_fourcc ==
mapping->image.format.fourcc) break;
} if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) {
av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for " "VAAPI format %#x.\n", mapping->image.format.fourcc);
err = AVERROR(EINVAL); goto fail_derived;
}
vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
&mapping->buffer_info); if (vas != VA_STATUS_SUCCESS) {
av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer " "handle from image %#x (derived from surface %#x): " "%d (%s).\n", mapping->image.buf, surface_id,
vas, vaErrorStr(vas));
err = AVERROR(EIO); goto fail_derived;
}
av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %"PRIdPTR".\n",
mapping->buffer_info.handle);
mapping->drm_desc.nb_objects = 1;
mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) {
.fd = mapping->buffer_info.handle,
.size = mapping->image.data_size, // There is no way to get the format modifier with this API.
.format_modifier = DRM_FORMAT_MOD_INVALID,
};
#if HAVE_VAAPI_DRM while (!display && try_drm) { // If the device is specified, try to open it as a DRM device node. // If not, look for a usable render node, possibly restricted to those // using a specified kernel driver. int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR; if (device) {
priv->drm_fd = open(device, O_RDWR); if (priv->drm_fd < 0) {
av_log(ctx, loglevel, "Failed to open %s as " "DRM device node.\n", device); break;
}
} else { char path[64]; int n, max_devices = 8; #if CONFIG_LIBDRM
drmVersion *info; const AVDictionaryEntry *kernel_driver; const AVDictionaryEntry *vendor_id;
kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0);
vendor_id = av_dict_get(opts, "vendor_id", NULL, 0); #endif for (n = 0; n < max_devices; n++) {
snprintf(path, sizeof(path), "/dev/dri/renderD%d", 128 + n);
priv->drm_fd = open(path, O_RDWR); if (priv->drm_fd < 0) { if (errno == ENOENT) { if (n != max_devices - 1) {
av_log(ctx, AV_LOG_VERBOSE, "No render device %s, try next device for " "DRM render node.\n", path); continue;
}
av_log(ctx, AV_LOG_VERBOSE, "No available render device " "for DRM render node.\n");
} else
av_log(ctx, AV_LOG_VERBOSE, "Cannot open " "DRM render node for device %d.\n", n); break;
} #if CONFIG_LIBDRM
info = drmGetVersion(priv->drm_fd); if (!info) {
av_log(ctx, AV_LOG_VERBOSE, "Failed to get DRM version for device %d.\n", n);
close(priv->drm_fd);
priv->drm_fd = -1; continue;
} if (kernel_driver) { if (strcmp(kernel_driver->value, info->name)) {
av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " "with non-matching kernel driver (%s).\n",
n, info->name);
drmFreeVersion(info);
close(priv->drm_fd);
priv->drm_fd = -1; continue;
}
av_log(ctx, AV_LOG_VERBOSE, "Trying to use " "DRM render node for device %d, " "with matching kernel driver (%s).\n",
n, info->name);
drmFreeVersion(info); break; // drmGetVersion() ensures |info->name| is 0-terminated.
} elseif (!strcmp(info->name, "vgem")) {
av_log(ctx, AV_LOG_VERBOSE, "Skipping vgem node for device %d.\n", n);
drmFreeVersion(info);
close(priv->drm_fd);
priv->drm_fd = -1; continue;
} elseif (vendor_id) {
drmDevicePtr device; char drm_vendor[8]; if (drmGetDevice(priv->drm_fd, &device)) {
av_log(ctx, AV_LOG_VERBOSE, "Failed to get DRM device info for device %d.\n", n);
close(priv->drm_fd);
priv->drm_fd = -1; continue;
}
snprintf(drm_vendor, sizeof(drm_vendor), "0x%x", device->deviceinfo.pci->vendor_id); if (strcmp(vendor_id->value, drm_vendor)) {
av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " "with non-matching vendor id (%s).\n",
n, vendor_id->value);
drmFreeDevice(&device);
close(priv->drm_fd);
priv->drm_fd = -1; continue;
}
av_log(ctx, AV_LOG_VERBOSE, "Trying to use " "DRM render node for device %d, " "with matching vendor id (%s).\n",
n, vendor_id->value);
drmFreeDevice(&device); break;
}
drmFreeVersion(info); #endif
av_log(ctx, AV_LOG_VERBOSE, "Trying to use " "DRM render node for device %d.\n", n); break;
} if (n >= max_devices) break;
}
display = vaGetDisplayDRM(priv->drm_fd); if (!display) {
av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display " "from DRM device %s.\n", device); return AVERROR_EXTERNAL;
} break;
} #endif
#if HAVE_VAAPI_X11 if (!display && try_x11) { // Try to open the device as an X11 display.
priv->x11_display = XOpenDisplay(device); if (!priv->x11_display) {
av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display " "%s.\n", XDisplayName(device));
} else {
display = vaGetDisplay(priv->x11_display); if (!display) {
av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " "from X11 display %s.\n", XDisplayName(device)); return AVERROR_UNKNOWN;
}
av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " "X11 display %s.\n", XDisplayName(device));
}
} #endif
#if HAVE_VAAPI_WIN32 if (!display && try_win32) { // Try to create a display from the specified device, if any. if (!device) {
display = vaGetDisplayWin32(NULL);
} else {
IDXGIFactory2 *pDXGIFactory = NULL;
IDXGIAdapter *pAdapter = NULL; #if !HAVE_UWP
HANDLE dxgi = dlopen("dxgi.dll", 0); if (!dxgi) {
av_log(ctx, AV_LOG_ERROR, "Failed to load dxgi.dll\n"); return AVERROR_UNKNOWN;
}
PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
(PFN_CREATE_DXGI_FACTORY)dlsym(dxgi, "CreateDXGIFactory"); if (!pfnCreateDXGIFactory) {
av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory load failed\n");
dlclose(dxgi); return AVERROR_UNKNOWN;
} #else // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't // available, only CreateDXGIFactory1
PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
(PFN_CREATE_DXGI_FACTORY)CreateDXGIFactory1; #endif if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
(void **)&pDXGIFactory))) { int adapter = atoi(device); if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
adapter,
&pAdapter))) {
DXGI_ADAPTER_DESC desc; if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &desc))) {
av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
desc.VendorId, desc.DeviceId, desc.Description,
desc.AdapterLuid.LowPart,
desc.AdapterLuid.HighPart);
display = vaGetDisplayWin32(&desc.AdapterLuid);
}
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.