Skip to content

Conversation

@gxalpha
Copy link
Member

@gxalpha gxalpha commented Jun 11, 2024

Description

To fix the problem of what to do when a video source has no video, we create a system for the user to indicate what they want the source to do.
Presented to the user as a separate setting, the user can choose between invisible, the last frame, or a black image the size of the last frame.
OBS handles when a source indicates that it no longer has video.

Motivation and Context

Some video sources, like window capture, video capture, or media sources, at some point in their lifetime might not have any video to display.
Currently, what sources do is that scenario is pretty much a wild west.
For example, macOS Screen Capture shows the last known frame, Media Sources have a checkbox between invisible and the last known frame, Game Capture (Windows) shows nothing (to my knowledge), etc.
Past discussions have shown that different users expect differnt things to happen in this case.
Some want the last frame, others want nothing, etc.
Part of this are privacy concerns on what is shown, however this goes both ways: A window capture that shows the last frame may not be supposed to do that as the user clicked the window away since they showed something they didn't mean to; meanwhile a source that suddenly shows nothing could expose what is below it.
Giving control over this to the user should address those conerns.

Link to RFC

Please comment your thoughts!

```
If a source at some point has no video, it should query what state is set via
`obs_source_get_no_video_behavior`
According to what is set, it is then the source's responsibility to output what is asked of it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest changing the obs_source_output_video() function to instead handle NULL frame pointers in accordance to this setting. That way, a source which is ending can just send NULL and libobs will handle it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was my initial thought, but it wouldnt work with synchronous sources that don’t care about that function (which is how I ended up with this current design). Do you have an idea how something similar could be done with sync sources?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest changing the obs_source_output_video() function to instead handle NULL frame pointers in accordance to this setting. That way, a source which is ending can just send NULL and libobs will handle it.

I've changed the section to do this.
Now, only synchronous sources need to do implement some special handling (adding has_video (and only when they have the flag set), see the reworked section).


A video source that at some point might not have video it should indicate so via a new capability flag (The exact value of this might change if `(1 << 17)` is taken by the time of implementation) in its `obs_source_info`:
```c
#define OBS_SOURCE_CAP_MIGHT_NOT_HAVE_VIDEO (1 << 17)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have examples of sources which would not populate this flag? I feel like pretty much every source has some kind of "error" or "unconfigured" state. Would an image source use this flag, and what would happen if I have an image source configured, then clear the image path?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In OBS, the Color Source, Groups and Nested Scenes would not populate that. Additionally, there are third-party plugins (e.g. Kamae's "Main View Source") that would probably not fall under this.

My thinking is that the image source would show this flag, and indicate that no video is available when the image file can't be found, but not when it has been explicitly cleared.

If an async source at some point no longer has new video to output (e.g., because a Video Capture Device gets disconnected), it should call `obs_source_output_video(source, NULL)`.
Note that passing `NULL` as the parameter no longer means that no video will be shown - libobs will handle the actual video output.

Asynchronous sources should not call `obs_source_output_video(source, NULL)` if they do not set the `OBS_SOURCE_CAP_MIGHT_NOT_HAVE_VIDEO` flag.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a big fan of this behavior, as there are a lot of third-party sources which send NULL to libobs, which would suddenly be triggering undefined behavior. I would much prefer that it did the same thing it currently does, which is clear the frame cache and become invisible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense especially when sources might still want to send empty frames even if they implement this, yeah. I guess this should be replaced with a obs_source_output_no_video(source) method or similar to indicate that an async source doesn't have video.

```c
struct obs_source_info {
/* ... */
bool (*has_video)(void *data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally would rather implement this as bool (*obs_source_info.video_render2)(void *data, gs_effect_t *effect), where false signifies that there is no video to render. If there are legitimate performance drawbacks to that, then perhaps that means we should stick with your idea.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle that sounds fine to me. The only drawback is for sources that do not set the "no video" flag - should those then also implement video_render2 and not be allowed to return false? video_render2 would indicate to me that it's a replacement for video_render in all cases.

If tabbed properties are not an option, the options could be radio button added at the bottom of the source's properties.
However, it would not technically be a property and not set any "normal" source settings (though to the user it would look like a normal property).

Showing the black image is the default behavior, and is also what gets returned by `obs_source_get_no_video_behavior` by default.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What resolution would this source get? I also imagine this being an unfavorable scenario, where you might be streaming and want to add a source (for example, an image source). You probably wouldn't want your stream to immediately go black until you configure some kind of setting that makes actual content appear.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also imagine this being an unfavorable scenario, where you might be streaming and want to add a source (for example, an image source). You probably wouldn't want your stream to immediately go black until you configure some kind of setting that makes actual content appear.

Assuming it is agreed that unconfigured sources (e.g. Image Sources with an image path explicitly cleared, see https://github.com/obsproject/rfcs/pull/62/files#r1729999264) do not go into the "no video" state, I don't think that should pose an issue. A source that's newly added would have a cleared file path or similar, meaning that it wouldn't trigger this.

What resolution would this source get?

I don't think there is a correct answer for this since (since there can be multiple canvases, etc), I'd go for some arbitrary value (e.g 800x800). I can't of the top of my head think of a source that would go into "no video" on initial creation (see above), and as soon as it has video at some point that resolution will get remembered.

@gxalpha
Copy link
Member Author

gxalpha commented Aug 24, 2024

I suppose "no video" is a bit broad when it's meant address "no video when video might be expected". I'll change that when integrating the other feedback above.

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.

2 participants