Fix filter-chain rendering#1279
Conversation
|
According to my tests, these changes do allow the size of the Dedicated NDI output filter to reflect the size and content of the previous filter in the chain. You mentioned some edge cases where it does not work. Could you elaborate on the cases so we can determine if they are show stoppers? |
|
As mentioned in Discord already, this behavior is currently in place: 20250526-1418-19.6363461.mp4
I've tried finding a way to make sure we just don't render it at all when the parent source is hidden but I am not sure if that exists... |
|
There is no way to tell if a source has been hidden in a scene. So I dont think this should stop us from implementing the code to react to the closed window. However, the 2x2 pixel empty frame seems a little kludgy. It would be better to destroy the sender and create when we get a non empty frame. |
|
Well the 2x2 pixel code is part of the other PR, #1276 Though yes, I can see how to best implement that in the other one |
There was a problem hiding this comment.
This change looks good. Previous attempts to use the target instead of the parent failed, but using main_renderED_callback instead, seems to have fixed the black screen issue.
This will need to wait for 6.1.1.
Edit: This is incorrect, the black screen issue is not resolved!
|
As I've mentioned in the Discord, I've found a much better way to fix not just the issue I've had with the disabled source and opening the filters tab or properties (where it started to render it a 2nd time with all filters applied once again) I need more testing on the new code though. It also uses the Edit: |
Turns out this does not fix the problem of a black screen in the Dedicated NDI Output. Need to dismiss my review.
|
After much investigation, it is not possible to output the previous filter output in the NDI dedicated output filter. This is mostly due to the way we extract the frame data from OBS. Since we use non-public APIs to achieve this, we are not left with a way to fix this deficiency. @Lordmau5 had this summary in Discord:
|
|
I personally believe the best approach would be to go with the final output from the parent after all filters. As I've said, this would be in line with what would be possible with Canvases as well once support for those is available. That way users can already prepare themselves for how to use it going forward. Do you want me to adapt the PR to have that functionality instead? |
|
Bumping this up. Source with filter (in this order):
Here are some of the test cases I had in mind (please add / suggest) Case 1 :Filter chain rendering
Filter C & D are only visible in OBS but do not output to NDI Case 2Hidden source behavior
Case 3Stop Hidden Source
@Lordmau5 Are Case 1 & 2 fixed with this PR? Case 3 should be a dedicated PR as it will be quite a bigger change. |
|
The PR in its current form doesn't 100% fix the issue that's present currently. The better approach I've mentioned a few times, which would then also prepare users for the eventual Canvases implementation, would be to use the synchronous Case 1 would not be functional in that way anymore - it would send whatever the final output of the parent / source is that is also visible inside OBS. However, this can be worked around by simply cloning the source without any active filters (e.g. with Exeldro's Source Clone plugin) and then attaching either just the filters necessary or not use filters at all (besides the Dedicated NDI Output filter of course) Case 2 is not really possible with this approach as the source is simply not giving any video output in the Case 3 would pretty much be the only realistic solution I see with this that wouldn't cause issues. |

Preface: I almost went bald over this.
This fixes issue #969 (Filter scaling setting not respected) as well as improves on PR #1239 (Use previous filter as source for dedicated NDI output filter)
It uses
obs_filter_get_targetinstead ofobs_filter_get_parent, which will get the previous filter in the chain or, if there is no previous filter, the parent / main source.Additionally, it uses
obs_source_skip_video_filterinstead ofobs_source_video_renderto properly handle drawing of the parent / main source when the Dedicated NDI Output filter is the first one in the chain (without it it will render the final output of the filter chain)Screen.Recording.2025-05-25.220019.mp4
Also since we aren't drawing anything, we use the rendered versions of the callback calls.

Without those the results would look something like this where it somehow renders all the filters twice (as well as blank / black on the NDI receiver end)