Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linux-v4l2: Fix virtual camera start failure #11906

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

stephematician
Copy link

@stephematician stephematician commented Feb 28, 2025

Skip the non-compliant usage of STREAMON ioctl when loopback module version is newer than 0.13.2

Description

When starting (or stopping) the virtual camera:

  • Check the version of v4l2loopback module by reading /sys/modules/v4l2loopback/version;
  • If the version is later than 0.13.2, skip the STREAMON (STREAMOFF) kludges.

Motivation and Context

Fixes #11891 (thanks to the release of v4l2loopback 0.14.0).

v4l2loopback source was recently updated to have stronger compliance with V4L2 UAPI; thus, the invocation of STREAMON by OBS when no streaming I/O buffers have been negotiated (e.g. via REQBUFS) results in an error. If a user has the newer v4l2loopback, then OBS needs to skip the old STREAMON kludge (see #4808 and fca624e). If the user has the older v4l2loopback (version 0.13.2 or earlier); then the existing behaviour should be maintained.

How Has This Been Tested?

Built on Ubuntu 24.04, x64 machine, with the v4l2loopback source:

  1. Commmit 77bf1e2, to confirm that the error occurs.
  2. v4l2loopback @ 0.14.0, to confirm that the virtual camera starts, stops, and restarts.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@Fenrirthviti
Copy link
Member

For clarification, is there a reason to hold on to the old behavior for older versions? If the issue is stricter requirements on the v4l2loopback side, wouldn't this just be a backwards compatible change?

What breaks in the old versions with this change, or is that untested and just an attempt to not change what has been working?

@stephematician
Copy link
Author

The existing behaviour should be kept when using loopback <= 0.13.2, otherwise there'll be regression to #4808

An alternative solution: Simply ignore any errors from STREAMON or STREAMOFF. In a way; this would be cleaner - but there is a relatively harmless issue where, say, a user has an older loopback module and STREAMON fails for a legitimate reason. In that case - presumably the next call to write() will fail and if the user tries to view the virtual camera, they'll see nothing (but also have no feedback as to why it isn't working).

@stephematician
Copy link
Author

I just remembered I forgot to close the file pointer. Such a noob mistake!

@Fenrirthviti
Copy link
Member

I'm mostly just confused by the presentation of what this is actually fixing.

It sounds like this is actually resulting from what was a bug in v4l2loopback, and we had previously put a workaround in place for, and now that bug is fixed (in the name of better compliance, presumably) and the workaround is now causing issues.

@stephematician
Copy link
Author

I'm mostly just confused by the presentation of what this is actually fixing.

It sounds like this is actually resulting from what was a bug in v4l2loopback, and we had previously put a workaround in place for, and now that bug is fixed (in the name of better compliance, presumably) and the workaround is now causing issues.

Yes. Sorry, I should have answered your quetion.

That is exactly the issue.

  1. loopback <= 0.13.2 had a problem with internal state, meaning that cameras did not restart.
  2. OBS introduced a call to STREAMON call as a workaround.
  3. loopback > 0.13.2 (once released) no longer has a problem with internal state, but it will complain about STREAMON (because this use of STREAMON is not V4L2 UAPI compliant - pretty sure it will fail on every compliant device).
  4. as long as OBS doesn't call STREAMON (or ignores errors); then the camera starts/stops/restarts cleanly with loopback > 0.13.2

Happy to change approach with this PR if needed.

@Fenrirthviti
Copy link
Member

I'll leave the technical specifics to others to comment on, we were just a bit confused on the context around this.

Makes perfect sense now, thanks!

@stephematician
Copy link
Author

just a bit confused

I can relate. It took me a ridiculously long time to get my head about the loopback module as I was updating it. Thanks for your questions!

@stephematician
Copy link
Author

FWIW: the "simpler" fix would be to treat the failed STREAMON (or STREAMOFF) as an info/warning message and not an error; e.g. in v4l2-output.c:

	if (ioctl(vcam->device, VIDIOC_STREAMON, &parm) < 0) {
-		blog(LOG_ERROR, "Failed to start streaming on '%s' (%s)", device, strerror(errno));
-		goto fail_close_device;
+		if (errno == -EINVAL) {
+			blog(LOG_INFO, "EINVAL returned from loopback STREAMON, likely an error in loopback version <= 0.13.2");
+		} else {
+			blog(LOG_ERROR, "Failed to start streaming on '%s' (%s)", device, strerror(errno));
+			goto fail_close_device;
+		}
	}

	blog(LOG_INFO, "Virtual camera started");

@WizardCM WizardCM added the Bug Fix Non-breaking change which fixes an issue label Mar 1, 2025
@stephematician
Copy link
Author

Somewhat tidied up; also noticed that the dimensions (and pixel format) returned by S_FMT were being ignored; which can lead to unexpected behaviour if the (virtual) device chooses a different size (or pixel format) to the request. So that's fixed now, too.

Skip the non-compliant usage of STREAMON ioctl when loopback module
version is newer than 0.13.2
S_FMT can succeed even if it does not set the pixel format and
dimensions to the requested value. Use the return value to check that
the pixel format was set, and use the returned dimensions for
conversion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Fix Non-breaking change which fixes an issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Failed to start virtual camera
3 participants