Skip to content

Commit aa97365

Browse files
committed
feat(example): Automatic detection RGB565 endianess in display_camera_video example
1 parent fd9291c commit aa97365

File tree

3 files changed

+71
-18
lines changed

3 files changed

+71
-18
lines changed

examples/display_camera_video/main/app_video.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: CC0-1.0
55
*/
@@ -14,6 +14,7 @@
1414
#include <sys/errno.h>
1515
#include "esp_err.h"
1616
#include "esp_log.h"
17+
#include <inttypes.h>
1718
#include "linux/videodev2.h"
1819
#include "esp_video_init.h"
1920
#include "app_video.h"
@@ -31,6 +32,7 @@ typedef struct {
3132
size_t camera_buf_size;
3233
uint32_t camera_buf_hes;
3334
uint32_t camera_buf_ves;
35+
uint32_t camera_pixelformat;
3436
struct v4l2_buffer v4l2_buf;
3537
uint8_t camera_mem_mode;
3638
app_video_frame_operation_cb_t user_camera_video_frame_operation_cb;
@@ -41,6 +43,23 @@ typedef struct {
4143

4244
static app_video_t app_camera_video;
4345

46+
uint32_t app_video_get_pixelformat(void)
47+
{
48+
return app_camera_video.camera_pixelformat;
49+
}
50+
51+
static void log_v4l2_fourcc(uint32_t f, const char *prefix)
52+
{
53+
char s[5] = {
54+
(char)(f & 0xff),
55+
(char)((f >> 8) & 0xff),
56+
(char)((f >> 16) & 0xff),
57+
(char)((f >> 24) & 0xff),
58+
0
59+
};
60+
ESP_LOGI(TAG, "%s: %s (0x%08" PRIx32 ")", prefix, s, f);
61+
}
62+
4463
int app_video_open(char *dev, video_fmt_t init_fmt)
4564
{
4665
struct v4l2_format default_format;
@@ -73,11 +92,10 @@ int app_video_open(char *dev, video_fmt_t init_fmt)
7392
}
7493

7594
ESP_LOGI(TAG, "width=%" PRIu32 " height=%" PRIu32, default_format.fmt.pix.width, default_format.fmt.pix.height);
95+
log_v4l2_fourcc(default_format.fmt.pix.pixelformat, "initial pixel format");
7696

77-
app_camera_video.camera_buf_hes = default_format.fmt.pix.width;
78-
app_camera_video.camera_buf_ves = default_format.fmt.pix.height;
79-
80-
if (default_format.fmt.pix.pixelformat != init_fmt) {
97+
if (init_fmt != APP_VIDEO_FMT_DRIVER_DEFAULT &&
98+
default_format.fmt.pix.pixelformat != (uint32_t)init_fmt) {
8199
struct v4l2_format format = {
82100
.type = type,
83101
.fmt.pix.width = default_format.fmt.pix.width,
@@ -116,6 +134,18 @@ int app_video_open(char *dev, video_fmt_t init_fmt)
116134
}
117135
#endif
118136

137+
memset(&default_format, 0, sizeof(struct v4l2_format));
138+
default_format.type = type;
139+
if (ioctl(fd, VIDIOC_G_FMT, &default_format) != 0) {
140+
ESP_LOGE(TAG, "failed to get final format");
141+
goto exit_0;
142+
}
143+
144+
app_camera_video.camera_buf_hes = default_format.fmt.pix.width;
145+
app_camera_video.camera_buf_ves = default_format.fmt.pix.height;
146+
app_camera_video.camera_pixelformat = default_format.fmt.pix.pixelformat;
147+
log_v4l2_fourcc(app_camera_video.camera_pixelformat, "capture pixel format");
148+
119149
app_camera_video.video_stop_sem = xSemaphoreCreateBinary();
120150

121151
return fd;

examples/display_camera_video/main/app_video.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -15,10 +15,13 @@ extern "C" {
1515
#endif
1616

1717
typedef enum {
18+
/** Keep pipeline default (e.g. from menuconfig); do not call VIDIOC_S_FMT for pixel format. */
19+
APP_VIDEO_FMT_DRIVER_DEFAULT = 0,
1820
APP_VIDEO_FMT_RAW8 = V4L2_PIX_FMT_SBGGR8,
1921
APP_VIDEO_FMT_RAW10 = V4L2_PIX_FMT_SBGGR10,
2022
APP_VIDEO_FMT_GREY = V4L2_PIX_FMT_GREY,
2123
APP_VIDEO_FMT_RGB565 = V4L2_PIX_FMT_RGB565,
24+
APP_VIDEO_FMT_RGB565_BE = V4L2_PIX_FMT_RGB565X,
2225
APP_VIDEO_FMT_RGB888 = V4L2_PIX_FMT_RGB24,
2326
APP_VIDEO_FMT_YUV422 = V4L2_PIX_FMT_YUV422P,
2427
APP_VIDEO_FMT_YUV420 = V4L2_PIX_FMT_YUV420,
@@ -36,12 +39,18 @@ typedef void (*app_video_frame_operation_cb_t)(uint8_t *camera_buf, uint8_t came
3639
* vertical or horizontal mirroring if enabled in the configuration.
3740
*
3841
* @param dev The device path of the video capture (e.g., "/dev/video0").
39-
* @param init_fmt The desired pixel format for the video capture.
42+
* @param init_fmt The desired pixel format for the video capture, or APP_VIDEO_FMT_DRIVER_DEFAULT
43+
* to use the format already configured by the driver (sensor / menuconfig).
4044
* @return Returns the file descriptor for the opened video device on success;
4145
* returns -1 on failure, indicating an error occurred during the operation.
4246
*/
4347
int app_video_open(char *dev, video_fmt_t init_fmt);
4448

49+
/**
50+
* @brief V4L2 pixelformat fourcc after app_video_open() (from VIDIOC_G_FMT).
51+
*/
52+
uint32_t app_video_get_pixelformat(void);
53+
4554
/**
4655
* @brief Set up video capture buffers.
4756
*

examples/display_camera_video/main/main.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: CC0-1.0
55
*/
@@ -43,6 +43,19 @@ static size_t data_cache_line_size = 0;
4343
static lv_obj_t *camera_canvas = NULL;
4444
static uint8_t *cam_buff[NUM_BUFS];
4545
static uint32_t cam_buff_size = 0;
46+
static lv_color_format_t lvgl_cam_rgb565_fmt;
47+
48+
static lv_color_format_t lvgl_rgb565_fmt_from_v4l2(uint32_t pixelformat)
49+
{
50+
if (pixelformat == V4L2_PIX_FMT_RGB565X) {
51+
return LV_COLOR_FORMAT_RGB565_SWAPPED;
52+
}
53+
if (pixelformat == V4L2_PIX_FMT_RGB565) {
54+
return LV_COLOR_FORMAT_RGB565;
55+
}
56+
ESP_LOGW(TAG, "Unexpected RGB565 pixel format, using LV_COLOR_FORMAT_RGB565");
57+
return LV_COLOR_FORMAT_RGB565;
58+
}
4659

4760
#if SOC_PPA_SUPPORTED
4861
static void app_ppa_init(void)
@@ -156,7 +169,7 @@ static void camera_video_frame_operation(uint8_t *camera_buf, uint8_t camera_buf
156169
#endif
157170

158171
bsp_display_lock(0);
159-
lv_canvas_set_buffer(camera_canvas, out_buf, out_w, out_h, LV_COLOR_FORMAT_RGB565);
172+
lv_canvas_set_buffer(camera_canvas, out_buf, out_w, out_h, lvgl_cam_rgb565_fmt);
160173
lv_obj_center(camera_canvas);
161174
lv_obj_invalidate(camera_canvas);
162175
bsp_display_unlock();
@@ -194,22 +207,23 @@ void app_main(void)
194207
}
195208
}
196209

210+
/* Open video first: pixel format comes from menuconfig / driver (VIDIOC_G_FMT). */
211+
int fd = app_video_open(BSP_CAMERA_DEVICE, APP_VIDEO_FMT_DRIVER_DEFAULT);
212+
if (fd < 0) {
213+
ESP_LOGE(TAG, "Failed to open video device");
214+
ESP_LOGW(TAG, "Please, try to select another camera sensor in menuconfig.");
215+
return;
216+
}
217+
lvgl_cam_rgb565_fmt = lvgl_rgb565_fmt_from_v4l2(app_video_get_pixelformat());
218+
197219
/* Create LVGL canvas for camera image */
198220
bsp_display_lock(0);
199221
camera_canvas = lv_canvas_create(lv_scr_act());
200-
lv_canvas_set_buffer(camera_canvas, cam_buff[0], BSP_LCD_H_RES, BSP_LCD_V_RES, LV_COLOR_FORMAT_RGB565);
222+
lv_canvas_set_buffer(camera_canvas, cam_buff[0], BSP_LCD_H_RES, BSP_LCD_V_RES, lvgl_cam_rgb565_fmt);
201223
assert(camera_canvas);
202224
lv_obj_center(camera_canvas);
203225
bsp_display_unlock();
204226

205-
/* Open video device */
206-
int fd = app_video_open(BSP_CAMERA_DEVICE, APP_VIDEO_FMT_RGB565);
207-
if (fd < 0) {
208-
ESP_LOGE(TAG, "Failed to open video device");
209-
ESP_LOGW(TAG, "Please, try to select another camera sensor in menuconfig.");
210-
return;
211-
}
212-
213227
/* Initialize video capture device */
214228
ret = app_video_set_bufs(fd, NUM_BUFS, NULL);
215229
if (ret != ESP_OK) {

0 commit comments

Comments
 (0)