-
Notifications
You must be signed in to change notification settings - Fork 7.3k
drivers: video: sw_generator: add more formats and try to simplify #85968
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
base: main
Are you sure you want to change the base?
Conversation
948ae06
to
d803873
Compare
force-push:
This is a draft until I can properly test every format, i.e. with UVC or other ways. Ideally this would be having unit tests like done by the capture sample, but this would need to come in another PR. |
584c08c
to
ff7d7f6
Compare
Force-push:
There is a challenge though: the YUYV is actually YUV BT.709 (used by sRGB and HDTV), not BT.601 (used by JPEG).
|
8caaa0d
to
334c03f
Compare
force-push:
|
334c03f
to
80be4fd
Compare
@@ -10,6 +10,8 @@ | |||
#include <zephyr/drivers/video.h> | |||
#include <zephyr/drivers/video-controls.h> | |||
#include <zephyr/logging/log.h> | |||
#include <zephyr/sys/util.h> | |||
#include <zephyr/sys/byteorder.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You didn't use any thing in this byteorder.h
header. I think you need it in another commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: this change is now in the commit that uses sys_cpu_to_le32()
. Github moved the comment to a different commit it seems.
drivers/video/video_sw_generator.c
Outdated
vbuf->bytesused = 0; | ||
|
||
if (vbuf->size < data->fmt.pitch) { | ||
LOG_WRN("Buffer %p has only %u bytes, shorter than pitch %u", | ||
vbuf, vbuf->size, data->fmt.pitch); | ||
return; | ||
} | ||
|
||
/* Generate the first line of data */ | ||
for (int w = 0, i = 0; w < data->fmt.width; w++) { | ||
int color_idx = data->ctrl_vflip ? 7 - w / bw : w / bw; | ||
|
||
if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) { | ||
uint16_t *pixel = (uint16_t *)&vbuf->buffer[i]; | ||
*pixel = sys_cpu_to_le16(rgb565_colorbar_value[color_idx]); | ||
} else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) { | ||
uint32_t *pixel = (uint32_t *)&vbuf->buffer[i]; | ||
*pixel = sys_cpu_to_le32(xrgb32_colorbar_value[color_idx]); | ||
} | ||
i += video_bits_per_pixel(data->fmt.pixelformat) / BITS_PER_BYTE; | ||
} | ||
|
||
/* Duplicate the first line all over the buffer */ | ||
for (int h = 1; h < data->fmt.height; h++) { | ||
if (vbuf->size < vbuf->bytesused + data->fmt.pitch) { | ||
break; | ||
} | ||
|
||
memcpy(vbuf->buffer + h * data->fmt.pitch, vbuf->buffer, data->fmt.pitch); | ||
vbuf->bytesused += data->fmt.pitch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the old code is OK. I think we don't need to check the buffer against the format's pitch because
- In the current v4z framework, when application allocates the video buffer, it is supposed to allocate sufficient memory for the requested format, if not, it will simply not work.
- Otherwise, there is a problem in the current framework which will be pointed out in my upcomming buffer management PR:
- the application should not specify the format->pitch as it has no knowdlege about this (this should be set by the driver, e.g. driver can add padding to the width line, etc.)
- the application also should not specify the buffer size, it just set the format, the number of buffers and request the framework / driver to alloc the buffers on the video buffer heap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced data->fmt.pitch
by a local pitch
variable that is computed locally: the driver knows what it generates, let me know if that does not solve the concerns fully.
(2.) takes the entire buffer management out of the application developer way! 😯
drivers/video/video_sw_generator.c
Outdated
if (fmt->pitch != fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE) { | ||
LOG_ERR("The pitch is not consistent with the other parameters"); | ||
return -EINVAL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here. This reveals the weak point of the current framework : application should not set the format's pitch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
drivers/video/video_sw_generator.c
Outdated
while (fmts[i].pixelformat && (fmts[i].pixelformat != fie->format->pixelformat)) { | ||
i++; | ||
for (i = 0; fmts[i].pixelformat != 0; ++i) { | ||
if (fie->format->pixelformat == fmts[i].pixelformat && | ||
IN_RANGE(fie->format->width, fmts[i].width_min, fmts[i].width_max) && | ||
IN_RANGE(fie->format->height, fmts[i].height_min, fmts[i].height_max)) { | ||
break; | ||
} | ||
} | ||
|
||
if ((i == ARRAY_SIZE(fmts)) || (fie->format->width > fmts[i].width_max) || | ||
(fie->format->width < fmts[i].width_min) || | ||
(fie->format->height > fmts[i].height_max) || | ||
(fie->format->height < fmts[i].height_min)) { | ||
if (fmts[i].pixelformat == 0) { | ||
LOG_ERR("Nothing matching the requested format was found"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the change is the same as the old code except the use of IN_RANGE(). But well, both are fine to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just an attempt at using idioms.
I reverted fmts[i].pixelformat == 0
back to i == ARRAY_SIZE(fmts)
to avoid too many distracting changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unchanged since last time, but it is ok to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I forgot to change it there... I notice that maybe ARRAY_SIZE(fmts)
needs to be ARRAY_SIZE(fmts) - 1
to exclude the {0}
terminator from the comparisons. Same as here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this reason along with avoiding memory allocation, it could be convenient to switch to video_enum_format()
like video_enum_frmival()
. For another RFC/PR maybe!
80be4fd
to
3cfe8af
Compare
drivers/video/video_sw_generator.c
Outdated
while (fmts[i].pixelformat && (fmts[i].pixelformat != fie->format->pixelformat)) { | ||
i++; | ||
for (i = 0; fmts[i].pixelformat != 0; ++i) { | ||
if (fie->format->pixelformat == fmts[i].pixelformat && | ||
IN_RANGE(fie->format->width, fmts[i].width_min, fmts[i].width_max) && | ||
IN_RANGE(fie->format->height, fmts[i].height_min, fmts[i].height_max)) { | ||
break; | ||
} | ||
} | ||
|
||
if ((i == ARRAY_SIZE(fmts)) || (fie->format->width > fmts[i].width_max) || | ||
(fie->format->width < fmts[i].width_min) || | ||
(fie->format->height > fmts[i].height_max) || | ||
(fie->format->height < fmts[i].height_min)) { | ||
if (fmts[i].pixelformat == 0) { | ||
LOG_ERR("Nothing matching the requested format was found"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unchanged since last time, but it is ok to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR enhances the video software generator by adding support for additional pixel formats and simplifying several functions. Key changes include updating header comments and macros to support the new VIDEO_PIX_FMT_RGB24 format, refactoring the format capabilities array using a macro, and splitting the fill_colorbar logic into multiple dedicated fill functions.
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
include/zephyr/drivers/video.h | Updated comments and added definitions for the new RGB24 pixel format. |
drivers/video/video_sw_generator.c | Refactored work handling, format selection, and added new fill routines for various pixel formats. |
{0xFF, 0x00, 0xFF}, {0xFF, 0x00, 0x00}, {0x00, 0x00, 0xFF}, {0x00, 0x00, 0x00}, | ||
}; | ||
|
||
static int video_sw_generator_fill_yuyv(uint8_t *buffer, uint16_t width) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loop in video_sw_generator_fill_yuyv assumes that width is even. To avoid potential out-of-bound writes when width is odd, consider adding a check or enforcing even width via an assertion.
{ | |
{ | |
__ASSERT((width % 2) == 0, "Width must be even to avoid out-of-bound writes"); |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's increase assert density then!
3cfe8af
to
11b85d5
Compare
11b85d5
to
b749191
Compare
force-push:
|
…ions In order to help debugging through GDB and other error messages and debug tools, convert the __xxx prefix to video_sw_generator_xxx full prefix. To help keep function names short, use slightly shorter sufixes. Signed-off-by: Josuah Demangeon <[email protected]>
Help with maintainance and possibly readability by using a more regular layout for various tables of numbers. This adds a comma on the last element to help with formatters like clang-format. Signed-off-by: Josuah Demangeon <[email protected]>
Use the IN_RANGE() macro to compare a format against the format caps width/height_min and width/height_max fields. Signed-off-by: Josuah Demangeon <[email protected]>
Fix video_sw_generator_enum_frmival() only matching the first size of a pixel format. The selection loop was stopping at the first matching pixel format rather than pixel format + size pair. Signed-off-by: Josuah Demangeon <[email protected]>
fb15800
to
25982fa
Compare
Add a check for the array size to avoid overwriting unrelated memory when the buffer is too small for the full format. It first check if there is enough buffer for one line, and fill it programmatically. Then, it will try to duplicate that line over the entire buffer, in the limit of the room available. Signed-off-by: Josuah Demangeon <[email protected]>
This refactors the pattern generator functions to also offer bayer formats as input. 4 variant of bayer formats are proposed. The pixel packing is also now split from the color selection: only a single RGB and single YUV array used by all the pattern generators. Signed-off-by: Josuah Demangeon <[email protected]>
25982fa
to
d7605bf
Compare
This complements the 32-bit RGB (XRGB32) test pattern with an equivalent 24-bit RGB (RGB24) implementation. Signed-off-by: Josuah Demangeon <[email protected]>
The documentation of k_work_cancel_delayable_sync() states that the input k_work_sync parameter needs to be valid until the function call returns, so there is no need to preserve the state across successive calls. Now that there is a single work-related field in the struct, rename it to simply "work". Signed-off-by: Josuah Demangeon <[email protected]>
The struct video_format_caps fmts[] is an array terminated by an empty entry which should not be used while searching or comparing the formats. If using ARRAY_SIZE(), this terminator entry should be subtracted from the list. Signed-off-by: Josuah Demangeon <[email protected]>
d7605bf
to
4b08f4b
Compare
This includes several incremental, small changes to the software generator.
It was not broken on ideal conditions: this only help it be more robust during misuse.