Code review findings from before merging feat/livekit-integration to main: - I1: sourceDestroy set self->stopping outside self->mutex, then notified. The worker's condition-variable predicate reads `stopping` under that same mutex, so the store+notify could land between the worker's predicate check and it entering the wait, dropping the notification and leaving the worker asleep for its full backoff (up to 30s) with the OBS UI thread blocked in worker.join(). Now set under the lock, matching how `generation` is already mutated in applySettings. - I3: the LiveKit SDK archive download in cmake/LiveKitSDK.cmake had no SHA256 pin wired up from the top-level CMakeLists.txt, unlike the obs-deps bootstrap right next to it. Added real SHA256 hashes -- computed by downloading each release archive and running sha256sum -- for every triple the pinned v1.10.1 release can resolve to (Linux x64/arm64, macOS x64/arm64, Windows x64), keyed by version+triple so a future version bump fails loudly (via message(WARNING)) instead of silently going unverified. Verified end-to-end locally: a deliberately wrong hash makes the configure step fail with a HASH mismatch error. Only Linux was also build-tested in this environment; macOS/Windows archives were downloaded and hashed but not build-tested here. - I4: the curl HTTP backend followed up to 3 redirects while the read key travels as a URL query parameter, so a malicious/misconfigured redirect (including an HTTPS->HTTP downgrade, which curl doesn't refuse by default) could leak the key. This client only ever talks to two fixed, first-party endpoints, so redirects are disabled outright (CURLOPT_FOLLOWLOCATION 0), matching the WinHTTP backend's existing default behavior. Left normalizeServerUrl's explicit-http:// pass-through as-is with a comment, per review guidance. - I5: ApiClient::redactedUrl was tested but never called. No current call site logs a request URL, so rather than inventing one, added a one-line comment marking it a deliberate guard rail for future logging. - I7: the LiveKit SDK log bridge (livekitLogToObs) wrote SDK messages straight into the OBS log. LiveKit's signaling URL carries the access token as a query parameter; defensively scrub "access_token=" and "key=" values before they ever reach obs_log. New ApiClient::redactSensitiveParams generalizes redactedUrl's redaction pattern to arbitrary text (not just a bare URL), with 6 new unit tests in test_api_client.cpp. - I2: added a code comment on session.cpp's auto_subscribe=true noting the known, unaddressed bandwidth/CPU cost of pulling every participant's track in multi-camera rooms, and that per-publication unsubscribe is a future optimization. No behavior change (out of scope per review). Verified: cmake configure + build + `ctest --test-dir build --output-on-failure` all pass, 6/6 suites (test_api_client now 127 checks, up from 121). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
198 lines
9.6 KiB
CMake
198 lines
9.6 KiB
CMake
cmake_minimum_required(VERSION 3.19)
|
|
|
|
project(obs-streamer-tools-plugin
|
|
VERSION 0.1.0
|
|
DESCRIPTION "OBS Studio source plugin for streamer-tools camera feeds"
|
|
LANGUAGES C CXX
|
|
)
|
|
|
|
set(CMAKE_C_STANDARD 11)
|
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
endif()
|
|
|
|
enable_testing()
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/common")
|
|
|
|
# --- OBS SDK ---------------------------------------------------------------
|
|
# Linux gets libobs from the distribution (Ubuntu's libobs-dev ships real
|
|
# libobsConfig.cmake), and that path is left exactly as it was.
|
|
#
|
|
# macOS and Windows have no such package, so they use obs-plugintemplate's
|
|
# buildspec bootstrap, trimmed: it downloads the pinned obs-deps bundle and
|
|
# the pinned obs-studio source, then builds and installs just `libobs`. See
|
|
# buildspec.json for why the OBS pin is deliberately low, and
|
|
# cmake/common/buildspec_common.cmake for every change from upstream.
|
|
#
|
|
# STPLUGIN_BOOTSTRAP_OBS=OFF falls back to plain find_package(libobs), for a
|
|
# developer who already has an OBS SDK on their prefix path and does not want
|
|
# a from-source libobs build.
|
|
option(STPLUGIN_BOOTSTRAP_OBS "Download and build libobs from source (macOS/Windows)" ON)
|
|
|
|
# Fallbacks for imported targets that were exported under a different
|
|
# configuration name than the one being built, lifted from
|
|
# obs-plugintemplate's cmake/common/bootstrap.cmake. Without these, an
|
|
# imported libobs exported as (say) RelWithDebInfo fails a Release build with
|
|
# "IMPORTED_LOCATION or IMPORTED_IMPLIB not set for imported target
|
|
# OBS::libobs configuration Release".
|
|
set(CMAKE_MAP_IMPORTED_CONFIG_RELEASE Release RelWithDebInfo MinSizeRel None "")
|
|
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO RelWithDebInfo Release MinSizeRel None "")
|
|
set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL MinSizeRel Release RelWithDebInfo None "")
|
|
set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Debug RelWithDebInfo Release MinSizeRel None "")
|
|
|
|
include(osconfig)
|
|
if(STPLUGIN_BOOTSTRAP_OBS AND (OS_MACOS OR OS_WINDOWS))
|
|
if(OS_MACOS)
|
|
# client-sdk-cpp ships single-arch dylibs, so this plugin is built for
|
|
# one architecture even though the libobs it links is universal.
|
|
if(NOT CMAKE_OSX_ARCHITECTURES)
|
|
set(CMAKE_OSX_ARCHITECTURES "${CMAKE_HOST_SYSTEM_PROCESSOR}" CACHE STRING "" FORCE)
|
|
endif()
|
|
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0" CACHE STRING "" FORCE)
|
|
endif()
|
|
endif()
|
|
include(buildspec)
|
|
endif()
|
|
|
|
# --- LiveKit C++ client SDK -------------------------------------------------
|
|
# Pinned, prebuilt release of livekit/client-sdk-cpp, downloaded and unpacked
|
|
# by cmake/LiveKitSDK.cmake, then consumed through its own CMake package
|
|
# config as the LiveKit::livekit imported target. See the design doc's
|
|
# "Resolved (2026-09-07)" section: an exact pin, never "latest".
|
|
set(STPLUGIN_LIVEKIT_SDK_VERSION "1.10.1" CACHE STRING
|
|
"Pinned livekit/client-sdk-cpp release version")
|
|
set(STPLUGIN_LIVEKIT_SDK_TRIPLE "" CACHE STRING
|
|
"Override the client-sdk-cpp release triple (e.g. ubuntu-24.04-x64); empty = autodetect")
|
|
set(STPLUGIN_LIVEKIT_SDK_DIR "${CMAKE_BINARY_DIR}/_deps/livekit-sdk" CACHE PATH
|
|
"Directory the client-sdk-cpp release archive is extracted into (point at a persistent path to cache it across CI builds)")
|
|
|
|
# Pinned SHA256 checksums for the client-sdk-cpp v1.10.1 release archives,
|
|
# so the download in cmake/LiveKitSDK.cmake is verified the same way the
|
|
# obs-deps bootstrap next to it already is (see
|
|
# cmake/common/buildspec_common.cmake ~line 324). Each hash below was
|
|
# computed by downloading the real GitHub release asset and running
|
|
# `sha256sum` on it (2026-09-06/07) -- none of these were guessed or copied
|
|
# from an unverified source. To add a hash for a new version or triple:
|
|
# curl -LO https://github.com/livekit/client-sdk-cpp/releases/download/v<VERSION>/livekit-sdk-<TRIPLE>-<VERSION>.<tar.gz|zip>
|
|
# sha256sum livekit-sdk-<TRIPLE>-<VERSION>.*
|
|
# Covers every triple _lk_default_triple() can resolve to for this pinned
|
|
# version: Linux (ubuntu-22.04-x64/arm64), macOS (macos-x64/arm64) and
|
|
# Windows (windows-x64). Verified by extracting each archive
|
|
# (tar tzf / unzip -l) and confirming a real LiveKitConfig.cmake inside --
|
|
# only Linux was also verified by an actual local CMake configure+build in
|
|
# this environment; macOS and Windows were downloaded and hashed but not
|
|
# build-tested here.
|
|
set(_stplugin_livekit_sha256_1.10.1_ubuntu-22.04-x64 "6f4fc8143f36952d42bfd5ff8d1782cf6211ba8fd6b055877e9ef85441d66324")
|
|
set(_stplugin_livekit_sha256_1.10.1_ubuntu-22.04-arm64 "399677167b474b7f107c6937904ea01898c9ec8da648cbed669387e599c6ea45")
|
|
set(_stplugin_livekit_sha256_1.10.1_macos-x64 "7102655c1f2947be4b06a95f9fafa1a11379219328e82ad875e5ebccfc9ac7e3")
|
|
set(_stplugin_livekit_sha256_1.10.1_macos-arm64 "0822af7014519a473c5b5cd019bde58c26cc2bfe5b78e4a790395ead232dc55b")
|
|
set(_stplugin_livekit_sha256_1.10.1_windows-x64 "b9fc6b2865298d7e3d032205d7e74fb9628cfe55a2ed28cb657db0a481cd518c")
|
|
|
|
include(LiveKitSDK)
|
|
if(STPLUGIN_LIVEKIT_SDK_TRIPLE)
|
|
set(_stplugin_livekit_triple "${STPLUGIN_LIVEKIT_SDK_TRIPLE}")
|
|
else()
|
|
# Mirrors LiveKitSDK.cmake's own autodetection so the checksum lookup
|
|
# below matches whatever triple livekit_sdk_setup() will actually
|
|
# resolve to and download.
|
|
_lk_default_triple(_stplugin_livekit_triple)
|
|
endif()
|
|
|
|
set(_stplugin_livekit_sha256_var
|
|
"_stplugin_livekit_sha256_${STPLUGIN_LIVEKIT_SDK_VERSION}_${_stplugin_livekit_triple}")
|
|
if(DEFINED ${_stplugin_livekit_sha256_var})
|
|
set(_stplugin_livekit_sha256 "${${_stplugin_livekit_sha256_var}}")
|
|
else()
|
|
set(_stplugin_livekit_sha256 "")
|
|
message(WARNING
|
|
"LiveKitSDK: no pinned SHA256 for triple '${_stplugin_livekit_triple}' "
|
|
"at version ${STPLUGIN_LIVEKIT_SDK_VERSION} -- the downloaded archive "
|
|
"will NOT be integrity-checked. Compute one (see the comment above "
|
|
"this block) and add it to CMakeLists.txt.")
|
|
endif()
|
|
|
|
if(STPLUGIN_LIVEKIT_SDK_TRIPLE)
|
|
livekit_sdk_setup(
|
|
VERSION "${STPLUGIN_LIVEKIT_SDK_VERSION}"
|
|
SDK_DIR "${STPLUGIN_LIVEKIT_SDK_DIR}"
|
|
TRIPLE "${STPLUGIN_LIVEKIT_SDK_TRIPLE}"
|
|
SHA256 "${_stplugin_livekit_sha256}"
|
|
)
|
|
else()
|
|
livekit_sdk_setup(
|
|
VERSION "${STPLUGIN_LIVEKIT_SDK_VERSION}"
|
|
SDK_DIR "${STPLUGIN_LIVEKIT_SDK_DIR}"
|
|
SHA256 "${_stplugin_livekit_sha256}"
|
|
)
|
|
endif()
|
|
find_package(LiveKit CONFIG REQUIRED)
|
|
|
|
add_subdirectory(core)
|
|
|
|
find_package(libobs QUIET)
|
|
|
|
# The imported OBS::libobs target can come back without a location. OBS 30.0.2
|
|
# installs libobsTargets.cmake but not the per-configuration
|
|
# libobsTargets-<config>.cmake alongside it when libobs is built on its own,
|
|
# and CMake then fails at generate time with:
|
|
#
|
|
# IMPORTED_LOCATION or IMPORTED_IMPLIB not set for imported target
|
|
# "OBS::libobs" configuration "Release".
|
|
#
|
|
# Repair it here rather than fighting OBS's export machinery: the library the
|
|
# bootstrap just built is in a known place, and pointing the imported target
|
|
# at it is exactly what the missing file would have done. Distribution
|
|
# packages (Ubuntu's libobs-dev) export a complete target and never take this
|
|
# path.
|
|
if(libobs_FOUND AND TARGET OBS::libobs)
|
|
get_target_property(_stplugin_obs_location OBS::libobs IMPORTED_LOCATION)
|
|
get_target_property(_stplugin_obs_location_release OBS::libobs IMPORTED_LOCATION_RELEASE)
|
|
get_target_property(_stplugin_obs_implib OBS::libobs IMPORTED_IMPLIB)
|
|
get_target_property(_stplugin_obs_implib_release OBS::libobs IMPORTED_IMPLIB_RELEASE)
|
|
if(NOT _stplugin_obs_location
|
|
AND NOT _stplugin_obs_location_release
|
|
AND NOT _stplugin_obs_implib
|
|
AND NOT _stplugin_obs_implib_release)
|
|
set(_stplugin_deps "${CMAKE_CURRENT_SOURCE_DIR}/.deps")
|
|
if(APPLE)
|
|
set(_stplugin_obs_binary "${_stplugin_deps}/Frameworks/libobs.framework/Versions/A/libobs")
|
|
if(NOT EXISTS "${_stplugin_obs_binary}")
|
|
set(_stplugin_obs_binary "${_stplugin_deps}/Frameworks/libobs.framework/libobs")
|
|
endif()
|
|
if(EXISTS "${_stplugin_obs_binary}")
|
|
set_target_properties(
|
|
OBS::libobs
|
|
PROPERTIES
|
|
IMPORTED_LOCATION "${_stplugin_obs_binary}"
|
|
INTERFACE_INCLUDE_DIRECTORIES "${_stplugin_deps}/Frameworks/libobs.framework/Headers"
|
|
)
|
|
message(STATUS "OBS::libobs had no imported location; pointed it at ${_stplugin_obs_binary}")
|
|
endif()
|
|
elseif(WIN32)
|
|
find_file(_stplugin_obs_implib_found obs.lib PATHS "${_stplugin_deps}/lib" NO_DEFAULT_PATH)
|
|
find_file(_stplugin_obs_dll_found obs.dll PATHS "${_stplugin_deps}/bin" NO_DEFAULT_PATH)
|
|
if(_stplugin_obs_implib_found)
|
|
set_target_properties(OBS::libobs PROPERTIES IMPORTED_IMPLIB "${_stplugin_obs_implib_found}")
|
|
if(_stplugin_obs_dll_found)
|
|
set_target_properties(OBS::libobs PROPERTIES IMPORTED_LOCATION "${_stplugin_obs_dll_found}")
|
|
endif()
|
|
message(STATUS "OBS::libobs had no imported location; pointed it at ${_stplugin_obs_implib_found}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
if(libobs_FOUND)
|
|
message(STATUS "libobs found (${libobs_DIR}) -- building OBS adapter module")
|
|
add_subdirectory(obs-adapter)
|
|
else()
|
|
message(WARNING "libobs NOT found -- skipping OBS adapter module; core library still builds/tests")
|
|
endif()
|