diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.cpp b/app/streaming/video/ffmpeg-renderers/vaapi.cpp index ef5ea048..7585f027 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.cpp +++ b/app/streaming/video/ffmpeg-renderers/vaapi.cpp @@ -7,6 +7,10 @@ #include "utils.h" #include +#ifdef HAVE_LIBVA_DRM +#include +#endif + #include #include @@ -26,6 +30,10 @@ VAAPIRenderer::VAAPIRenderer(int decoderSelectionPass) SDL_zero(m_PrimeDescriptor); #endif +#ifdef HAVE_LIBVA_DRM + m_DrmFd = -1; +#endif + SDL_zero(m_OverlayImage); SDL_zero(m_OverlaySubpicture); SDL_zero(m_OverlayFormat); @@ -56,6 +64,12 @@ VAAPIRenderer::~VAAPIRenderer() } } +#ifdef HAVE_LIBVA_DRM + if (m_DrmFd >= 0) { + close(m_DrmFd); + } +#endif + if (m_OverlayMutex != nullptr) { SDL_DestroyMutex(m_OverlayMutex); } @@ -109,7 +123,41 @@ VAAPIRenderer::openDisplay(SDL_Window* window) #if defined(SDL_VIDEO_DRIVER_KMSDRM) && defined(HAVE_LIBVA_DRM) && SDL_VERSION_ATLEAST(2, 0, 15) else if (info.subsystem == SDL_SYSWM_KMSDRM) { SDL_assert(info.info.kmsdrm.drm_fd >= 0); - display = vaGetDisplayDRM(info.info.kmsdrm.drm_fd); + + // It's possible to enter this function several times as we're probing VA drivers. + // Make sure to only duplicate the DRM FD the first time through. + if (m_DrmFd < 0) { + // If the KMSDRM FD is not a render node FD, open the render node for libva to use. + // Since libva 2.20, using a primary node will fail in vaGetDriverNames(). + if (drmGetNodeTypeFromFd(info.info.kmsdrm.drm_fd) != DRM_NODE_RENDER) { + char* renderNodePath = drmGetRenderDeviceNameFromFd(info.info.kmsdrm.drm_fd); + if (renderNodePath) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Opening render node for VAAPI: %s", + renderNodePath); + m_DrmFd = open(renderNodePath, O_RDWR | O_CLOEXEC); + free(renderNodePath); + if (m_DrmFd < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to open render node: %d", + errno); + return nullptr; + } + } + else { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Failed to get render node path. Using the SDL FD directly."); + m_DrmFd = dup(info.info.kmsdrm.drm_fd); + } + } + else { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "KMSDRM FD is already a render node. Using the SDL FD directly."); + m_DrmFd = dup(info.info.kmsdrm.drm_fd); + } + } + + display = vaGetDisplayDRM(m_DrmFd); if (display == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to open DRM display for VAAPI"); diff --git a/app/streaming/video/ffmpeg-renderers/vaapi.h b/app/streaming/video/ffmpeg-renderers/vaapi.h index 3fabdb11..8f15cb41 100644 --- a/app/streaming/video/ffmpeg-renderers/vaapi.h +++ b/app/streaming/video/ffmpeg-renderers/vaapi.h @@ -4,16 +4,34 @@ // Avoid X11 if SDL was built without it #if !defined(SDL_VIDEO_DRIVER_X11) && defined(HAVE_LIBVA_X11) -#warning Unable to use libva-x11 without SDL support +#warning Unable to use libva-x11 without SDL X11 backend #undef HAVE_LIBVA_X11 #endif // Avoid Wayland if SDL was built without it #if !defined(SDL_VIDEO_DRIVER_WAYLAND) && defined(HAVE_LIBVA_WAYLAND) -#warning Unable to use libva-wayland without SDL support +#warning Unable to use libva-wayland without SDL Wayland backend #undef HAVE_LIBVA_WAYLAND #endif +// Avoid KMSDRM if SDL was built without it +#if !defined(SDL_VIDEO_DRIVER_KMSDRM) && defined(HAVE_LIBVA_DRM) +#warning Unable to use libva-drm without SDL KMSDRM backend +#undef HAVE_LIBVA_DRM +#endif + +// Avoid KMSDRM if SDL is too old for FD sharing +#if defined(HAVE_LIBVA_DRM) && defined(SDL_VIDEO_DRIVER_KMSDRM) && !SDL_VERSION_ATLEAST(2, 0, 15) +#warning Unable to use libva-drm because SDL is not version 2.0.16 or later +#undef HAVE_LIBVA_DRM +#endif + +// Avoid KMSDRM if built without libdrm +#if defined(HAVE_LIBVA_DRM) && !defined(HAVE_DRM) +#warning Unable to use libva-drm without libdrm available +#undef HAVE_LIBVA_DRM +#endif + #ifdef HAVE_EGL #include "eglimagefactory.h" #endif @@ -89,6 +107,10 @@ private: Window m_XWindow; #endif +#ifdef HAVE_LIBVA_DRM + int m_DrmFd; +#endif + int m_VideoWidth; int m_VideoHeight; int m_VideoFormat;