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

Stronger V4L2 compliance in REQBUF #611

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

stephematician
Copy link
Contributor

🚧 A work in progress 🚧

Originally raised in #598. The goal is to improve compliance with the V4L2 REQBUFS specification:

Applications can call ioctl VIDIOC_REQBUFS again to change the number of buffers. Note that if any buffers are still mapped or exported via DMABUF, then ioctl VIDIOC_REQBUFS can only succeed if the V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS capability is set. Otherwise ioctl VIDIOC_REQBUFS will return the EBUSY error code ... A count value of zero frees or orphans all buffers, after aborting or finishing any DMA in progress, an implicit VIDIOC_STREAMOFF.

This first appeared as an issue in some earlier experiments I was doing with tiagocoutinho/linuxpy.

Summary

If an opener REQBUFS successfully; then both the format and number of buffers should be fixed until (all) openers have freed the buffers (REQBUFS with count zero). If another opener tries to S_FMT, or REQBUFS while they are fixed - it has to eat what it is served (but they will return success). ENUM_FMT will report all available formats unless keep_format is set.

There is now less distinction between a reader and a writer prior to acquiring a claim (or 'reference') to buffers - so readers may 'lock' in a format if no writers have already done so.

Details

To achieve this the existing ready_for_capture, ready_for_output, active_readers, and opener->type are retired - and instead:

  1. The device records how many openers have allocated ('claimed') buffers via REQBUFS in image_ref_count.
    • An opener releases its claim via REQBUFS with count = 0 ('frees' buffers - but doesn't actually free them).
    • A REQBUFS with count = 0 now performs a STREAMOFF as suggested in V4L2.
  2. If there are any other openers with a claim; REQBUFS will return the device's used_buffers as the count - provided there are no other errors.
  3. An opener can STREAMON if it has claimed buffers of the correct type (e.g. CAPTURE or OUTPUT); otherwise EINVAL.
  4. Once an opener has started streaming, the device releases a write (or read) token, and the opener acquires it.
    • In a STREAMOFF, the opener releases the token, and the device acquires it.
  5. write() uses REQBUFS to allocate buffers and STREAMON to acquire write token
  6. close(), via REQBUFS with count = 0, releases any held token and 'frees' (claim to) buffers.

In progress

There is still testing to do to ensure that existing behaviour is preserved, and stricter compliance is achieved. The final commit needs to be tidied up once testing is complete.

Some minor quality-of-life improvements are included:

  1. (trivial) Tidied some repeated string formatting for FOURCC. cc7eab6
  2. (trivial) Tidied the code for debug info about buffers. a8c2c89
  3. Guarded the list in REQBUFs. e35149a
  4. Better use of atomic operators for open_count in close(). 248b3f5
  5. (trivial) Fixed V4L2 compliance issue with the timeout_image_io CTRL. ba4789a
  6. (trivial) Fixed (default) assignment of exclusive caps when using v4l2loopback-ctl. 5931810
  7. (trivial) Set a valid pix_format in add() (sizeimage was missing). e40cf90

@umlaeute
Copy link
Owner

looking forward to this.

Allow either writer or reader to enumerate all formats except when the
format has been fixed (by, say, a writer, or keep_format).
Use macros for all buffer flag-setting, including return values.
Add prepare_buffer_queue which can both increase and decrease the size
of outbufs_list
assign opener type in first call to read()
use REQBUFS for allocation in first call to read() and write()
@stephematician stephematician force-pushed the reqbuf_fixes branch 2 times, most recently from 126c93b to ced5930 Compare January 27, 2025 11:28
V4L2 UAPI states that REQBUFS has STREAMOFF effect when the count is
zero.
Use REQBUFS as a (safe) mechanism to 'free' buffers when file handle is
closed; ensures that any future improvements to REQBUFS or STREAMOFF
will also uplift open()/close().
Ensure that format and buffer (type) negotiation ioctls follow a
consistent convention for whether the buffer type is available. When
announcing all (device) capabilities, no restrictions. When not
announcing all; allow OUTPUT when `ready_for_output`; and allow CAPTURE
when `keep_format` or `ready_for_capture`.
@stephematician
Copy link
Contributor Author

stephematician commented Jan 27, 2025

Apologies for the extra actions - I had to rebase and fix an incompatibility with the older kernel UAPI.

There's still a few commits to come - just going through some more testing, and trying to make each commit as 'small' as possible so there's a reasonably clear progression from start to finish.

[edit]
I'll add oldstable and 16.04 (Xenial) to my virt-manager guests so that (hopefully) future pushes don't fail on the older distros/kernels
[/edit]

@umlaeute
Copy link
Owner

i take it, that a Draft-PR is only partially working, and you'll probably want to clean it up in the end - so don't worry about intermediate build failures.

and while I do think it is great to support older kernels, sometimes it is simply not feasible. e.g. i think that the xenial builds fail because the base images are broken (because it is really old and github-actions wrongly assume that they can run a newer bulid of nodejs on such a platform)... in which case you can simply ignore the failures :-)

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