Просмотр исходного кода

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.
Carlo Castoldi 4 лет назад
Родитель
Сommit
4623a6b4bc

+ 2 - 1
.github/workflows/main.yml

@@ -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/[email protected]

+ 49 - 0
cmake/Modules/FindLibpci.cmake

@@ -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()

+ 7 - 1
plugins/obs-ffmpeg/CMakeLists.txt

@@ -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)

+ 80 - 9
plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c

@@ -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;
+			}
 		}
 	}