diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c1e61e..889bf8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,22 @@ else() target_link_libraries(obs-moq PRIVATE moq::moq) endif() +# libmoq is a Rust static library; its std runtime pulls in symbols from Windows +# system libraries (e.g. NtCreateNamedPipeFile from ntdll) that MSVC does not +# auto-resolve when the archive is linked into this module. These are the OS +# import libraries reported by `rustc --print native-static-libs` that aren't +# linked by default; they resolve by name from the Windows SDK (no hard-coded +# paths). The libmoq package config also declares these, but linking them here +# keeps the plugin buildable against any libmoq (local dev tree or prebuilt +# release) whose config may predate that declaration. Duplicate links are +# harmless. +if(WIN32) + target_link_libraries( + obs-moq + PRIVATE ntdll userenv ws2_32 dbghelp bcrypt + ) +endif() + # The obs-deps Qt6 build references the AGL framework transitively (via # WrapOpenGL), but recent macOS SDKs ship no linkable AGL binary -- it exists # only in the runtime dyld shared cache. Generate a stub whose install name diff --git a/README.md b/README.md index d5c3be3..bc815f0 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,24 @@ ## Features -* **Protocol:** Media over QUIC (MoQ) -* **Video Codecs:** H.264, HEVC (H.265), AV1 -* **Audio Codecs:** AAC, Opus -* **Low Latency:** Leverages QUIC for efficient and low-latency media transport. +- **Protocol:** Media over QUIC (MoQ) +- **Video Codecs:** H.264, HEVC (H.265), AV1 +- **Audio Codecs:** AAC, Opus +- **Low Latency:** Leverages QUIC for efficient and low-latency media transport. ## Installation ### Setup Prerequisites: -* CMake 3.20+ -* C++ Compiler (Clang/GCC/MSVC) -* OBS Studio development libraries (libobs) -* [Fork of OBS-Studio](https://github.com/brianmed/obs-studio) just to show MoQ in the UI. + +- CMake 3.20+ +- C++ Compiler (Clang/GCC/MSVC) +- OBS Studio development libraries (libobs) +- [Fork of OBS-Studio](https://github.com/brianmed/obs-studio) just to show MoQ in the UI. 1. Clone the repos: + ```bash git clone https://github.com/moq-dev/obs.git moq-obs git clone https://github.com/brianmed/obs-studio.git obs-studio @@ -28,16 +30,25 @@ Prerequisites: git clone https://github.com/moq-dev/moq.git moq ``` -2. Build the OBS fork: +2. Build the OBS fork: + ```bash cd obs-studio - # Replace with your platform + # Configure for Windows (generator and architecture come from the preset) + cmake --preset windows-x64 + # Configure for macos cmake --preset macos + + # Build for Windows + cmake --build --preset windows-x64 + + # Build for macOS cmake --build --preset macos ``` 3. Configure the plugin: + ```bash cd moq-obs @@ -50,11 +61,12 @@ Prerequisites: ### Build 1. Build the plugin: + ```bash just build ``` -2. Copy the plugin to the OBS Studio plugins directory and run it: +2. Copy the plugin to the OBS Studio plugins directory and run it: ```bash # macOS only: @@ -63,6 +75,7 @@ just run ``` On linux you'll have to do: + ```bash cp build_x86_64/obs-moq.so ~/.config/obs-studio/plugins/obs-moq/bin/64bit/obs-moq.so # TODO: add Linux command to `just run` @@ -74,19 +87,19 @@ cp build_x86_64/obs-moq.so ~/.config/obs-studio/plugins/obs-moq/bin/64bit/obs-mo 2. Go to **Settings** > **Stream**. 3. In the **Service** dropdown, select **MoQ**. 4. Enter your MoQ Server details: - * For development (`just dev`): `http://localhost:4443/anon`. - * For testing: `https://cdn.moq.dev/anon`. + - For development (`just dev`): `http://localhost:4443/anon`. + - For testing: `https://cdn.moq.dev/anon`. 5. Enter the broadcast name/path: - * For testing: `obs` or some unique string. - * Watch it here: https://moq.dev/watch/?name=obs -5. Configure your Output settings (Codecs, Bitrate) as desired. - * Currently, only: `h264` and `aac` are supported. -6. Start Streaming! - + - For testing: `obs` or some unique string. + - Watch it here: https://moq.dev/watch/?name=obs +6. Configure your Output settings (Codecs, Bitrate) as desired. + - Currently, only: `h264` and `aac` are supported. +7. Start Streaming! ## Manual MoQ Output Streaming Configuration For configuring via a file, prior to launching OBS you can add this to your OBS Profile directory (eg: "Untitled"): + ```bash # Linux $ cat ~/.config/obs-studio/basic/profiles/Untitled/service.json @@ -111,25 +124,22 @@ $ cat ~/Library/Application\ Support/obs-studio/basic/profiles/Untitled/service. 1. Open OBS Studio 2. Goto **Sources** > (right-click) **MoQ Source** 3. Enter your MoQ Server details, eg: - * For development (`just dev`): `http://localhost:4443/anon`. -4. Enter the broadcast name/path: - * For development: `bbb`. + - For development (`just dev`): `http://localhost:4443/anon`. +4. Enter the broadcast name/path: + - For development: `bbb`. 5. Click **OK** - ## Supported Build Environments -| Platform | Tool | -|-----------|--------| -| Windows | Visual Studio 17 2022 | -| macOS | Xcode 16.0 | -| Windows, macOS | CMake 3.30.5 | -| Ubuntu 24.04 | CMake 3.28.3 | -| Ubuntu 24.04 | `ninja-build` | -| Ubuntu 24.04 | `pkg-config` -| Ubuntu 24.04 | `build-essential` | - - +| Platform | Tool | +| -------------- | --------------------- | +| Windows | Visual Studio 17 2022 | +| macOS | Xcode 16.0 | +| Windows, macOS | CMake 3.30.5 | +| Ubuntu 24.04 | CMake 3.28.3 | +| Ubuntu 24.04 | `ninja-build` | +| Ubuntu 24.04 | `pkg-config` | +| Ubuntu 24.04 | `build-essential` | ## License diff --git a/WINDOWS.md b/WINDOWS.md new file mode 100644 index 0000000..73ac8db --- /dev/null +++ b/WINDOWS.md @@ -0,0 +1,37 @@ +## Windows Build Instructions + +### Build Setup + +```powershell +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + choco install -y git + choco install -y cmake --installargs 'ADD_CMAKE_TO_PATH=System' + choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" + choco install rustup +``` + +During the rustup installation choose the `nightly` variant. + +Locate "Visual Studio Installer". Click "Modify". Choose "Desktop Development with C++". Check C++ ATL For x64 + +### Build the OBS fork + +```powershell +cd obs-studio +cmake --preset windows-x64 +cmake --build --preset windows-x64 +``` + +### Build the obs-moq plugin and install + +```powershell +cd obs +cmake --preset windows-x64 -DMOQ_LOCAL="../moq" +cmake --build --preset windows-x64 --target install +``` + +## Debugging Moq Plugin + +```powershell + $env:RUST_LOG="debug"; $env:RUST_BACKTRACE=1; $env:OBS_LOG_LEVEL="debug"; Set-Location "build_x64\rundir\RelWithDebInfo\bin\64bit"; & .\obs64.exe --verbose +``` diff --git a/cmake/windows/defaults.cmake b/cmake/windows/defaults.cmake index c6ec842..bea3ef3 100644 --- a/cmake/windows/defaults.cmake +++ b/cmake/windows/defaults.cmake @@ -8,9 +8,10 @@ set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL TRUE) include(buildspec) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + cmake_path(SET ALLUSERSPROFILE_PATH $ENV{ALLUSERSPROFILE}) set( CMAKE_INSTALL_PREFIX - "$ENV{ALLUSERSPROFILE}/obs-studio/plugins" + "${ALLUSERSPROFILE_PATH}/obs-studio/plugins" CACHE STRING "Default plugin installation directory" FORCE diff --git a/src/moq-dock.cpp b/src/moq-dock.cpp index dda20dd..924e60d 100644 --- a/src/moq-dock.cpp +++ b/src/moq-dock.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #ifndef MOQ_VERSION_STRING @@ -71,16 +72,30 @@ std::string SettingsPath() return s; } +// Default broadcast name "obs-" so distinct setups don't collide on a +// shared relay out of the box. Only used until the user edits/saves their own. +std::string RandomBroadcastName() +{ + static const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, (int)sizeof(charset) - 2); + std::string s = "obs-"; + for (int i = 0; i < 6; i++) + s += charset[dist(gen)]; + return s; +} + } // namespace MoQDock::MoQDock(QWidget *parent) : QWidget(parent) { urlEdit = new QLineEdit(this); - urlEdit->setText("http://localhost:4443/anon"); - urlEdit->setPlaceholderText("https://cdn.moq.dev/anon"); + urlEdit->setText("https://cdn.moq.dev/anon"); + urlEdit->setPlaceholderText("http://localhost:4443/anon"); pathEdit = new QLineEdit(this); - pathEdit->setText("obs"); + pathEdit->setText(QString::fromStdString(RandomBroadcastName())); pathEdit->setPlaceholderText("(optional) broadcast name"); // Labels above the fields (WrapAllRows), and let the fields grow to the full diff --git a/src/obs-moq.cpp b/src/obs-moq.cpp index 678f815..d564c2f 100644 --- a/src/obs-moq.cpp +++ b/src/obs-moq.cpp @@ -30,6 +30,13 @@ extern "C" { #include "moq.h" } +#ifdef _WIN64 +#include +#include +#include +#include +#endif + OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-moq", "en-US") MODULE_EXPORT const char *obs_module_description(void) @@ -39,6 +46,19 @@ MODULE_EXPORT const char *obs_module_description(void) bool obs_module_load(void) { + // On Windows, allocate a console when RUST_LOG=debug *before* initializing + // the Rust logger below, so its output binds to a valid stderr. AllocConsole + // sets the process std handles, but the C runtime streams must be reopened + // onto the console device for that output to be visible. +#ifdef _WIN64 + const char *logLevel = std::getenv("RUST_LOG"); + if (logLevel && strcmp(logLevel, "debug") == 0) { + AllocConsole(); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } +#endif + // Use RUST_LOG env var for more verbose output // The second argument is the string length of the first argument. moq_log_level("info", 4);