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 3 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
/**
* @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 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
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

@josuah
Copy link
Collaborator Author

josuah commented Oct 21, 2024

force-push:

  • split formats out of <zephyr/drivers/video.h> to allow it being included in non-C files, as well as allow the list to grow without cluttering video.h, now containing no more "database-like" definitions.
  • _BPP is replaced by _BITS as _BPP could mean Bytes Per Pixel or Bits Per Pixel
  • Introduce a video_bits_per_pixel(pixfmt) using the _BITS marcros.
  • Fix copyrights (presence only to files changed >50%)

This also propagate the changes to the various files involved.
I can do another variant where the changes are only adding the extra macros/functions, and letting each vendor import the changes progressively.

@josuah
Copy link
Collaborator Author

josuah commented Oct 24, 2024

force-push:

@ngphibang
Copy link
Contributor

Since #76475 is merged, you will need some rebase. Overall, LGTM.

@josuah
Copy link
Collaborator Author

josuah commented Oct 25, 2024

force-push:

About the naming of video_bits_per_pixel(), I would have be glad to keep video_pix_fmt_bpp(), but I feared that keeping the same function name and changing the meaning (byte -> bit) could cause issue. Glad to use some other name!

/**
* 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
Copy link
Collaborator Author

josuah commented Oct 25, 2024

force-push:

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

ngphibang
ngphibang previously approved these changes Oct 26, 2024
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]>
*/
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
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 Required Release notes required for this change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants