Skip to content

Commit 152175b

Browse files
committed
drivers: video: sw_generator: modify video_sw_generator_fill_colorbar()
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 <me@josuah.net>
1 parent e2b066e commit 152175b

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

drivers/video/video_sw_generator.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/drivers/video-controls.h>
1212
#include <zephyr/logging/log.h>
1313
#include <zephyr/sys/util.h>
14+
#include <zephyr/sys/byteorder.h>
1415

1516
#include "video_ctrls.h"
1617
#include "video_device.h"
@@ -123,29 +124,50 @@ uint32_t xrgb32_colorbar_value[] = {
123124
0xFF00FF00, 0xFF00FFFF, 0xFFFFFF00, 0xFFFFFFFF,
124125
};
125126

127+
static inline int video_sw_generator_get_color_idx(uint16_t w, uint16_t width, bool hflip)
128+
{
129+
/* If hflip is on, start from the right instead */
130+
w = (hflip) ? (width - w - 1) : (w);
131+
132+
/* Downscale from w/width to #/8 */
133+
return 8 * w / width;
134+
}
135+
126136
static void video_sw_generator_fill_colorbar(struct video_sw_generator_data *data,
127137
struct video_buffer *vbuf)
128138
{
129139
int bw = data->fmt.width / 8;
130-
int h, w, i = 0;
131-
132-
for (h = 0; h < data->fmt.height; h++) {
133-
for (w = 0; w < data->fmt.width; w++) {
134-
int color_idx = data->ctrls.hflip.val ? 7 - w / bw : w / bw;
135-
if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) {
136-
uint16_t *pixel = (uint16_t *)&vbuf->buffer[i];
137-
*pixel = rgb565_colorbar_value[color_idx];
138-
i += 2;
139-
} else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) {
140-
uint32_t *pixel = (uint32_t *)&vbuf->buffer[i];
141-
*pixel = xrgb32_colorbar_value[color_idx];
142-
i += 4;
143-
}
140+
struct video_format *fmt = &data->fmt;
141+
size_t pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
142+
bool hflip = data->ctrls.hflip.val;
143+
144+
vbuf->bytesused = 0;
145+
146+
/* Generate the first line of data */
147+
for (int w = 0, i = 0; w < data->fmt.width; w++) {
148+
int color_idx = video_sw_generator_get_color_idx(w, width, hflip);
149+
150+
if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) {
151+
uint16_t *pixel = (uint16_t *)&vbuf->buffer[i];
152+
*pixel = sys_cpu_to_le16(rgb565_colorbar_value[color_idx]);
153+
} else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) {
154+
uint32_t *pixel = (uint32_t *)&vbuf->buffer[i];
155+
*pixel = sys_cpu_to_le32(xrgb32_colorbar_value[color_idx]);
144156
}
157+
i += video_bits_per_pixel(data->fmt.pixelformat) / BITS_PER_BYTE;
158+
}
159+
160+
/* Duplicate the first line all over the buffer */
161+
for (int h = 1; h < data->fmt.height; h++) {
162+
if (vbuf->size < vbuf->bytesused + pitch) {
163+
break;
164+
}
165+
166+
memcpy(vbuf->buffer + h * pitch, vbuf->buffer, pitch);
167+
vbuf->bytesused += pitch;
145168
}
146169

147170
vbuf->timestamp = k_uptime_get_32();
148-
vbuf->bytesused = i;
149171
vbuf->line_offset = 0;
150172
}
151173

0 commit comments

Comments
 (0)