X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libavutil%2Fhwcontext_vaapi.c;h=12bc95119a105e6b68df16ef6193f3e4372f0b39;hb=2b01b7918beebe7b392ebf255f887e396a59e4c6;hp=c3a98bc4b11bcab30e044a70bd7642d7ac736d36;hpb=55e5af3c03898ffbac352fe4af83208fa4129c71;p=platform%2Fupstream%2Fffmpeg.git diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index c3a98bc..12bc951 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -18,6 +18,15 @@ #include "config.h" +#if HAVE_VAAPI_WIN32 +# include +#define COBJMACROS +# include +# include +# include "compat/w32dlfcn.h" +# include +typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); +#endif #if HAVE_VAAPI_X11 # include #endif @@ -122,13 +131,22 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = { #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), @@ -142,6 +160,16 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = { #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 @@ -189,7 +217,7 @@ static int vaapi_get_image_format(AVHWDeviceContext *hwdev, return 0; } } - return AVERROR(EINVAL); + return AVERROR(ENOSYS); } static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, @@ -789,7 +817,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc, err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format); if (err < 0) { // Requested format is not a valid output format. - return AVERROR(EINVAL); + return err; } map = av_malloc(sizeof(*map)); @@ -964,7 +992,7 @@ static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, if (dst->format != AV_PIX_FMT_NONE) { err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL); if (err < 0) - return AVERROR(ENOSYS); + return err; } err = vaapi_map_frame(hwfc, dst, src, flags); @@ -998,6 +1026,9 @@ static const struct { #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616), #endif +#if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16) + DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616), +#endif DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888), DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888), DRM_MAP(RGBA, 1, DRM_FORMAT_ABGR8888), @@ -1008,6 +1039,18 @@ static const struct { #endif DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888), DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888), +#if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888) + DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888), +#endif +#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010) + DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010), +#endif +#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616) + DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616), +#endif +#if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010) + DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010), +#endif }; #undef DRM_MAP @@ -1288,8 +1331,17 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst, surface_id = (VASurfaceID)(uintptr_t)src->data[3]; export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS; - if (flags & AV_HWFRAME_MAP_READ) + if (flags & AV_HWFRAME_MAP_READ) { export_flags |= VA_EXPORT_SURFACE_READ_ONLY; + + 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)); + return AVERROR(EIO); + } + } + if (flags & AV_HWFRAME_MAP_WRITE) export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY; @@ -1480,7 +1532,7 @@ static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst, goto fail_derived; } - av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %ld.\n", + av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %"PRIdPTR".\n", mapping->buffer_info.handle); mapping->drm_desc.nb_objects = 1; @@ -1623,7 +1675,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, VAAPIDevicePriv *priv; VADisplay display = NULL; const AVDictionaryEntry *ent; - int try_drm, try_x11, try_all; + int try_drm, try_x11, try_win32, try_all; priv = av_mallocz(sizeof(*priv)); if (!priv) @@ -1636,11 +1688,13 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, ent = av_dict_get(opts, "connection_type", NULL, 0); if (ent) { - try_all = try_drm = try_x11 = 0; + try_all = try_drm = try_x11 = try_win32 = 0; if (!strcmp(ent->value, "drm")) { try_drm = 1; } else if (!strcmp(ent->value, "x11")) { try_x11 = 1; + } else if (!strcmp(ent->value, "win32")) { + try_win32 = 1; } else { av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n", ent->value); @@ -1650,6 +1704,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, try_all = 1; try_drm = HAVE_VAAPI_DRM; try_x11 = HAVE_VAAPI_X11; + try_win32 = HAVE_VAAPI_WIN32; } #if HAVE_VAAPI_DRM @@ -1669,6 +1724,7 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, char path[64]; int n, max_devices = 8; #if CONFIG_LIBDRM + drmVersion *info; const AVDictionaryEntry *kernel_driver; kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0); #endif @@ -1682,9 +1738,15 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, 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) { - drmVersion *info; - info = drmGetVersion(priv->drm_fd); if (strcmp(kernel_driver->value, info->name)) { av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " "with non-matching kernel driver (%s).\n", @@ -1699,12 +1761,20 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, "with matching kernel driver (%s).\n", n, info->name); drmFreeVersion(info); - } else -#endif - { - av_log(ctx, AV_LOG_VERBOSE, "Trying to use " - "DRM render node for device %d.\n", n); + break; + // drmGetVersion() ensures |info->name| is 0-terminated. + } else if (!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; } + 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) @@ -1742,6 +1812,68 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *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); + } + IDXGIAdapter_Release(pAdapter); + } + IDXGIFactory2_Release(pDXGIFactory); + } +#if !HAVE_UWP + dlclose(dxgi); +#endif + } + + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from Win32 display.\n"); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "Win32 display.\n"); + } +#endif + if (!display) { if (device) av_log(ctx, AV_LOG_ERROR, "No VA display found for "