From e206138a3967fb5d4e3daa483f007f6f1b599ea5 Mon Sep 17 00:00:00 2001 From: materus Date: Tue, 25 Jun 2024 11:59:28 +0200 Subject: [PATCH] obs-amf: remove, libcef: remove, ffmpeg: use from nixpkgs --- pkgs/apps/ffmpeg/default.nix | 4 - pkgs/apps/ffmpeg/old.nix | 719 ---- ...ss-and-universal-access-for-file-URL.patch | 36 - pkgs/apps/obs/av1-vaapi.patch | 3826 ----------------- pkgs/apps/obs/default.nix | 196 - pkgs/apps/obs/ffmpeg61.patch | 286 -- pkgs/apps/obs/fix-nix-plugin-path.patch | 26 - pkgs/apps/obs/obs-amf-patch.patch | 649 --- pkgs/apps/obs/onevpl.nix | 44 - pkgs/apps/obs/qrcodegencpp.nix | 27 - pkgs/default.nix | 16 +- pkgs/libs/libcef.nix | 130 - 12 files changed, 1 insertion(+), 5958 deletions(-) delete mode 100644 pkgs/apps/ffmpeg/default.nix delete mode 100644 pkgs/apps/ffmpeg/old.nix delete mode 100644 pkgs/apps/obs/Enable-file-access-and-universal-access-for-file-URL.patch delete mode 100644 pkgs/apps/obs/av1-vaapi.patch delete mode 100644 pkgs/apps/obs/default.nix delete mode 100644 pkgs/apps/obs/ffmpeg61.patch delete mode 100644 pkgs/apps/obs/fix-nix-plugin-path.patch delete mode 100644 pkgs/apps/obs/obs-amf-patch.patch delete mode 100644 pkgs/apps/obs/onevpl.nix delete mode 100644 pkgs/apps/obs/qrcodegencpp.nix delete mode 100644 pkgs/libs/libcef.nix diff --git a/pkgs/apps/ffmpeg/default.nix b/pkgs/apps/ffmpeg/default.nix deleted file mode 100644 index d54ae6d..0000000 --- a/pkgs/apps/ffmpeg/default.nix +++ /dev/null @@ -1,4 +0,0 @@ -import ./old.nix rec { - version = "6.1"; - sha256 = "sha256-NzhD2D16bCVCyCXo0TRwZYp3Ta5eFSfoQPa+iRkeNZg="; -} \ No newline at end of file diff --git a/pkgs/apps/ffmpeg/old.nix b/pkgs/apps/ffmpeg/old.nix deleted file mode 100644 index 3d97a21..0000000 --- a/pkgs/apps/ffmpeg/old.nix +++ /dev/null @@ -1,719 +0,0 @@ -#FFMPEG from nixpkgs, added AMF flag, defaults to full ffmpeg - -{ version, sha256, extraPatches ? [], knownVulnerabilities ? [] }: - -{ lib, stdenv, buildPackages, removeReferencesTo, addOpenGLRunpath, pkg-config, perl, texinfo, yasm - -, ffmpegVariant ? "full" # Decides which dependencies are enabled by default - - # Build with headless deps; excludes dependencies that are only necessary for - # GUI applications. To be used for purposes that don't generally need such - # components and i.e. only depend on libav -, withHeadlessDeps ? ffmpegVariant == "headless" || withSmallDeps - - # Dependencies a user might customarily expect from a regular ffmpeg build. - # /All/ packages that depend on ffmpeg and some of its feaures should depend - # on the small variant. Small means the minimal set of features that satisfies - # all dependants in Nixpkgs -, withSmallDeps ? ffmpegVariant == "small" || withFullDeps - - # Everything enabled; only guarded behind platform exclusivity or brokeness. - # If you need to depend on ffmpeg-full because ffmpeg is missing some feature - # your package needs, you should enable that feature in regular ffmpeg - # instead. -, withFullDeps ? ffmpegVariant == "full" - -, fetchgit -, fetchpatch - - # Feature flags -, withAmf ? withFullDeps -, withAlsa ? withHeadlessDeps && stdenv.isLinux # Alsa in/output supporT -, withAom ? withFullDeps # AV1 reference encoder -, withAss ? withHeadlessDeps && stdenv.hostPlatform == stdenv.buildPlatform # (Advanced) SubStation Alpha subtitle rendering -, withBluray ? withFullDeps # BluRay reading -, withBs2b ? withFullDeps # bs2b DSP library -, withBzlib ? withHeadlessDeps -, withCaca ? withFullDeps # Textual display (ASCII art) -, withCelt ? withFullDeps # CELT decoder -, withCrystalhd ? withFullDeps -, withCuda ? withFullDeps && (with stdenv; (!isDarwin && !hostPlatform.isAarch)) -, withCudaLLVM ? withFullDeps -, withDav1d ? withHeadlessDeps # AV1 decoder (focused on speed and correctness) -, withDc1394 ? withFullDeps && !stdenv.isDarwin # IIDC-1394 grabbing (ieee 1394) -, withDrm ? withHeadlessDeps && (with stdenv; isLinux || isFreeBSD) # libdrm support -, withFdkAac ? withFullDeps && withUnfree # Fraunhofer FDK AAC de/encoder -, withFontconfig ? withHeadlessDeps # Needed for drawtext filter -, withFreetype ? withHeadlessDeps # Needed for drawtext filter -, withFrei0r ? withFullDeps # frei0r video filtering -, withFribidi ? withFullDeps # Needed for drawtext filter -, withGlslang ? withFullDeps && !stdenv.isDarwin -, withGme ? withFullDeps # Game Music Emulator -, withGnutls ? withHeadlessDeps -, withGsm ? withFullDeps # GSM de/encoder -, withIconv ? withHeadlessDeps -, withIlbc ? withFullDeps -, withJack ? withFullDeps && !stdenv.isDarwin # Jack audio -, withLadspa ? withFullDeps # LADSPA audio filtering -, withLibplacebo ? withFullDeps && !stdenv.isDarwin # libplacebo video processing library -, withLzma ? withHeadlessDeps # xz-utils -, withMfx ? withFullDeps && (with stdenv.targetPlatform; isLinux && !isAarch) # Hardware acceleration via intel-media-sdk/libmfx -, withModplug ? withFullDeps && !stdenv.isDarwin # ModPlug support -, withMp3lame ? withHeadlessDeps # LAME MP3 encoder -, withMysofa ? withFullDeps # HRTF support via SOFAlizer -, withNvdec ? withHeadlessDeps && !stdenv.isDarwin && stdenv.hostPlatform == stdenv.buildPlatform && !stdenv.isAarch32 -, withNvenc ? withHeadlessDeps && !stdenv.isDarwin && stdenv.hostPlatform == stdenv.buildPlatform && !stdenv.isAarch32 -, withOgg ? withHeadlessDeps # Ogg container used by vorbis & theora -, withOpenal ? withFullDeps # OpenAL 1.1 capture support -, withOpencl ? withFullDeps -, withOpencoreAmrnb ? withFullDeps # AMR-NB de/encoder & AMR-WB decoder -, withOpengl ? withFullDeps # OpenGL rendering -, withOpenh264 ? withFullDeps # H.264/AVC encoder -, withOpenjpeg ? withFullDeps # JPEG 2000 de/encoder -, withOpenmpt ? withFullDeps # Tracked music files decoder -, withOpus ? withHeadlessDeps # Opus de/encoder -, withPulse ? withSmallDeps && !stdenv.isDarwin # Pulseaudio input support -, withRav1e ? withFullDeps # AV1 encoder (focused on speed and safety) -, withRtmp ? false # RTMP[E] support -, withSamba ? withFullDeps && !stdenv.isDarwin # Samba protocol -, withSdl2 ? withSmallDeps -, withSoxr ? withHeadlessDeps # Resampling via soxr -, withSpeex ? withHeadlessDeps # Speex de/encoder -, withSrt ? withHeadlessDeps # Secure Reliable Transport (SRT) protocol -, withSsh ? withHeadlessDeps # SFTP protocol -, withSvg ? withFullDeps # SVG protocol -, withSvtav1 ? withFullDeps && !stdenv.isAarch64 # AV1 encoder/decoder (focused on speed and correctness) -, withTensorflow ? false # Tensorflow dnn backend support -, withTheora ? withHeadlessDeps # Theora encoder -, withV4l2 ? withFullDeps && !stdenv.isDarwin # Video 4 Linux support -, withV4l2M2m ? withV4l2 -, withVaapi ? withHeadlessDeps && (with stdenv; isLinux || isFreeBSD) # Vaapi hardware acceleration -, withVdpau ? withSmallDeps # Vdpau hardware acceleration -, withVidStab ? withFullDeps # Video stabilization -, withVmaf ? withFullDeps && withGPLv3 && !stdenv.isAarch64 # Netflix's VMAF (Video Multi-Method Assessment Fusion) -, withVoAmrwbenc ? withFullDeps # AMR-WB encoder -, withVorbis ? withHeadlessDeps # Vorbis de/encoding, native encoder exists -, withVpx ? withHeadlessDeps && stdenv.buildPlatform == stdenv.hostPlatform # VP8 & VP9 de/encoding -, withVulkan ? withFullDeps && !stdenv.isDarwin -, withWebp ? withFullDeps # WebP encoder -, withX264 ? withHeadlessDeps # H.264/AVC encoder -, withX265 ? withHeadlessDeps # H.265/HEVC encoder -, withXavs ? withFullDeps # AVS encoder -, withXcb ? withXcbShm || withXcbxfixes || withXcbShape # X11 grabbing using XCB -, withXcbShape ? withFullDeps # X11 grabbing shape rendering -, withXcbShm ? withFullDeps # X11 grabbing shm communication -, withXcbxfixes ? withFullDeps # X11 grabbing mouse rendering -, withXlib ? withFullDeps # Xlib support -, withXml2 ? withFullDeps # libxml2 support, for IMF and DASH demuxers -, withXvid ? withHeadlessDeps # Xvid encoder, native encoder exists -, withZimg ? withHeadlessDeps -, withZlib ? withHeadlessDeps -, withZmq ? withFullDeps # Message passing - - -/* - * Licensing options (yes some are listed twice, filters and such are not listed) - */ -, withGPL ? true -, withGPLv3 ? true -, withUnfree ? false - -/* - * Build options - */ -, withSmallBuild ? false # Optimize for size instead of speed -, withRuntimeCPUDetection ? true # Detect CPU capabilities at runtime (disable to compile natively) -, withGrayscale ? withFullDeps # Full grayscale support -, withSwscaleAlpha ? buildSwscale # Alpha channel support in swscale. You probably want this when buildSwscale. -, withHardcodedTables ? withHeadlessDeps # Hardcode decode tables instead of runtime generation -, withSafeBitstreamReader ? withHeadlessDeps # Buffer boundary checking in bitreaders -, withMultithread ? true # Multithreading via pthreads/win32 threads -, withNetwork ? withHeadlessDeps # Network support -, withPixelutils ? withHeadlessDeps # Pixel utils in libavutil -/* - * Program options - */ -, buildFfmpeg ? withHeadlessDeps # Build ffmpeg executable -, buildFfplay ? withFullDeps # Build ffplay executable -, buildFfprobe ? withHeadlessDeps # Build ffprobe executable -, buildQtFaststart ? withFullDeps # Build qt-faststart executable -, withBin ? buildFfmpeg || buildFfplay || buildFfprobe || buildQtFaststart -/* - * Library options - */ -, buildAvcodec ? withHeadlessDeps # Build avcodec library -, buildAvdevice ? withHeadlessDeps # Build avdevice library -, buildAvfilter ? withHeadlessDeps # Build avfilter library -, buildAvformat ? withHeadlessDeps # Build avformat library -# Deprecated but depended upon by some packages. -# https://github.com/NixOS/nixpkgs/pull/211834#issuecomment-1417435991) -, buildAvresample ? withHeadlessDeps && lib.versionOlder version "5" # Build avresample library -, buildAvutil ? withHeadlessDeps # Build avutil library -, buildPostproc ? withHeadlessDeps # Build postproc library -, buildSwresample ? withHeadlessDeps # Build swresample library -, buildSwscale ? withHeadlessDeps # Build swscale library -, withLib ? buildAvcodec - || buildAvdevice - || buildAvfilter - || buildAvformat - || buildAvutil - || buildPostproc - || buildSwresample - || buildSwscale -/* - * Documentation options - */ -, withDocumentation ? withHtmlDoc || withManPages || withPodDoc || withTxtDoc -, withHtmlDoc ? withHeadlessDeps # HTML documentation pages -, withManPages ? withHeadlessDeps # Man documentation pages -, withPodDoc ? withHeadlessDeps # POD documentation pages -, withTxtDoc ? withHeadlessDeps # Text documentation pages -# Whether a "doc" output will be produced. Note that withManPages does not produce -# a "doc" output because its files go to "man". -, withDoc ? withDocumentation && (withHtmlDoc || withPodDoc || withTxtDoc) - -/* - * Developer options - */ -, withDebug ? false -, withOptimisations ? true -, withExtraWarnings ? false -, withStripping ? false - -/* - * External libraries options - */ -, amf-headers -, alsa-lib -, bzip2 -, clang -, celt -, dav1d -, fdk_aac -, fontconfig -, freetype -, frei0r -, fribidi -, game-music-emu -, gnutls -, gsm -, libjack2 -, ladspaH -, lame -, libass -, libaom -, libbluray -, libbs2b -, libcaca -, libdc1394 -, libraw1394 -, libdrm -, libiconv -, intel-media-sdk -, libmodplug -, libmysofa -, libogg -, libopenmpt -, libopus -, libplacebo -, librsvg -, libssh -, libtensorflow -, libtheora -, libv4l -, libva -, libva-minimal -, libvdpau -, libvmaf -, libvorbis -, libvpx -, libwebp -, libX11 -, libxcb -, libXv -, libXext -, libxml2 -, xz -, openal -, ocl-icd # OpenCL ICD -, opencl-headers # OpenCL headers -, opencore-amr -, libGL -, libGLU -, openh264 -, openjpeg -, libpulseaudio -, rav1e -, svt-av1 -, rtmpdump -, samba -, SDL2 -, soxr -, speex -, srt -, vid-stab -, vo-amrwbenc -, x264 -, x265 -, xavs -, xvidcore -, zeromq4 -, zimg -, zlib -, vulkan-headers -, vulkan-loader -, glslang -/* - * Darwin frameworks - */ -, AVFoundation -, Cocoa -, CoreAudio -, CoreMedia -, CoreServices -, MediaToolbox -, VideoDecodeAcceleration -, VideoToolbox -/* - * Testing - */ -, testers -}: - -/* Maintainer notes: - * - * Version bumps: - * It should always be safe to bump patch releases (e.g. 2.1.x, x being a patch release) - * If adding a new branch, note any configure flags that were added, changed, or deprecated/removed - * and make the necessary changes. - * - * Known issues: - * Cross-compiling will disable features not present on host OS - * (e.g. dxva2 support [DirectX] will not be enabled unless natively compiled on Cygwin) - * - */ - -let - inherit (lib) optional optionals optionalString enableFeature versionAtLeast; -in - - -assert lib.elem ffmpegVariant [ "headless" "small" "full" ]; - -/* - * Licensing dependencies - */ -assert withGPLv3 -> withGPL; -assert withUnfree -> withGPL && withGPLv3; -/* - * Build dependencies - */ -assert withPixelutils -> buildAvutil; -/* - * Program dependencies - */ -assert buildFfmpeg -> buildAvcodec - && buildAvfilter - && buildAvformat - && (buildSwresample || buildAvresample); -assert buildFfplay -> buildAvcodec - && buildAvformat - && buildSwscale - && (buildSwresample || buildAvresample); -assert buildFfprobe -> buildAvcodec && buildAvformat; -/* - * Library dependencies - */ -assert buildAvcodec -> buildAvutil; # configure flag since 0.6 -assert buildAvdevice -> buildAvformat - && buildAvcodec - && buildAvutil; # configure flag since 0.6 -assert buildAvformat -> buildAvcodec && buildAvutil; # configure flag since 0.6 -assert buildPostproc -> buildAvutil; -assert buildSwscale -> buildAvutil; - -stdenv.mkDerivation (finalAttrs: { - pname = "ffmpeg" + (if ffmpegVariant == "small" then "" else "-${ffmpegVariant}") + (if withAmf then "-amf" else ""); - inherit version; - - src = fetchgit { - url = "https://git.ffmpeg.org/ffmpeg.git"; - rev = "n${finalAttrs.version}"; - inherit sha256; - }; - - postPatch = '' - patchShebangs . - '' + lib.optionalString withFrei0r '' - substituteInPlace libavfilter/vf_frei0r.c \ - --replace /usr/local/lib/frei0r-1 ${frei0r}/lib/frei0r-1 - substituteInPlace doc/filters.texi \ - --replace /usr/local/lib/frei0r-1 ${frei0r}/lib/frei0r-1 - ''; - - patches = map (patch: fetchpatch patch) (extraPatches - ++ (lib.optional (lib.versionAtLeast version "6" && lib.versionOlder version "6.1") - { # this can be removed post 6.1 - name = "fix_aacps_tablegen"; - url = "https://git.ffmpeg.org/gitweb/ffmpeg.git/patch/814178f92647be2411516bbb82f48532373d2554"; - hash = "sha256-FQV9/PiarPXCm45ldtCsxGHjlrriL8DKpn1LaKJ8owI="; - } - )); - - configurePlatforms = []; - setOutputFlags = false; # Only accepts some of them - configureFlags = [ - #mingw64 is internally treated as mingw32, so 32 and 64 make no difference here - "--target_os=${if stdenv.hostPlatform.isMinGW then "mingw64" else stdenv.hostPlatform.parsed.kernel.name}" - "--arch=${stdenv.hostPlatform.parsed.cpu.name}" - "--pkg-config=${buildPackages.pkg-config.targetPrefix}pkg-config" - /* - * Licensing flags - */ - (enableFeature withGPL "gpl") - (enableFeature withGPLv3 "version3") - (enableFeature withUnfree "nonfree") - /* - * Build flags - */ - # On some ARM platforms --enable-thumb - "--enable-shared" - "--enable-pic" - - (enableFeature withSmallBuild "small") - (enableFeature withRuntimeCPUDetection "runtime-cpudetect") - (enableFeature withGrayscale "gray") - (enableFeature withSwscaleAlpha "swscale-alpha") - (enableFeature withHardcodedTables "hardcoded-tables") - (enableFeature withSafeBitstreamReader "safe-bitstream-reader") - - (enableFeature (withMultithread && stdenv.targetPlatform.isUnix) "pthreads") - (enableFeature (withMultithread && stdenv.targetPlatform.isWindows) "w32threads") - "--disable-os2threads" # We don't support OS/2 - - (enableFeature withNetwork "network") - (enableFeature withPixelutils "pixelutils") - - "--datadir=${placeholder "data"}/share/ffmpeg" - - /* - * Program flags - */ - (enableFeature buildFfmpeg "ffmpeg") - (enableFeature buildFfplay "ffplay") - (enableFeature buildFfprobe "ffprobe") - ] ++ optionals withBin [ - "--bindir=${placeholder "bin"}/bin" - ] ++ [ - /* - * Library flags - */ - (enableFeature buildAvcodec "avcodec") - (enableFeature buildAvdevice "avdevice") - (enableFeature buildAvfilter "avfilter") - (enableFeature buildAvformat "avformat") - ] ++ optionals (lib.versionOlder version "5") [ - # Ffmpeg > 4 doesn't know about the flag anymore - (enableFeature buildAvresample "avresample") - ] ++ [ - (enableFeature buildAvutil "avutil") - (enableFeature (buildPostproc && withGPL) "postproc") - (enableFeature buildSwresample "swresample") - (enableFeature buildSwscale "swscale") - ] ++ optionals withLib [ - "--libdir=${placeholder "lib"}/lib" - "--incdir=${placeholder "dev"}/include" - ] ++ [ - /* - * Documentation flags - */ - (enableFeature withDocumentation "doc") - (enableFeature withHtmlDoc "htmlpages") - (enableFeature withManPages "manpages") - ] ++ optionals withManPages [ - "--mandir=${placeholder "man"}/share/man" - ] ++ [ - (enableFeature withPodDoc "podpages") - (enableFeature withTxtDoc "txtpages") - ] ++ optionals withDoc [ - "--docdir=${placeholder "doc"}/share/doc/ffmpeg" - ] ++ [ - /* - * External libraries - */ - (enableFeature withAmf "amf") - (enableFeature withAlsa "alsa") - (enableFeature withBzlib "bzlib") - (enableFeature withCelt "libcelt") - (enableFeature withCuda "cuda") - (enableFeature withCudaLLVM "cuda-llvm") - (enableFeature withDav1d "libdav1d") - (enableFeature withFdkAac "libfdk-aac") - "--disable-libflite" # Force disable until a solution is found - (enableFeature withFontconfig "fontconfig") - (enableFeature withFreetype "libfreetype") - (enableFeature withFrei0r "frei0r") - (enableFeature withFribidi "libfribidi") - (enableFeature withGme "libgme") - (enableFeature withGnutls "gnutls") - (enableFeature withGsm "libgsm") - (enableFeature withLadspa "ladspa") - (enableFeature withMp3lame "libmp3lame") - (enableFeature withAom "libaom") - (enableFeature withAss "libass") - (enableFeature withBluray "libbluray") - (enableFeature withBs2b "libbs2b") - (enableFeature withDc1394 "libdc1394") - (enableFeature withDrm "libdrm") - (enableFeature withIconv "iconv") - (enableFeature withJack "libjack") - (enableFeature withMfx "libmfx") - (enableFeature withModplug "libmodplug") - (enableFeature withMysofa "libmysofa") - (enableFeature withOpus "libopus") - (optionalString (versionAtLeast version "5.0" && withLibplacebo) "--enable-libplacebo") - (enableFeature withSvg "librsvg") - (enableFeature withSrt "libsrt") - (enableFeature withSsh "libssh") - (enableFeature withTensorflow "libtensorflow") - (enableFeature withTheora "libtheora") - (enableFeature withV4l2 "libv4l2") - (enableFeature withV4l2M2m "v4l2-m2m") - (enableFeature withVaapi "vaapi") - (enableFeature withVdpau "vdpau") - (enableFeature withVorbis "libvorbis") - (enableFeature withVmaf "libvmaf") - (enableFeature withVpx "libvpx") - (enableFeature withWebp "libwebp") - (enableFeature withXlib "xlib") - (enableFeature withXcb "libxcb") - (enableFeature withXcbShm "libxcb-shm") - (enableFeature withXcbxfixes "libxcb-xfixes") - (enableFeature withXcbShape "libxcb-shape") - (enableFeature withXml2 "libxml2") - (enableFeature withLzma "lzma") - (enableFeature withNvdec "cuvid") - (enableFeature withNvdec "nvdec") - (enableFeature withNvenc "nvenc") - (enableFeature withOpenal "openal") - (enableFeature withOpencl "opencl") - (enableFeature withOpencoreAmrnb "libopencore-amrnb") - (enableFeature withOpengl "opengl") - (enableFeature withOpenh264 "libopenh264") - (enableFeature withOpenjpeg "libopenjpeg") - (enableFeature withOpenmpt "libopenmpt") - (enableFeature withPulse "libpulse") - (enableFeature withRav1e "librav1e") - (enableFeature withSvtav1 "libsvtav1") - (enableFeature withRtmp "librtmp") - (enableFeature withSdl2 "sdl2") - (enableFeature withSoxr "libsoxr") - (enableFeature withSpeex "libspeex") - (enableFeature withVidStab "libvidstab") # Actual min. version 2.0 - (enableFeature withVoAmrwbenc "libvo-amrwbenc") - (enableFeature withX264 "libx264") - (enableFeature withX265 "libx265") - (enableFeature withXavs "libxavs") - (enableFeature withXvid "libxvid") - (enableFeature withZmq "libzmq") - (enableFeature withZimg "libzimg") - (enableFeature withZlib "zlib") - (enableFeature withVulkan "vulkan") - (enableFeature withGlslang "libglslang") - (enableFeature withSamba "libsmbclient") - /* - * Developer flags - */ - (enableFeature withDebug "debug") - (enableFeature withOptimisations "optimizations") - (enableFeature withExtraWarnings "extra-warnings") - (enableFeature withStripping "stripping") - ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ - "--cross-prefix=${stdenv.cc.targetPrefix}" - "--enable-cross-compile" - "--host-cc=${buildPackages.stdenv.cc}/bin/cc" - ] ++ optionals stdenv.cc.isClang [ - "--cc=clang" - "--cxx=clang++" - ]; - - # ffmpeg embeds the configureFlags verbatim in its binaries and because we - # configure binary, include, library dir etc., this causes references in - # outputs where we don't want them. Patch the generated config.h to remove all - # such references except for data. - postConfigure = let - toStrip = lib.remove "data" finalAttrs.outputs; # We want to keep references to the data dir. - in - "remove-references-to ${lib.concatStringsSep " " (map (o: "-t ${placeholder o}") toStrip)} config.h"; - - nativeBuildInputs = [ removeReferencesTo addOpenGLRunpath perl pkg-config texinfo yasm ]; - - # TODO This was always in buildInputs before, why? - buildInputs = - let - nv-codec-headers = stdenv.mkDerivation rec { - pname = "nv-codec-headers"; - version = "12.1.14.0"; - src = fetchgit { - url = "https://git.videolan.org/git/ffmpeg/nv-codec-headers.git"; - rev = "n${version}"; - sha256 = "sha256-WJYuFmMGSW+B32LwE7oXv/IeTln6TNEeXSkquHh85Go="; - }; - makeFlags = [ - "PREFIX=$(out)" - ]; - -}; - in - optionals withFullDeps [ libdc1394 ] - ++ optionals (withFullDeps && !stdenv.isDarwin) [ libraw1394 ] # TODO where does this belong to - ++ optionals (withNvdec || withNvenc || withCuda) [ nv-codec-headers ] - ++ optionals withAmf [ amf-headers ] - ++ optionals withAlsa [ alsa-lib ] - ++ optionals withAom [ libaom ] - ++ optionals withAss [ libass ] - ++ optionals withBluray [ libbluray ] - ++ optionals withBs2b [ libbs2b ] - ++ optionals withBzlib [ bzip2 ] - ++ optionals withCaca [ libcaca ] - ++ optionals withCelt [ celt ] - ++ optionals withCudaLLVM [ clang ] - ++ optionals withDav1d [ dav1d ] - ++ optionals withDrm [ libdrm ] - ++ optionals withFdkAac [ fdk_aac ] - ++ optionals withFontconfig [ fontconfig ] - ++ optionals withFreetype [ freetype ] - ++ optionals withFrei0r [ frei0r ] - ++ optionals withFribidi [ fribidi ] - ++ optionals withGlslang [ glslang ] - ++ optionals withGme [ game-music-emu ] - ++ optionals withGnutls [ gnutls ] - ++ optionals withGsm [ gsm ] - ++ optionals withIconv [ libiconv ] # On Linux this should be in libc, do we really need it? - ++ optionals withJack [ libjack2 ] - ++ optionals withLadspa [ ladspaH ] - ++ optionals withLibplacebo [ libplacebo vulkan-headers ] - ++ optionals withLzma [ xz ] - ++ optionals withMfx [ intel-media-sdk ] - ++ optionals withModplug [ libmodplug ] - ++ optionals withMp3lame [ lame ] - ++ optionals withMysofa [ libmysofa ] - ++ optionals withOgg [ libogg ] - ++ optionals withOpenal [ openal ] - ++ optionals withOpencl [ ocl-icd opencl-headers ] - ++ optionals withOpencoreAmrnb [ opencore-amr ] - ++ optionals withOpengl [ libGL libGLU ] - ++ optionals withOpenh264 [ openh264 ] - ++ optionals withOpenjpeg [ openjpeg ] - ++ optionals withOpenmpt [ libopenmpt ] - ++ optionals withOpus [ libopus ] - ++ optionals withPulse [ libpulseaudio ] - ++ optionals withRav1e [ rav1e ] - ++ optionals withRtmp [ rtmpdump ] - ++ optionals withSamba [ samba ] - ++ optionals withSdl2 [ SDL2 ] - ++ optionals withSoxr [ soxr ] - ++ optionals withSpeex [ speex ] - ++ optionals withSrt [ srt ] - ++ optionals withSsh [ libssh ] - ++ optionals withSvg [ librsvg ] - ++ optionals withSvtav1 [ svt-av1 ] - ++ optionals withTensorflow [ libtensorflow ] - ++ optionals withTheora [ libtheora ] - ++ optionals withVaapi [ (if withSmallDeps then libva else libva-minimal) ] - ++ optionals withVdpau [ libvdpau ] - ++ optionals withVidStab [ vid-stab ] - ++ optionals withVmaf [ libvmaf ] - ++ optionals withVoAmrwbenc [ vo-amrwbenc ] - ++ optionals withVorbis [ libvorbis ] - ++ optionals withVpx [ libvpx ] - ++ optionals withV4l2 [ libv4l ] - ++ optionals withVulkan [ vulkan-headers vulkan-loader ] - ++ optionals withWebp [ libwebp ] - ++ optionals withX264 [ x264 ] - ++ optionals withX265 [ x265 ] - ++ optionals withXavs [ xavs ] - ++ optionals withXcb [ libxcb ] - ++ optionals withXlib [ libX11 libXv libXext ] - ++ optionals withXml2 [ libxml2 ] - ++ optionals withXvid [ xvidcore ] - ++ optionals withZimg [ zimg ] - ++ optionals withZlib [ zlib ] - ++ optionals withZmq [ zeromq4 ] - ++ optionals stdenv.isDarwin [ - # TODO fine-grained flags - AVFoundation - Cocoa - CoreAudio - CoreMedia - CoreServices - MediaToolbox - VideoDecodeAcceleration - VideoToolbox - ]; - - buildFlags = [ "all" ] - ++ optional buildQtFaststart "tools/qt-faststart"; # Build qt-faststart executable - - doCheck = stdenv.hostPlatform == stdenv.buildPlatform; - - # Fails with SIGABRT otherwise FIXME: Why? - checkPhase = let - ldLibraryPathEnv = if stdenv.isDarwin then "DYLD_LIBRARY_PATH" else "LD_LIBRARY_PATH"; - libsToLink = [ ] - ++ optional buildAvcodec "libavcodec" - ++ optional buildAvdevice "libavdevice" - ++ optional buildAvfilter "libavfilter" - ++ optional buildAvformat "libavformat" - ++ optional buildAvresample "libavresample" - ++ optional buildAvutil "libavutil" - ++ optional buildPostproc "libpostproc" - ++ optional buildSwresample "libswresample" - ++ optional buildSwscale "libswscale" - ; - in '' - ${ldLibraryPathEnv}="${lib.concatStringsSep ":" libsToLink}" make check -j$NIX_BUILD_CORES - ''; - - outputs = optionals withBin [ "bin" ] # The first output is the one that gets symlinked by default! - ++ optionals withLib [ "lib" "dev" ] - ++ optionals withDoc [ "doc" ] - ++ optionals withManPages [ "man" ] - ++ [ "data" "out" ] # We need an "out" output because we get an error otherwise. It's just an empty dir. - ; - - postInstall = optionalString buildQtFaststart '' - install -D tools/qt-faststart -t $bin/bin - ''; - - # Set RUNPATH so that libnvcuvid and libcuda in /run/opengl-driver(-32)/lib can be found. - # See the explanation in addOpenGLRunpath. - postFixup = optionalString (stdenv.isLinux && withLib) '' - addOpenGLRunpath ${placeholder "lib"}/lib/libavcodec.so - addOpenGLRunpath ${placeholder "lib"}/lib/libavutil.so - ''; - - enableParallelBuilding = true; - - passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; - - meta = with lib; { - description = "A complete, cross-platform solution to record, convert and stream audio and video"; - homepage = "https://www.ffmpeg.org/"; - changelog = "https://github.com/FFmpeg/FFmpeg/blob/n${version}/Changelog"; - longDescription = '' - FFmpeg is the leading multimedia framework, able to decode, encode, transcode, - mux, demux, stream, filter and play pretty much anything that humans and machines - have created. It supports the most obscure ancient formats up to the cutting edge. - No matter if they were designed by some standards committee, the community or - a corporation. - ''; - license = with licenses; [ lgpl21Plus ] - ++ optional withGPL gpl2Plus - ++ optional withGPLv3 gpl3Plus - ++ optional withUnfree unfreeRedistributable; - pkgConfigModules = [ "libavutil" ]; - platforms = platforms.all; - maintainers = with maintainers; [ atemu ]; - }; -}) diff --git a/pkgs/apps/obs/Enable-file-access-and-universal-access-for-file-URL.patch b/pkgs/apps/obs/Enable-file-access-and-universal-access-for-file-URL.patch deleted file mode 100644 index 49d01ba..0000000 --- a/pkgs/apps/obs/Enable-file-access-and-universal-access-for-file-URL.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0de0a90f8fe5e1e48fa4ec7aa7c825ef88770f9d Mon Sep 17 00:00:00 2001 -From: Ryan Foster -Date: Mon, 9 Sep 2019 23:55:02 -0400 -Subject: [PATCH] Enable file access and universal access for file URLs - -When loading a local file, instead of disabling CEF's web security, -enable file access and universal access for file URLs. This should allow -local files to make CORS requests without completely disabling CEF's -security model. ---- - obs-browser-source.cpp | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp -index ab1181e..c775283 100644 ---- a/plugins/obs-browser/obs-browser-source.cpp -+++ b/plugins/obs-browser/obs-browser-source.cpp -@@ -179,9 +179,12 @@ bool BrowserSource::CreateBrowser() - - #if ENABLE_LOCAL_FILE_URL_SCHEME - if (is_local) { -- /* Disable web security for file:// URLs to allow -- * local content access to remote APIs */ -- cefBrowserSettings.web_security = STATE_DISABLED; -+ /* Enable file access and universal access from file:// -+ * URLs to allow local content access to remote APIs */ -+ cefBrowserSettings.file_access_from_file_urls = -+ STATE_ENABLED; -+ cefBrowserSettings.universal_access_from_file_urls = -+ STATE_ENABLED; - } - #endif - --- -2.31.1 - diff --git a/pkgs/apps/obs/av1-vaapi.patch b/pkgs/apps/obs/av1-vaapi.patch deleted file mode 100644 index 3b7710d..0000000 --- a/pkgs/apps/obs/av1-vaapi.patch +++ /dev/null @@ -1,3826 +0,0 @@ -diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss -index e7c70496a..a4be95b8c 100644 ---- a/UI/data/themes/Acri.qss -+++ b/UI/data/themes/Acri.qss -@@ -166,7 +166,7 @@ QMenu::item:disabled { - } - - QMenu::right-arrow { -- image: url(./Dark/expand.svg); -+ image: url(theme:Dark/expand.svg); - } - - /* Top Menu Bar Items */ -@@ -304,8 +304,8 @@ QDockWidget { - font-size: 10.5pt; - font-weight: bold; - -- titlebar-close-icon: url('./Dark/close.svg'); -- titlebar-normal-icon: url('./Dark/popout.svg'); -+ titlebar-close-icon: url(theme:Dark/close.svg); -+ titlebar-normal-icon: url(theme:Dark/popout.svg); - } - - QDockWidget::title { -@@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { - } - - QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - /* Scenes and Sources toolbar */ -@@ -493,55 +493,55 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Dark/plus.svg); -+ qproperty-icon: url(theme:Dark/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Dark/trash.svg); -+ qproperty-icon: url(theme:Dark/trash.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Dark/entry-clear.svg); -+ qproperty-icon: url(theme:Dark/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Dark/refresh.svg); -+ qproperty-icon: url(theme:Dark/refresh.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Dark/cogs.svg); -+ qproperty-icon: url(theme:Dark/cogs.svg); - } - - #sourceInteractButton { -- qproperty-icon: url(./Dark/interact.svg); -+ qproperty-icon: url(theme:Dark/interact.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Dark/up.svg); -+ qproperty-icon: url(theme:Dark/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Dark/down.svg); -+ qproperty-icon: url(theme:Dark/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Dark/media-pause.svg); -+ qproperty-icon: url(theme:Dark/media-pause.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - QToolBarExtension { -@@ -551,7 +551,7 @@ QToolBarExtension { - padding: 4px 0px; - margin-left: 0px; - -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - -@@ -647,7 +647,7 @@ QDateTimeEdit::drop-down { - QComboBox::down-arrow, - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/updown.svg); -+ image: url(theme:Dark/updown.svg); - width: 100%; - } - -@@ -669,7 +669,7 @@ QDateTimeEdit::drop-down:editable { - QComboBox::down-arrow:editable, - QDateTimeEdit::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 8%; - } - -@@ -757,13 +757,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Dark/up.svg); -+ image: url(theme:Dark/up.svg); - width: 100%; - margin: 2px; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - padding: 2px; - } -@@ -844,7 +844,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -995,15 +995,15 @@ QHeaderView::section { - /* Mute CheckBox */ - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -1102,14 +1102,14 @@ OBSBasicFilters #widget_2 QPushButton { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Dark/settings/general.svg); -- qproperty-streamIcon: url(./Dark/settings/stream.svg); -- qproperty-outputIcon: url(./Dark/settings/output.svg); -- qproperty-audioIcon: url(./Dark/settings/audio.svg); -- qproperty-videoIcon: url(./Dark/settings/video.svg); -- qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Dark/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Dark/settings/general.svg); -+ qproperty-streamIcon: url(theme:Dark/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Dark/settings/output.svg); -+ qproperty-audioIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Dark/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); - } - - /* Checkboxes */ -@@ -1129,34 +1129,34 @@ QGroupBox::indicator { - - QCheckBox::indicator:unchecked, - QGroupBox::indicator:unchecked { -- image: url(./Yami/checkbox_unchecked.svg); -+ image: url(theme:Yami/checkbox_unchecked.svg); - } - - QCheckBox::indicator:unchecked:hover, - QGroupBox::indicator:unchecked:hover { - border: none; -- image: url(./Yami/checkbox_unchecked_focus.svg); -+ image: url(theme:Yami/checkbox_unchecked_focus.svg); - } - - QCheckBox::indicator:checked, - QGroupBox::indicator:checked { -- image: url(./Yami/checkbox_checked.svg); -+ image: url(theme:Yami/checkbox_checked.svg); - } - - QCheckBox::indicator:checked:hover, - QGroupBox::indicator:checked:hover { - border: none; -- image: url(./Yami/checkbox_checked_focus.svg); -+ image: url(theme:Yami/checkbox_checked_focus.svg); - } - - QCheckBox::indicator:checked:disabled, - QGroupBox::indicator:checked:disabled { -- image: url(./Yami/checkbox_checked_disabled.svg); -+ image: url(theme:Yami/checkbox_checked_disabled.svg); - } - - QCheckBox::indicator:unchecked:disabled, - QGroupBox::indicator:unchecked:disabled { -- image: url(./Yami/checkbox_unchecked_disabled.svg); -+ image: url(theme:Yami/checkbox_unchecked_disabled.svg); - } - - /* Locked CheckBox */ -@@ -1173,7 +1173,7 @@ LockedCheckBox::indicator { - - LockedCheckBox::indicator:checked, - LockedCheckBox::indicator:checked:hover { -- image: url(./Dark/locked.svg); -+ image: url(theme:Dark/locked.svg); - } - - LockedCheckBox::indicator:unchecked, -@@ -1195,7 +1195,7 @@ VisibilityCheckBox::indicator { - - VisibilityCheckBox::indicator:checked, - VisibilityCheckBox::indicator:checked:hover { -- image: url(./Dark/visible.svg); -+ image: url(theme:Dark/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked, -@@ -1204,7 +1204,7 @@ VisibilityCheckBox::indicator:unchecked:hover { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Dark/revert.svg); -+ qproperty-icon: url(theme:Dark/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -1233,35 +1233,35 @@ MuteCheckBox::indicator { - } - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:hover { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:focus { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:checked:hover { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:focus { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:disabled { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked:disabled { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - #hotkeyFilterReset { -@@ -1291,46 +1291,46 @@ OBSHotkeyWidget QPushButton { - - /* Sources List Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - padding: 0px; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 12px; - height: 12px; - } - --SourceTreeSubItemCheckBox::indicator:checked, --SourceTreeSubItemCheckBox::indicator:checked:hover { -- image: url(./Dark/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked, -+QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { -+ image: url(theme:Dark/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked, --SourceTreeSubItemCheckBox::indicator:unchecked:hover { -- image: url(./Dark/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { -+ image: url(theme:Dark/collapse.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Dark/sources/image.svg); -- qproperty-colorIcon: url(./Dark/sources/brush.svg); -- qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Dark/settings/video.svg); -- qproperty-windowCapIcon: url(./Dark/sources/window.svg); -- qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Dark/sources/camera.svg); -- qproperty-textIcon: url(./Dark/sources/text.svg); -- qproperty-mediaIcon: url(./Dark/sources/media.svg); -- qproperty-browserIcon: url(./Dark/sources/globe.svg); -- qproperty-groupIcon: url(./Dark/sources/group.svg); -- qproperty-sceneIcon: url(./Dark/sources/scene.svg); -- qproperty-defaultIcon: url(./Dark/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Dark/sources/image.svg); -+ qproperty-colorIcon: url(theme:Dark/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); -+ qproperty-textIcon: url(theme:Dark/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Dark/sources/media.svg); -+ qproperty-browserIcon: url(theme:Dark/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Dark/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Dark/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); - } - - /* Scene Tree Grid Mode */ -@@ -1366,7 +1366,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Dark/save.svg); -+ qproperty-icon: url(theme:Dark/save.svg); - } - - /* Studio Mode T-Bar */ -@@ -1396,32 +1396,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Dark/media/media_play.svg); -+ qproperty-icon: url(theme:Dark/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Dark/media/media_pause.svg); -+ qproperty-icon: url(theme:Dark/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Dark/media/media_restart.svg); -+ qproperty-icon: url(theme:Dark/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Dark/media/media_stop.svg); -+ qproperty-icon: url(theme:Dark/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Dark/media/media_next.svg); -+ qproperty-icon: url(theme:Dark/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Dark/media/media_previous.svg); -+ qproperty-icon: url(theme:Dark/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); - } - - #ytEventList QLabel { -@@ -1449,7 +1449,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -1472,7 +1472,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1482,13 +1482,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss -index 6c96a902c..a2e262d4e 100644 ---- a/UI/data/themes/Dark.qss -+++ b/UI/data/themes/Dark.qss -@@ -132,8 +132,8 @@ QMainWindow::separator { - /* Dock Widget */ - - QDockWidget { -- titlebar-close-icon: url('./Dark/close.svg'); -- titlebar-normal-icon: url('./Dark/popout.svg'); -+ titlebar-close-icon: url(theme:Dark/close.svg); -+ titlebar-normal-icon: url(theme:Dark/popout.svg); - } - - QDockWidget::title { -@@ -242,15 +242,15 @@ QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, QScrollBa - } - - #contextContainer QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - #contextContainer QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - #contextContainer QPushButton#sourceInteractButton { -- qproperty-icon: url(./Dark/interact.svg); -+ qproperty-icon: url(theme:Dark/interact.svg); - } - - /* Scenes and Sources toolbar */ -@@ -286,51 +286,51 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Dark/plus.svg); -+ qproperty-icon: url(theme:Dark/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Dark/minus.svg); -+ qproperty-icon: url(theme:Dark/minus.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Dark/entry-clear.svg); -+ qproperty-icon: url(theme:Dark/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Dark/refresh.svg); -+ qproperty-icon: url(theme:Dark/refresh.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Dark/up.svg); -+ qproperty-icon: url(theme:Dark/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Dark/down.svg); -+ qproperty-icon: url(theme:Dark/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Dark/media-pause.svg); -+ qproperty-icon: url(theme:Dark/media-pause.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Dark/cogs.svg); -+ qproperty-icon: url(theme:Dark/cogs.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - /* Tab Widget */ -@@ -407,7 +407,7 @@ QComboBox::drop-down { - QDateTimeEdit::down-arrow, - QComboBox::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/updown.svg); -+ image: url(theme:Dark/updown.svg); - width: 100%; - } - -@@ -431,7 +431,7 @@ QComboBox::drop-down:editable { - QDateTimeEdit::down-arrow:editable, - QComboBox::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 8%; - } - -@@ -497,12 +497,12 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Dark/up.svg); -+ image: url(theme:Dark/up.svg); - width: 100%; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -540,7 +540,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -680,15 +680,15 @@ MuteCheckBox { - } - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -697,22 +697,22 @@ OBSHotkeyLabel[hotkeyPairHover=true] { - - /* Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 10px; - height: 10px; - } - --SourceTreeSubItemCheckBox::indicator:checked { -- image: url(./Dark/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked { -+ image: url(theme:Dark/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked { -- image: url(./Dark/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked { -+ image: url(theme:Dark/collapse.svg); - } - - -@@ -780,14 +780,14 @@ OBSQTDisplay { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Dark/settings/general.svg); -- qproperty-streamIcon: url(./Dark/settings/stream.svg); -- qproperty-outputIcon: url(./Dark/settings/output.svg); -- qproperty-audioIcon: url(./Dark/settings/audio.svg); -- qproperty-videoIcon: url(./Dark/settings/video.svg); -- qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Dark/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Dark/settings/general.svg); -+ qproperty-streamIcon: url(theme:Dark/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Dark/settings/output.svg); -+ qproperty-audioIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Dark/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); - } - - OBSBasicSettings QListWidget::item { -@@ -803,7 +803,7 @@ LockedCheckBox { - } - - LockedCheckBox::indicator:checked { -- image: url(./Dark/locked.svg); -+ image: url(theme:Dark/locked.svg); - } - - LockedCheckBox::indicator:unchecked { -@@ -818,7 +818,7 @@ VisibilityCheckBox { - } - - VisibilityCheckBox::indicator:checked { -- image: url(./Dark/visible.svg); -+ image: url(theme:Dark/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked { -@@ -826,7 +826,7 @@ VisibilityCheckBox::indicator:unchecked { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Dark/revert.svg); -+ qproperty-icon: url(theme:Dark/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -842,28 +842,28 @@ QPushButton#extraPanelDelete:pressed { - } - - OBSMissingFiles { -- qproperty-warningIcon: url(./Dark/alert.svg); -+ qproperty-warningIcon: url(theme:Dark/alert.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Dark/sources/image.svg); -- qproperty-colorIcon: url(./Dark/sources/brush.svg); -- qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Dark/settings/video.svg); -- qproperty-windowCapIcon: url(./Dark/sources/window.svg); -- qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Dark/sources/camera.svg); -- qproperty-textIcon: url(./Dark/sources/text.svg); -- qproperty-mediaIcon: url(./Dark/sources/media.svg); -- qproperty-browserIcon: url(./Dark/sources/globe.svg); -- qproperty-groupIcon: url(./Dark/sources/group.svg); -- qproperty-sceneIcon: url(./Dark/sources/scene.svg); -- qproperty-defaultIcon: url(./Dark/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Dark/sources/image.svg); -+ qproperty-colorIcon: url(theme:Dark/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); -+ qproperty-textIcon: url(theme:Dark/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Dark/sources/media.svg); -+ qproperty-browserIcon: url(theme:Dark/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Dark/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Dark/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); - } - - /* Scene Tree */ -@@ -903,7 +903,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Dark/save.svg); -+ qproperty-icon: url(theme:Dark/save.svg); - } - - /* Studio Mode T-Bar */ -@@ -933,32 +933,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Dark/media/media_play.svg); -+ qproperty-icon: url(theme:Dark/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Dark/media/media_pause.svg); -+ qproperty-icon: url(theme:Dark/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Dark/media/media_restart.svg); -+ qproperty-icon: url(theme:Dark/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Dark/media/media_stop.svg); -+ qproperty-icon: url(theme:Dark/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Dark/media/media_next.svg); -+ qproperty-icon: url(theme:Dark/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Dark/media/media_previous.svg); -+ qproperty-icon: url(theme:Dark/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); - } - - #ytEventList QLabel { -@@ -981,7 +981,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -1004,7 +1004,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1014,13 +1014,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/Grey.qss b/UI/data/themes/Grey.qss -index 0748deffa..b19434bfd 100644 ---- a/UI/data/themes/Grey.qss -+++ b/UI/data/themes/Grey.qss -@@ -166,7 +166,7 @@ QMenu::item:disabled { - } - - QMenu::right-arrow { -- image: url(./Dark/expand.svg); -+ image: url(theme:Dark/expand.svg); - } - - /* Top Menu Bar Items */ -@@ -304,8 +304,8 @@ QDockWidget { - font-size: 10.5pt; - font-weight: bold; - -- titlebar-close-icon: url('./Dark/close.svg'); -- titlebar-normal-icon: url('./Dark/popout.svg'); -+ titlebar-close-icon: url(theme:Dark/close.svg); -+ titlebar-normal-icon: url(theme:Dark/popout.svg); - } - - QDockWidget::title { -@@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { - } - - QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - /* Scenes and Sources toolbar */ -@@ -491,55 +491,55 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Dark/plus.svg); -+ qproperty-icon: url(theme:Dark/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Dark/trash.svg); -+ qproperty-icon: url(theme:Dark/trash.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Dark/entry-clear.svg); -+ qproperty-icon: url(theme:Dark/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Dark/refresh.svg); -+ qproperty-icon: url(theme:Dark/refresh.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Dark/cogs.svg); -+ qproperty-icon: url(theme:Dark/cogs.svg); - } - - #sourceInteractButton { -- qproperty-icon: url(./Dark/interact.svg); -+ qproperty-icon: url(theme:Dark/interact.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Dark/up.svg); -+ qproperty-icon: url(theme:Dark/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Dark/down.svg); -+ qproperty-icon: url(theme:Dark/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Dark/media-pause.svg); -+ qproperty-icon: url(theme:Dark/media-pause.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - QToolBarExtension { -@@ -549,7 +549,7 @@ QToolBarExtension { - padding: 4px 0px; - margin-left: 0px; - -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - -@@ -645,7 +645,7 @@ QDateTimeEdit::drop-down { - QComboBox::down-arrow, - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/updown.svg); -+ image: url(theme:Dark/updown.svg); - width: 100%; - } - -@@ -667,7 +667,7 @@ QDateTimeEdit::drop-down:editable { - QComboBox::down-arrow:editable, - QDateTimeEdit::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 8%; - } - -@@ -755,13 +755,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Dark/up.svg); -+ image: url(theme:Dark/up.svg); - width: 100%; - margin: 2px; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - padding: 2px; - } -@@ -833,7 +833,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -983,15 +983,15 @@ QHeaderView::section { - /* Mute CheckBox */ - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -1090,14 +1090,14 @@ OBSBasicFilters #widget_2 QPushButton { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Dark/settings/general.svg); -- qproperty-streamIcon: url(./Dark/settings/stream.svg); -- qproperty-outputIcon: url(./Dark/settings/output.svg); -- qproperty-audioIcon: url(./Dark/settings/audio.svg); -- qproperty-videoIcon: url(./Dark/settings/video.svg); -- qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Dark/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Dark/settings/general.svg); -+ qproperty-streamIcon: url(theme:Dark/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Dark/settings/output.svg); -+ qproperty-audioIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Dark/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); - } - - /* Checkboxes */ -@@ -1117,34 +1117,34 @@ QGroupBox::indicator { - - QCheckBox::indicator:unchecked, - QGroupBox::indicator:unchecked { -- image: url(./Yami/checkbox_unchecked.svg); -+ image: url(theme:Yami/checkbox_unchecked.svg); - } - - QCheckBox::indicator:unchecked:hover, - QGroupBox::indicator:unchecked:hover { - border: none; -- image: url(./Yami/checkbox_unchecked_focus.svg); -+ image: url(theme:Yami/checkbox_unchecked_focus.svg); - } - - QCheckBox::indicator:checked, - QGroupBox::indicator:checked { -- image: url(./Yami/checkbox_checked.svg); -+ image: url(theme:Yami/checkbox_checked.svg); - } - - QCheckBox::indicator:checked:hover, - QGroupBox::indicator:checked:hover { - border: none; -- image: url(./Yami/checkbox_checked_focus.svg); -+ image: url(theme:Yami/checkbox_checked_focus.svg); - } - - QCheckBox::indicator:checked:disabled, - QGroupBox::indicator:checked:disabled { -- image: url(./Yami/checkbox_checked_disabled.svg); -+ image: url(theme:Yami/checkbox_checked_disabled.svg); - } - - QCheckBox::indicator:unchecked:disabled, - QGroupBox::indicator:unchecked:disabled { -- image: url(./Yami/checkbox_unchecked_disabled.svg); -+ image: url(theme:Yami/checkbox_unchecked_disabled.svg); - } - - /* Locked CheckBox */ -@@ -1161,7 +1161,7 @@ LockedCheckBox::indicator { - - LockedCheckBox::indicator:checked, - LockedCheckBox::indicator:checked:hover { -- image: url(./Dark/locked.svg); -+ image: url(theme:Dark/locked.svg); - } - - LockedCheckBox::indicator:unchecked, -@@ -1183,7 +1183,7 @@ VisibilityCheckBox::indicator { - - VisibilityCheckBox::indicator:checked, - VisibilityCheckBox::indicator:checked:hover { -- image: url(./Dark/visible.svg); -+ image: url(theme:Dark/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked, -@@ -1192,7 +1192,7 @@ VisibilityCheckBox::indicator:unchecked:hover { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Dark/revert.svg); -+ qproperty-icon: url(theme:Dark/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -1221,35 +1221,35 @@ MuteCheckBox::indicator { - } - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:hover { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:focus { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:checked:hover { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:focus { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:disabled { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked:disabled { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - #hotkeyFilterReset { -@@ -1279,46 +1279,46 @@ OBSHotkeyWidget QPushButton { - - /* Sources List Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - padding: 0px; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 12px; - height: 12px; - } - --SourceTreeSubItemCheckBox::indicator:checked, --SourceTreeSubItemCheckBox::indicator:checked:hover { -- image: url(./Dark/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked, -+QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { -+ image: url(theme:Dark/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked, --SourceTreeSubItemCheckBox::indicator:unchecked:hover { -- image: url(./Dark/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { -+ image: url(theme:Dark/collapse.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Dark/sources/image.svg); -- qproperty-colorIcon: url(./Dark/sources/brush.svg); -- qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Dark/settings/video.svg); -- qproperty-windowCapIcon: url(./Dark/sources/window.svg); -- qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Dark/sources/camera.svg); -- qproperty-textIcon: url(./Dark/sources/text.svg); -- qproperty-mediaIcon: url(./Dark/sources/media.svg); -- qproperty-browserIcon: url(./Dark/sources/globe.svg); -- qproperty-groupIcon: url(./Dark/sources/group.svg); -- qproperty-sceneIcon: url(./Dark/sources/scene.svg); -- qproperty-defaultIcon: url(./Dark/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Dark/sources/image.svg); -+ qproperty-colorIcon: url(theme:Dark/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); -+ qproperty-textIcon: url(theme:Dark/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Dark/sources/media.svg); -+ qproperty-browserIcon: url(theme:Dark/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Dark/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Dark/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); - } - - /* Scene Tree Grid Mode */ -@@ -1354,7 +1354,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Dark/save.svg); -+ qproperty-icon: url(theme:Dark/save.svg); - } - - /* Studio Mode T-Bar */ -@@ -1384,32 +1384,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Dark/media/media_play.svg); -+ qproperty-icon: url(theme:Dark/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Dark/media/media_pause.svg); -+ qproperty-icon: url(theme:Dark/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Dark/media/media_restart.svg); -+ qproperty-icon: url(theme:Dark/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Dark/media/media_stop.svg); -+ qproperty-icon: url(theme:Dark/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Dark/media/media_next.svg); -+ qproperty-icon: url(theme:Dark/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Dark/media/media_previous.svg); -+ qproperty-icon: url(theme:Dark/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); - } - - #ytEventList QLabel { -@@ -1437,7 +1437,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -1460,7 +1460,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1470,13 +1470,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/Light.qss b/UI/data/themes/Light.qss -index e6c9a6be0..87795ed52 100644 ---- a/UI/data/themes/Light.qss -+++ b/UI/data/themes/Light.qss -@@ -166,7 +166,7 @@ QMenu::item:disabled { - } - - QMenu::right-arrow { -- image: url(./Light/expand.svg); -+ image: url(theme:Light/expand.svg); - } - - /* Top Menu Bar Items */ -@@ -304,8 +304,8 @@ QDockWidget { - font-size: 10.5pt; - font-weight: bold; - -- titlebar-close-icon: url('./Light/close.svg'); -- titlebar-normal-icon: url('./Light/popout.svg'); -+ titlebar-close-icon: url(theme:Light/close.svg); -+ titlebar-normal-icon: url(theme:Light/popout.svg); - } - - QDockWidget::title { -@@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { - } - - QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Light/settings/general.svg); -+ qproperty-icon: url(theme:Light/settings/general.svg); - } - - QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Light/filter.svg); -+ qproperty-icon: url(theme:Light/filter.svg); - } - - /* Scenes and Sources toolbar */ -@@ -491,55 +491,55 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Light/plus.svg); -+ qproperty-icon: url(theme:Light/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Light/trash.svg); -+ qproperty-icon: url(theme:Light/trash.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Light/entry-clear.svg); -+ qproperty-icon: url(theme:Light/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Light/settings/general.svg); -+ qproperty-icon: url(theme:Light/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Light/settings/general.svg); -+ qproperty-icon: url(theme:Light/settings/general.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Light/dots-vert.svg); -+ qproperty-icon: url(theme:Light/dots-vert.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Light/refresh.svg); -+ qproperty-icon: url(theme:Light/refresh.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Light/cogs.svg); -+ qproperty-icon: url(theme:Light/cogs.svg); - } - - #sourceInteractButton { -- qproperty-icon: url(./Light/interact.svg); -+ qproperty-icon: url(theme:Light/interact.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Light/up.svg); -+ qproperty-icon: url(theme:Light/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Light/down.svg); -+ qproperty-icon: url(theme:Light/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Light/media-pause.svg); -+ qproperty-icon: url(theme:Light/media-pause.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Light/filter.svg); -+ qproperty-icon: url(theme:Light/filter.svg); - } - - QToolBarExtension { -@@ -549,7 +549,7 @@ QToolBarExtension { - padding: 4px 0px; - margin-left: 0px; - -- qproperty-icon: url(./Light/dots-vert.svg); -+ qproperty-icon: url(theme:Light/dots-vert.svg); - } - - -@@ -645,7 +645,7 @@ QDateTimeEdit::drop-down { - QComboBox::down-arrow, - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Light/updown.svg); -+ image: url(theme:Light/updown.svg); - width: 100%; - } - -@@ -667,7 +667,7 @@ QDateTimeEdit::drop-down:editable { - QComboBox::down-arrow:editable, - QDateTimeEdit::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Light/down.svg); -+ image: url(theme:Light/down.svg); - width: 8%; - } - -@@ -755,13 +755,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Light/up.svg); -+ image: url(theme:Light/up.svg); - width: 100%; - margin: 2px; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Light/down.svg); -+ image: url(theme:Light/down.svg); - width: 100%; - padding: 2px; - } -@@ -833,7 +833,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Light/down.svg); -+ image: url(theme:Light/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -983,15 +983,15 @@ QHeaderView::section { - /* Mute CheckBox */ - - MuteCheckBox::indicator:checked { -- image: url(./Light/mute.svg); -+ image: url(theme:Light/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Light/settings/audio.svg); -+ image: url(theme:Light/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -1090,14 +1090,14 @@ OBSBasicFilters #widget_2 QPushButton { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Light/settings/general.svg); -- qproperty-streamIcon: url(./Light/settings/stream.svg); -- qproperty-outputIcon: url(./Light/settings/output.svg); -- qproperty-audioIcon: url(./Light/settings/audio.svg); -- qproperty-videoIcon: url(./Light/settings/video.svg); -- qproperty-hotkeysIcon: url(./Light/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Light/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Light/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Light/settings/general.svg); -+ qproperty-streamIcon: url(theme:Light/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Light/settings/output.svg); -+ qproperty-audioIcon: url(theme:Light/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Light/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Light/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Light/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Light/settings/advanced.svg); - } - - /* Checkboxes */ -@@ -1117,34 +1117,34 @@ QGroupBox::indicator { - - QCheckBox::indicator:unchecked, - QGroupBox::indicator:unchecked { -- image: url(./Light/checkbox_unchecked.svg); -+ image: url(theme:Light/checkbox_unchecked.svg); - } - - QCheckBox::indicator:unchecked:hover, - QGroupBox::indicator:unchecked:hover { - border: none; -- image: url(./Light/checkbox_unchecked_focus.svg); -+ image: url(theme:Light/checkbox_unchecked_focus.svg); - } - - QCheckBox::indicator:checked, - QGroupBox::indicator:checked { -- image: url(./Light/checkbox_checked.svg); -+ image: url(theme:Light/checkbox_checked.svg); - } - - QCheckBox::indicator:checked:hover, - QGroupBox::indicator:checked:hover { - border: none; -- image: url(./Light/checkbox_checked_focus.svg); -+ image: url(theme:Light/checkbox_checked_focus.svg); - } - - QCheckBox::indicator:checked:disabled, - QGroupBox::indicator:checked:disabled { -- image: url(./Light/checkbox_checked_disabled.svg); -+ image: url(theme:Light/checkbox_checked_disabled.svg); - } - - QCheckBox::indicator:unchecked:disabled, - QGroupBox::indicator:unchecked:disabled { -- image: url(./Light/checkbox_unchecked_disabled.svg); -+ image: url(theme:Light/checkbox_unchecked_disabled.svg); - } - - /* Locked CheckBox */ -@@ -1161,7 +1161,7 @@ LockedCheckBox::indicator { - - LockedCheckBox::indicator:checked, - LockedCheckBox::indicator:checked:hover { -- image: url(./Light/locked.svg); -+ image: url(theme:Light/locked.svg); - } - - LockedCheckBox::indicator:unchecked, -@@ -1183,7 +1183,7 @@ VisibilityCheckBox::indicator { - - VisibilityCheckBox::indicator:checked, - VisibilityCheckBox::indicator:checked:hover { -- image: url(./Light/visible.svg); -+ image: url(theme:Light/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked, -@@ -1192,7 +1192,7 @@ VisibilityCheckBox::indicator:unchecked:hover { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Light/revert.svg); -+ qproperty-icon: url(theme:Light/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -1221,35 +1221,35 @@ MuteCheckBox::indicator { - } - - MuteCheckBox::indicator:checked { -- image: url(./Light/mute.svg); -+ image: url(theme:Light/mute.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Light/settings/audio.svg); -+ image: url(theme:Light/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:hover { -- image: url(./Light/settings/audio.svg); -+ image: url(theme:Light/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:focus { -- image: url(./Light/settings/audio.svg); -+ image: url(theme:Light/settings/audio.svg); - } - - MuteCheckBox::indicator:checked:hover { -- image: url(./Light/mute.svg); -+ image: url(theme:Light/mute.svg); - } - - MuteCheckBox::indicator:checked:focus { -- image: url(./Light/mute.svg); -+ image: url(theme:Light/mute.svg); - } - - MuteCheckBox::indicator:checked:disabled { -- image: url(./Light/mute.svg); -+ image: url(theme:Light/mute.svg); - } - - MuteCheckBox::indicator:unchecked:disabled { -- image: url(./Light/settings/audio.svg); -+ image: url(theme:Light/settings/audio.svg); - } - - #hotkeyFilterReset { -@@ -1279,46 +1279,46 @@ OBSHotkeyWidget QPushButton { - - /* Sources List Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - padding: 0px; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 12px; - height: 12px; - } - --SourceTreeSubItemCheckBox::indicator:checked, --SourceTreeSubItemCheckBox::indicator:checked:hover { -- image: url(./Light/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked, -+QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { -+ image: url(theme:Light/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked, --SourceTreeSubItemCheckBox::indicator:unchecked:hover { -- image: url(./Light/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { -+ image: url(theme:Light/collapse.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Light/sources/image.svg); -- qproperty-colorIcon: url(./Light/sources/brush.svg); -- qproperty-slideshowIcon: url(./Light/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Light/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Light/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Light/settings/video.svg); -- qproperty-windowCapIcon: url(./Light/sources/window.svg); -- qproperty-gameCapIcon: url(./Light/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Light/sources/camera.svg); -- qproperty-textIcon: url(./Light/sources/text.svg); -- qproperty-mediaIcon: url(./Light/sources/media.svg); -- qproperty-browserIcon: url(./Light/sources/globe.svg); -- qproperty-groupIcon: url(./Light/sources/group.svg); -- qproperty-sceneIcon: url(./Light/sources/scene.svg); -- qproperty-defaultIcon: url(./Light/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Light/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Light/sources/image.svg); -+ qproperty-colorIcon: url(theme:Light/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Light/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Light/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Light/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Light/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Light/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Light/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Light/sources/camera.svg); -+ qproperty-textIcon: url(theme:Light/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Light/sources/media.svg); -+ qproperty-browserIcon: url(theme:Light/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Light/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Light/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Light/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Light/sources/windowaudio.svg); - } - - /* Scene Tree Grid Mode */ -@@ -1354,7 +1354,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Light/save.svg); -+ qproperty-icon: url(theme:Light/save.svg); - } - - /* Studio Mode Labels */ -@@ -1390,32 +1390,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Light/media/media_play.svg); -+ qproperty-icon: url(theme:Light/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Light/media/media_pause.svg); -+ qproperty-icon: url(theme:Light/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Light/media/media_restart.svg); -+ qproperty-icon: url(theme:Light/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Light/media/media_stop.svg); -+ qproperty-icon: url(theme:Light/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Light/media/media_next.svg); -+ qproperty-icon: url(theme:Light/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Light/media/media_previous.svg); -+ qproperty-icon: url(theme:Light/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Light/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Light/sources/image.svg); - } - - #ytEventList QLabel { -@@ -1443,7 +1443,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Light/down.svg); -+ image: url(theme:Light/down.svg); - width: 100%; - } - -@@ -1466,7 +1466,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Light/down.svg); -+ image: url(theme:Light/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1476,13 +1476,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Light/left.svg); -+ qproperty-icon: url(theme:Light/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Light/right.svg); -+ qproperty-icon: url(theme:Light/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss -index 92880cfd0..579737ea9 100644 ---- a/UI/data/themes/Rachni.qss -+++ b/UI/data/themes/Rachni.qss -@@ -168,7 +168,7 @@ QMenu::item:disabled { - } - - QMenu::right-arrow { -- image: url(./Dark/expand.svg); -+ image: url(theme:Dark/expand.svg); - } - - /* Top Menu Bar Items */ -@@ -306,8 +306,8 @@ QDockWidget { - font-size: 10.5pt; - font-weight: bold; - -- titlebar-close-icon: url('./Dark/close.svg'); -- titlebar-normal-icon: url('./Dark/popout.svg'); -+ titlebar-close-icon: url(theme:Dark/close.svg); -+ titlebar-normal-icon: url(theme:Dark/popout.svg); - } - - QDockWidget::title { -@@ -456,11 +456,11 @@ QScrollBar::handle:horizontal { - } - - QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - /* Scenes and Sources toolbar */ -@@ -499,55 +499,55 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Dark/plus.svg); -+ qproperty-icon: url(theme:Dark/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Dark/trash.svg); -+ qproperty-icon: url(theme:Dark/trash.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Dark/entry-clear.svg); -+ qproperty-icon: url(theme:Dark/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Dark/refresh.svg); -+ qproperty-icon: url(theme:Dark/refresh.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Dark/cogs.svg); -+ qproperty-icon: url(theme:Dark/cogs.svg); - } - - #sourceInteractButton { -- qproperty-icon: url(./Dark/interact.svg); -+ qproperty-icon: url(theme:Dark/interact.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Dark/up.svg); -+ qproperty-icon: url(theme:Dark/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Dark/down.svg); -+ qproperty-icon: url(theme:Dark/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Dark/media-pause.svg); -+ qproperty-icon: url(theme:Dark/media-pause.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - QToolBarExtension { -@@ -557,7 +557,7 @@ QToolBarExtension { - padding: 4px 0px; - margin-left: 0px; - -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - -@@ -652,7 +652,7 @@ QDateTimeEdit::drop-down { - QComboBox::down-arrow, - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/updown.svg); -+ image: url(theme:Dark/updown.svg); - width: 100%; - } - -@@ -674,7 +674,7 @@ QDateTimeEdit::drop-down:editable { - QComboBox::down-arrow:editable, - QDateTimeEdit::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 8%; - } - -@@ -759,13 +759,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Dark/up.svg); -+ image: url(theme:Dark/up.svg); - width: 100%; - margin: 2px; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - padding: 2px; - } -@@ -837,7 +837,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -987,15 +987,15 @@ QHeaderView::section { - /* Mute CheckBox */ - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -1094,14 +1094,14 @@ OBSBasicFilters #widget_2 QPushButton { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Dark/settings/general.svg); -- qproperty-streamIcon: url(./Dark/settings/stream.svg); -- qproperty-outputIcon: url(./Dark/settings/output.svg); -- qproperty-audioIcon: url(./Dark/settings/audio.svg); -- qproperty-videoIcon: url(./Dark/settings/video.svg); -- qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Dark/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Dark/settings/general.svg); -+ qproperty-streamIcon: url(theme:Dark/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Dark/settings/output.svg); -+ qproperty-audioIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Dark/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); - } - - /* Checkboxes */ -@@ -1121,34 +1121,34 @@ QGroupBox::indicator { - - QCheckBox::indicator:unchecked, - QGroupBox::indicator:unchecked { -- image: url(./Yami/checkbox_unchecked.svg); -+ image: url(theme:Yami/checkbox_unchecked.svg); - } - - QCheckBox::indicator:unchecked:hover, - QGroupBox::indicator:unchecked:hover { - border: none; -- image: url(./Yami/checkbox_unchecked_focus.svg); -+ image: url(theme:Yami/checkbox_unchecked_focus.svg); - } - - QCheckBox::indicator:checked, - QGroupBox::indicator:checked { -- image: url(./Yami/checkbox_checked.svg); -+ image: url(theme:Yami/checkbox_checked.svg); - } - - QCheckBox::indicator:checked:hover, - QGroupBox::indicator:checked:hover { - border: none; -- image: url(./Yami/checkbox_checked_focus.svg); -+ image: url(theme:Yami/checkbox_checked_focus.svg); - } - - QCheckBox::indicator:checked:disabled, - QGroupBox::indicator:checked:disabled { -- image: url(./Yami/checkbox_checked_disabled.svg); -+ image: url(theme:Yami/checkbox_checked_disabled.svg); - } - - QCheckBox::indicator:unchecked:disabled, - QGroupBox::indicator:unchecked:disabled { -- image: url(./Yami/checkbox_unchecked_disabled.svg); -+ image: url(theme:Yami/checkbox_unchecked_disabled.svg); - } - - /* Locked CheckBox */ -@@ -1165,7 +1165,7 @@ LockedCheckBox::indicator { - - LockedCheckBox::indicator:checked, - LockedCheckBox::indicator:checked:hover { -- image: url(./Dark/locked.svg); -+ image: url(theme:Dark/locked.svg); - } - - LockedCheckBox::indicator:unchecked, -@@ -1187,7 +1187,7 @@ VisibilityCheckBox::indicator { - - VisibilityCheckBox::indicator:checked, - VisibilityCheckBox::indicator:checked:hover { -- image: url(./Dark/visible.svg); -+ image: url(theme:Dark/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked, -@@ -1196,7 +1196,7 @@ VisibilityCheckBox::indicator:unchecked:hover { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Dark/revert.svg); -+ qproperty-icon: url(theme:Dark/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -1225,35 +1225,35 @@ MuteCheckBox::indicator { - } - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:hover { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:focus { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:checked:hover { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:focus { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:disabled { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked:disabled { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - #hotkeyFilterReset { -@@ -1283,46 +1283,46 @@ OBSHotkeyWidget QPushButton { - - /* Sources List Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - padding: 0px; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 12px; - height: 12px; - } - --SourceTreeSubItemCheckBox::indicator:checked, --SourceTreeSubItemCheckBox::indicator:checked:hover { -- image: url(./Dark/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked, -+QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { -+ image: url(theme:Dark/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked, --SourceTreeSubItemCheckBox::indicator:unchecked:hover { -- image: url(./Dark/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { -+ image: url(theme:Dark/collapse.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Dark/sources/image.svg); -- qproperty-colorIcon: url(./Dark/sources/brush.svg); -- qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Dark/settings/video.svg); -- qproperty-windowCapIcon: url(./Dark/sources/window.svg); -- qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Dark/sources/camera.svg); -- qproperty-textIcon: url(./Dark/sources/text.svg); -- qproperty-mediaIcon: url(./Dark/sources/media.svg); -- qproperty-browserIcon: url(./Dark/sources/globe.svg); -- qproperty-groupIcon: url(./Dark/sources/group.svg); -- qproperty-sceneIcon: url(./Dark/sources/scene.svg); -- qproperty-defaultIcon: url(./Dark/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Dark/sources/image.svg); -+ qproperty-colorIcon: url(theme:Dark/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); -+ qproperty-textIcon: url(theme:Dark/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Dark/sources/media.svg); -+ qproperty-browserIcon: url(theme:Dark/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Dark/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Dark/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); - } - - /* Scene Tree Grid Mode */ -@@ -1358,7 +1358,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Dark/save.svg); -+ qproperty-icon: url(theme:Dark/save.svg); - } - - /* Studio Mode T-Bar */ -@@ -1388,32 +1388,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Dark/media/media_play.svg); -+ qproperty-icon: url(theme:Dark/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Dark/media/media_pause.svg); -+ qproperty-icon: url(theme:Dark/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Dark/media/media_restart.svg); -+ qproperty-icon: url(theme:Dark/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Dark/media/media_stop.svg); -+ qproperty-icon: url(theme:Dark/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Dark/media/media_next.svg); -+ qproperty-icon: url(theme:Dark/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Dark/media/media_previous.svg); -+ qproperty-icon: url(theme:Dark/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); - } - - #ytEventList QLabel { -@@ -1441,7 +1441,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -1464,7 +1464,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1474,13 +1474,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/System.qss b/UI/data/themes/System.qss -index 94c446673..a2476d367 100644 ---- a/UI/data/themes/System.qss -+++ b/UI/data/themes/System.qss -@@ -71,28 +71,28 @@ MuteCheckBox::indicator:checked { - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { - image: url(:/settings/images/settings/audio.svg); - } - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 10px; - height: 10px; - } - --SourceTreeSubItemCheckBox::indicator:checked { -+QCheckBox[sourceTreeSubItem=true]::indicator:checked { - image: url(:/res/images/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked { -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked { - image: url(:/res/images/collapse.svg); - } - -@@ -378,7 +378,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 2px; -@@ -393,13 +393,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/data/themes/Yami.qss b/UI/data/themes/Yami.qss -index b32a7b47d..819b507ec 100644 ---- a/UI/data/themes/Yami.qss -+++ b/UI/data/themes/Yami.qss -@@ -166,7 +166,7 @@ QMenu::item:disabled { - } - - QMenu::right-arrow { -- image: url(./Dark/expand.svg); -+ image: url(theme:Dark/expand.svg); - } - - /* Top Menu Bar Items */ -@@ -308,8 +308,8 @@ QDockWidget { - font-size: 10.5pt; - font-weight: bold; - -- titlebar-close-icon: url('./Dark/close.svg'); -- titlebar-normal-icon: url('./Dark/popout.svg'); -+ titlebar-close-icon: url(theme:Dark/close.svg); -+ titlebar-normal-icon: url(theme:Dark/popout.svg); - } - - QDockWidget::title { -@@ -457,11 +457,11 @@ QScrollBar::handle:horizontal { - } - - QPushButton#sourcePropertiesButton { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - QPushButton#sourceFiltersButton { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - /* Scenes and Sources toolbar */ -@@ -495,55 +495,55 @@ QToolButton:pressed { - } - - * [themeID="addIconSmall"] { -- qproperty-icon: url(./Dark/plus.svg); -+ qproperty-icon: url(theme:Dark/plus.svg); - } - - * [themeID="removeIconSmall"] { -- qproperty-icon: url(./Dark/trash.svg); -+ qproperty-icon: url(theme:Dark/trash.svg); - } - - * [themeID="clearIconSmall"] { -- qproperty-icon: url(./Dark/entry-clear.svg); -+ qproperty-icon: url(theme:Dark/entry-clear.svg); - } - - * [themeID="propertiesIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="configIconSmall"] { -- qproperty-icon: url(./Dark/settings/general.svg); -+ qproperty-icon: url(theme:Dark/settings/general.svg); - } - - * [themeID="menuIconSmall"] { -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - * [themeID="refreshIconSmall"] { -- qproperty-icon: url(./Dark/refresh.svg); -+ qproperty-icon: url(theme:Dark/refresh.svg); - } - - * [themeID="cogsIcon"] { -- qproperty-icon: url(./Dark/cogs.svg); -+ qproperty-icon: url(theme:Dark/cogs.svg); - } - - #sourceInteractButton { -- qproperty-icon: url(./Dark/interact.svg); -+ qproperty-icon: url(theme:Dark/interact.svg); - } - - * [themeID="upArrowIconSmall"] { -- qproperty-icon: url(./Dark/up.svg); -+ qproperty-icon: url(theme:Dark/up.svg); - } - - * [themeID="downArrowIconSmall"] { -- qproperty-icon: url(./Dark/down.svg); -+ qproperty-icon: url(theme:Dark/down.svg); - } - - * [themeID="pauseIconSmall"] { -- qproperty-icon: url(./Dark/media-pause.svg); -+ qproperty-icon: url(theme:Dark/media-pause.svg); - } - - * [themeID="filtersIcon"] { -- qproperty-icon: url(./Dark/filter.svg); -+ qproperty-icon: url(theme:Dark/filter.svg); - } - - QToolBarExtension { -@@ -553,7 +553,7 @@ QToolBarExtension { - padding: 4px 0px; - margin-left: 0px; - -- qproperty-icon: url(./Dark/dots-vert.svg); -+ qproperty-icon: url(theme:Dark/dots-vert.svg); - } - - -@@ -649,7 +649,7 @@ QDateTimeEdit::drop-down { - QComboBox::down-arrow, - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/updown.svg); -+ image: url(theme:Dark/updown.svg); - width: 100%; - } - -@@ -671,7 +671,7 @@ QDateTimeEdit::drop-down:editable { - QComboBox::down-arrow:editable, - QDateTimeEdit::down-arrow:editable { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 8%; - } - -@@ -759,13 +759,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo - } - - QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { -- image: url(./Dark/up.svg); -+ image: url(theme:Dark/up.svg); - width: 100%; - margin: 2px; - } - - QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - padding: 2px; - } -@@ -837,7 +837,7 @@ QPushButton:disabled, QToolButton:disabled { - } - - QPushButton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - subcontrol-origin: padding; - width: 25px; -@@ -987,15 +987,15 @@ QHeaderView::section { - /* Mute CheckBox */ - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:indeterminate { -- image: url(./Dark/unassigned.svg); -+ image: url(theme:Dark/unassigned.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - OBSHotkeyLabel[hotkeyPairHover=true] { -@@ -1094,14 +1094,14 @@ OBSBasicFilters #widget_2 QPushButton { - /* Settings Icons */ - - OBSBasicSettings { -- qproperty-generalIcon: url(./Dark/settings/general.svg); -- qproperty-streamIcon: url(./Dark/settings/stream.svg); -- qproperty-outputIcon: url(./Dark/settings/output.svg); -- qproperty-audioIcon: url(./Dark/settings/audio.svg); -- qproperty-videoIcon: url(./Dark/settings/video.svg); -- qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); -- qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); -- qproperty-advancedIcon: url(./Dark/settings/advanced.svg); -+ qproperty-generalIcon: url(theme:Dark/settings/general.svg); -+ qproperty-streamIcon: url(theme:Dark/settings/stream.svg); -+ qproperty-outputIcon: url(theme:Dark/settings/output.svg); -+ qproperty-audioIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-videoIcon: url(theme:Dark/settings/video.svg); -+ qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); -+ qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); -+ qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); - } - - /* Checkboxes */ -@@ -1121,34 +1121,34 @@ QGroupBox::indicator { - - QCheckBox::indicator:unchecked, - QGroupBox::indicator:unchecked { -- image: url(./Yami/checkbox_unchecked.svg); -+ image: url(theme:Yami/checkbox_unchecked.svg); - } - - QCheckBox::indicator:unchecked:hover, - QGroupBox::indicator:unchecked:hover { - border: none; -- image: url(./Yami/checkbox_unchecked_focus.svg); -+ image: url(theme:Yami/checkbox_unchecked_focus.svg); - } - - QCheckBox::indicator:checked, - QGroupBox::indicator:checked { -- image: url(./Yami/checkbox_checked.svg); -+ image: url(theme:Yami/checkbox_checked.svg); - } - - QCheckBox::indicator:checked:hover, - QGroupBox::indicator:checked:hover { - border: none; -- image: url(./Yami/checkbox_checked_focus.svg); -+ image: url(theme:Yami/checkbox_checked_focus.svg); - } - - QCheckBox::indicator:checked:disabled, - QGroupBox::indicator:checked:disabled { -- image: url(./Yami/checkbox_checked_disabled.svg); -+ image: url(theme:Yami/checkbox_checked_disabled.svg); - } - - QCheckBox::indicator:unchecked:disabled, - QGroupBox::indicator:unchecked:disabled { -- image: url(./Yami/checkbox_unchecked_disabled.svg); -+ image: url(theme:Yami/checkbox_unchecked_disabled.svg); - } - - /* Locked CheckBox */ -@@ -1165,7 +1165,7 @@ LockedCheckBox::indicator { - - LockedCheckBox::indicator:checked, - LockedCheckBox::indicator:checked:hover { -- image: url(./Dark/locked.svg); -+ image: url(theme:Dark/locked.svg); - } - - LockedCheckBox::indicator:unchecked, -@@ -1187,7 +1187,7 @@ VisibilityCheckBox::indicator { - - VisibilityCheckBox::indicator:checked, - VisibilityCheckBox::indicator:checked:hover { -- image: url(./Dark/visible.svg); -+ image: url(theme:Dark/visible.svg); - } - - VisibilityCheckBox::indicator:unchecked, -@@ -1196,7 +1196,7 @@ VisibilityCheckBox::indicator:unchecked:hover { - } - - * [themeID="revertIcon"] { -- qproperty-icon: url(./Dark/revert.svg); -+ qproperty-icon: url(theme:Dark/revert.svg); - } - - QPushButton#extraPanelDelete { -@@ -1225,35 +1225,35 @@ MuteCheckBox::indicator { - } - - MuteCheckBox::indicator:checked { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:hover { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:unchecked:focus { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - MuteCheckBox::indicator:checked:hover { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:focus { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:checked:disabled { -- image: url(./Dark/mute.svg); -+ image: url(theme:Dark/mute.svg); - } - - MuteCheckBox::indicator:unchecked:disabled { -- image: url(./Dark/settings/audio.svg); -+ image: url(theme:Dark/settings/audio.svg); - } - - #hotkeyFilterReset { -@@ -1283,46 +1283,46 @@ OBSHotkeyWidget QPushButton { - - /* Sources List Group Collapse Checkbox */ - --SourceTreeSubItemCheckBox { -+QCheckBox[sourceTreeSubItem=true] { - background: transparent; - outline: none; - padding: 0px; - } - --SourceTreeSubItemCheckBox::indicator { -+QCheckBox[sourceTreeSubItem=true]::indicator { - width: 12px; - height: 12px; - } - --SourceTreeSubItemCheckBox::indicator:checked, --SourceTreeSubItemCheckBox::indicator:checked:hover { -- image: url(./Dark/expand.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:checked, -+QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { -+ image: url(theme:Dark/expand.svg); - } - --SourceTreeSubItemCheckBox::indicator:unchecked, --SourceTreeSubItemCheckBox::indicator:unchecked:hover { -- image: url(./Dark/collapse.svg); -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, -+QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { -+ image: url(theme:Dark/collapse.svg); - } - - /* Source Icons */ - - OBSBasic { -- qproperty-imageIcon: url(./Dark/sources/image.svg); -- qproperty-colorIcon: url(./Dark/sources/brush.svg); -- qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); -- qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); -- qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); -- qproperty-desktopCapIcon: url(./Dark/settings/video.svg); -- qproperty-windowCapIcon: url(./Dark/sources/window.svg); -- qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); -- qproperty-cameraIcon: url(./Dark/sources/camera.svg); -- qproperty-textIcon: url(./Dark/sources/text.svg); -- qproperty-mediaIcon: url(./Dark/sources/media.svg); -- qproperty-browserIcon: url(./Dark/sources/globe.svg); -- qproperty-groupIcon: url(./Dark/sources/group.svg); -- qproperty-sceneIcon: url(./Dark/sources/scene.svg); -- qproperty-defaultIcon: url(./Dark/sources/default.svg); -- qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); -+ qproperty-imageIcon: url(theme:Dark/sources/image.svg); -+ qproperty-colorIcon: url(theme:Dark/sources/brush.svg); -+ qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); -+ qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); -+ qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); -+ qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); -+ qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); -+ qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); -+ qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); -+ qproperty-textIcon: url(theme:Dark/sources/text.svg); -+ qproperty-mediaIcon: url(theme:Dark/sources/media.svg); -+ qproperty-browserIcon: url(theme:Dark/sources/globe.svg); -+ qproperty-groupIcon: url(theme:Dark/sources/group.svg); -+ qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); -+ qproperty-defaultIcon: url(theme:Dark/sources/default.svg); -+ qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); - } - - /* Scene Tree Grid Mode */ -@@ -1358,7 +1358,7 @@ SceneTree { - /* Save icon */ - - * [themeID="replayIconSmall"] { -- qproperty-icon: url(./Dark/save.svg); -+ qproperty-icon: url(theme:Dark/save.svg); - } - - /* Studio Mode T-Bar */ -@@ -1388,32 +1388,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { - /* Media icons */ - - * [themeID="playIcon"] { -- qproperty-icon: url(./Dark/media/media_play.svg); -+ qproperty-icon: url(theme:Dark/media/media_play.svg); - } - - * [themeID="pauseIcon"] { -- qproperty-icon: url(./Dark/media/media_pause.svg); -+ qproperty-icon: url(theme:Dark/media/media_pause.svg); - } - - * [themeID="restartIcon"] { -- qproperty-icon: url(./Dark/media/media_restart.svg); -+ qproperty-icon: url(theme:Dark/media/media_restart.svg); - } - - * [themeID="stopIcon"] { -- qproperty-icon: url(./Dark/media/media_stop.svg); -+ qproperty-icon: url(theme:Dark/media/media_stop.svg); - } - - * [themeID="nextIcon"] { -- qproperty-icon: url(./Dark/media/media_next.svg); -+ qproperty-icon: url(theme:Dark/media/media_next.svg); - } - - * [themeID="previousIcon"] { -- qproperty-icon: url(./Dark/media/media_previous.svg); -+ qproperty-icon: url(theme:Dark/media/media_previous.svg); - } - - /* YouTube Integration */ - OBSYoutubeActions { -- qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); -+ qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); - } - - #ytEventList QLabel { -@@ -1441,7 +1441,7 @@ OBSYoutubeActions { - /* Calendar Widget */ - QDateTimeEdit::down-arrow { - qproperty-alignment: AlignTop; -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - width: 100%; - } - -@@ -1464,7 +1464,7 @@ QCalendarWidget QToolButton { - } - - #qt_calendar_monthbutton::menu-indicator { -- image: url(./Dark/down.svg); -+ image: url(theme:Dark/down.svg); - subcontrol-position: right; - padding-top: 2px; - padding-right: 6px; -@@ -1474,13 +1474,13 @@ QCalendarWidget QToolButton { - - QCalendarWidget #qt_calendar_prevmonth { - padding: 2px; -- qproperty-icon: url(./Dark/left.svg); -+ qproperty-icon: url(theme:Dark/left.svg); - icon-size: 16px, 16px; - } - - QCalendarWidget #qt_calendar_nextmonth { - padding: 2px; -- qproperty-icon: url(./Dark/right.svg); -+ qproperty-icon: url(theme:Dark/right.svg); - icon-size: 16px, 16px; - } - -diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp -index c98408c4a..887d6bb63 100644 ---- a/UI/obs-app.cpp -+++ b/UI/obs-app.cpp -@@ -31,6 +31,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -1272,6 +1273,19 @@ bool OBSApp::InitTheme() - defaultPalette = palette(); - setStyle(new OBSProxyStyle()); - -+ /* Set search paths for custom 'theme:' URI prefix */ -+ string searchDir; -+ if (GetDataFilePath("themes", searchDir)) { -+ auto installSearchDir = filesystem::u8path(searchDir); -+ QDir::addSearchPath("theme", absolute(installSearchDir)); -+ } -+ -+ char userDir[512]; -+ if (GetConfigPath(userDir, sizeof(userDir), "obs-studio/themes")) { -+ auto configSearchDir = filesystem::u8path(userDir); -+ QDir::addSearchPath("theme", absolute(configSearchDir)); -+ } -+ - const char *themeName = - config_get_string(globalConfig, "General", "CurrentTheme3"); - if (!themeName) -diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp -index 3cfdcd5ed..66f44da71 100644 ---- a/UI/source-tree.cpp -+++ b/UI/source-tree.cpp -@@ -577,7 +577,8 @@ void SourceTreeItem::Update(bool force) - boxLayout->insertItem(0, spacer); - - } else if (type == Type::Group) { -- expand = new SourceTreeSubItemCheckBox(); -+ expand = new QCheckBox(); -+ expand->setProperty("sourceTreeSubItem", true); - expand->setSizePolicy(QSizePolicy::Maximum, - QSizePolicy::Maximum); - expand->setMaximumSize(10, 16); -@@ -1664,11 +1665,8 @@ void SourceTree::AddGroup() - - void SourceTree::UpdateNoSourcesMessage() - { -- std::string darkPath; -- GetDataFilePath("themes/Dark/no_sources.svg", darkPath); -- - QString file = !App()->IsThemeDark() ? ":res/images/no_sources.svg" -- : darkPath.c_str(); -+ : "theme:Dark/no_sources.svg"; - iconNoSources.load(file); - - QTextOption opt(Qt::AlignHCenter); -diff --git a/UI/source-tree.hpp b/UI/source-tree.hpp -index 0ab3ad80f..c4b419686 100644 ---- a/UI/source-tree.hpp -+++ b/UI/source-tree.hpp -@@ -22,10 +22,6 @@ class LockedCheckBox; - class VisibilityCheckBox; - class VisibilityItemWidget; - --class SourceTreeSubItemCheckBox : public QCheckBox { -- Q_OBJECT --}; -- - class SourceTreeItem : public QFrame { - Q_OBJECT - -diff --git a/UI/window-basic-status-bar.cpp b/UI/window-basic-status-bar.cpp -index 300b769c5..5f08ba78b 100644 ---- a/UI/window-basic-status-bar.cpp -+++ b/UI/window-basic-status-bar.cpp -@@ -569,19 +569,9 @@ void OBSBasicStatusBar::RecordingUnpaused() - - static QPixmap GetPixmap(const QString &filename) - { -- bool darkTheme = obs_frontend_is_theme_dark(); -- QString path; -- -- if (darkTheme) { -- std::string darkPath; -- QString themePath = QString("themes/Dark/") + filename; -- GetDataFilePath(QT_TO_UTF8(themePath), darkPath); -- path = QT_UTF8(darkPath.c_str()); -- } else { -- path = QString(":/res/images/" + filename); -- } -- -- return QIcon(path).pixmap(QSize(16, 16)); -+ QString path = obs_frontend_is_theme_dark() ? "theme:Dark/" -+ : ":/res/images/"; -+ return QIcon(path + filename).pixmap(QSize(16, 16)); - } - - void OBSBasicStatusBar::UpdateIcons() -diff --git a/deps/obs-scripting/obs-scripting-lua.c b/deps/obs-scripting/obs-scripting-lua.c -index c322e0850..9b3c44441 100644 ---- a/deps/obs-scripting/obs-scripting-lua.c -+++ b/deps/obs-scripting/obs-scripting-lua.c -@@ -52,6 +52,7 @@ static const char *get_script_path_func = "\ - function script_path()\n\ - return \"%s\"\n\ - end\n\ -+package.cpath = package.cpath .. \";\" .. script_path() .. \"/?." SO_EXT "\"\n\ - package.path = package.path .. \";\" .. script_path() .. \"/?.lua\"\n"; - - static char *startup_script = NULL; -diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt -index 39bfa1fd0..279dab4c1 100644 ---- a/libobs/CMakeLists.txt -+++ b/libobs/CMakeLists.txt -@@ -33,6 +33,8 @@ target_sources( - obs-audio-controls.c - obs-audio-controls.h - obs-audio.c -+ obs-av1.c -+ obs-av1.h - obs-avc.c - obs-avc.h - obs-data.c -diff --git a/libobs/cmake/legacy.cmake b/libobs/cmake/legacy.cmake -index 5f13c4c0f..dd77cdfb9 100644 ---- a/libobs/cmake/legacy.cmake -+++ b/libobs/cmake/legacy.cmake -@@ -32,6 +32,8 @@ target_sources( - obs-audio.c - obs-audio-controls.c - obs-audio-controls.h -+ obs-av1.c -+ obs-av1.h - obs-avc.c - obs-avc.h - obs-data.c -diff --git a/libobs/obs-av1.c b/libobs/obs-av1.c -new file mode 100644 -index 000000000..a01513053 ---- /dev/null -+++ b/libobs/obs-av1.c -@@ -0,0 +1,123 @@ -+// SPDX-FileCopyrightText: 2023 David Rosca -+// -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+#include "obs-av1.h" -+ -+#include "obs.h" -+ -+static inline uint64_t leb128(const uint8_t *buf, size_t size, size_t *len) -+{ -+ uint64_t value = 0; -+ uint8_t leb128_byte; -+ -+ *len = 0; -+ -+ for (int i = 0; i < 8; i++) { -+ if (size-- < 1) -+ break; -+ (*len)++; -+ leb128_byte = buf[i]; -+ value |= (leb128_byte & 0x7f) << (i * 7); -+ if (!(leb128_byte & 0x80)) -+ break; -+ } -+ -+ return value; -+} -+ -+static inline unsigned int get_bits(uint8_t val, unsigned int n, -+ unsigned int count) -+{ -+ return (val >> (8 - n - count)) & ((1 << (count - 1)) * 2 - 1); -+} -+ -+static void parse_obu_header(const uint8_t *buf, size_t size, size_t *obu_start, -+ size_t *obu_size, int *obu_type) -+{ -+ int extension_flag, has_size_field; -+ size_t size_len = 0; -+ -+ *obu_start = 0; -+ *obu_size = 0; -+ *obu_type = 0; -+ -+ if (size < 1) -+ return; -+ -+ *obu_type = get_bits(*buf, 1, 4); -+ extension_flag = get_bits(*buf, 5, 1); -+ has_size_field = get_bits(*buf, 6, 1); -+ -+ if (extension_flag) -+ (*obu_start)++; -+ -+ (*obu_start)++; -+ -+ if (has_size_field) -+ *obu_size = (size_t)leb128(buf + *obu_start, size - *obu_start, -+ &size_len); -+ else -+ *obu_size = size - 1; -+ -+ *obu_start += size_len; -+} -+ -+bool obs_av1_keyframe(const uint8_t *data, size_t size) -+{ -+ const uint8_t *start = data, *end = data + size; -+ -+ while (start < end) { -+ size_t obu_start, obu_size; -+ int obu_type; -+ parse_obu_header(start, end - start, &obu_start, &obu_size, -+ &obu_type); -+ -+ if (obu_size) { -+ if (obu_type == OBS_OBU_FRAME || -+ obu_type == OBS_OBU_FRAME_HEADER) { -+ uint8_t val = *(start + obu_start); -+ if (!get_bits(val, 0, 1)) // show_existing_frame -+ return get_bits(val, 1, 2) == -+ 0; // frame_type -+ return false; -+ } -+ } -+ -+ start += obu_start + obu_size; -+ } -+ -+ return false; -+} -+ -+void obs_extract_av1_headers(const uint8_t *packet, size_t size, -+ uint8_t **new_packet_data, size_t *new_packet_size, -+ uint8_t **header_data, size_t *header_size) -+{ -+ DARRAY(uint8_t) new_packet; -+ DARRAY(uint8_t) header; -+ const uint8_t *start = packet, *end = packet + size; -+ -+ da_init(new_packet); -+ da_init(header); -+ -+ while (start < end) { -+ size_t obu_start, obu_size; -+ int obu_type; -+ parse_obu_header(start, end - start, &obu_start, &obu_size, -+ &obu_type); -+ -+ if (obu_type == OBS_OBU_METADATA || -+ obu_type == OBS_OBU_SEQUENCE_HEADER) { -+ da_push_back_array(header, start, obu_start + obu_size); -+ } -+ da_push_back_array(new_packet, start, obu_start + obu_size); -+ -+ start += obu_start + obu_size; -+ } -+ -+ *new_packet_data = new_packet.array; -+ *new_packet_size = new_packet.num; -+ *header_data = header.array; -+ *header_size = header.num; -+} -diff --git a/libobs/obs-av1.h b/libobs/obs-av1.h -new file mode 100644 -index 000000000..031299da0 ---- /dev/null -+++ b/libobs/obs-av1.h -@@ -0,0 +1,35 @@ -+// SPDX-FileCopyrightText: 2023 David Rosca -+// -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+#pragma once -+ -+#include "util/c99defs.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+enum { -+ OBS_OBU_SEQUENCE_HEADER = 1, -+ OBS_OBU_TEMPORAL_DELIMITER = 2, -+ OBS_OBU_FRAME_HEADER = 3, -+ OBS_OBU_TILE_GROUP = 4, -+ OBS_OBU_METADATA = 5, -+ OBS_OBU_FRAME = 6, -+ OBS_OBU_REDUNDANT_FRAME_HEADER = 7, -+ OBS_OBU_TILE_LIST = 8, -+ OBS_OBU_PADDING = 15, -+}; -+ -+/* Helpers for parsing AV1 OB units. */ -+ -+EXPORT bool obs_av1_keyframe(const uint8_t *data, size_t size); -+EXPORT void obs_extract_av1_headers(const uint8_t *packet, size_t size, -+ uint8_t **new_packet_data, -+ size_t *new_packet_size, -+ uint8_t **header_data, size_t *header_size); -+ -+#ifdef __cplusplus -+} -+#endif -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c -index 25c5f7900..b7e5d5edd 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - #ifdef ENABLE_HEVC - #include - #endif -@@ -51,8 +52,15 @@ - #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) - #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) - -+enum codec_type { -+ CODEC_H264, -+ CODEC_HEVC, -+ CODEC_AV1, -+}; -+ - struct vaapi_encoder { - obs_encoder_t *encoder; -+ enum codec_type codec; - - AVBufferRef *vadevice_ref; - AVBufferRef *vaframes_ref; -@@ -83,59 +91,48 @@ static const char *h264_vaapi_getname(void *unused) - return "FFmpeg VAAPI H.264"; - } - --#ifdef ENABLE_HEVC --static const char *hevc_vaapi_getname(void *unused) -+static const char *av1_vaapi_getname(void *unused) - { - UNUSED_PARAMETER(unused); -- return "FFmpeg VAAPI HEVC"; --} --#endif -- --static inline bool h264_valid_format(enum video_format format) --{ -- return format == VIDEO_FORMAT_NV12; -+ return "FFmpeg VAAPI AV1"; - } - - #ifdef ENABLE_HEVC --static inline bool hevc_valid_format(enum video_format format) -+static const char *hevc_vaapi_getname(void *unused) - { -- return (format == VIDEO_FORMAT_NV12) || (format == VIDEO_FORMAT_P010); -+ UNUSED_PARAMETER(unused); -+ return "FFmpeg VAAPI HEVC"; - } - #endif - --static void h264_vaapi_video_info(void *data, struct video_scale_info *info) -+static inline bool vaapi_valid_format(struct vaapi_encoder *enc, -+ enum video_format format) - { -- struct vaapi_encoder *enc = data; -- enum video_format pref_format; -- -- pref_format = obs_encoder_get_preferred_video_format(enc->encoder); -- -- if (!h264_valid_format(pref_format)) { -- pref_format = h264_valid_format(info->format) -- ? info->format -- : VIDEO_FORMAT_NV12; -+ if (enc->codec == CODEC_H264) { -+ return format == VIDEO_FORMAT_NV12; -+ } else if (enc->codec == CODEC_HEVC || enc->codec == CODEC_AV1) { -+ return (format == VIDEO_FORMAT_NV12) || -+ (format == VIDEO_FORMAT_P010); -+ } else { -+ return false; - } -- -- info->format = pref_format; - } - --#ifdef ENABLE_HEVC --static void hevc_vaapi_video_info(void *data, struct video_scale_info *info) -+static void vaapi_video_info(void *data, struct video_scale_info *info) - { - struct vaapi_encoder *enc = data; - enum video_format pref_format; - - pref_format = obs_encoder_get_preferred_video_format(enc->encoder); - -- if (!hevc_valid_format(pref_format)) { -- pref_format = hevc_valid_format(info->format) -+ if (!vaapi_valid_format(enc, pref_format)) { -+ pref_format = vaapi_valid_format(enc, info->format) - ? info->format - : VIDEO_FORMAT_NV12; - } - - info->format = pref_format; - } --#endif - - static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path) - { -@@ -232,7 +229,7 @@ static const rc_mode_t *get_rc_mode(const char *name) - return rc_mode ? rc_mode : RC_MODES; - } - --static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) -+static bool vaapi_update(void *data, obs_data_t *settings) - { - struct vaapi_encoder *enc = data; - -@@ -247,7 +244,7 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) - int bf = (int)obs_data_get_int(settings, "bf"); - int qp = rc_mode->qp ? (int)obs_data_get_int(settings, "qp") : 0; - -- av_opt_set_int(enc->context->priv_data, "qp", qp, 0); -+ enc->context->global_quality = enc->codec == CODEC_AV1 ? qp * 5 : qp; - - int level = (int)obs_data_get_int(settings, "level"); - int bitrate = rc_mode->bitrate -@@ -277,21 +274,15 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) - info.range = voi->range; - - #ifdef ENABLE_HEVC -- if (hevc) { -+ if (enc->codec == CODEC_HEVC) { - if ((profile == FF_PROFILE_HEVC_MAIN) && - (info.format == VIDEO_FORMAT_P010)) { - warn("Forcing Main10 for P010"); - profile = FF_PROFILE_HEVC_MAIN_10; - } -- -- hevc_vaapi_video_info(enc, &info); -- } else --#else -- UNUSED_PARAMETER(hevc); --#endif -- { -- h264_vaapi_video_info(enc, &info); - } -+#endif -+ vaapi_video_info(enc, &info); - - enc->context->profile = profile; - enc->context->max_b_frames = bf; -@@ -418,16 +409,28 @@ static void vaapi_destroy(void *data) - bfree(enc); - } - -+static inline const char *vaapi_encoder_name(enum codec_type codec) -+{ -+ if (codec == CODEC_H264) { -+ return "h264_vaapi"; -+ } else if (codec == CODEC_HEVC) { -+ return "hevc_vaapi"; -+ } else if (codec == CODEC_AV1) { -+ return "av1_vaapi"; -+ } -+ return NULL; -+} -+ - static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, -- bool hevc) -+ enum codec_type codec) - { - struct vaapi_encoder *enc; - - enc = bzalloc(sizeof(*enc)); - enc->encoder = encoder; - -- const char *const name = hevc ? "hevc_vaapi" : "h264_vaapi"; -- enc->vaapi = avcodec_find_encoder_by_name(name); -+ enc->codec = codec; -+ enc->vaapi = avcodec_find_encoder_by_name(vaapi_encoder_name(codec)); - - enc->first_packet = true; - -@@ -444,7 +447,7 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, - goto fail; - } - -- if (!vaapi_update(enc, settings, hevc)) -+ if (!vaapi_update(enc, settings)) - goto fail; - - return enc; -@@ -456,13 +459,18 @@ fail: - - static void *h264_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) - { -- return vaapi_create_internal(settings, encoder, false); -+ return vaapi_create_internal(settings, encoder, CODEC_H264); -+} -+ -+static void *av1_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) -+{ -+ return vaapi_create_internal(settings, encoder, CODEC_AV1); - } - - #ifdef ENABLE_HEVC - static void *hevc_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) - { -- return vaapi_create_internal(settings, encoder, true); -+ return vaapi_create_internal(settings, encoder, CODEC_HEVC); - } - #endif - -@@ -492,9 +500,8 @@ static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame, - } - } - --static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, -- struct encoder_packet *packet, -- bool *received_packet, bool hevc) -+static bool vaapi_encode(void *data, struct encoder_frame *frame, -+ struct encoder_packet *packet, bool *received_packet) - { - struct vaapi_encoder *enc = data; - AVFrame *hwframe = NULL; -@@ -556,22 +563,26 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, - - enc->first_packet = false; - #ifdef ENABLE_HEVC -- if (hevc) { -+ if (enc->codec == CODEC_HEVC) { - obs_extract_hevc_headers( - enc->packet->data, enc->packet->size, - &new_packet, &size, &enc->header, - &enc->header_size, &enc->sei, - &enc->sei_size); - } else --#else -- UNUSED_PARAMETER(hevc); - #endif -- { -+ if (enc->codec == CODEC_H264) { - obs_extract_avc_headers( - enc->packet->data, enc->packet->size, - &new_packet, &size, &enc->header, - &enc->header_size, &enc->sei, - &enc->sei_size); -+ } else if (enc->codec == CODEC_AV1) { -+ obs_extract_av1_headers(enc->packet->data, -+ enc->packet->size, -+ &new_packet, &size, -+ &enc->header, -+ &enc->header_size); - } - - da_copy_array(enc->buffer, new_packet, size); -@@ -587,14 +598,17 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, - packet->size = enc->buffer.num; - packet->type = OBS_ENCODER_VIDEO; - #ifdef ENABLE_HEVC -- if (hevc) { -+ if (enc->codec == CODEC_HEVC) { - packet->keyframe = - obs_hevc_keyframe(packet->data, packet->size); - } else - #endif -- { -+ if (enc->codec == CODEC_H264) { - packet->keyframe = - obs_avc_keyframe(packet->data, packet->size); -+ } else if (enc->codec == CODEC_AV1) { -+ packet->keyframe = -+ obs_av1_keyframe(packet->data, packet->size); - } - *received_packet = true; - } else { -@@ -610,58 +624,60 @@ fail: - return false; - } - --static bool h264_vaapi_encode(void *data, struct encoder_frame *frame, -- struct encoder_packet *packet, -- bool *received_packet) -+static void set_visible(obs_properties_t *ppts, const char *name, bool visible) - { -- return vaapi_encode_internal(data, frame, packet, received_packet, -- false); -+ obs_property_t *p = obs_properties_get(ppts, name); -+ obs_property_set_visible(p, visible); - } - --#ifdef ENABLE_HEVC --static bool hevc_vaapi_encode(void *data, struct encoder_frame *frame, -- struct encoder_packet *packet, -- bool *received_packet) -+static inline VAProfile vaapi_profile(enum codec_type codec) - { -- return vaapi_encode_internal(data, frame, packet, received_packet, -- true); --} -+ if (codec == CODEC_H264) { -+ return VAProfileH264ConstrainedBaseline; -+ } else if (codec == CODEC_AV1) { -+ return VAProfileAV1Profile0; -+#if ENABLE_HEVC -+ } else if (codec == CODEC_HEVC) { -+ return VAProfileHEVCMain; - #endif -- --static void set_visible(obs_properties_t *ppts, const char *name, bool visible) --{ -- obs_property_t *p = obs_properties_get(ppts, name); -- obs_property_set_visible(p, visible); -+ } -+ return VAProfileNone; - } - --static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) -+static inline const char *vaapi_default_device(enum codec_type codec) - { --#ifdef ENABLE_HEVC -- const char *device = hevc ? vaapi_get_hevc_default_device() -- : vaapi_get_h264_default_device(); --#else -- const char *const device = vaapi_get_h264_default_device(); -+ if (codec == CODEC_H264) { -+ return vaapi_get_h264_default_device(); -+ } else if (codec == CODEC_AV1) { -+ return vaapi_get_av1_default_device(); -+#if ENABLE_HEVC -+ } else if (codec == CODEC_HEVC) { -+ return vaapi_get_hevc_default_device(); - #endif -+ } -+ return NULL; -+} - -+static void vaapi_defaults_internal(obs_data_t *settings, enum codec_type codec) -+{ -+ const char *const device = vaapi_default_device(codec); - obs_data_set_default_string(settings, "vaapi_device", device); - #ifdef ENABLE_HEVC -- if (hevc) { -+ if (codec == CODEC_HEVC) - obs_data_set_default_int(settings, "profile", - FF_PROFILE_HEVC_MAIN); -- -- } else --#else -- UNUSED_PARAMETER(hevc); -+ else - #endif -- { -+ if (codec == CODEC_H264) - obs_data_set_default_int(settings, "profile", -- FF_PROFILE_H264_CONSTRAINED_BASELINE); -- } -- obs_data_set_default_int(settings, "level", 40); -+ FF_PROFILE_H264_HIGH); -+ else if (codec == CODEC_AV1) -+ obs_data_set_default_int(settings, "profile", -+ FF_PROFILE_AV1_MAIN); -+ obs_data_set_default_int(settings, "level", FF_LEVEL_UNKNOWN); - obs_data_set_default_int(settings, "bitrate", 2500); - obs_data_set_default_int(settings, "keyint_sec", 0); - obs_data_set_default_int(settings, "bf", 0); -- obs_data_set_default_int(settings, "rendermode", 0); - obs_data_set_default_int(settings, "qp", 20); - obs_data_set_default_int(settings, "maxrate", 0); - -@@ -670,12 +686,7 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) - if (!va_dpy) - return; - --#ifdef ENABLE_HEVC -- const VAProfile profile = hevc ? VAProfileHEVCMain -- : VAProfileH264ConstrainedBaseline; --#else -- const VAProfile profile = VAProfileH264ConstrainedBaseline; --#endif -+ const VAProfile profile = vaapi_profile(codec); - if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) - obs_data_set_default_string(settings, "rate_control", "CBR"); - else if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) -@@ -688,12 +699,17 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) - - static void h264_vaapi_defaults(obs_data_t *settings) - { -- vaapi_defaults_internal(settings, false); -+ vaapi_defaults_internal(settings, CODEC_H264); -+} -+ -+static void av1_vaapi_defaults(obs_data_t *settings) -+{ -+ vaapi_defaults_internal(settings, CODEC_AV1); - } - - static void hevc_vaapi_defaults(obs_data_t *settings) - { -- vaapi_defaults_internal(settings, true); -+ vaapi_defaults_internal(settings, CODEC_HEVC); - } - - static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, -@@ -729,6 +745,11 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, - goto fail; - profile = VAProfileH264High; - break; -+ case FF_PROFILE_AV1_MAIN: -+ if (!vaapi_display_av1_supported(va_dpy, device)) -+ goto fail; -+ profile = VAProfileAV1Profile0; -+ break; - #ifdef ENABLE_HEVC - case FF_PROFILE_HEVC_MAIN: - if (!vaapi_display_hevc_supported(va_dpy, device)) -@@ -744,7 +765,7 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, - } - - if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) -- obs_property_list_add_string(rc_p, "CBR (default)", "CBR"); -+ obs_property_list_add_string(rc_p, "CBR", "CBR"); - - if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) - obs_property_list_add_string(rc_p, "VBR", "VBR"); -@@ -752,6 +773,8 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, - if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CQP, device)) - obs_property_list_add_string(rc_p, "CQP", "CQP"); - -+ set_visible(ppts, "bf", vaapi_device_bframe_supported(profile, va_dpy)); -+ - fail: - vaapi_close_device(&drm_fd, va_dpy); - return true; -@@ -800,7 +823,7 @@ static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot, - return false; - } - --static obs_properties_t *vaapi_properties_internal(bool hevc) -+static obs_properties_t *vaapi_properties_internal(enum codec_type codec) - { - obs_properties_t *props = obs_properties_create(); - obs_property_t *list; -@@ -891,16 +914,17 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) - obs_module_text("Profile"), - OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); -- if (hevc) { -+ if (codec == CODEC_HEVC) { - obs_property_list_add_int(list, "Main", FF_PROFILE_HEVC_MAIN); - obs_property_list_add_int(list, "Main10", - FF_PROFILE_HEVC_MAIN_10); -- } else { -- obs_property_list_add_int(list, -- "Constrained Baseline (default)", -+ } else if (codec == CODEC_H264) { -+ obs_property_list_add_int(list, "Constrained Baseline", - FF_PROFILE_H264_CONSTRAINED_BASELINE); - obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN); - obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH); -+ } else if (codec == CODEC_AV1) { -+ obs_property_list_add_int(list, "Main", FF_PROFILE_AV1_MAIN); - } - - obs_property_set_modified_callback(list, vaapi_device_modified); -@@ -909,15 +933,33 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) - OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN); -- obs_property_list_add_int(list, "3.0", 30); -- obs_property_list_add_int(list, "3.1", 31); -- obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)", -- 40); -- obs_property_list_add_int(list, "4.1", 41); -- obs_property_list_add_int(list, "4.2", 42); -- obs_property_list_add_int(list, "5.0", 50); -- obs_property_list_add_int(list, "5.1", 51); -- obs_property_list_add_int(list, "5.2", 52); -+ if (codec == CODEC_H264) { -+ obs_property_list_add_int(list, "3.0", 30); -+ obs_property_list_add_int(list, "3.1", 31); -+ obs_property_list_add_int(list, "4.0", 40); -+ obs_property_list_add_int(list, "4.1", 41); -+ obs_property_list_add_int(list, "4.2", 42); -+ obs_property_list_add_int(list, "5.0", 50); -+ obs_property_list_add_int(list, "5.1", 51); -+ obs_property_list_add_int(list, "5.2", 52); -+ } else if (codec == CODEC_HEVC) { -+ obs_property_list_add_int(list, "3.0", 90); -+ obs_property_list_add_int(list, "3.1", 93); -+ obs_property_list_add_int(list, "4.0", 120); -+ obs_property_list_add_int(list, "4.1", 123); -+ obs_property_list_add_int(list, "5.0", 150); -+ obs_property_list_add_int(list, "5.1", 153); -+ obs_property_list_add_int(list, "5.2", 156); -+ } else if (codec == CODEC_AV1) { -+ obs_property_list_add_int(list, "3.0", 4); -+ obs_property_list_add_int(list, "3.1", 5); -+ obs_property_list_add_int(list, "4.0", 8); -+ obs_property_list_add_int(list, "4.1", 9); -+ obs_property_list_add_int(list, "5.0", 12); -+ obs_property_list_add_int(list, "5.1", 13); -+ obs_property_list_add_int(list, "5.2", 14); -+ obs_property_list_add_int(list, "5.3", 15); -+ } - - list = obs_properties_add_list(props, "rate_control", - obs_module_text("RateControl"), -@@ -942,6 +984,9 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) - 20, 1); - obs_property_int_set_suffix(p, " s"); - -+ obs_properties_add_int(props, "bf", obs_module_text("BFrames"), 0, 4, -+ 1); -+ - obs_properties_add_text(props, "ffmpeg_opts", - obs_module_text("FFmpegOpts"), - OBS_TEXT_DEFAULT); -@@ -952,14 +997,20 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) - static obs_properties_t *h264_vaapi_properties(void *unused) - { - UNUSED_PARAMETER(unused); -- return vaapi_properties_internal(false); -+ return vaapi_properties_internal(CODEC_H264); -+} -+ -+static obs_properties_t *av1_vaapi_properties(void *unused) -+{ -+ UNUSED_PARAMETER(unused); -+ return vaapi_properties_internal(CODEC_AV1); - } - - #ifdef ENABLE_HEVC - static obs_properties_t *hevc_vaapi_properties(void *unused) - { - UNUSED_PARAMETER(unused); -- return vaapi_properties_internal(true); -+ return vaapi_properties_internal(CODEC_HEVC); - } - #endif - -@@ -988,12 +1039,27 @@ struct obs_encoder_info h264_vaapi_encoder_info = { - .get_name = h264_vaapi_getname, - .create = h264_vaapi_create, - .destroy = vaapi_destroy, -- .encode = h264_vaapi_encode, -+ .encode = vaapi_encode, - .get_defaults = h264_vaapi_defaults, - .get_properties = h264_vaapi_properties, - .get_extra_data = vaapi_extra_data, - .get_sei_data = vaapi_sei_data, -- .get_video_info = h264_vaapi_video_info, -+ .get_video_info = vaapi_video_info, -+}; -+ -+struct obs_encoder_info av1_vaapi_encoder_info = { -+ .id = "av1_ffmpeg_vaapi", -+ .type = OBS_ENCODER_VIDEO, -+ .codec = "av1", -+ .get_name = av1_vaapi_getname, -+ .create = av1_vaapi_create, -+ .destroy = vaapi_destroy, -+ .encode = vaapi_encode, -+ .get_defaults = av1_vaapi_defaults, -+ .get_properties = av1_vaapi_properties, -+ .get_extra_data = vaapi_extra_data, -+ .get_sei_data = vaapi_sei_data, -+ .get_video_info = vaapi_video_info, - }; - - #ifdef ENABLE_HEVC -@@ -1004,11 +1070,11 @@ struct obs_encoder_info hevc_vaapi_encoder_info = { - .get_name = hevc_vaapi_getname, - .create = hevc_vaapi_create, - .destroy = vaapi_destroy, -- .encode = hevc_vaapi_encode, -+ .encode = vaapi_encode, - .get_defaults = hevc_vaapi_defaults, - .get_properties = hevc_vaapi_properties, - .get_extra_data = vaapi_extra_data, - .get_sei_data = vaapi_sei_data, -- .get_video_info = hevc_vaapi_video_info, -+ .get_video_info = vaapi_video_info, - }; - #endif -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c -index 7eb9a876d..981bb9c65 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg.c -@@ -47,6 +47,7 @@ extern struct obs_encoder_info aom_av1_encoder_info; - - #ifdef LIBAVUTIL_VAAPI_AVAILABLE - extern struct obs_encoder_info h264_vaapi_encoder_info; -+extern struct obs_encoder_info av1_vaapi_encoder_info; - #ifdef ENABLE_HEVC - extern struct obs_encoder_info hevc_vaapi_encoder_info; - #endif -@@ -337,6 +338,17 @@ static bool h264_vaapi_supported(void) - * that support H264. */ - return vaapi_get_h264_default_device() != NULL; - } -+static bool av1_vaapi_supported(void) -+{ -+ const AVCodec *vaenc = avcodec_find_encoder_by_name("av1_vaapi"); -+ -+ if (!vaenc) -+ return false; -+ -+ /* NOTE: If default device is NULL, it means there is no device -+ * that support AV1. */ -+ return vaapi_get_av1_default_device() != NULL; -+} - #ifdef ENABLE_HEVC - static bool hevc_vaapi_supported(void) - { -@@ -447,6 +459,13 @@ bool obs_module_load(void) - blog(LOG_INFO, "FFmpeg VAAPI H264 encoding not supported"); - } - -+ if (av1_vaapi_supported()) { -+ blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding supported"); -+ obs_register_encoder(&av1_vaapi_encoder_info); -+ } else { -+ blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding not supported"); -+ } -+ - #ifdef ENABLE_HEVC - if (hevc_vaapi_supported()) { - blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding supported"); -diff --git a/plugins/obs-ffmpeg/vaapi-utils.c b/plugins/obs-ffmpeg/vaapi-utils.c -index 4198ee59c..2ca7e468c 100644 ---- a/plugins/obs-ffmpeg/vaapi-utils.c -+++ b/plugins/obs-ffmpeg/vaapi-utils.c -@@ -185,6 +185,38 @@ bool vaapi_device_rc_supported(VAProfile profile, VADisplay dpy, uint32_t rc, - return false; - } - -+static bool vaapi_display_ep_bframe_supported(VAProfile profile, -+ VAEntrypoint entrypoint, -+ VADisplay dpy) -+{ -+ bool ret = false; -+ VAStatus va_status; -+ VAConfigAttrib attrib[1]; -+ attrib->type = VAConfigAttribEncMaxRefFrames; -+ -+ va_status = vaGetConfigAttributes(dpy, profile, entrypoint, attrib, 1); -+ -+ if (va_status == VA_STATUS_SUCCESS && -+ attrib->value != VA_ATTRIB_NOT_SUPPORTED) -+ return attrib->value >> 16; -+ -+ return false; -+} -+ -+bool vaapi_device_bframe_supported(VAProfile profile, VADisplay dpy) -+{ -+ bool ret = vaapi_display_ep_bframe_supported(profile, -+ VAEntrypointEncSlice, dpy); -+ if (ret) -+ return true; -+ ret = vaapi_display_ep_bframe_supported(profile, VAEntrypointEncSliceLP, -+ dpy); -+ if (ret) -+ return true; -+ -+ return false; -+} -+ - #define CHECK_PROFILE(ret, profile, va_dpy, device_path) \ - if (vaapi_display_ep_combo_supported(profile, VAEntrypointEncSlice, \ - va_dpy, device_path)) { \ -@@ -261,6 +293,61 @@ const char *vaapi_get_h264_default_device() - return default_h264_device; - } - -+bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path) -+{ -+ bool ret = false; -+ -+ CHECK_PROFILE(ret, VAProfileAV1Profile0, dpy, device_path); -+ -+ if (!ret) { -+ CHECK_PROFILE_LP(ret, VAProfileAV1Profile0, dpy, device_path); -+ } -+ -+ return ret; -+} -+ -+bool vaapi_device_av1_supported(const char *device_path) -+{ -+ bool ret = false; -+ VADisplay va_dpy; -+ -+ int drm_fd = -1; -+ -+ va_dpy = vaapi_open_device(&drm_fd, device_path, -+ "vaapi_device_av1_supported"); -+ if (!va_dpy) -+ return false; -+ -+ ret = vaapi_display_av1_supported(va_dpy, device_path); -+ -+ vaapi_close_device(&drm_fd, va_dpy); -+ -+ return ret; -+} -+ -+const char *vaapi_get_av1_default_device() -+{ -+ static const char *default_av1_device = NULL; -+ -+ if (!default_av1_device) { -+ bool ret = false; -+ char path[32] = "/dev/dri/renderD1"; -+ for (int i = 28;; i++) { -+ sprintf(path, "/dev/dri/renderD1%d", i); -+ if (access(path, F_OK) != 0) -+ break; -+ -+ ret = vaapi_device_av1_supported(path); -+ if (ret) { -+ default_av1_device = strdup(path); -+ break; -+ } -+ } -+ } -+ -+ return default_av1_device; -+} -+ - #ifdef ENABLE_HEVC - - bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path) -diff --git a/plugins/obs-ffmpeg/vaapi-utils.h b/plugins/obs-ffmpeg/vaapi-utils.h -index b90b23947..d458bad2c 100644 ---- a/plugins/obs-ffmpeg/vaapi-utils.h -+++ b/plugins/obs-ffmpeg/vaapi-utils.h -@@ -14,11 +14,16 @@ void vaapi_close_device(int *fd, VADisplay dpy); - - bool vaapi_device_rc_supported(VAProfile profile, VADisplay dpy, uint32_t rc, - const char *device_path); -+bool vaapi_device_bframe_supported(VAProfile profile, VADisplay dpy); - - bool vaapi_display_h264_supported(VADisplay dpy, const char *device_path); - bool vaapi_device_h264_supported(const char *device_path); - const char *vaapi_get_h264_default_device(void); - -+bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path); -+bool vaapi_device_av1_supported(const char *device_path); -+const char *vaapi_get_av1_default_device(void); -+ - #ifdef ENABLE_HEVC - bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path); - bool vaapi_device_hevc_supported(const char *device_path); \ No newline at end of file diff --git a/pkgs/apps/obs/default.nix b/pkgs/apps/obs/default.nix deleted file mode 100644 index 46f6420..0000000 --- a/pkgs/apps/obs/default.nix +++ /dev/null @@ -1,196 +0,0 @@ -{ config -, lib -, stdenv -, fetchFromGitHub -, addOpenGLRunpath -, cmake -, fdk_aac -, ffmpeg -, jansson -, libjack2 -, libxkbcommon -, libpthreadstubs -, libXdmcp -, qtbase -, qtsvg -, speex -, libv4l -, x264 -, curl -, wayland -, xorg -, pkg-config -, libvlc -, mbedtls -, wrapGAppsHook -, scriptingSupport ? true -, luajit -, swig4 -, python3 -, alsaSupport ? stdenv.isLinux -, alsa-lib -, pulseaudioSupport ? config.pulseaudio or stdenv.isLinux -, libpulseaudio -, pciutils -, pipewireSupport ? stdenv.isLinux -, pipewire -, libdrm -, libajantv2 -, librist -, libva -, srt -, qtwayland -, wrapQtAppsHook -, nlohmann_json -, asio -, websocketpp -, amf-headers -, libGL -, vulkan-loader -, decklinkSupport ? false -, blackmagic-desktop-video ? null -, libcef -, libdatachannel -, pkgs -, qrcodegencpp ? pkgs.callPackage ./qrcodegencpp.nix {} -, onevpl ? pkgs.callPackage ./onevpl.nix {} -}: -assert (!decklinkSupport || blackmagic-desktop-video!=null) || builtins.throw "decklinkSupport enabled but blackmagic-desktop-video is null"; -let - inherit (lib) optional optionals; -in -stdenv.mkDerivation rec { - pname = "obs-studio-amf"; - version = "30.0.2"; - src = fetchFromGitHub { - owner = "obsproject"; - repo = "obs-studio"; - rev = version; - sha256 = "sha256-8pX1kqibrtDIaE1+/Pey1A5bu6MwFTXLrBOah4rsF+4="; - fetchSubmodules = true; - }; - - env.NIX_CFLAGS_COMPILE = toString [ - "-Wno-error" - ]; - patches = [ - ./obs-amf-patch.patch # OBS AMF Patch - ./Enable-file-access-and-universal-access-for-file-URL.patch - ./fix-nix-plugin-path.patch - ./av1-vaapi.patch - ./ffmpeg61.patch - ]; - - nativeBuildInputs = [ - addOpenGLRunpath - cmake - pkg-config - wrapGAppsHook - wrapQtAppsHook - ] - ++ optional scriptingSupport swig4; - - buildInputs = [ - amf-headers - websocketpp - asio - nlohmann_json - curl - fdk_aac - ffmpeg - jansson - libcef - libjack2 - libv4l - libxkbcommon - libpthreadstubs - libXdmcp - qtbase - qtsvg - speex - wayland - x264 - libvlc - mbedtls - pciutils - libajantv2 - librist - libva - srt - qtwayland - libdatachannel - qrcodegencpp - onevpl - ] - ++ optionals scriptingSupport [ luajit python3 ] - ++ optional alsaSupport alsa-lib - ++ optional pulseaudioSupport libpulseaudio - ++ optionals pipewireSupport [ pipewire libdrm ]; - - # Copied from the obs-linuxbrowser - postUnpack = '' - cp -rs ${libcef}/share/cef cef - ''; - - # obs attempts to dlopen libobs-opengl, it fails unless we make sure - # DL_OPENGL is an explicit path. Not sure if there's a better way - # to handle this. - cmakeFlags = [ - "-DOBS_VERSION_OVERRIDE=${version}" - "-Wno-dev" # kill dev warnings that are useless for packaging - # Add support for browser source - "-DBUILD_BROWSER=ON" - "-DCEF_ROOT_DIR=../../cef" - "-DENABLE_JACK=ON" - ]; - - dontWrapGApps = true; - preFixup = let - wrapperLibraries = [ - xorg.libX11 - libvlc - ] ++ optionals decklinkSupport [ - blackmagic-desktop-video - ]; - in - '' - #Remove libs from libcef, they are symlinks and can't be patchelfed - rm $out/lib/obs-plugins/libcef.so $out/lib/obs-plugins/libEGL.so $out/lib/obs-plugins/libGLESv2.so $out/lib/obs-plugins/libvk_swiftshader.so - - #Suffix on libgl and vulkan-loader so it can be overriden by helper scripts from amdgpu-pro - qtWrapperArgs+=( - --prefix LD_LIBRARY_PATH : "$out/lib:${lib.makeLibraryPath wrapperLibraries}" - --suffix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ libGL vulkan-loader ]}" - ''${gappsWrapperArgs[@]} - ) - ''; - - postFixup = lib.optionalString stdenv.isLinux '' - addOpenGLRunpath $out/lib/lib*.so - addOpenGLRunpath $out/lib/obs-plugins/*.so - - ##Symlink libcef related things after patchelfing - ln -s ${libcef}/share/cef/Release/libcef.so $out/lib/obs-plugins/libcef.so - - #OBS seems to need those to be from libcef for hardware acceleration (at least on AMD card) - ln -s ${libcef}/share/cef/Release/libEGL.so $out/lib/obs-plugins/libEGL.so - ln -s ${libcef}/share/cef/Release/libGLESv2.so $out/lib/obs-plugins/libGLESv2.so - - #Doesn't seem needed but added anyway - ln -s ${libcef}/share/cef/Release/libvk_swiftshader.so $out/lib/obs-plugins/libvk_swiftshader.so - ''; - - meta = with lib; { - description = "Free and open source software for video recording and live streaming. With AMD AMF"; - longDescription = '' - This project is a rewrite of what was formerly known as "Open Broadcaster - Software", software originally designed for recording and streaming live - video content, efficiently - ''; - homepage = "https://obsproject.com"; - maintainers = with maintainers; [ ]; - license = licenses.gpl2Plus; - platforms = [ "x86_64-linux" ]; - mainProgram = "obs"; - }; -} \ No newline at end of file diff --git a/pkgs/apps/obs/ffmpeg61.patch b/pkgs/apps/obs/ffmpeg61.patch deleted file mode 100644 index e697952..0000000 --- a/pkgs/apps/obs/ffmpeg61.patch +++ /dev/null @@ -1,286 +0,0 @@ -From 7ed9b1f3a6b5e73a39daf906c8e8c19e93fce4b4 Mon Sep 17 00:00:00 2001 -From: Stephen Seo -Date: Wed, 29 Nov 2023 22:06:09 +0900 -Subject: [PATCH 1/4] deps/media-playback: Use new (nb_)coded_side_data FFmpeg - 6.1 API - -Fixes for using FFmpeg 6.1 due to deprecations. Uses `#if` macros to -allow builds for using older versions of FFmpeg. - -The change in deps/media-playback/media-playback/decode.c is due to -FFmpeg moving "side_data" into AVCodecParameters which is mentioned in -commit [1] in FFmpeg's repository. - -In summary of the "side_data" change, AVStream.side_data is deprecated -and replaced with AVStream.codecpar->coded_side_data, and -AVStream.nb_side_data is replaced with -AVStream.codecpar->nb_coded_side_data. - -[1]: avcodec/codec_par: add side data to AVCodecParameters -https://github.com/FFmpeg/FFmpeg/commit/21d7cc6fa9a26e94965fa71b25655d07568450fe ---- - deps/media-playback/media-playback/decode.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/deps/media-playback/media-playback/decode.c b/deps/media-playback/media-playback/decode.c -index 55b91c140ace4..40853f171bde7 100644 ---- a/deps/media-playback/media-playback/decode.c -+++ b/deps/media-playback/media-playback/decode.c -@@ -114,8 +114,14 @@ static uint16_t get_max_luminance(const AVStream *stream) - { - uint32_t max_luminance = 0; - -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - for (int i = 0; i < stream->nb_side_data; i++) { - const AVPacketSideData *const sd = &stream->side_data[i]; -+#else -+ for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) { -+ const AVPacketSideData *const sd = -+ &stream->codecpar->coded_side_data[i]; -+#endif - switch (sd->type) { - case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: { - const AVMasteringDisplayMetadata *mastering = - -From 92fc9f69ccff2cb12bb8ef877e9238f5d46588a8 Mon Sep 17 00:00:00 2001 -From: Stephen Seo -Date: Wed, 29 Nov 2023 22:08:42 +0900 -Subject: [PATCH 2/4] deps/media-playback: In check for key-frame, use new - FFmpeg 6.1 API - -Fixes for using FFmpeg 6.1 due to deprecations. Uses `#if` macros to -allow builds for using older versions of FFmpeg. - -AVFrame.key_frame was replaced with a flag in AVFrame.flags. The commit -adding the flag is [1] in FFmpeg's repository, and the deprecation is in -commit [2]. - -In summary of the "key_frame" change, AVFrame.key_frame is deprecated, -and AVFrame.flags indicates with a bit flag if it is a key frame (with -the enum/defined AV_FRAME_FLAG_KEY). - -[1]: avutil/frame: add a keyframe flag to AVFrame -https://github.com/FFmpeg/FFmpeg/commit/cc11191fda0471017b03c1434d6d8cb79f6914e5 - -[2]: avutil/frame: deprecate key_frame -https://github.com/FFmpeg/FFmpeg/commit/3e06f6f04020bef32fa42bc9d7f96e76a46453aa ---- - deps/media-playback/media-playback/media.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c -index 566eb9e35c9ef..07b040dd8235c 100644 ---- a/deps/media-playback/media-playback/media.c -+++ b/deps/media-playback/media-playback/media.c -@@ -504,7 +504,12 @@ void mp_media_next_video(mp_media_t *m, bool preload) - } - - if (!m->is_local_file && !d->got_first_keyframe) { -+ -+#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(58, 29, 100) - if (!f->key_frame) -+#else -+ if (!(f->flags & AV_FRAME_FLAG_KEY)) -+#endif - return; - - d->got_first_keyframe = true; - -From ed1e0795acde8349ab18b631c545f56e5a3acb9d Mon Sep 17 00:00:00 2001 -From: Stephen Seo -Date: Wed, 29 Nov 2023 20:07:10 +0900 -Subject: [PATCH 3/4] libobs: Fence off unnecessary code due to FFmpeg v6.1 - changes - -Fixes for using FFmpeg 6.1 due to deprecations. Uses `#if` macros to -allow builds for using older versions of FFmpeg. - -This commit prevents obs from using the "fenced" code if using FFmpeg -6.1, since in FFmpeg commit [1] the "side_data" is added to -`AVCodecParameters`, and therefore the existing/following -`avcodec_parameters_copy(...)` will account for the metadata. - -[1]: avcodec/codec_par: add side data to AVCodecParameters -https://github.com/FFmpeg/FFmpeg/commit/21d7cc6fa9a26e94965fa71b25655d07568450fe ---- - libobs/media-io/media-remux.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/libobs/media-io/media-remux.c b/libobs/media-io/media-remux.c -index 7d5eead200012..827d4e59b18ed 100644 ---- a/libobs/media-io/media-remux.c -+++ b/libobs/media-io/media-remux.c -@@ -91,6 +91,7 @@ static inline bool init_output(media_remux_job_t job, const char *out_filename) - return false; - } - -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - #if FF_API_BUFFER_SIZE_T - int content_size; - #else -@@ -125,6 +126,7 @@ static inline bool init_output(media_remux_job_t job, const char *out_filename) - mastering_size); - } - } -+#endif - - ret = avcodec_parameters_copy(out_stream->codecpar, - in_stream->codecpar); - -From 6d0381f98ce0a5624901b0042d624ea972a10c2b Mon Sep 17 00:00:00 2001 -From: Stephen Seo -Date: Wed, 29 Nov 2023 20:09:08 +0900 -Subject: [PATCH 4/4] obs-ffmpeg: Use new side-data FFmpeg 6.1 API - -Fixes for using FFmpeg 6.1 due to deprecations. Uses `#if` macros to -allow builds for using older versions of FFmpeg. - -This commit replaces usage of `av_stream_add_side_data(...)` with -`av_packet_side_data_add(...)`, as the former was deprecated in favor of -the latter. - -The FFmpeg commit that deprecated `av_stream_add_side_data(...)` is [1]. - -The FFmpeg commit that introduced `av_packet_side_data_add(...)` is [2]. - -Note that the deprecation commit is after the new API function. The -commit in between [3] appears to be changes that migrates to the usage -of the new API function. - -[1]: avformat/avformat: use the side data from AVStream.codecpar -https://github.com/FFmpeg/FFmpeg/commit/5432d2aacad5fa7420fe2d9369ed061d521e92d6 - -[2]: avcodec/packet: add generic side data helpers -https://github.com/FFmpeg/FFmpeg/commit/74279227dd28d01b447edb8e617a545982171c2c - -[3]: avcodec/codec_par: add side data to AVCodecParameters -https://github.com/FFmpeg/FFmpeg/commit/21d7cc6fa9a26e94965fa71b25655d07568450fe ---- - plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c | 16 ++++++++++++++++ - plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c | 16 ++++++++++++++++ - plugins/obs-ffmpeg/obs-ffmpeg-output.c | 16 ++++++++++++++++ - 3 files changed, 48 insertions(+) - -diff --git a/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c b/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c -index 740b60e5bf46e..8fb84aa7c4e0b 100644 ---- a/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c -+++ b/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c -@@ -498,9 +498,17 @@ static void create_video_stream(struct ffmpeg_mux *ffm) - av_content_light_metadata_alloc(&content_size); - content->MaxCLL = max_luminance; - content->MaxFALL = max_luminance; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(ffm->video_stream, - AV_PKT_DATA_CONTENT_LIGHT_LEVEL, - (uint8_t *)content, content_size); -+#else -+ av_packet_side_data_add( -+ &ffm->video_stream->codecpar->coded_side_data, -+ &ffm->video_stream->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_CONTENT_LIGHT_LEVEL, (uint8_t *)content, -+ content_size, 0); -+#endif - - AVMasteringDisplayMetadata *const mastering = - av_mastering_display_metadata_alloc(); -@@ -516,10 +524,18 @@ static void create_video_stream(struct ffmpeg_mux *ffm) - mastering->max_luminance = av_make_q(max_luminance, 1); - mastering->has_primaries = 1; - mastering->has_luminance = 1; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(ffm->video_stream, - AV_PKT_DATA_MASTERING_DISPLAY_METADATA, - (uint8_t *)mastering, - sizeof(*mastering)); -+#else -+ av_packet_side_data_add( -+ &ffm->video_stream->codecpar->coded_side_data, -+ &ffm->video_stream->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_MASTERING_DISPLAY_METADATA, -+ (uint8_t *)mastering, sizeof(*mastering), 0); -+#endif - } - - if (ffm->output->oformat->flags & AVFMT_GLOBALHEADER) -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c b/plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c -index f33ee77365274..a56dd91bcc38e 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg-mpegts.c -@@ -168,9 +168,17 @@ static bool create_video_stream(struct ffmpeg_output *stream, - av_content_light_metadata_alloc(&content_size); - content->MaxCLL = hdr_nominal_peak_level; - content->MaxFALL = hdr_nominal_peak_level; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(data->video, - AV_PKT_DATA_CONTENT_LIGHT_LEVEL, - (uint8_t *)content, content_size); -+#else -+ av_packet_side_data_add( -+ &data->video->codecpar->coded_side_data, -+ &data->video->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_CONTENT_LIGHT_LEVEL, (uint8_t *)content, -+ content_size, 0); -+#endif - - AVMasteringDisplayMetadata *const mastering = - av_mastering_display_metadata_alloc(); -@@ -186,10 +194,18 @@ static bool create_video_stream(struct ffmpeg_output *stream, - mastering->max_luminance = av_make_q(hdr_nominal_peak_level, 1); - mastering->has_primaries = 1; - mastering->has_luminance = 1; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(data->video, - AV_PKT_DATA_MASTERING_DISPLAY_METADATA, - (uint8_t *)mastering, - sizeof(*mastering)); -+#else -+ av_packet_side_data_add( -+ &data->video->codecpar->coded_side_data, -+ &data->video->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_MASTERING_DISPLAY_METADATA, -+ (uint8_t *)mastering, sizeof(*mastering), 0); -+#endif - } - context = avcodec_alloc_context3(NULL); - context->codec_type = codec->type; -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c -index ec02b59cda9d8..c7786153392e5 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c -@@ -213,9 +213,17 @@ static bool create_video_stream(struct ffmpeg_data *data) - av_content_light_metadata_alloc(&content_size); - content->MaxCLL = hdr_nominal_peak_level; - content->MaxFALL = hdr_nominal_peak_level; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(data->video, - AV_PKT_DATA_CONTENT_LIGHT_LEVEL, - (uint8_t *)content, content_size); -+#else -+ av_packet_side_data_add( -+ &data->video->codecpar->coded_side_data, -+ &data->video->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_CONTENT_LIGHT_LEVEL, (uint8_t *)content, -+ content_size, 0); -+#endif - - AVMasteringDisplayMetadata *const mastering = - av_mastering_display_metadata_alloc(); -@@ -231,10 +239,18 @@ static bool create_video_stream(struct ffmpeg_data *data) - mastering->max_luminance = av_make_q(hdr_nominal_peak_level, 1); - mastering->has_primaries = 1; - mastering->has_luminance = 1; -+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102) - av_stream_add_side_data(data->video, - AV_PKT_DATA_MASTERING_DISPLAY_METADATA, - (uint8_t *)mastering, - sizeof(*mastering)); -+#else -+ av_packet_side_data_add( -+ &data->video->codecpar->coded_side_data, -+ &data->video->codecpar->nb_coded_side_data, -+ AV_PKT_DATA_MASTERING_DISPLAY_METADATA, -+ (uint8_t *)mastering, sizeof(*mastering), 0); -+#endif - } - - closest_format = data->config.format; \ No newline at end of file diff --git a/pkgs/apps/obs/fix-nix-plugin-path.patch b/pkgs/apps/obs/fix-nix-plugin-path.patch deleted file mode 100644 index baf4510..0000000 --- a/pkgs/apps/obs/fix-nix-plugin-path.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/cmake/Modules/ObsDefaults_Linux.cmake b/cmake/Modules/ObsDefaults_Linux.cmake -index d1e58a083..a03c6b98e 100644 ---- a/cmake/Modules/ObsDefaults_Linux.cmake -+++ b/cmake/Modules/ObsDefaults_Linux.cmake -@@ -76,7 +76,7 @@ macro(setup_obs_project) - set(OBS_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/") - set(OBS_DATA_PATH "${OBS_DATA_DESTINATION}") - -- set(OBS_SCRIPT_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/${OBS_SCRIPT_PLUGIN_DESTINATION}") -+ set(OBS_SCRIPT_PLUGIN_PATH "${OBS_SCRIPT_PLUGIN_DESTINATION}") - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${OBS_LIBRARY_DESTINATION}") - else() - set(OBS_EXECUTABLE_DESTINATION "bin/${_ARCH_SUFFIX}bit") -diff --git a/libobs/obs-nix.c b/libobs/obs-nix.c -index b006a5598..531655eb3 100644 ---- a/libobs/obs-nix.c -+++ b/libobs/obs-nix.c -@@ -56,7 +56,7 @@ const char *get_module_extension(void) - #define FLATPAK_PLUGIN_PATH "/app/plugins" - - static const char *module_bin[] = { -- OBS_INSTALL_PREFIX "/" OBS_PLUGIN_DESTINATION, -+ OBS_PLUGIN_DESTINATION, - "../../obs-plugins/" BIT_STRING, - FLATPAK_PLUGIN_PATH "/" OBS_PLUGIN_DESTINATION, - }; diff --git a/pkgs/apps/obs/obs-amf-patch.patch b/pkgs/apps/obs/obs-amf-patch.patch deleted file mode 100644 index a7f054f..0000000 --- a/pkgs/apps/obs/obs-amf-patch.patch +++ /dev/null @@ -1,649 +0,0 @@ -diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt -index 04530ef39..51409f413 100644 ---- a/plugins/obs-ffmpeg/CMakeLists.txt -+++ b/plugins/obs-ffmpeg/CMakeLists.txt -@@ -103,10 +103,12 @@ if(OS_WINDOWS) - target_sources(obs-ffmpeg PRIVATE obs-nvenc-helpers.c obs-nvenc.c obs-nvenc.h obs-ffmpeg.rc texture-amf-opts.hpp - texture-amf.cpp) - elseif(OS_LINUX OR OS_FREEBSD) -+ add_subdirectory(obs-amf-test) -+ - find_package(Libva REQUIRED) - find_package(Libpci REQUIRED) - -- target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h) -+ target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h texture-amf.cpp) - target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm Libpci::pci) - endif() - -diff --git a/plugins/obs-ffmpeg/cmake/legacy.cmake b/plugins/obs-ffmpeg/cmake/legacy.cmake -index 4cc75b341..3319e8039 100644 ---- a/plugins/obs-ffmpeg/cmake/legacy.cmake -+++ b/plugins/obs-ffmpeg/cmake/legacy.cmake -@@ -107,9 +107,10 @@ if(OS_WINDOWS) - obs-ffmpeg.rc) - - elseif(OS_POSIX AND NOT OS_MACOS) -+ add_subdirectory(obs-amf-test) - find_package(Libva REQUIRED) - find_package(Libpci REQUIRED) -- target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h) -+ target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h texture-amf.cpp) - target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm LIBPCI::LIBPCI) - endif() - -diff --git a/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt b/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt -index 6221c69df..13068f813 100644 ---- a/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt -+++ b/plugins/obs-ffmpeg/obs-amf-test/CMakeLists.txt -@@ -7,9 +7,14 @@ find_package(AMF 1.4.29 REQUIRED) - add_executable(obs-amf-test) - add_executable(OBS::amf-test ALIAS obs-amf-test) - --target_sources(obs-amf-test PRIVATE obs-amf-test.cpp) --target_link_libraries(obs-amf-test PRIVATE OBS::COMutils AMF::AMF d3d11 dxgi dxguid) -- -+if(OS_WINDOWS) -+ target_sources(obs-amf-test PRIVATE obs-amf-test.cpp) -+ target_link_libraries(obs-amf-test PRIVATE OBS::COMutils AMF::AMF d3d11 dxgi dxguid) -+elseif(OS_POSIX AND NOT OS_MACOS) -+ find_package(Vulkan REQUIRED) -+ target_sources(obs-amf-test PRIVATE obs-amf-test-linux.cpp) -+ target_link_libraries(obs-amf-test dl Vulkan::Vulkan AMF::AMF) -+endif() - # cmake-format: off - set_target_properties_obs(obs-amf-test PROPERTIES FOLDER plugins/obs-ffmpeg) - # cmake-format: on -diff --git a/plugins/obs-ffmpeg/obs-amf-test/cmake/legacy.cmake b/plugins/obs-ffmpeg/obs-amf-test/cmake/legacy.cmake -index e00cef1cf..6620e359d 100644 ---- a/plugins/obs-ffmpeg/obs-amf-test/cmake/legacy.cmake -+++ b/plugins/obs-ffmpeg/obs-amf-test/cmake/legacy.cmake -@@ -6,9 +6,14 @@ find_package(AMF 1.4.29 REQUIRED) - - target_include_directories(obs-amf-test PRIVATE ${CMAKE_SOURCE_DIR}/libobs) - --target_sources(obs-amf-test PRIVATE obs-amf-test.cpp) --target_link_libraries(obs-amf-test d3d11 dxgi dxguid AMF::AMF) -- -+if(OS_WINDOWS) -+ target_sources(obs-amf-test PRIVATE obs-amf-test.cpp) -+ target_link_libraries(obs-amf-test d3d11 dxgi dxguid AMF::AMF) -+elseif(OS_POSIX AND NOT OS_MACOS) -+ find_package(Vulkan REQUIRED) -+ target_sources(obs-amf-test PRIVATE obs-amf-test-linux.cpp) -+ target_link_libraries(obs-amf-test dl Vulkan::Vulkan AMF::AMF) -+endif() - set_target_properties(obs-amf-test PROPERTIES FOLDER "plugins/obs-ffmpeg") - - setup_binary_target(obs-amf-test) -diff --git a/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp b/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp -new file mode 100644 -index 000000000..db437d851 ---- /dev/null -+++ b/plugins/obs-ffmpeg/obs-amf-test/obs-amf-test-linux.cpp -@@ -0,0 +1,140 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+using namespace amf; -+ -+struct adapter_caps { -+ bool is_amd = false; -+ bool supports_avc = false; -+ bool supports_hevc = false; -+ bool supports_av1 = false; -+}; -+ -+static AMFFactory *amf_factory = nullptr; -+static std::map adapter_info; -+ -+static bool has_encoder(AMFContextPtr &amf_context, const wchar_t *encoder_name) -+{ -+ AMFComponentPtr encoder; -+ AMF_RESULT res = amf_factory->CreateComponent(amf_context, encoder_name, -+ &encoder); -+ return res == AMF_OK; -+} -+ -+static bool get_adapter_caps(uint32_t adapter_idx) -+{ -+ if (adapter_idx) -+ return false; -+ -+ adapter_caps &caps = adapter_info[adapter_idx]; -+ -+ AMF_RESULT res; -+ AMFContextPtr amf_context; -+ res = amf_factory->CreateContext(&amf_context); -+ if (res != AMF_OK) -+ return true; -+ -+ AMFContext1 *context1 = NULL; -+ res = amf_context->QueryInterface(AMFContext1::IID(), -+ (void **)&context1); -+ if (res != AMF_OK) -+ return false; -+ res = context1->InitVulkan(nullptr); -+ context1->Release(); -+ if (res != AMF_OK) -+ return false; -+ -+ caps.is_amd = true; -+ caps.supports_avc = has_encoder(amf_context, AMFVideoEncoderVCE_AVC); -+ caps.supports_hevc = has_encoder(amf_context, AMFVideoEncoder_HEVC); -+ caps.supports_av1 = has_encoder(amf_context, AMFVideoEncoder_AV1); -+ -+ return true; -+} -+ -+int main(void) -+try { -+ AMF_RESULT res; -+ VkResult vkres; -+ -+ VkApplicationInfo app_info = {}; -+ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; -+ app_info.pApplicationName = "obs-amf-test"; -+ app_info.apiVersion = VK_API_VERSION_1_2; -+ -+ VkInstanceCreateInfo info = {}; -+ info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; -+ info.pApplicationInfo = &app_info; -+ -+ VkInstance instance; -+ vkres = vkCreateInstance(&info, nullptr, &instance); -+ if (vkres != VK_SUCCESS) -+ throw "Failed to initialize Vulkan"; -+ -+ uint32_t device_count; -+ vkres = vkEnumeratePhysicalDevices(instance, &device_count, nullptr); -+ if (vkres != VK_SUCCESS || !device_count) -+ throw "Failed to enumerate Vulkan devices"; -+ -+ VkPhysicalDevice *devices = new VkPhysicalDevice[device_count]; -+ vkres = vkEnumeratePhysicalDevices(instance, &device_count, devices); -+ if (vkres != VK_SUCCESS) -+ throw "Failed to enumerate Vulkan devices"; -+ -+ VkPhysicalDeviceDriverProperties driver_props = {}; -+ driver_props.sType = -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; -+ VkPhysicalDeviceProperties2 device_props = {}; -+ device_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; -+ device_props.pNext = &driver_props; -+ vkGetPhysicalDeviceProperties2(devices[0], &device_props); -+ -+ if (strcmp(driver_props.driverName, "AMD proprietary driver")) -+ throw "Not running AMD proprietary driver"; -+ -+ vkDestroyInstance(instance, nullptr); -+ -+ /* --------------------------------------------------------- */ -+ /* try initializing amf, I guess */ -+ -+ void *amf_module = dlopen(AMF_DLL_NAMEA, RTLD_LAZY); -+ if (!amf_module) -+ throw "Failed to load AMF lib"; -+ -+ auto init = (AMFInit_Fn)dlsym(amf_module, AMF_INIT_FUNCTION_NAME); -+ if (!init) -+ throw "Failed to get init func"; -+ -+ res = init(AMF_FULL_VERSION, &amf_factory); -+ if (res != AMF_OK) -+ throw "AMFInit failed"; -+ -+ uint32_t idx = 0; -+ while (get_adapter_caps(idx++)) -+ ; -+ -+ for (auto &[idx, caps] : adapter_info) { -+ printf("[%u]\n", idx); -+ printf("is_amd=%s\n", caps.is_amd ? "true" : "false"); -+ printf("supports_avc=%s\n", -+ caps.supports_avc ? "true" : "false"); -+ printf("supports_hevc=%s\n", -+ caps.supports_hevc ? "true" : "false"); -+ printf("supports_av1=%s\n", -+ caps.supports_av1 ? "true" : "false"); -+ } -+ -+ return 0; -+} catch (const char *text) { -+ printf("[error]\nstring=%s\n", text); -+ return 0; -+} -diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c -index 7eb9a876d..7b5c9bdc9 100644 ---- a/plugins/obs-ffmpeg/obs-ffmpeg.c -+++ b/plugins/obs-ffmpeg/obs-ffmpeg.c -@@ -355,6 +355,9 @@ static bool hevc_vaapi_supported(void) - #ifdef _WIN32 - extern void obs_nvenc_load(bool h264, bool hevc, bool av1); - extern void obs_nvenc_unload(void); -+#endif -+ -+#if defined(_WIN32) || defined(__linux__) - extern void amf_load(void); - extern void amf_unload(void); - #endif -@@ -429,7 +432,7 @@ bool obs_module_load(void) - #endif - } - --#ifdef _WIN32 -+#if defined(_WIN32) || defined(__linux__) - amf_load(); - #endif - -@@ -470,8 +473,11 @@ void obs_module_unload(void) - obs_ffmpeg_unload_logging(); - #endif - --#ifdef _WIN32 -+#if defined(_WIN32) || defined(__linux__) - amf_unload(); -+#endif -+ -+#ifdef _WIN32 - obs_nvenc_unload(); - #endif - } -diff --git a/plugins/obs-ffmpeg/texture-amf-opts.hpp b/plugins/obs-ffmpeg/texture-amf-opts.hpp -index b1c37d200..d28e3f77e 100644 ---- a/plugins/obs-ffmpeg/texture-amf-opts.hpp -+++ b/plugins/obs-ffmpeg/texture-amf-opts.hpp -@@ -321,7 +321,7 @@ static void amf_apply_opt(amf_base *enc, obs_option *opt) - val = atoi(opt->value); - } - -- os_utf8_to_wcs(opt->name, 0, wname, _countof(wname)); -+ os_utf8_to_wcs(opt->name, 0, wname, amf_countof(wname)); - if (is_bool) { - bool bool_val = (bool)val; - set_amf_property(enc, wname, bool_val); -diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp -index 7f45a8cc9..2c0b44c4e 100644 ---- a/plugins/obs-ffmpeg/texture-amf.cpp -+++ b/plugins/obs-ffmpeg/texture-amf.cpp -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -18,6 +19,7 @@ - #include - #include - -+#ifdef _WIN32 - #include - #include - #include -@@ -25,6 +27,8 @@ - #include - #include - #include -+#endif -+ - #include - #include - #include -@@ -55,8 +59,10 @@ struct amf_error { - - struct handle_tex { - uint32_t handle; -+#ifdef _WIN32 - ComPtr tex; - ComPtr km; -+#endif - }; - - struct adapter_caps { -@@ -72,7 +78,7 @@ static std::map caps; - static bool h264_supported = false; - static AMFFactory *amf_factory = nullptr; - static AMFTrace *amf_trace = nullptr; --static HMODULE amf_module = nullptr; -+static void *amf_module = nullptr; - static uint64_t amf_version = 0; - - /* ========================================================================= */ -@@ -121,9 +127,11 @@ struct amf_base { - virtual void init() = 0; - }; - --using d3dtex_t = ComPtr; - using buf_t = std::vector; - -+#ifdef _WIN32 -+using d3dtex_t = ComPtr; -+ - struct amf_texencode : amf_base, public AMFSurfaceObserver { - volatile bool destroying = false; - -@@ -160,6 +168,7 @@ struct amf_texencode : amf_base, public AMFSurfaceObserver { - throw amf_error("InitDX11 failed", res); - } - }; -+#endif - - struct amf_fallback : amf_base, public AMFSurfaceObserver { - volatile bool destroying = false; -@@ -187,9 +196,21 @@ struct amf_fallback : amf_base, public AMFSurfaceObserver { - - void init() override - { -+#if defined(_WIN32) - AMF_RESULT res = amf_context->InitDX11(nullptr, AMF_DX11_1); - if (res != AMF_OK) - throw amf_error("InitDX11 failed", res); -+#elif defined(__linux__) -+ AMFContext1 *context1 = NULL; -+ AMF_RESULT res = amf_context->QueryInterface( -+ AMFContext1::IID(), (void **)&context1); -+ if (res != AMF_OK) -+ throw amf_error("CreateContext1 failed", res); -+ res = context1->InitVulkan(nullptr); -+ context1->Release(); -+ if (res != AMF_OK) -+ throw amf_error("InitVulkan failed", res); -+#endif - } - }; - -@@ -231,13 +252,18 @@ static void set_amf_property(amf_base *enc, const wchar_t *name, const T &value) - : (enc->codec == amf_codec_type::HEVC) \ - ? AMF_VIDEO_ENCODER_HEVC_##name \ - : AMF_VIDEO_ENCODER_AV1_##name) -+#define get_opt_name_enum(name) \ -+ ((enc->codec == amf_codec_type::AVC) ? (int)AMF_VIDEO_ENCODER_##name \ -+ : (enc->codec == amf_codec_type::HEVC) \ -+ ? (int)AMF_VIDEO_ENCODER_HEVC_##name \ -+ : (int)AMF_VIDEO_ENCODER_AV1_##name) - #define set_opt(name, value) set_amf_property(enc, get_opt_name(name), value) - #define get_opt(name, value) get_amf_property(enc, get_opt_name(name), value) - #define set_avc_opt(name, value) set_avc_property(enc, name, value) - #define set_hevc_opt(name, value) set_hevc_property(enc, name, value) - #define set_av1_opt(name, value) set_av1_property(enc, name, value) - #define set_enum_opt(name, value) \ -- set_amf_property(enc, get_opt_name(name), get_opt_name(name##_##value)) -+ set_amf_property(enc, get_opt_name(name), get_opt_name_enum(name##_##value)) - #define set_avc_enum(name, value) \ - set_avc_property(enc, name, AMF_VIDEO_ENCODER_##name##_##value) - #define set_hevc_enum(name, value) \ -@@ -248,6 +274,7 @@ static void set_amf_property(amf_base *enc, const wchar_t *name, const T &value) - /* ------------------------------------------------------------------------- */ - /* Implementation */ - -+#ifdef _WIN32 - static HMODULE get_lib(const char *lib) - { - HMODULE mod = GetModuleHandleA(lib); -@@ -394,6 +421,7 @@ static void get_tex_from_handle(amf_texencode *enc, uint32_t handle, - *km_out = km.Detach(); - *tex_out = tex.Detach(); - } -+#endif - - static constexpr amf_int64 macroblock_size = 16; - -@@ -510,7 +538,7 @@ static void convert_to_encoder_packet(amf_base *enc, AMFDataPtr &data, - enc->packet_data = AMFBufferPtr(data); - data->GetProperty(L"PTS", &packet->pts); - -- const wchar_t *get_output_type; -+ const wchar_t *get_output_type = NULL; - switch (enc->codec) { - case amf_codec_type::AVC: - get_output_type = AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE; -@@ -644,6 +672,7 @@ static void amf_encode_base(amf_base *enc, AMFSurface *amf_surf, - static bool amf_encode_tex(void *data, uint32_t handle, int64_t pts, - uint64_t lock_key, uint64_t *next_key, - encoder_packet *packet, bool *received_packet) -+#ifdef _WIN32 - try { - amf_texencode *enc = (amf_texencode *)data; - ID3D11DeviceContext *context = enc->context; -@@ -720,6 +749,18 @@ try { - *received_packet = false; - return false; - } -+#else -+{ -+ UNUSED_PARAMETER(data); -+ UNUSED_PARAMETER(handle); -+ UNUSED_PARAMETER(pts); -+ UNUSED_PARAMETER(lock_key); -+ UNUSED_PARAMETER(next_key); -+ UNUSED_PARAMETER(packet); -+ UNUSED_PARAMETER(received_packet); -+ return false; -+} -+#endif - - static buf_t alloc_buf(amf_fallback *enc) - { -@@ -1184,6 +1225,7 @@ static const char *amf_avc_get_name(void *) - - static inline int get_avc_preset(amf_base *enc, const char *preset) - { -+ UNUSED_PARAMETER(enc); - if (astrcmpi(preset, "quality") == 0) - return AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY; - else if (astrcmpi(preset, "speed") == 0) -@@ -1298,7 +1340,7 @@ static bool amf_avc_init(void *data, obs_data_t *settings) - set_avc_property(enc, B_PIC_PATTERN, bf); - - } else if (bf != 0) { -- warn("B-Frames set to %lld but b-frames are not " -+ warn("B-Frames set to %" PRId64 " but b-frames are not " - "supported by this device", - bf); - bf = 0; -@@ -1343,12 +1385,12 @@ static bool amf_avc_init(void *data, obs_data_t *settings) - - info("settings:\n" - "\trate_control: %s\n" -- "\tbitrate: %d\n" -- "\tcqp: %d\n" -+ "\tbitrate: %" PRId64 "\n" -+ "\tcqp: %" PRId64 "\n" - "\tkeyint: %d\n" - "\tpreset: %s\n" - "\tprofile: %s\n" -- "\tb-frames: %d\n" -+ "\tb-frames: %" PRId64 "\n" - "\twidth: %d\n" - "\theight: %d\n" - "\tparams: %s", -@@ -1420,6 +1462,7 @@ static void amf_avc_create_internal(amf_base *enc, obs_data_t *settings) - - static void *amf_avc_create_texencode(obs_data_t *settings, - obs_encoder_t *encoder) -+#ifdef _WIN32 - try { - check_texture_encode_capability(encoder, amf_codec_type::AVC); - -@@ -1442,6 +1485,12 @@ try { - blog(LOG_ERROR, "[texture-amf-h264] %s: %s", __FUNCTION__, err); - return obs_encoder_create_rerouted(encoder, "h264_fallback_amf"); - } -+#else -+{ -+ UNUSED_PARAMETER(settings); -+ return obs_encoder_create_rerouted(encoder, "h264_fallback_amf"); -+} -+#endif - - static void *amf_avc_create_fallback(obs_data_t *settings, - obs_encoder_t *encoder) -@@ -1534,6 +1583,7 @@ static const char *amf_hevc_get_name(void *) - - static inline int get_hevc_preset(amf_base *enc, const char *preset) - { -+ UNUSED_PARAMETER(enc); - if (astrcmpi(preset, "balanced") == 0) - return AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED; - else if (astrcmpi(preset, "speed") == 0) -@@ -1657,8 +1707,8 @@ static bool amf_hevc_init(void *data, obs_data_t *settings) - - info("settings:\n" - "\trate_control: %s\n" -- "\tbitrate: %d\n" -- "\tcqp: %d\n" -+ "\tbitrate: %" PRId64 "\n" -+ "\tcqp: %" PRId64 "\n" - "\tkeyint: %d\n" - "\tpreset: %s\n" - "\tprofile: %s\n" -@@ -1778,6 +1828,7 @@ static void amf_hevc_create_internal(amf_base *enc, obs_data_t *settings) - - static void *amf_hevc_create_texencode(obs_data_t *settings, - obs_encoder_t *encoder) -+#ifdef _WIN32 - try { - check_texture_encode_capability(encoder, amf_codec_type::HEVC); - -@@ -1800,6 +1851,12 @@ try { - blog(LOG_ERROR, "[texture-amf-h265] %s: %s", __FUNCTION__, err); - return obs_encoder_create_rerouted(encoder, "h265_fallback_amf"); - } -+#else -+{ -+ UNUSED_PARAMETER(settings); -+ return obs_encoder_create_rerouted(encoder, "h265_fallback_amf"); -+} -+#endif - - static void *amf_hevc_create_fallback(obs_data_t *settings, - obs_encoder_t *encoder) -@@ -1888,6 +1945,7 @@ static const char *amf_av1_get_name(void *) - - static inline int get_av1_preset(amf_base *enc, const char *preset) - { -+ UNUSED_PARAMETER(enc); - if (astrcmpi(preset, "highquality") == 0) - return AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY; - else if (astrcmpi(preset, "quality") == 0) -@@ -2026,8 +2084,8 @@ static bool amf_av1_init(void *data, obs_data_t *settings) - - info("settings:\n" - "\trate_control: %s\n" -- "\tbitrate: %d\n" -- "\tcqp: %d\n" -+ "\tbitrate: %" PRId64 "\n" -+ "\tcqp: %" PRId64 "\n" - "\tkeyint: %d\n" - "\tpreset: %s\n" - "\tprofile: %s\n" -@@ -2094,6 +2152,7 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) - - static void *amf_av1_create_texencode(obs_data_t *settings, - obs_encoder_t *encoder) -+#ifdef _WIN32 - try { - check_texture_encode_capability(encoder, amf_codec_type::AV1); - -@@ -2116,6 +2175,12 @@ try { - blog(LOG_ERROR, "[texture-amf-av1] %s: %s", __FUNCTION__, err); - return obs_encoder_create_rerouted(encoder, "av1_fallback_amf"); - } -+#else -+{ -+ UNUSED_PARAMETER(settings); -+ return obs_encoder_create_rerouted(encoder, "av1_fallback_amf"); -+} -+#endif - - static void *amf_av1_create_fallback(obs_data_t *settings, - obs_encoder_t *encoder) -@@ -2213,9 +2278,16 @@ static bool enum_luids(void *param, uint32_t idx, uint64_t luid) - return true; - } - -+#ifdef _WIN32 -+#define OBS_AMF_TEST "obs-amf-test.exe" -+#else -+#define OBS_AMF_TEST "obs-amf-test" -+#endif -+ - extern "C" void amf_load(void) - try { - AMF_RESULT res; -+#ifdef _WIN32 - HMODULE amf_module_test; - - /* Check if the DLL is present before running the more expensive */ -@@ -2225,18 +2297,26 @@ try { - if (!amf_module_test) - throw "No AMF library"; - FreeLibrary(amf_module_test); -+#else -+ void *amf_module_test = os_dlopen(AMF_DLL_NAMEA); -+ if (!amf_module_test) -+ throw "No AMF library"; -+ os_dlclose(amf_module_test); -+#endif - - /* ----------------------------------- */ - /* Check for supported codecs */ - -- BPtr test_exe = os_get_executable_path_ptr("obs-amf-test.exe"); -+ BPtr test_exe = os_get_executable_path_ptr(OBS_AMF_TEST); - std::stringstream cmd; - std::string caps_str; - - cmd << '"'; - cmd << test_exe; - cmd << '"'; -+#ifdef _WIN32 - enum_graphics_device_luids(enum_luids, &cmd); -+#endif - - os_process_pipe_t *pp = os_process_pipe_create(cmd.str().c_str(), "r"); - if (!pp) -@@ -2296,12 +2376,12 @@ try { - /* ----------------------------------- */ - /* Init AMF */ - -- amf_module = LoadLibraryW(AMF_DLL_NAME); -+ amf_module = os_dlopen(AMF_DLL_NAMEA); - if (!amf_module) - throw "AMF library failed to load"; - - AMFInit_Fn init = -- (AMFInit_Fn)GetProcAddress(amf_module, AMF_INIT_FUNCTION_NAME); -+ (AMFInit_Fn)os_dlsym(amf_module, AMF_INIT_FUNCTION_NAME); - if (!init) - throw "Failed to get AMFInit address"; - -@@ -2313,7 +2393,7 @@ try { - if (res != AMF_OK) - throw amf_error("GetTrace failed", res); - -- AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)GetProcAddress( -+ AMFQueryVersion_Fn get_ver = (AMFQueryVersion_Fn)os_dlsym( - amf_module, AMF_QUERY_VERSION_FUNCTION_NAME); - if (!get_ver) - throw "Failed to get AMFQueryVersion address"; -@@ -2352,7 +2432,7 @@ try { - } catch (const amf_error &err) { - /* doing an error here because it means at least the library has loaded - * successfully, so they probably have AMD at this point */ -- blog(LOG_ERROR, "%s: %s: 0x%lX", __FUNCTION__, err.str, -+ blog(LOG_ERROR, "%s: %s: 0x%uX", __FUNCTION__, err.str, - (uint32_t)err.res); - } - diff --git a/pkgs/apps/obs/onevpl.nix b/pkgs/apps/obs/onevpl.nix deleted file mode 100644 index 5f81c8f..0000000 --- a/pkgs/apps/obs/onevpl.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ stdenv -, fetchFromGitHub -, wayland -, wayland-protocols -, xorg -, libva -, libdrm -, cmake -, pkg-config -}: - -stdenv.mkDerivation rec { - pname = "onevpl"; - version = "v2023.3.1"; - - src = fetchFromGitHub { - owner = "oneapi-src"; - repo = "oneVPL"; - rev = version; - hash = "sha256-kFW5n3uGTS+7ATKAuVff5fK3LwEKdCQVgGElgypmrG4="; - }; - nativeBuildInputs = [ - cmake - pkg-config - ]; - buildInputs = [ - wayland - wayland-protocols - xorg.libxcb - xorg.libX11 - xorg.libpciaccess - libva - libdrm - ]; - cmakeFlags = [ - "-DCMAKE_BUILD_TYPE=Release" - "-DCMAKE_INSTALL_LIBDIR=lib" - "-DENABLE_DRI3=ON" - "-DENABLE_DRM=ON" - "-DENABLE_VA=ON" - "-DENABLE_WAYLAND=ON" - "-DENABLE_X11=ON" - ]; -} diff --git a/pkgs/apps/obs/qrcodegencpp.nix b/pkgs/apps/obs/qrcodegencpp.nix deleted file mode 100644 index 9e64e2e..0000000 --- a/pkgs/apps/obs/qrcodegencpp.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ lib -, stdenv -, qrcodegen -}: - -stdenv.mkDerivation (finalAttrs: { - pname = "qrcodegencpp"; - version = qrcodegen.version; - - src = qrcodegen.src; - - sourceRoot = "${finalAttrs.src.name}/cpp"; - - nativeBuildInputs = lib.optionals stdenv.cc.isClang [ - stdenv.cc.cc.libllvm.out - ]; - - makeFlags = lib.optionals stdenv.cc.isClang [ "AR=llvm-ar" ]; - installPhase = '' - runHook preInstall - - install -Dt $out/lib/ libqrcodegencpp.a - install -Dt $out/include/qrcodegen/ qrcodegen.hpp - - runHook postInstall - ''; -}) diff --git a/pkgs/default.nix b/pkgs/default.nix index 3ab6ada..f66042f 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -9,17 +9,7 @@ rec { }; - ffmpeg6-amf-full = (if pkgs.lib.versionOlder pkgs.ffmpeg-full.version "6.1" then - pkgs.callPackage ./apps/ffmpeg - { - inherit (pkgs.darwin.apple_sdk.frameworks) - Cocoa CoreServices CoreAudio CoreMedia AVFoundation MediaToolbox - VideoDecodeAcceleration VideoToolbox; - } else - (pkgs.ffmpeg-full.overrideAttrs (finalAttrs: previousAttrs: { configureFlags = previousAttrs.configureFlags ++ [ "--enable-amf" ]; buildInputs = previousAttrs.buildInputs ++ [ pkgs.amf-headers ]; })) - ); - - obs-amf = pkgs.qt6Packages.callPackage ./apps/obs { ffmpeg = ffmpeg6-amf-full; inherit libcef; }; + ffmpeg_7-amf-full = (pkgs.ffmpeg_7-full.overrideAttrs (finalAttrs: previousAttrs: { configureFlags = previousAttrs.configureFlags ++ [ "--enable-amf" ]; buildInputs = previousAttrs.buildInputs ++ [ pkgs.amf-headers ]; })); polymc = pkgs.qt6Packages.callPackage ./apps/games/polymc { }; polymc-qt5 = pkgs.libsForQt5.callPackage ./apps/games/polymc { }; @@ -30,9 +20,5 @@ rec { fbset = callPackage ./apps/fbset.nix { }; - libcef = callPackage ./libs/libcef.nix { }; - lh2ctrl = callPackage ./apps/lh2ctrl.nix { }; - - emacs-materus = (pkgs.emacs29.override { withSQLite3 = true; withWebP = true; withX = true; withGTK3 = true; withAlsaLib = true; withGconf = true; withImageMagick = true; withXwidgets = true; }); } diff --git a/pkgs/libs/libcef.nix b/pkgs/libs/libcef.nix deleted file mode 100644 index 7c54be2..0000000 --- a/pkgs/libs/libcef.nix +++ /dev/null @@ -1,130 +0,0 @@ -{ lib -, stdenv -, fetchurl -, cmake -, glib -, nss -, nspr -, atk -, at-spi2-atk -, libdrm -, expat -, mesa -, gtk3 -, pango -, cairo -, alsa-lib -, dbus -, at-spi2-core -, cups -, libcef -, libxkbcommon -, xorg -, zlib -, openssl -, wayland -, systemd -, pkgs -}: - -let - vk_rpath = lib.makeLibraryPath [ - stdenv.cc.cc.lib - xorg.libX11 - ]; - gl_rpath = lib.makeLibraryPath [ - stdenv.cc.cc.lib - ]; - rpath = lib.makeLibraryPath [ - glib - nss - nspr - atk - at-spi2-atk - libdrm - expat - xorg.libxcb - libxkbcommon - xorg.libX11 - xorg.libXcomposite - xorg.libXdamage - xorg.libXext - xorg.libXfixes - xorg.libXrandr - mesa - gtk3 - pango - cairo - alsa-lib - dbus - at-spi2-core - cups - xorg.libxshmfence - ]; - platforms = { - "aarch64-linux" = { - platformStr = "linuxarm64"; - projectArch = "arm64"; - }; - "x86_64-linux" = { - platformStr = "linux64"; - projectArch = "x86_64"; - }; - }; - platforms."aarch64-linux".sha256 = "0c034h0hcsff4qmibizjn2ik5pq1jb4p6f0a4k6nrkank9m0x7ap"; - platforms."x86_64-linux".sha256 = "02pj4dgfswpaglxkmbd9970znixlv82wna4xxhwjh7i5ps24a0n6"; - - platformInfo = builtins.getAttr stdenv.targetPlatform.system platforms; -in -stdenv.mkDerivation rec { - pname = "cef-binary"; - version = pkgs.libcef.version; - src = pkgs.libcef.src; - - nativeBuildInputs = [ cmake ]; - cmakeFlags = [ "-DPROJECT_ARCH=${platformInfo.projectArch}" ]; - makeFlags = [ "libcef_dll_wrapper" ]; - dontStrip = true; - dontPatchELF = true; - - installPhase = '' - mkdir -p $out/lib/ $out/share/cef/ $out/bin/ - cp -r ../Release $out/share/cef/ - cp -r ../Resources $out/share/cef/ - cp -r ../include $out/share/cef/ - - cp -r libcef_dll_wrapper $out/share/cef/ - - patchelf --set-rpath "$out/share/cef/Release/:${rpath}" $out/share/cef/Release/libcef.so - patchelf --set-rpath "$out/share/cef/Release/:${gl_rpath}" $out/share/cef/Release/libEGL.so - patchelf --set-rpath "$out/share/cef/Release/:${gl_rpath}" $out/share/cef/Release/libGLESv2.so - patchelf --set-rpath "$out/share/cef/Release/:${vk_rpath}" $out/share/cef/Release/libvulkan.so.1 - patchelf --set-rpath "$out/share/cef/Release/:${vk_rpath}" $out/share/cef/Release/libvk_swiftshader.so - - patchelf --set-rpath "$out/share/cef/Release/:${vk_rpath}" --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out/share/cef/Release/chrome-sandbox - - ln -s $out/share/cef/Release/chrome-sandbox $out/bin - ln -s $out/share/cef/Release/libcef.so $out/lib - ln -s $out/share/cef/libcef_dll_wrapper/libcef_dll_wrapper.a $out/lib/ - ln -s $out/share/cef/include $out/ - - sed -i "s#./libvk_swiftshader.so#$out/share/cef/Release/libvk_swiftshader.so#" $out/share/cef/Release/vk_swiftshader_icd.json - - - - - ''; - passthru.updateScript = ./update.sh; - - meta = with lib; { - description = "Simple framework for embedding Chromium-based browsers in other applications"; - homepage = "https://cef-builds.spotifycdn.com/index.html"; - maintainers = with maintainers; []; - sourceProvenance = with sourceTypes; [ - fromSource - binaryNativeCode - ]; - license = licenses.bsd3; - platforms = [ "x86_64-linux" "aarch64-linux" ]; - }; -}