Skip to content

v4l2: stop advertising YVYU, coerce all requests to YUYV - #346

Open
kurobeats wants to merge 1 commit into
patjak:masterfrom
kurobeats:yuyv-only
Open

kurobeats wants to merge 1 commit into
patjak:masterfrom
kurobeats:yuyv-only

Conversation

@kurobeats

Copy link
Copy Markdown

The ISP firmware output for the YVYU pixel format is broken: the converted image renders green and pink. This hits any application that negotiates YVYU (GStreamer-based ones do, e.g. GNOME Snapshot/Cheese).

Repro, MacBookPro11,1, 1280x720, one frame captured per format with v4l2-ctl --stream-mmap --stream-count=1 and decoded as 4:2:2:

  • YUYV: valid image. Smooth chroma fields, mean U=130, V=127 (neutral), luma spatially smooth. Renders correct colors.
  • YVYU: corrupt image. Chroma means ~49 in both U and V, luma mean 128 with an alternating 127/129 pattern. Renders green/pink garbage.

So the firmware's 'pixelformat = 2' (YVYU) output mode produces data that is not valid YVYU, while 'pixelformat = 1' (YUYV) is correct.

Fix: make YUYV the only advertised format.

  • fthd_v4l2_ioctl_enum_fmt_vid_cap: drop the YVYU case.
  • fthd_v4l2_adjust_format: coerce any non-YUYV request to YUYV.
  • fthd_v4l2_ioctl_s_fmt_vid_cap: drop YVYU from the planes switch.
  • fthd_v4l2_ioctl_enum_framesizes / enum_frameintervals: reject YVYU like any other unsupported format.

The YVYU -> pixelformat=2 mapping in fthd_isp.c is kept as-is for reference; it is now unreachable since no code path can negotiate YVYU.

Verified: module builds cleanly, --list-formats shows only YUYV, --try-fmt-video=pixelformat=YVYU reports invalid format, and captured frames render with correct colors.

The ISP firmware output for the YVYU pixel format is broken: the
converted image renders green and pink. This hits any application that
negotiates YVYU (GStreamer-based ones do, e.g. GNOME Snapshot/Cheese).

Repro, MacBookPro11,1, 1280x720, one frame captured per format with
v4l2-ctl --stream-mmap --stream-count=1 and decoded as 4:2:2:

- YUYV: valid image. Smooth chroma fields, mean U=130, V=127 (neutral),
  luma spatially smooth. Renders correct colors.
- YVYU: corrupt image. Chroma means ~49 in both U and V, luma mean 128
  with an alternating 127/129 pattern. Renders green/pink garbage.

So the firmware's 'pixelformat = 2' (YVYU) output mode produces data
that is not valid YVYU, while 'pixelformat = 1' (YUYV) is correct.

Fix: make YUYV the only advertised format.

- fthd_v4l2_ioctl_enum_fmt_vid_cap: drop the YVYU case.
- fthd_v4l2_adjust_format: coerce any non-YUYV request to YUYV.
- fthd_v4l2_ioctl_s_fmt_vid_cap: drop YVYU from the planes switch.
- fthd_v4l2_ioctl_enum_framesizes / enum_frameintervals: reject YVYU
  like any other unsupported format.

The YVYU -> pixelformat=2 mapping in fthd_isp.c is kept as-is for
reference; it is now unreachable since no code path can negotiate YVYU.

Verified: module builds cleanly, --list-formats shows only YUYV,
--try-fmt-video=pixelformat=YVYU reports invalid format, and captured
frames render with correct colors.
@vrilutza

Copy link
Copy Markdown
Contributor

Same symptom here on a MacBookPro14,1, and your repro reproduces. One thing the numbers suggest, though: the data does not look invalid, it looks correctly formed but shifted by one byte.

Measured with v4l2-ctl --stream-mmap --stream-count=3 --stream-to=..., reading the buffer as 4-byte groups and taking the mean and standard deviation of each position:

                                Y             C0       C1
YUYV                        83.4 (sd 44.2)   128.9    130.3
YVYU, read as-is           129.5 (sd 11.5)    83.3     83.3
YVYU, read at offset 1      83.3 (sd 44.0)   130.1    128.8
YVYU, read at offset 3      83.3 (sd 44.0)   128.8    130.1

The evidence is inside the YVYU buffer alone. Read as-is, the two chroma positions carry identical statistics (83.3 and 83.3) and the luma position is flat (sd 11.5): that is two luma samples sitting where chroma is expected. Read one byte later, the luma position has the variance of a real image and the two chroma positions become two different neutral values. At offset 3 the same thing appears with the two chroma swapped, which is exactly the U/V order that distinguishes YVYU from YUYV.

The YUYV capture is a different frame of the same scene, so it is corroboration rather than a byte-for-byte comparison, but the signatures line up.

Constant across sizes: 1280x720, 640x480 and 800x600 all show the same one-byte offset.

I do not know whether the offset comes from the firmware or from how the driver configures the output for pixelformat = 2, and I have not chased it. It is the same shape as the misalignment handled in #333, though.

None of this argues against the change: a format that renders garbage as shipped is worth removing, and the mapping you keep in fthd_isp.c means nothing is lost. It seemed worth recording before it is dropped, in case YVYU turns out to be recoverable rather than broken. Happy to test a candidate fix on this hardware.

Unrelated, but useful to whoever merges: I checked that this does not collide with #331. Merging both onto master is clean, and the result rejects YVYU and reports the stepwise range.

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