Skip to content

fix: Start only outputs whose OBS counterpart is active when restarting in Individual interlock - #193

Merged
hanatyan128 merged 1 commit into
devfrom
fix/issue-189-individual-restart-start-conditions
Sep 23, 2026
Merged

hanatyan128 merged 1 commit into
devfrom
fix/issue-189-individual-restart-start-conditions

Conversation

@hanatyan128

@hanatyan128 hanatyan128 commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes the restarts reported in #189. With the "Individual" interlock, a restart of a running filter now starts only the output types whose matching OBS output is running. A streaming slot no longer goes live while OBS is not streaming, and a replay buffer or stream recording is no longer started only to be stopped on a later tick.

  • startOutput() and restartOutput() take the interlock type. All callers are in onIntervalTimerTimeout(), which already has it.
  • startOutput() decides once per output type whether to start it:
    • The type is enabled in the settings and its dock toggle is on.
    • In Individual mode, its matching OBS output is also running (obs_frontend_streaming_active() / obs_frontend_recording_active() / obs_frontend_replay_buffer_active()).
  • The same decision selects the start helpers, so the check and the start cannot disagree.
  • When no type qualifies, startOutput() returns before building the infrastructure.
  • Both restart paths that run while outputs are running use it: the settings change restart through restartOutput() and the source resolution change restart.
  • Other interlock modes start the same set of output types as before.
  • The FIXME at the restartOutput() call that pointed at Individual interlock restarts start outputs whose OBS counterpart is not running, and the next tick stops them #189 is removed. The reconnect FIXME next to it is kept.

Only src/plugin-main.cpp and src/plugin-main.hpp are changed.

Root cause

  • The Individual start paths check the matching OBS output before starting each type, but the two restart paths called startOutput(), which started every type that was configured and had its dock toggle on, without looking at the interlock.
  • The Individual stop check then stopped the types whose matching OBS output was not running.
  • A streaming slot started this way stayed up until its "activate" or "stop" signal, because someStreamingsStarting() returns early from every tick until then, so it went live on its service before it was stopped.
  • A replay buffer started this way was stopped before it had received any packet, which blocked the interval timer callback on the UI thread for several seconds, as described in Enabling an output type with Apply while another output runs starts it and restarts everything one tick later, stalling the UI for a new replay buffer #184.

Known limitations

  • The OBS output state is read once per restart. If OBS starts or stops an output between that read and the start, the existing Individual start and stop checks correct it on a later tick, the same as on dev.
  • An output stopped before it has received a packet still blocks the stop, for example an output started from a dock toggle followed within one GOP by an Apply. This fix only removes the starts that led to that stop.
  • A restart can still reach obs_output_stop() on a reconnecting output (the reconnect FIXME), and an Apply without any change still restarts the outputs (Applying the filter properties without changing anything restarts the outputs #178). Both are unchanged from dev.

Verification

  • clang-format 17 check passed.
  • RelWithDebInfo build passed (Windows x64).
  • One round of design review (OBS reviewer) found no Critical or Major issues; its two optional notes were applied to the design.
  • One round of code review (C++ reviewer) and comment review found no issues.

Manual testing

Watch the log for Settings change detected, Attempting restart and the Starting ... succeeded lines that follow it.

Individual interlock:

  • Enable Stream Recording and Replay Buffer, start only OBS recording, change the video bitrate and click Apply. Only Starting recording output succeeded follows the restart, there is no Starting replay buffer succeeded, and the UI does not freeze.
  • Same as above with a streaming slot instead of the replay buffer, while OBS is not streaming. The slot does not connect to its service.
  • Turn off "Don't reset output when source resolution changes", enable Stream Recording plus a streaming slot or the replay buffer with its dock toggle on, start only OBS recording, and change the parent source's resolution. Only the stream recording restarts.
  • With OBS streaming and recording running, click Apply after a change. Both the streaming slots and the stream recording restart.
  • Disable the only running output type and click Apply. The output stops and nothing is restarted.
  • After the steps above, start OBS streaming or OBS's replay buffer. The matching filter output starts on the next tick.

Other interlock modes:

  • "Always ON" and "Streaming": click Apply after a change. Every enabled output type restarts, as on dev.
  • "Always ON": disable and re-enable the filter. Every enabled output type starts.

Shutdown:

  • After the tests above, exit OBS. It exits normally and the log reports 0 memory leaks.
    • OBS 31.1 and 30.1 reported leaks after the full run. They also occur without Branch Output activity (OBS 31.1: OBS outputs only with the interlock set to "Always OFF") or do not reproduce with the changed restart paths alone (OBS 30.1), so they are unrelated to this change.

Environments:

  • OBS 30.1.2 (Windows x64)
  • OBS 31.1.1 (Windows x64)
  • OBS 32.2.1 (Windows x64)

Fixes #189

🤖 Generated with Claude Code

@hanatyan128 hanatyan128 self-assigned this Sep 23, 2026
@hanatyan128 hanatyan128 mentioned this pull request Sep 23, 2026
@hanatyan128
hanatyan128 merged commit d814d85 into dev Sep 23, 2026
6 checks passed
@hanatyan128
hanatyan128 deleted the fix/issue-189-individual-restart-start-conditions branch September 23, 2026 13:38
@hanatyan128 hanatyan128 added this to the 1.1.0 milestone Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Individual interlock restarts start outputs whose OBS counterpart is not running, and the next tick stops them

1 participant