v4l2: fix ALIGN(pix->width, 7); second commit re-does 545cb18 and should wait - #331
v4l2: fix ALIGN(pix->width, 7); second commit re-does 545cb18 and should wait#331vrilutza wants to merge 2 commits into
Conversation
|
Worth knowing before this is merged, and it is not a reason not to merge it. Reporting a real stepwise range is correct. But on a released PipeWire it has two user-visible
The resolution is the obvious one. The startup cost is the surprising one: with a range in the caps, Both are PipeWire defects, not driver ones, and both already have fixes posted: So it is not wrong — it exposes two things already broken for any camera reporting a range. But as of (Edited 22 Aug: this branch now also carries the |
9992af1 to
1709f26
Compare
1709f26 to
13bb476
Compare
fthd_v4l2_adjust_format() does ALIGN(pix->width, 7). ALIGN() computes (x + a - 1) & ~(a - 1) and needs a power of two; with 7 it is (x + 6) & ~6, which clears bits 1 and 2 but leaves bit 0 alone, so the parity of the request survives and every odd width stays odd. YUYV packs two pixels into four bytes, so an odd width cannot be represented. The intended constraint is two functions further down, in fthd_v4l2_ioctl_enum_frameintervals(), which rejects any width that is not a multiple of eight. Both lines are from 2015 and two days apart -- 6bbe371 added the '& 7' check, 230e57a the ALIGN() -- so VIDIOC_S_FMT has been granting widths that VIDIOC_ENUM_FRAMEINTERVALS refuses ever since. Measured on a MacBookPro14,1: S_FMT(323) returned 329 before this change and 328 after, and ENUM_FRAMEINTERVALS accepts 328 while refusing 329. Signed-off-by: Viorel Cernateanu <vrilutza@gmail.com>
This re-does part of 545cb18 ("Revert to discrete frame sizes and frame intervals", May 2020), which went back to discrete because Skype could not handle a stepwise range, with the same step of 8 by 1. What that cost: since then VIDIOC_ENUM_FRAMESIZES advertises a single size while fthd_v4l2_adjust_format() accepts anything from FTHD_MIN_WIDTH/HEIGHT up to the detected sensor size, with the scaler covering everything between. Applications that pick a resolution from the enumeration never offer the smaller sizes; issues patjak#243 and patjak#323 are both that, and both were opened after the revert. Report a stepwise range matching what adjust_format() does, keeping the sensor detection from 98b55fd as the upper bound. The horizontal step of 8 is the constraint enum_frameintervals() has always enforced, and the one the previous patch makes true. Nothing enforces a vertical step, and heights of 241, 245 and 481 were verified to capture, so it is 1. On a MacBookPro14,1 the enumeration goes from "Discrete 1296x736" to "Stepwise 320x240 - 1296x736 with step 8/1", and v4l2-compliance 1.32.0 from "test Scaling: FAIL" to "OK". The reason for the 2020 revert has not gone away, only moved: on a released PipeWire a range still makes an application negotiate the minimum. Fixes for that are posted upstream and this should wait for them. Signed-off-by: Viorel Cernateanu <vrilutza@gmail.com>
13bb476 to
2ee5e47
Compare
|
I've cherry picked the alignment fix. Let's wait for userspace to be fixed before merging the other. |
Before anything else: the second commit here re-does part of 545cb18 (May 2020), where you deliberately went back to discrete because Skype could not handle a stepwise range — with the same
step_width = 8, step_height = 1. I did not find that before opening this, and the first version of this description cited #52 as support when #52 is part of what led you to revert. Sorry for the noise.The two commits now have very different standing.
Commit 1 —
ALIGN(pix->width, 7). Plain bug, take it whenever.ALIGN(x, a)expands to((x) + (a - 1)) & ~(a - 1)and needs a power of two. With 7 the mask clears bits 1 and 2 but not bit 0, so the parity of the request survives and every odd width stays odd — and YUYV, two pixels in four bytes, cannot represent one.The driver then contradicts itself, two commands apart on the same device:
S_FMThad just granted 329.enum_frameintervals()has rejected non-multiples of 8 since 6bbe371 (28 Nov 2015); the brokenALIGN()arrived in 230e57a two days later. Independent of commit 2 and of 545cb18.Commit 2 — stepwise enumeration. Please do not take this yet.
What the revert cost. Since 545cb18 the driver advertises one size while
adjust_format()accepts anything from 320x240 up to the sensor. #243 (2021) and #323 (2026) are both people who cannot get a lower resolution out of an application, and both were opened after it.Why it might be different now. The Skype desktop client that broke in 2016 is gone; applications reach the camera through PipeWire or GStreamer.
Why I would still not merge it today. I measured it, and the 2020 problem has not gone away — it moved. On a released PipeWire a stepwise range makes GNOME Snapshot negotiate 320x240 instead of 1296x736, and take ~4100 ms to a continuous viewfinder instead of ~1500 ms. Same class of failure as Skype, different application. Numbers in the note below. Both are PipeWire bugs with fixes posted upstream, but until those land this would make the camera worse than it is.
Happy to split the two into separate PRs if that is easier to handle.
The series
Seven PRs on this driver, all on master (
364b1c6), all found while debugging a camera problem on a MacBookPro14,1:break, hardcoded buffer countVIDIOC_STREAMONcmd.y1never assigned in the crop command — one lineALIGN(width, 7)aligns nothing; second commit re-does 545cb18 and should waitThey can be taken in any order, with one exception: the second commit of #331 should not be taken yet — reasons in that PR.
(Until 23 August there was a second exception: #328 and #334 both carried the same
mdelay→msleepcommit, so whichever merged first made the other conflict. I have dropped it from #328; it lives in #334. The seven are now independent of each other.)There is one more patch not sent yet: the channel-start crop returns the top left corner of the frame at any size below the sensor. It is measured and ready, and it sits on top of #330. I am holding it back rather than adding an eighth PR to the pile.