obs-ffmpeg: Set DRI devices and their name persistently

retrieving the DRI devices from /dev/dri/by-path/ instead of
/dev/dri/renderDXXX. This enable us to use lspci to get the device
name as well.
master
Carlo Castoldi 2021-09-27 20:37:52 +02:00 committed by Matt Gajownik
parent c9b327d0f0
commit 4623a6b4bc
4 changed files with 138 additions and 11 deletions

View File

@ -441,7 +441,8 @@ jobs:
qtbase5-private-dev \
libqt5svg5-dev \
swig \
libcmocka-dev
libcmocka-dev \
libpci-dev
- name: 'Restore Chromium Embedded Framework from cache'
id: cef-cache
uses: actions/cache@v2.1.2

View File

@ -0,0 +1,49 @@
# * Try to find Libpci
# Once done this will define
#
# LIBPCI_FOUND - system has Libpci
# LIBPCI_INCLUDE_DIRS - the Libpci include directory
# LIBPCI_LIBRARIES - the libraries needed to use Libpci
# LIBPCI_DEFINITIONS - Compiler switches required for using Libpci
# Use pkg-config to get the directories and then use these values in the
# find_path() and find_library() calls
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(_LIBPCI libpci)
endif()
find_path(
LIBPCI_INCLUDE_DIR
NAMES pci.h
HINTS ${_LIBPCI_INCLUDE_DIRS}
PATHS /usr/include /usr/local/include /opt/local/include
PATH_SUFFIXES pci/)
find_library(
LIBPCI_LIB
NAMES ${_LIBPCI_LIBRARIES} libpci
HINTS ${_LIBPCI_LIBRARY_DIRS}
PATHS /usr/lib /usr/local/lib /opt/local/lib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libpci REQUIRED_VARS LIBPCI_LIB LIBPCI_INCLUDE_DIR)
mark_as_advanced(LIBPCI_INCLUDE_DIR LIBPCI_LIB)
if(LIBPCI_FOUND)
set(LIBPCI_INCLUDE_DIRS ${LIBPCI_INCLUDE_DIR})
set(LIBPCI_LIBRARIES ${LIBPCI_LIB})
if(NOT TARGET LIBPCI::LIBPCI)
if(IS_ABSOLUTE "${LIBPCI_LIBRARIES}")
add_library(LIBPCI::LIBPCI UNKNOWN IMPORTED)
set_target_properties(LIBPCI::LIBPCI PROPERTIES IMPORTED_LOCATION
"${LIBPCI_LIBRARIES}")
else()
add_library(LIBPCI::LIBPCI INTERFACE IMPORTED)
set_target_properties(LIBPCI::LIBPCI PROPERTIES IMPORTED_LIBNAME
"${LIBPCI_LIBRARIES}")
endif()
endif()
endif()

View File

@ -11,6 +11,11 @@ find_package(FFmpeg REQUIRED
COMPONENTS avcodec avfilter avdevice avutil swscale avformat swresample)
include_directories(${FFMPEG_INCLUDE_DIRS})
if(UNIX AND NOT APPLE)
find_package(Libpci REQUIRED)
include_directories(${LIBPCI_INCLUDE_DIRS})
endif()
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/obs-ffmpeg-config.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/obs-ffmpeg-config.h")
@ -38,7 +43,8 @@ if(UNIX AND NOT APPLE)
list(APPEND obs-ffmpeg_SOURCES
obs-ffmpeg-vaapi.c)
LIST(APPEND obs-ffmpeg_PLATFORM_DEPS
${LIBVA_LBRARIES})
${LIBVA_LBRARIES}
${LIBPCI_LIBRARIES})
endif()
if(ENABLE_FFMPEG_LOGGING)

View File

@ -22,6 +22,7 @@
#include <util/darray.h>
#include <util/dstr.h>
#include <util/base.h>
#include <util/platform.h>
#include <media-io/video-io.h>
#include <obs-module.h>
#include <obs-avc.h>
@ -35,6 +36,8 @@
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <pci/pci.h>
#include "obs-ffmpeg-formats.h"
#define do_log(level, format, ...) \
@ -538,6 +541,31 @@ static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p,
return true;
}
static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot,
char *buf, int size)
{
struct pci_filter filter;
struct pci_dev *dev;
char *name;
pci_filter_init(pacc, &filter);
if (pci_filter_parse_slot(&filter, pci_slot))
return false;
pci_scan_bus(pacc);
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
pci_fill_info(dev, PCI_FILL_IDENT);
name = pci_lookup_name(pacc, buf, size,
PCI_LOOKUP_DEVICE,
dev->vendor_id, dev->device_id);
strcpy(buf, name);
return true;
}
}
return false;
}
static obs_properties_t *vaapi_properties(void *unused)
{
UNUSED_PARAMETER(unused);
@ -549,15 +577,58 @@ static obs_properties_t *vaapi_properties(void *unused)
obs_module_text("VAAPI.Device"),
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
char path[32] = "/dev/dri/renderD1";
for (int i = 28;; i++) {
sprintf(path, "/dev/dri/renderD1%d", i);
if (access(path, F_OK) == 0) {
char card[128] = "Card: ";
sprintf(card, "Card%d: %s", i - 28, path);
obs_property_list_add_string(list, card, path);
} else {
break;
if (os_file_exists("/dev/dri/by-path")) {
os_dir_t *by_path_dir = os_opendir("/dev/dri/by-path");
struct pci_access *pacc = pci_alloc();
struct os_dirent *file;
char namebuf[1024];
char pci_slot[13];
char *type;
pci_init(pacc);
while ((file = os_readdir(by_path_dir)) != NULL) {
// file_name pattern: pci-<pci_slot::12>-<type::{"card","render"}>
char *file_name = file->d_name;
if (strcmp(file_name, ".") == 0 ||
strcmp(file_name, "..") == 0)
continue;
char path[64] = "\0";
sprintf(path, "/dev/dri/by-path/%s", file_name);
type = strrchr(file_name, '-');
if (type == NULL)
continue;
else
type++;
if (strcmp(type, "render") == 0) {
strncpy(pci_slot, file_name + 4, 12);
pci_slot[12] = 0;
bool name_found = get_device_name_from_pci(
pacc, pci_slot, namebuf,
sizeof(namebuf));
if (!name_found)
obs_property_list_add_string(list, path,
path);
else
obs_property_list_add_string(
list, namebuf, path);
}
}
pci_cleanup(pacc);
os_closedir(by_path_dir);
}
if (obs_property_list_item_count(list) == 0) {
char path[32] = "/dev/dri/renderD1";
for (int i = 28;; i++) {
sprintf(path, "/dev/dri/renderD1%d", i);
if (access(path, F_OK) == 0) {
char card[128] = "Card: ";
sprintf(card, "Card%d: %s", i - 28, path);
obs_property_list_add_string(list, card, path);
} else {
break;
}
}
}