Repository navigation
obs-websocket: Encode 10-bit sources to sRGB in screenshots - #1146
Merged
Merged
Conversation
5 of 6 tasks
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 17, 2026
rdoupe
added a commit
to rdoupe/obs-studio
that referenced
this pull request
Oct 17, 2026
Moves the submodule to the fork fix "forms: Show session durations of a minute and longer", and on to d79d2c2, the same commit obs-rust#1146 uses, so the two PRs agree whichever merges first (d79d2c2 adds only the screenshot fix for obs-rust#1141 on top). The Session Duration column of the obs-websocket settings dialog went empty after 59 seconds because QTime(0, 0, s) rejects 60 seconds and more (upstream obsproject/obs-websocket#1208, reported by bryce-seifert; DanielLester83 found the QTime limit in obsproject/obs-websocket#1179). FormatSessionDuration() now builds hh:mm:ss from the seconds count, with the hours counting on past 24 and a clock set back showing 00:00:00. test_ws_session_duration passes 5 of 5. Fixes obs-rust#1116. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rces GetSourceScreenshot and SaveSourceScreenshot of a 10-bit source (P010, I010, I210: HEVC Main10, ProRes, 10-bit capture cards) come out too dark: orange (255, 96, 0) as (255, 30, 0), mid grey 128 as 55, while the program output shows the right colours. libobs keeps these frames as linear float, and the screenshot draws the source into an 8-bit target without the sRGB encode that scenes and the previews use. Moves the submodule to the fork commit "utils: Move the source screenshot render into a helper", which moves TakeSourceScreenshot() unchanged into utils/SourceScreenshot.cpp. test_ws_screenshot_srgb builds that file against libobs and the OpenGL module, shows a flat colour as the program scene, and compares the screenshot with the expected sRGB colour and the program output. P010 grey, P010 orange, I010 orange and I210 orange fail; the 8-bit NV12 and half-transparent BGRA controls pass. Refs obs-rust#1141. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the submodule to the fork fix "utils: Encode high-bit-depth sources to sRGB in screenshots". GetSourceScreenshot and SaveSourceScreenshot of a 10- or 12-bit source came out too dark because the source was drawn into the 8-bit image with linear sRGB off. It is now drawn with linear sRGB on when its colour space is not 8-bit sRGB, as scenes and the previews draw it; 8-bit sources are unchanged. test_ws_screenshot_srgb passes 6 of 6. Fixes obs-rust#1141. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
|
Maintainer push: rebased onto master after #1145 merged. GitHub's own rebase reported a conflict; a local rebase was clean. The two commits are unchanged, now |
zackees
force-pushed
the
fix/ws-screenshot-srgb
branch
from
October 17, 2026 08:21
1ce9f47 to
5ac5bcb
Compare
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 17, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1141
Merge after #1145 (the Session Duration submodule bump) (same obs-websocket master, ws#15 comes before ws#16 there), so the submodule only moves forward.
What and why
obs-websocket's
GetSourceScreenshotandSaveSourceScreenshotof a 10- or 12-bit source now show the colours the program shows, instead of a much darker picture.TakeSourceScreenshot()(plugins/obs-websocket/src/requesthandler/RequestHandler_Sources.cpp) rendered the source on its own into an 8-bitGS_RGBAtexrender with linear sRGB off. libobs keeps I010/P010/I210/I412 frames (HEVC Main10, VP9 profile 2, ProRes, 10-bit capture cards) as a linear float texture (need_linear_output(),GS_CS_SRGB_16F). It only turns on the framebuffer's sRGB encode while linear sRGB is on, so the linear values went into the image unencoded: orange (255, 96, 0) became (255, 30, 0), mid grey 128 became 55. Scenes (render_item()inlibobs/obs-scene.c) and the Properties/Filters/Interaction previews draw withgs_set_linear_srgb(true), so the program, the preview, scene screenshots and recordings were right.src/utils/SourceScreenshot.cpp(Utils::TakeSourceScreenshot()). It then draws the source with linear sRGB on when its colour space (obs_source_get_color_space()with SRGB, SRGB_16F and 709_EXTENDED preferred, the list transitions use) is not 8-bit sRGB. This PR moves the submodule to it.DrawNonlinearAlpha), and the PNG would get darker edges. HDR (PQ/HLG) async sources were already tone mapped with linear sRGB forced on by libobs, so nothing changes for them.imageFormat: jpgobsproject/obs-websocket#1298 the MIME type.Reproduced in release v0.1.0-beta.20261014 (AppImage, headless: private Xvfb, private HOME,
dbus-run-session,--multi, loopback-only network namespace). A Media Source is the only item of the program scene, playing ordinary files made by ffmpeg from one pattern (below the top strip: left half (255, 96, 0), right half (0, 96, 255)). Left patch ofGetSourceScreenshotof the source / of the scene / a recording frame:The two 8-bit source screenshots are byte-identical to the release's in both lanes (all 48000 pixels below the pattern's changing strip).
RED → GREEN
test/cmocka: Add failing test for websocket screenshots of 10-bit sources. It moves the submodule from master's pin f06b040 to e87c6e1, the fork PR's first commit, which movesTakeSourceScreenshot()intoUtils::TakeSourceScreenshot()unchanged.test_ws_screenshot_srgbbuilds that file against libobs and the built OpenGL module (GRAPHICS_MODULE_PATH), with Qt Gui for QImage. It shows a flat full-range BT.709 colour from a test async source as the only item of the program scene (BGRA output), and checks the screenshot's centre pixel against the expected sRGB colour and the program output. It fails 4 of 6 cases in both lanes:p010_grey_is_srgb(55 instead of 128),p010_orange_is_srgb,i010_orange_is_srgbandi210_orange_is_srgb((255, 30, 0) instead of (255, 96, 0), the program (255, 96, 0)). The controlsnv12_orange_is_unchangedandbgra_with_alpha_keeps_straight_colour(200, 100, 50 at alpha 128 stays as sent) pass. Linux only, like the other tests that load the OpenGL module; the cases skip without a display (checked withDISPLAYunset).plugins/obs-websocketfrom e87c6e1 to d79d2c2, the fix (d79d2c2 once utils: Encode high-bit-depth sources to sRGB in screenshots obs-websocket#16 merges; forward only). 6 of 6 pass withENABLE_RUST_LIBOBSOFF and ON. Full OBS build (frontend + obs-websocket) in both lanes. Full ctest -j8 (private Xvfb,dbus-run-session, systemlibobs-openglmasked, TMPDIR unset): 275/275 in both lanes, andtest_ws_screenshot_srgbran all 6 cases there. Every PipeWire/PulseAudio test ran. Skipped onlyopen_crashes_without_obs_core(both lanes) and, in the Rust lane,test_startup_alloc_stable: its one case skips when one of its 100obs_startup()calls fails under load, and it passed on a rerun alone. clang-format 22.1.3, gersemi andci/test_registration.pyclean.Checklist
master-W..., ratchets): noneAI note: Claude Code (Claude Opus 5.5) wrote the code, the test, the commit messages and this text under the submitter's direction, and ran the tests above on the submitter's machines.
🤖 Generated with Claude Code