build(linux) make vaapi optional without dlopen (#1979)
Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
This commit is contained in:
parent
0dff8b16fd
commit
bc6cc2078e
10 changed files with 136 additions and 252 deletions
70
cmake/FindLibva.cmake
Normal file
70
cmake/FindLibva.cmake
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# - Try to find Libva
|
||||||
|
# This module defines the following variables:
|
||||||
|
#
|
||||||
|
# * LIBVA_FOUND - The component was found
|
||||||
|
# * LIBVA_INCLUDE_DIRS - The component include directory
|
||||||
|
# * LIBVA_LIBRARIES - The component library Libva
|
||||||
|
# * LIBVA_DRM_LIBRARIES - The component library Libva DRM
|
||||||
|
|
||||||
|
# Use pkg-config to get the directories and then use these values in the
|
||||||
|
# find_path() and find_library() calls
|
||||||
|
# cmake-format: on
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
if(PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(_LIBVA libva)
|
||||||
|
pkg_check_modules(_LIBVA_DRM libva-drm)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_path(
|
||||||
|
LIBVA_INCLUDE_DIR
|
||||||
|
NAMES va/va.h va/va_drm.h
|
||||||
|
HINTS ${_LIBVA_INCLUDE_DIRS}
|
||||||
|
PATHS /usr/include /usr/local/include /opt/local/include)
|
||||||
|
|
||||||
|
find_library(
|
||||||
|
LIBVA_LIB
|
||||||
|
NAMES ${_LIBVA_LIBRARIES} libva
|
||||||
|
HINTS ${_LIBVA_LIBRARY_DIRS}
|
||||||
|
PATHS /usr/lib /usr/local/lib /opt/local/lib)
|
||||||
|
|
||||||
|
find_library(
|
||||||
|
LIBVA_DRM_LIB
|
||||||
|
NAMES ${_LIBVA_DRM_LIBRARIES} libva-drm
|
||||||
|
HINTS ${_LIBVA_DRM_LIBRARY_DIRS}
|
||||||
|
PATHS /usr/lib /usr/local/lib /opt/local/lib)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Libva REQUIRED_VARS LIBVA_INCLUDE_DIR LIBVA_LIB LIBVA_DRM_LIB)
|
||||||
|
mark_as_advanced(LIBVA_INCLUDE_DIR LIBVA_LIB LIBVA_DRM_LIB)
|
||||||
|
|
||||||
|
if(LIBVA_FOUND)
|
||||||
|
set(LIBVA_INCLUDE_DIRS ${LIBVA_INCLUDE_DIR})
|
||||||
|
set(LIBVA_LIBRARIES ${LIBVA_LIB})
|
||||||
|
set(LIBVA_DRM_LIBRARIES ${LIBVA_DRM_LIB})
|
||||||
|
|
||||||
|
if(NOT TARGET Libva::va)
|
||||||
|
if(IS_ABSOLUTE "${LIBVA_LIBRARIES}")
|
||||||
|
add_library(Libva::va UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(Libva::va PROPERTIES IMPORTED_LOCATION "${LIBVA_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
add_library(Libva::va INTERFACE IMPORTED)
|
||||||
|
set_target_properties(Libva::va PROPERTIES IMPORTED_LIBNAME "${LIBVA_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(Libva::va PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIRS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET Libva::drm)
|
||||||
|
if(IS_ABSOLUTE "${LIBVA_DRM_LIBRARIES}")
|
||||||
|
add_library(Libva::drm UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(Libva::drm PROPERTIES IMPORTED_LOCATION "${LIBVA_DRM_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
add_library(Libva::drm INTERFACE IMPORTED)
|
||||||
|
set_target_properties(Libva::drm PROPERTIES IMPORTED_LIBNAME "${LIBVA_DRM_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(Libva::drm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIRS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
@ -120,6 +120,21 @@ elseif(NOT LIBDRM_FOUND)
|
||||||
message(WARNING "Missing libcap")
|
message(WARNING "Missing libcap")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# vaapi
|
||||||
|
if(${SUNSHINE_ENABLE_VAAPI})
|
||||||
|
find_package(Libva)
|
||||||
|
else()
|
||||||
|
set(LIBVA_FOUND OFF)
|
||||||
|
endif()
|
||||||
|
if(LIBVA_FOUND)
|
||||||
|
add_compile_definitions(SUNSHINE_BUILD_VAAPI)
|
||||||
|
include_directories(SYSTEM ${LIBVA_INCLUDE_DIR})
|
||||||
|
list(APPEND PLATFORM_LIBRARIES ${LIBVA_LIBRARIES} ${LIBVA_DRM_LIBRARIES})
|
||||||
|
list(APPEND PLATFORM_TARGET_FILES
|
||||||
|
src/platform/linux/vaapi.h
|
||||||
|
src/platform/linux/vaapi.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
# wayland
|
# wayland
|
||||||
if(${SUNSHINE_ENABLE_WAYLAND})
|
if(${SUNSHINE_ENABLE_WAYLAND})
|
||||||
find_package(Wayland)
|
find_package(Wayland)
|
||||||
|
|
@ -167,8 +182,12 @@ if(X11_FOUND)
|
||||||
src/platform/linux/x11grab.cpp)
|
src/platform/linux/x11grab.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT ${CUDA_FOUND} AND NOT ${WAYLAND_FOUND} AND NOT ${X11_FOUND} AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND}))
|
if(NOT ${CUDA_FOUND}
|
||||||
message(FATAL_ERROR "Couldn't find either x11, wayland, cuda or (libdrm and libcap)")
|
AND NOT ${WAYLAND_FOUND}
|
||||||
|
AND NOT ${X11_FOUND}
|
||||||
|
AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND})
|
||||||
|
AND NOT ${LIBVA_FOUND})
|
||||||
|
message(FATAL_ERROR "Couldn't find either cuda, wayland, x11, (libdrm and libcap), or libva")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# tray icon
|
# tray icon
|
||||||
|
|
@ -206,8 +225,6 @@ endif()
|
||||||
|
|
||||||
list(APPEND PLATFORM_TARGET_FILES
|
list(APPEND PLATFORM_TARGET_FILES
|
||||||
src/platform/linux/publish.cpp
|
src/platform/linux/publish.cpp
|
||||||
src/platform/linux/vaapi.h
|
|
||||||
src/platform/linux/vaapi.cpp
|
|
||||||
src/platform/linux/graphics.h
|
src/platform/linux/graphics.h
|
||||||
src/platform/linux/graphics.cpp
|
src/platform/linux/graphics.cpp
|
||||||
src/platform/linux/misc.h
|
src/platform/linux/misc.h
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ elseif(UNIX) # Linux
|
||||||
"Enable cuda specific code." ON)
|
"Enable cuda specific code." ON)
|
||||||
option(SUNSHINE_ENABLE_DRM
|
option(SUNSHINE_ENABLE_DRM
|
||||||
"Enable KMS grab if available." ON)
|
"Enable KMS grab if available." ON)
|
||||||
|
option(SUNSHINE_ENABLE_VAAPI
|
||||||
|
"Enable building vaapi specific code." ON)
|
||||||
option(SUNSHINE_ENABLE_WAYLAND
|
option(SUNSHINE_ENABLE_WAYLAND
|
||||||
"Enable building wayland specific code." ON)
|
"Enable building wayland specific code." ON)
|
||||||
option(SUNSHINE_ENABLE_X11
|
option(SUNSHINE_ENABLE_X11
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ Install Requirements
|
||||||
libopus-dev \
|
libopus-dev \
|
||||||
libpulse-dev \
|
libpulse-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libva-dev \
|
libva-dev \ # VA-API
|
||||||
libvdpau-dev \
|
libvdpau-dev \
|
||||||
libwayland-dev \ # Wayland
|
libwayland-dev \ # Wayland
|
||||||
libx11-dev \ # X11
|
libx11-dev \ # X11
|
||||||
|
|
@ -67,7 +67,7 @@ Install Requirements
|
||||||
libdrm-devel \
|
libdrm-devel \
|
||||||
libevdev-devel \
|
libevdev-devel \
|
||||||
libnotify-devel \
|
libnotify-devel \
|
||||||
libva-devel \
|
libva-devel \ # VA-API
|
||||||
libvdpau-devel \
|
libvdpau-devel \
|
||||||
libX11-devel \ # X11
|
libX11-devel \ # X11
|
||||||
libxcb-devel \ # X11
|
libxcb-devel \ # X11
|
||||||
|
|
@ -115,7 +115,7 @@ Install Requirements
|
||||||
libopus-dev \
|
libopus-dev \
|
||||||
libpulse-dev \
|
libpulse-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libva-dev \
|
libva-dev \ # VA-API
|
||||||
libvdpau-dev \
|
libvdpau-dev \
|
||||||
libwayland-dev \ # Wayland
|
libwayland-dev \ # Wayland
|
||||||
libx11-dev \ # X11
|
libx11-dev \ # X11
|
||||||
|
|
@ -165,6 +165,7 @@ Install Requirements
|
||||||
libopus-dev \
|
libopus-dev \
|
||||||
libpulse-dev \
|
libpulse-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
|
libva-dev \ # VA-API
|
||||||
libwayland-dev \ # Wayland
|
libwayland-dev \ # Wayland
|
||||||
libx11-dev \ # X11
|
libx11-dev \ # X11
|
||||||
libxcb-shm0-dev \ # X11
|
libxcb-shm0-dev \ # X11
|
||||||
|
|
|
||||||
|
|
@ -793,9 +793,11 @@ namespace platf {
|
||||||
|
|
||||||
std::unique_ptr<avcodec_encode_device_t>
|
std::unique_ptr<avcodec_encode_device_t>
|
||||||
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (mem_type == mem_type_e::vaapi) {
|
if (mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_avcodec_encode_device(width, height, false);
|
return va::make_avcodec_encode_device(width, height, false);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return std::make_unique<avcodec_encode_device_t>();
|
return std::make_unique<avcodec_encode_device_t>();
|
||||||
}
|
}
|
||||||
|
|
@ -862,9 +864,11 @@ namespace platf {
|
||||||
|
|
||||||
std::unique_ptr<avcodec_encode_device_t>
|
std::unique_ptr<avcodec_encode_device_t>
|
||||||
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (mem_type == mem_type_e::vaapi) {
|
if (mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_avcodec_encode_device(width, height, dup(card.render_fd.el), img_offset_x, img_offset_y, true);
|
return va::make_avcodec_encode_device(width, height, dup(card.render_fd.el), img_offset_x, img_offset_y, true);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_LOG(error) << "Unsupported pixel format for egl::display_vram_t: "sv << platf::from_pix_fmt(pix_fmt);
|
BOOST_LOG(error) << "Unsupported pixel format for egl::display_vram_t: "sv << platf::from_pix_fmt(pix_fmt);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -977,7 +981,11 @@ namespace platf {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (!va::validate(card.render_fd.el)) {
|
if (!va::validate(card.render_fd.el)) {
|
||||||
|
#else
|
||||||
|
if (true) {
|
||||||
|
#endif
|
||||||
BOOST_LOG(warning) << "Monitor "sv << display_name << " doesn't support hardware encoding. Reverting back to GPU -> RAM -> GPU"sv;
|
BOOST_LOG(warning) << "Monitor "sv << display_name << " doesn't support hardware encoding. Reverting back to GPU -> RAM -> GPU"sv;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -724,7 +724,6 @@ namespace platf {
|
||||||
init() {
|
init() {
|
||||||
// These are allowed to fail.
|
// These are allowed to fail.
|
||||||
gbm::init();
|
gbm::init();
|
||||||
va::init();
|
|
||||||
|
|
||||||
window_system = window_system_e::NONE;
|
window_system = window_system_e::NONE;
|
||||||
#ifdef SUNSHINE_BUILD_WAYLAND
|
#ifdef SUNSHINE_BUILD_WAYLAND
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <va/va.h>
|
#include <va/va.h>
|
||||||
|
#include <va/va_drm.h>
|
||||||
#if !VA_CHECK_VERSION(1, 9, 0)
|
#if !VA_CHECK_VERSION(1, 9, 0)
|
||||||
// vaSyncBuffer stub allows Sunshine built against libva <2.9.0 to link against ffmpeg on libva 2.9.0 or later
|
// vaSyncBuffer stub allows Sunshine built against libva <2.9.0 to link against ffmpeg on libva 2.9.0 or later
|
||||||
VAStatus
|
VAStatus
|
||||||
|
|
@ -85,209 +86,7 @@ namespace va {
|
||||||
} layers[4];
|
} layers[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
using display_t = util::safe_ptr_v2<void, VAStatus, vaTerminate>;
|
||||||
* @brief Defined profiles
|
|
||||||
*/
|
|
||||||
enum class profile_e {
|
|
||||||
// Profile ID used for video processing.
|
|
||||||
ProfileNone = -1,
|
|
||||||
MPEG2Simple = 0,
|
|
||||||
MPEG2Main = 1,
|
|
||||||
MPEG4Simple = 2,
|
|
||||||
MPEG4AdvancedSimple = 3,
|
|
||||||
MPEG4Main = 4,
|
|
||||||
H264Baseline = 5,
|
|
||||||
H264Main = 6,
|
|
||||||
H264High = 7,
|
|
||||||
VC1Simple = 8,
|
|
||||||
VC1Main = 9,
|
|
||||||
VC1Advanced = 10,
|
|
||||||
H263Baseline = 11,
|
|
||||||
JPEGBaseline = 12,
|
|
||||||
H264ConstrainedBaseline = 13,
|
|
||||||
VP8Version0_3 = 14,
|
|
||||||
H264MultiviewHigh = 15,
|
|
||||||
H264StereoHigh = 16,
|
|
||||||
HEVCMain = 17,
|
|
||||||
HEVCMain10 = 18,
|
|
||||||
VP9Profile0 = 19,
|
|
||||||
VP9Profile1 = 20,
|
|
||||||
VP9Profile2 = 21,
|
|
||||||
VP9Profile3 = 22,
|
|
||||||
HEVCMain12 = 23,
|
|
||||||
HEVCMain422_10 = 24,
|
|
||||||
HEVCMain422_12 = 25,
|
|
||||||
HEVCMain444 = 26,
|
|
||||||
HEVCMain444_10 = 27,
|
|
||||||
HEVCMain444_12 = 28,
|
|
||||||
HEVCSccMain = 29,
|
|
||||||
HEVCSccMain10 = 30,
|
|
||||||
HEVCSccMain444 = 31,
|
|
||||||
AV1Profile0 = 32,
|
|
||||||
AV1Profile1 = 33,
|
|
||||||
HEVCSccMain444_10 = 34,
|
|
||||||
|
|
||||||
// Profile ID used for protected video playback.
|
|
||||||
Protected = 35
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class entry_e {
|
|
||||||
VLD = 1,
|
|
||||||
IZZ = 2,
|
|
||||||
IDCT = 3,
|
|
||||||
MoComp = 4,
|
|
||||||
Deblocking = 5,
|
|
||||||
EncSlice = 6, /** slice level encode */
|
|
||||||
EncPicture = 7, /** picture encode, JPEG, etc */
|
|
||||||
/**
|
|
||||||
* For an implementation that supports a low power/high performance variant
|
|
||||||
* for slice level encode, it can choose to expose the
|
|
||||||
* VAEntrypointEncSliceLP entrypoint. Certain encoding tools may not be
|
|
||||||
* available with this entrypoint (e.g. interlace, MBAFF) and the
|
|
||||||
* application can query the encoding configuration attributes to find
|
|
||||||
* out more details if this entrypoint is supported.
|
|
||||||
*/
|
|
||||||
EncSliceLP = 8,
|
|
||||||
VideoProc = 10, /**< Video pre/post-processing. */
|
|
||||||
/**
|
|
||||||
* @brief FEI
|
|
||||||
*
|
|
||||||
* The purpose of FEI (Flexible Encoding Infrastructure) is to allow applications to
|
|
||||||
* have more controls and trade off quality for speed with their own IPs.
|
|
||||||
* The application can optionally provide input to ENC for extra encode control
|
|
||||||
* and get the output from ENC. Application can chose to modify the ENC
|
|
||||||
* output/PAK input during encoding, but the performance impact is significant.
|
|
||||||
*
|
|
||||||
* On top of the existing buffers for normal encode, there will be
|
|
||||||
* one extra input buffer (VAEncMiscParameterFEIFrameControl) and
|
|
||||||
* three extra output buffers (VAEncFEIMVBufferType, VAEncFEIMBModeBufferType
|
|
||||||
* and VAEncFEIDistortionBufferType) for FEI entry function.
|
|
||||||
* If separate PAK is set, two extra input buffers
|
|
||||||
* (VAEncFEIMVBufferType, VAEncFEIMBModeBufferType) are needed for PAK input.
|
|
||||||
*/
|
|
||||||
FEI = 11,
|
|
||||||
/**
|
|
||||||
* @brief Stats
|
|
||||||
*
|
|
||||||
* A pre-processing function for getting some statistics and motion vectors is added,
|
|
||||||
* and some extra controls for Encode pipeline are provided. The application can
|
|
||||||
* optionally call the statistics function to get motion vectors and statistics like
|
|
||||||
* variances, distortions before calling Encode function via this entry point.
|
|
||||||
*
|
|
||||||
* Checking whether Statistics is supported can be performed with vaQueryConfigEntrypoints().
|
|
||||||
* If Statistics entry point is supported, then the list of returned entry-points will
|
|
||||||
* include #Stats. Supported pixel format, maximum resolution and statistics
|
|
||||||
* specific attributes can be obtained via normal attribute query. One input buffer
|
|
||||||
* (VAStatsStatisticsParameterBufferType) and one or two output buffers
|
|
||||||
* (VAStatsStatisticsBufferType, VAStatsStatisticsBottomFieldBufferType (for interlace only)
|
|
||||||
* and VAStatsMVBufferType) are needed for this entry point.
|
|
||||||
*/
|
|
||||||
Stats = 12,
|
|
||||||
/**
|
|
||||||
* @brief ProtectedTEEComm
|
|
||||||
*
|
|
||||||
* A function for communicating with TEE (Trusted Execution Environment).
|
|
||||||
*/
|
|
||||||
ProtectedTEEComm = 13,
|
|
||||||
/**
|
|
||||||
* @brief ProtectedContent
|
|
||||||
*
|
|
||||||
* A function for protected content to decrypt encrypted content.
|
|
||||||
*/
|
|
||||||
ProtectedContent = 14,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef VAStatus (*queryConfigEntrypoints_fn)(VADisplay dpy, profile_e profile, entry_e *entrypoint_list, int *num_entrypoints);
|
|
||||||
typedef int (*maxNumEntrypoints_fn)(VADisplay dpy);
|
|
||||||
typedef VADisplay (*getDisplayDRM_fn)(int fd);
|
|
||||||
typedef VAStatus (*terminate_fn)(VADisplay dpy);
|
|
||||||
typedef VAStatus (*initialize_fn)(VADisplay dpy, int *major_version, int *minor_version);
|
|
||||||
typedef const char *(*errorStr_fn)(VAStatus error_status);
|
|
||||||
typedef void (*VAMessageCallback)(void *user_context, const char *message);
|
|
||||||
typedef VAMessageCallback (*setErrorCallback_fn)(VADisplay dpy, VAMessageCallback callback, void *user_context);
|
|
||||||
typedef VAMessageCallback (*setInfoCallback_fn)(VADisplay dpy, VAMessageCallback callback, void *user_context);
|
|
||||||
typedef const char *(*queryVendorString_fn)(VADisplay dpy);
|
|
||||||
typedef VAStatus (*exportSurfaceHandle_fn)(
|
|
||||||
VADisplay dpy, VASurfaceID surface_id,
|
|
||||||
uint32_t mem_type, uint32_t flags,
|
|
||||||
void *descriptor);
|
|
||||||
|
|
||||||
static maxNumEntrypoints_fn maxNumEntrypoints;
|
|
||||||
static queryConfigEntrypoints_fn queryConfigEntrypoints;
|
|
||||||
static getDisplayDRM_fn getDisplayDRM;
|
|
||||||
static terminate_fn terminate;
|
|
||||||
static initialize_fn initialize;
|
|
||||||
static errorStr_fn errorStr;
|
|
||||||
static setErrorCallback_fn setErrorCallback;
|
|
||||||
static setInfoCallback_fn setInfoCallback;
|
|
||||||
static queryVendorString_fn queryVendorString;
|
|
||||||
static exportSurfaceHandle_fn exportSurfaceHandle;
|
|
||||||
|
|
||||||
using display_t = util::dyn_safe_ptr_v2<void, VAStatus, &terminate>;
|
|
||||||
|
|
||||||
int
|
|
||||||
init_main_va() {
|
|
||||||
static void *handle { nullptr };
|
|
||||||
static bool funcs_loaded = false;
|
|
||||||
|
|
||||||
if (funcs_loaded) return 0;
|
|
||||||
|
|
||||||
if (!handle) {
|
|
||||||
handle = dyn::handle({ "libva.so.2", "libva.so" });
|
|
||||||
if (!handle) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
|
||||||
{ (dyn::apiproc *) &maxNumEntrypoints, "vaMaxNumEntrypoints" },
|
|
||||||
{ (dyn::apiproc *) &queryConfigEntrypoints, "vaQueryConfigEntrypoints" },
|
|
||||||
{ (dyn::apiproc *) &terminate, "vaTerminate" },
|
|
||||||
{ (dyn::apiproc *) &initialize, "vaInitialize" },
|
|
||||||
{ (dyn::apiproc *) &errorStr, "vaErrorStr" },
|
|
||||||
{ (dyn::apiproc *) &setErrorCallback, "vaSetErrorCallback" },
|
|
||||||
{ (dyn::apiproc *) &setInfoCallback, "vaSetInfoCallback" },
|
|
||||||
{ (dyn::apiproc *) &queryVendorString, "vaQueryVendorString" },
|
|
||||||
{ (dyn::apiproc *) &exportSurfaceHandle, "vaExportSurfaceHandle" },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (dyn::load(handle, funcs)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcs_loaded = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
init() {
|
|
||||||
if (init_main_va()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *handle { nullptr };
|
|
||||||
static bool funcs_loaded = false;
|
|
||||||
|
|
||||||
if (funcs_loaded) return 0;
|
|
||||||
|
|
||||||
if (!handle) {
|
|
||||||
handle = dyn::handle({ "libva-drm.so.2", "libva-drm.so" });
|
|
||||||
if (!handle) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::tuple<dyn::apiproc *, const char *>> funcs {
|
|
||||||
{ (dyn::apiproc *) &getDisplayDRM, "vaGetDisplayDRM" },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (dyn::load(handle, funcs)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
funcs_loaded = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *encode_device, AVBufferRef **hw_device_buf);
|
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *encode_device, AVBufferRef **hw_device_buf);
|
||||||
|
|
@ -298,9 +97,8 @@ namespace va {
|
||||||
init(int in_width, int in_height, file_t &&render_device) {
|
init(int in_width, int in_height, file_t &&render_device) {
|
||||||
file = std::move(render_device);
|
file = std::move(render_device);
|
||||||
|
|
||||||
if (!va::initialize || !gbm::create_device) {
|
if (!gbm::create_device) {
|
||||||
if (!va::initialize) BOOST_LOG(warning) << "libva not initialized"sv;
|
BOOST_LOG(warning) << "libgbm not initialized"sv;
|
||||||
if (!gbm::create_device) BOOST_LOG(warning) << "libgbm not initialized"sv;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,14 +144,14 @@ namespace va {
|
||||||
va::DRMPRIMESurfaceDescriptor prime;
|
va::DRMPRIMESurfaceDescriptor prime;
|
||||||
va::VASurfaceID surface = (std::uintptr_t) frame->data[3];
|
va::VASurfaceID surface = (std::uintptr_t) frame->data[3];
|
||||||
|
|
||||||
auto status = va::exportSurfaceHandle(
|
auto status = vaExportSurfaceHandle(
|
||||||
this->va_display,
|
this->va_display,
|
||||||
surface,
|
surface,
|
||||||
va::SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
va::SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
||||||
va::EXPORT_SURFACE_WRITE_ONLY | va::EXPORT_SURFACE_SEPARATE_LAYERS,
|
va::EXPORT_SURFACE_WRITE_ONLY | va::EXPORT_SURFACE_SEPARATE_LAYERS,
|
||||||
&prime);
|
&prime);
|
||||||
if (status) {
|
if (status) {
|
||||||
BOOST_LOG(error) << "Couldn't export va surface handle: ["sv << (int) surface << "]: "sv << va::errorStr(status);
|
BOOST_LOG(error) << "Couldn't export va surface handle: ["sv << (int) surface << "]: "sv << vaErrorStr(status);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -524,23 +322,13 @@ namespace va {
|
||||||
auto hwctx = (AVVAAPIDeviceContext *) ctx->hwctx;
|
auto hwctx = (AVVAAPIDeviceContext *) ctx->hwctx;
|
||||||
auto priv = (VAAPIDevicePriv *) ctx->user_opaque;
|
auto priv = (VAAPIDevicePriv *) ctx->user_opaque;
|
||||||
|
|
||||||
terminate(hwctx->display);
|
vaTerminate(hwctx->display);
|
||||||
close(priv->drm_fd);
|
close(priv->drm_fd);
|
||||||
av_freep(&priv);
|
av_freep(&priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *base, AVBufferRef **hw_device_buf) {
|
vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_device_t *base, AVBufferRef **hw_device_buf) {
|
||||||
if (!va::initialize) {
|
|
||||||
BOOST_LOG(warning) << "libva not loaded"sv;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!va::getDisplayDRM) {
|
|
||||||
BOOST_LOG(warning) << "libva-drm not loaded"sv;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto va = (va::va_t *) base;
|
auto va = (va::va_t *) base;
|
||||||
auto fd = dup(va->file.el);
|
auto fd = dup(va->file.el);
|
||||||
|
|
||||||
|
|
@ -552,7 +340,7 @@ namespace va {
|
||||||
av_free(priv);
|
av_free(priv);
|
||||||
});
|
});
|
||||||
|
|
||||||
va::display_t display { va::getDisplayDRM(fd) };
|
va::display_t display { vaGetDisplayDRM(fd) };
|
||||||
if (!display) {
|
if (!display) {
|
||||||
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
|
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
|
||||||
|
|
||||||
|
|
@ -562,17 +350,17 @@ namespace va {
|
||||||
|
|
||||||
va->va_display = display.get();
|
va->va_display = display.get();
|
||||||
|
|
||||||
va::setErrorCallback(display.get(), __log, &error);
|
vaSetErrorCallback(display.get(), __log, &error);
|
||||||
va::setErrorCallback(display.get(), __log, &info);
|
vaSetErrorCallback(display.get(), __log, &info);
|
||||||
|
|
||||||
int major, minor;
|
int major, minor;
|
||||||
auto status = va::initialize(display.get(), &major, &minor);
|
auto status = vaInitialize(display.get(), &major, &minor);
|
||||||
if (status) {
|
if (status) {
|
||||||
BOOST_LOG(error) << "Couldn't initialize va display: "sv << va::errorStr(status);
|
BOOST_LOG(error) << "Couldn't initialize va display: "sv << vaErrorStr(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG(debug) << "vaapi vendor: "sv << va::queryVendorString(display.get());
|
BOOST_LOG(debug) << "vaapi vendor: "sv << vaQueryVendorString(display.get());
|
||||||
|
|
||||||
*hw_device_buf = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
|
*hw_device_buf = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
|
||||||
auto ctx = (AVHWDeviceContext *) (*hw_device_buf)->data;
|
auto ctx = (AVHWDeviceContext *) (*hw_device_buf)->data;
|
||||||
|
|
@ -596,20 +384,20 @@ namespace va {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
query(display_t::pointer display, profile_e profile) {
|
query(display_t::pointer display, VAProfile profile) {
|
||||||
std::vector<entry_e> entrypoints;
|
std::vector<VAEntrypoint> entrypoints;
|
||||||
entrypoints.resize(maxNumEntrypoints(display));
|
entrypoints.resize(vaMaxNumEntrypoints(display));
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
auto status = queryConfigEntrypoints(display, profile, entrypoints.data(), &count);
|
auto status = vaQueryConfigEntrypoints(display, profile, entrypoints.data(), &count);
|
||||||
if (status) {
|
if (status) {
|
||||||
BOOST_LOG(error) << "Couldn't query entrypoints: "sv << va::errorStr(status);
|
BOOST_LOG(error) << "Couldn't query entrypoints: "sv << vaErrorStr(status);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
entrypoints.resize(count);
|
entrypoints.resize(count);
|
||||||
|
|
||||||
for (auto entrypoint : entrypoints) {
|
for (auto entrypoint : entrypoints) {
|
||||||
if (entrypoint == entry_e::EncSlice || entrypoint == entry_e::EncSliceLP) {
|
if (entrypoint == VAEntrypointEncSlice || entrypoint == VAEntrypointEncSliceLP) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -619,11 +407,7 @@ namespace va {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
validate(int fd) {
|
validate(int fd) {
|
||||||
if (init()) {
|
va::display_t display { vaGetDisplayDRM(fd) };
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
va::display_t display { va::getDisplayDRM(fd) };
|
|
||||||
if (!display) {
|
if (!display) {
|
||||||
char string[1024];
|
char string[1024];
|
||||||
|
|
||||||
|
|
@ -636,21 +420,21 @@ namespace va {
|
||||||
}
|
}
|
||||||
|
|
||||||
int major, minor;
|
int major, minor;
|
||||||
auto status = initialize(display.get(), &major, &minor);
|
auto status = vaInitialize(display.get(), &major, &minor);
|
||||||
if (status) {
|
if (status) {
|
||||||
BOOST_LOG(error) << "Couldn't initialize va display: "sv << va::errorStr(status);
|
BOOST_LOG(error) << "Couldn't initialize va display: "sv << vaErrorStr(status);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!query(display.get(), profile_e::H264Main)) {
|
if (!query(display.get(), VAProfileH264Main)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video::active_hevc_mode > 1 && !query(display.get(), profile_e::HEVCMain)) {
|
if (video::active_hevc_mode > 1 && !query(display.get(), VAProfileHEVCMain)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video::active_hevc_mode > 2 && !query(display.get(), profile_e::HEVCMain10)) {
|
if (video::active_hevc_mode > 2 && !query(display.get(), VAProfileHEVCMain10)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,4 @@ namespace va {
|
||||||
// Ensure the render device pointed to by fd is capable of encoding h264 with the hevc_mode configured
|
// Ensure the render device pointed to by fd is capable of encoding h264 with the hevc_mode configured
|
||||||
bool
|
bool
|
||||||
validate(int fd);
|
validate(int fd);
|
||||||
|
|
||||||
int
|
|
||||||
init();
|
|
||||||
} // namespace va
|
} // namespace va
|
||||||
|
|
|
||||||
|
|
@ -211,9 +211,11 @@ namespace wl {
|
||||||
|
|
||||||
std::unique_ptr<platf::avcodec_encode_device_t>
|
std::unique_ptr<platf::avcodec_encode_device_t>
|
||||||
make_avcodec_encode_device(platf::pix_fmt_e pix_fmt) override {
|
make_avcodec_encode_device(platf::pix_fmt_e pix_fmt) override {
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (mem_type == platf::mem_type_e::vaapi) {
|
if (mem_type == platf::mem_type_e::vaapi) {
|
||||||
return va::make_avcodec_encode_device(width, height, false);
|
return va::make_avcodec_encode_device(width, height, false);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return std::make_unique<platf::avcodec_encode_device_t>();
|
return std::make_unique<platf::avcodec_encode_device_t>();
|
||||||
}
|
}
|
||||||
|
|
@ -321,9 +323,11 @@ namespace wl {
|
||||||
|
|
||||||
std::unique_ptr<platf::avcodec_encode_device_t>
|
std::unique_ptr<platf::avcodec_encode_device_t>
|
||||||
make_avcodec_encode_device(platf::pix_fmt_e pix_fmt) override {
|
make_avcodec_encode_device(platf::pix_fmt_e pix_fmt) override {
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (mem_type == platf::mem_type_e::vaapi) {
|
if (mem_type == platf::mem_type_e::vaapi) {
|
||||||
return va::make_avcodec_encode_device(width, height, 0, 0, true);
|
return va::make_avcodec_encode_device(width, height, 0, 0, true);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return std::make_unique<platf::avcodec_encode_device_t>();
|
return std::make_unique<platf::avcodec_encode_device_t>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -555,9 +555,11 @@ namespace platf {
|
||||||
|
|
||||||
std::unique_ptr<avcodec_encode_device_t>
|
std::unique_ptr<avcodec_encode_device_t>
|
||||||
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
make_avcodec_encode_device(pix_fmt_e pix_fmt) override {
|
||||||
|
#ifdef SUNSHINE_BUILD_VAAPI
|
||||||
if (mem_type == mem_type_e::vaapi) {
|
if (mem_type == mem_type_e::vaapi) {
|
||||||
return va::make_avcodec_encode_device(width, height, false);
|
return va::make_avcodec_encode_device(width, height, false);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SUNSHINE_BUILD_CUDA
|
#ifdef SUNSHINE_BUILD_CUDA
|
||||||
if (mem_type == mem_type_e::cuda) {
|
if (mem_type == mem_type_e::cuda) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue