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

drivers: video: add format utilities to improve usability #79476

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

josuah
Copy link
Collaborator

@josuah josuah commented Oct 6, 2024

Introduce several enhancements for dealing with the video API:

  • Documentation of formats inspired from this LWN article [EDIT: this representation is convenient, but note that the bit packing of RGB565, RGB555, RGB565X, RGB555X are wrong in it].

note: this image is wrong for RGB565 format!
scrot_20241006_203817_655x344

But in a text-based format to be easy to maintain and colorblindness-friendly, and easy to grep through[EDIT: fixed version below]:

* | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | Bbbbbbbb | Gggggggg | ...
* | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | Gggggggg | Rrrrrrrr | ...
*
* | gggBbbbb | RrrrrGgg | ...
*
* | Xxxxxxxx Rrrrrrrr Gggggggg Bbbbbbbb | ...
  • Add a printf() formatter like stdint.h's PRIu32: printf("video format: " PRIvfmt, PRIvfmt_arg(&fmt));
    This is present elsewhere on Zephyr

  • Convert video_fourcc() to VIDEO_FOURCC() and make it visible to the documentation, now that it is used outside of the header itself.

  • Add a VIDEO_FOURCC_FROM_STR() to easily convert a string from i.e. Kconfig or the devicetree.

Looking forward to your feedback and advises.

@josuah josuah added Enhancement Changes/Updates/Additions to existing features area: Video Video subsystem labels Oct 6, 2024
@zephyrbot zephyrbot added the area: Samples Samples label Oct 6, 2024
@zephyrbot zephyrbot requested review from kartben and nashif October 6, 2024 18:52
/**
* @brief Print formatter to use in printf() style format strings.
*
* This prints a video format in the form of "{width}x{height} {fourcc}" format
Copy link
Collaborator

Choose a reason for hiding this comment

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

From macro below, should be "{fourcc} {width}x{height}" ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You are right, I changed it after seeing how v4l2-ctl and the examples show the formats but forgot to update thedoc. I will adjust it along with other doc fixups.
Thank you for pointing it!

@loicpoulain loicpoulain self-requested a review October 11, 2024 20:04
@josuah josuah force-pushed the pr-video-format-utilities branch from 29a4758 to 6c21f48 Compare October 14, 2024 11:40
loicpoulain
loicpoulain previously approved these changes Oct 14, 2024
@josuah josuah force-pushed the pr-video-format-utilities branch 3 times, most recently from c021247 to d541c10 Compare October 14, 2024 21:53
@josuah
Copy link
Collaborator Author

josuah commented Oct 14, 2024

force-push: CI fixes
force-push: rebase

@josuah josuah force-pushed the pr-video-format-utilities branch from d541c10 to a9587f1 Compare October 15, 2024 16:14
@josuah
Copy link
Collaborator Author

josuah commented Oct 15, 2024

force-push: use _BPP instead of _BITS_PER_PIXEL following this new function naming:
https://github.com/zephyrproject-rtos/zephyr/pull/76475/files#diff-70c4de6949b97c13ac893b4bfb16fbcc433593fbfa96ec8947bb5cb83c4d04bcR835-R852

@josuah
Copy link
Collaborator Author

josuah commented Oct 21, 2024

force-push: split <zephyr/drivers/video-formats.h> into <zephyr/drivers/video/formats.h>, like it is done for all other Zephyr driver includes: include/zephyr/drivers

@zephyrbot zephyrbot requested a review from MaureenHelm October 21, 2024 10:03
@josuah josuah force-pushed the pr-video-format-utilities branch from 75345f9 to ac056cf Compare October 21, 2024 10:08
/**
* 5-bit blue followed by 6-bit green followed by 5-bit red, in little-endian over two bytes.
* @verbatim
* | gggRrrrr | BbbbbGgg | ...
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I documented the BGR565-LE instead of RGB565-LE, but let's resolve the RGB565 discussion first...
#79996

Copy link
Collaborator Author

@josuah josuah Oct 25, 2024

Choose a reason for hiding this comment

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

Nevermind, this is the RGB565, even if R is on the right in the MSB first representation, it is at BIT(0), and seems to be what is expected.

Copy link
Contributor

@ngphibang ngphibang Oct 26, 2024

Choose a reason for hiding this comment

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

I think this is BGR565-LE. Per my understanding, for RGB565, R always needs to be presented first.
In BE, it begins at bit 15 while in LE it begins at bit 8 (because of byte order). I don't understand why here, R begin at bit 4 (in the middle of the byte) ?

Copy link
Contributor

@ngphibang ngphibang Oct 26, 2024

Choose a reason for hiding this comment

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

Endianess is about the byte address order (a chunk of 8 bits), not about the bit order (MSB or LSB first), neither a chunk of 4 bits.

To get it simple, I think we can begin with BE first. An RGB565 in BE is represented as two bytes with the most significant byte stored first in memory address.

  • RRRRRGGG(1st byte in memory) then GGGBBBBB(2nd byte in memory)

At this point, I think we all agree with this. Then, LE is basically just reversing the byte order (only for a multi-byte value), i.e. lower significant bytes get lower addresses. So it becomes:

  • GGGBBBBB(1st byte in memory) then RRRRRGGG(2nd byte in memory)

Copy link
Collaborator Author

@josuah josuah Oct 26, 2024

Choose a reason for hiding this comment

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

What I documented here follows Libav and the LWN article, from where I had the representation:

If representing the format in MSBit first, B is on the left.
Big-endian, MSBit first:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
B b b b b G g g g g g R r r r r

little-endian, MSBit first:
7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8
g g g R r r r r B b b b b G g g

scrot_20241026_115436_453x25
scrot_20241026_115322_450x30
THIS ⬆️ MIGHT BE WRONG

If representing the format in LSBit first, R is on the left. This representation is confusing when mixing bit-endianness and byte endianness.

big-endian, LSBit first:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
r r r r R g g g g g G b b b b B

little-endian, LSBit first:
8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7
g g G b b b b B r r r r R g g g

At this point, I think we all agree with this.

I am trying to understand what the major implementations did agree... and they seem to differ? I am really not sure as they are around since a lot of time. ^_^' Can we settle that the hardware is right to break the tie?

Looking at #79996 (comment) it looks like red in MSBit position wins.

A test pattern generator looks "ok" (stripes of color) even with the wrong color order, and the LWN article is just text, not code that was checked against hardware. Some deeply anchored confusion in tech it seems!

Thank you for your patience and sorry for the confusion.

Committing the fix.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I believe strongly that the LWN article is WRONG. Personally, If I need a reference, I am usually based on the kernel document. The kernel document of the latest Linux release describes the same layout about the RGB565-LE as I pointed in above comment:

https://www.kernel.org/doc/html/v6.11/userspace-api/media/v4l/pixfmt-rgb.html

@josuah josuah force-pushed the pr-video-format-utilities branch 2 times, most recently from 9f922fe to cc79ee7 Compare October 25, 2024 17:05
@josuah
Copy link
Collaborator Author

josuah commented Oct 25, 2024

force-push:

  • Remove the _BITS macros as discussed here
  • Typo fixes as discussed here
  • Fix an inversion in a bayer format documentation
  • Add extra description of the RGB565 with the bit position to avoid ambiguity as discussed here (glad to make further edits if this is not fully resolved!)
  • Add the RGB565X format for the sole purpose of having the big-endian version at sight on the documentation.
  • Other typo fixes.

@josuah josuah force-pushed the pr-video-format-utilities branch from cc79ee7 to 5e8e31d Compare October 25, 2024 17:33
@josuah
Copy link
Collaborator Author

josuah commented Oct 25, 2024

force-push:

  • Doc fix, I did not spot it from running make -C doc doxygen!

@josuah josuah force-pushed the pr-video-format-utilities branch from 5e8e31d to e95d1c6 Compare October 26, 2024 11:47
ngphibang
ngphibang previously approved these changes Oct 26, 2024
@josuah josuah force-pushed the pr-video-format-utilities branch 2 times, most recently from 7069a8b to 97746bd Compare October 26, 2024 16:22
ngphibang
ngphibang previously approved these changes Oct 26, 2024
*/
static inline unsigned int video_pix_fmt_bpp(uint32_t pixfmt)
static inline unsigned int video_bits_per_pixel(uint32_t pixfmt)
Copy link
Collaborator

Choose a reason for hiding this comment

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

need migration guide for the dropped API

Copy link
Contributor

@ngphibang ngphibang Nov 8, 2024

Choose a reason for hiding this comment

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

This one is not an API. It's just an utility / helper function. Do we also need migration guide for this ?

Copy link
Contributor

@ngphibang ngphibang Nov 8, 2024

Choose a reason for hiding this comment

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

Perhaps I misunderstood ... It seems all functions in a .h are considered as APIs.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Anything that's part of a public header and not explicitly marked as internal is to be considered de-facto API :) (see e.g. https://docs.zephyrproject.org/latest/doxygen/html/group__video__interface.html#gabc1c6fd4e13480b269cac9f224ee1c5b)
You may want to review the current API and look for those utilities you folks would like to mark as internal (but that would still require a heads-up to users in the form of a migration guide so that they are aware they might want to move away from using the now internal API).
FWIW it looks to me as if it would be fine to actually keep this as a public API though, it's a utility that might be useful for any user, not just in-tree drivers..?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, it should not be internal and can be used by any user. Thanks

@josuah josuah added the Release Notes Required Release notes required for this change label Nov 8, 2024
@kartben kartben assigned ngphibang and unassigned kartben Dec 12, 2024
@kartben
Copy link
Collaborator

kartben commented Dec 20, 2024

@josuah will you be coming back to this?

@josuah
Copy link
Collaborator Author

josuah commented Dec 20, 2024

Yes absolutely. As soon as the "must finish before end of the year" race is over if possible.

Introduce a new text documentation of the video formats, describing
every bit, gives the position of the most significant bit, outline how
it is cut in bytes, and show the pixel segmentation.

Extra care is taken for the RGB565 which requies paying attention to the
bit endianess as well as the byte endianess.

Signed-off-by: Josuah Demangeon <[email protected]>
Rename video_fourcc() to VIDEO_FOURCC(), differing from the Linux
implementation, but more compliant with the coding style.

Also introduce a VIDEO_FOURCC_FROM_STR() to generate a FOURCC format
code out of a 4-characters string.

Signed-off-by: Josuah Demangeon <[email protected]>
This was present in the form of video_pix_fmt_bpp() inside ST and NXP
drivers, and was returning the number of bytes, which does not allow
support for 10-bits, 4-bits or non-byte aligned video formats.
The helper leverages the VIDEO_PIX_FMT_*_BITS macros.

Signed-off-by: Josuah Demangeon <[email protected]>
The previous commit introduces video_bits_per_pixel() and converts
all invocation relying on video_pix_fmt_bpp(), 3rd-party users will
need to do the same on their code, and this is not a 100% drop-in API,
so better document it on the release notes.

Signed-off-by: Josuah Demangeon <[email protected]>
@zephyrbot zephyrbot added the Release Notes To be mentioned in the release notes label Jan 10, 2025
@josuah josuah removed the Release Notes Required Release notes required for this change label Jan 10, 2025
@josuah
Copy link
Collaborator Author

josuah commented Jan 10, 2025

force-push:

  • rebased on main
  • added a release note and migration guide

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: C++ area: Process area: Samples Samples area: Video Video subsystem Enhancement Changes/Updates/Additions to existing features platform: NXP Drivers NXP Semiconductors, drivers platform: STM32 ST Micro STM32 Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants