Skip to content

Commit 1e674fa

Browse files
committed
feat(cam): support format conversion function
1 parent 42b065b commit 1e674fa

File tree

14 files changed

+256
-3
lines changed

14 files changed

+256
-3
lines changed

components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static esp_err_t s_ctlr_csi_stop(esp_cam_ctlr_handle_t handle);
5252
static esp_err_t s_csi_ctlr_disable(esp_cam_ctlr_handle_t ctlr);
5353
static esp_err_t s_ctlr_csi_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
5454
static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
55+
static esp_err_t s_csi_ctlr_format_conversion(esp_cam_ctlr_t *handle, const cam_ctlr_format_conv_config_t *config);
5556

5657
static esp_err_t s_csi_claim_controller(csi_controller_t *controller)
5758
{
@@ -227,6 +228,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_
227228
ctlr->base.get_internal_buffer = s_csi_ctlr_get_internal_buffer;
228229
ctlr->base.get_buffer_len = s_csi_ctlr_get_buffer_length;
229230
ctlr->base.alloc_buffer = s_csi_ctlr_alloc_buffer;
231+
ctlr->base.format_conversion = s_csi_ctlr_format_conversion;
230232

231233
*ret_handle = &(ctlr->base);
232234

@@ -560,3 +562,10 @@ static void *s_csi_ctlr_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32
560562

561563
return buffer;
562564
}
565+
566+
static esp_err_t s_csi_ctlr_format_conversion(esp_cam_ctlr_t *handle, const cam_ctlr_format_conv_config_t *config)
567+
{
568+
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
569+
// CSI controller doesn't support format conversion yet
570+
return ESP_ERR_NOT_SUPPORTED;
571+
}

components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,31 @@ static void *esp_cam_ctlr_dvp_cam_alloc_buffer(esp_cam_ctlr_t *handle, size_t si
782782
return buffer;
783783
}
784784

785+
/**
786+
* @brief Configure format conversion
787+
*
788+
* @param cam_handle Camera controller handle
789+
* @param src_format Source format
790+
* @param dst_format Destination format
791+
* @return ESP_OK on success, ESP_FAIL on failure
792+
*/
793+
esp_err_t esp_cam_ctlr_dvp_format_conversion(esp_cam_ctlr_handle_t cam_handle,
794+
const cam_ctlr_format_conv_config_t *config)
795+
{
796+
if (cam_handle == NULL) {
797+
return ESP_ERR_INVALID_ARG;
798+
}
799+
800+
esp_cam_ctlr_dvp_cam_t *ctlr = (esp_cam_ctlr_dvp_cam_t *)cam_handle;
801+
802+
ESP_LOGD(TAG, "Configure format conversion: %d -> %d", config->src_format, config->dst_format);
803+
804+
// Configure color format conversion
805+
cam_hal_color_format_convert(&ctlr->hal, config);
806+
807+
return ESP_OK;
808+
}
809+
785810
/**
786811
* @brief New ESP CAM DVP controller
787812
*
@@ -876,6 +901,7 @@ esp_err_t esp_cam_new_dvp_ctlr(const esp_cam_ctlr_dvp_config_t *config, esp_cam_
876901
ctlr->base.get_internal_buffer = esp_cam_ctlr_dvp_cam_get_internal_buffer;
877902
ctlr->base.get_buffer_len = esp_cam_ctlr_get_dvp_cam_frame_buffer_len;
878903
ctlr->base.alloc_buffer = esp_cam_ctlr_dvp_cam_alloc_buffer;
904+
ctlr->base.format_conversion = esp_cam_ctlr_dvp_format_conversion;
879905

880906
*ret_handle = &ctlr->base;
881907

components/esp_driver_cam/esp_cam_ctlr.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,13 @@ void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint3
9999

100100
return handle->alloc_buffer(handle, size, buf_caps);
101101
}
102+
103+
esp_err_t esp_cam_ctlr_format_conversion(esp_cam_ctlr_handle_t handle,
104+
const cam_ctlr_format_conv_config_t *conv_cfg)
105+
{
106+
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
107+
ESP_RETURN_ON_FALSE(conv_cfg, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null conv_cfg");
108+
ESP_RETURN_ON_FALSE(handle->format_conversion, ESP_ERR_NOT_SUPPORTED, TAG, "format conversion function not supported");
109+
110+
return handle->format_conversion(handle, conv_cfg);
111+
}

components/esp_driver_cam/include/esp_cam_ctlr.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "esp_err.h"
1212
#include "esp_heap_caps.h"
1313
#include "esp_cam_ctlr_types.h"
14+
#include "hal/cam_ctlr_types.h"
1415

1516
#ifdef __cplusplus
1617
extern "C" {
@@ -150,6 +151,20 @@ esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t
150151
*/
151152
void *esp_cam_ctlr_alloc_buffer(esp_cam_ctlr_handle_t handle, size_t size, uint32_t buf_caps);
152153

154+
/**
155+
* @brief Configure format conversion
156+
*
157+
* @param[in] handle ESP CAM controller handle
158+
* @param[in] conv_cfg Color conversion configuration, contains source and destination formats
159+
*
160+
* @return
161+
* - ESP_OK on success
162+
* - ESP_ERR_INVALID_ARG: Invalid argument
163+
* - ESP_ERR_NOT_SUPPORTED: Format conversion not supported by this controller
164+
*/
165+
esp_err_t esp_cam_ctlr_format_conversion(esp_cam_ctlr_handle_t handle,
166+
const cam_ctlr_format_conv_config_t *conv_cfg);
167+
153168
#ifdef __cplusplus
154169
}
155170
#endif

components/esp_driver_cam/interface/esp_cam_ctlr_interface.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdbool.h>
99
#include "esp_err.h"
1010
#include "esp_cam_ctlr_types.h"
11+
#include "hal/cam_ctlr_types.h"
1112

1213
#ifdef __cplusplus
1314
extern "C" {
@@ -146,6 +147,19 @@ struct esp_cam_ctlr_t {
146147
*/
147148
void *(*alloc_buffer)(esp_cam_ctlr_t *, size_t, uint32_t);
148149

150+
/**
151+
* @brief Configure format conversion
152+
*
153+
* @param[in] esp_cam_ctlr_t * ESP CAM controller handle
154+
* @param[in] const cam_ctlr_format_conv_config_t * Color conversion configuration
155+
*
156+
* @return
157+
* - ESP_OK on success
158+
* - ESP_ERR_INVALID_ARG: Invalid argument
159+
* - ESP_ERR_NOT_SUPPORTED: Format conversion not supported by this controller
160+
*/
161+
esp_err_t (*format_conversion)(esp_cam_ctlr_t *, const cam_ctlr_format_conv_config_t *);
162+
149163
void *user_data; ///< User data
150164
};
151165

components/esp_driver_cam/isp_dvp/src/esp_cam_ctlr_isp_dvp.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static esp_err_t s_isp_dvp_stop(esp_cam_ctlr_handle_t handle);
8686
static esp_err_t s_isp_dvp_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_t *trans, uint32_t timeout_ms);
8787
static bool s_dvp_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data);
8888
static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_t buf_caps);
89+
static esp_err_t s_isp_dvp_format_conversion(esp_cam_ctlr_t *handle, const cam_ctlr_format_conv_config_t *config);
8990

9091
esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctlr_isp_dvp_cfg_t *ctlr_config, esp_cam_ctlr_handle_t *ret_handle)
9192
{
@@ -202,6 +203,7 @@ esp_err_t esp_cam_new_isp_dvp_ctlr(isp_proc_handle_t isp_proc, const esp_cam_ctl
202203
cam_ctlr->get_internal_buffer = s_isp_dvp_get_frame_buffer;
203204
cam_ctlr->get_buffer_len = s_isp_dvp_get_frame_buffer_length;
204205
cam_ctlr->alloc_buffer = s_isp_dvp_alloc_buffer;
206+
cam_ctlr->format_conversion = s_isp_dvp_format_conversion;
205207
*ret_handle = cam_ctlr;
206208

207209
return ESP_OK;
@@ -616,3 +618,10 @@ static void *s_isp_dvp_alloc_buffer(esp_cam_ctlr_t *handle, size_t size, uint32_
616618

617619
return buffer;
618620
}
621+
622+
static esp_err_t s_isp_dvp_format_conversion(esp_cam_ctlr_t *handle, const cam_ctlr_format_conv_config_t *config)
623+
{
624+
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
625+
// ISP DVP controller doesn't support format conversion yet
626+
return ESP_ERR_NOT_SUPPORTED;
627+
}

components/hal/cam_hal.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

77
#include "hal/cam_ll.h"
88
#include "hal/cam_hal.h"
9+
#include "hal/color_types.h"
910
#include "soc/soc_caps.h"
1011
#include "soc/cam_periph.h"
1112

13+
/**
14+
* @brief Default format conversion configuration
15+
*/
16+
#define CAM_HAL_DEFAULT_FORMAT_CONV_CONFIG { \
17+
.conv_std = COLOR_CONV_STD_RGB_YUV_BT601, \
18+
.data_width = 8, \
19+
.input_range = COLOR_RANGE_LIMIT, \
20+
.output_range = COLOR_RANGE_LIMIT \
21+
}
22+
1223
/**
1324
* @brief Configure line number to trigger interrupt
1425
*
@@ -119,3 +130,59 @@ void cam_hal_stop_streaming(cam_hal_context_t *hal)
119130
{
120131
cam_ll_stop(hal->hw);
121132
}
133+
134+
/**
135+
* @brief Configure color format conversion
136+
*
137+
* This function handles all types of color format conversions:
138+
* - YUV to RGB conversion
139+
* - RGB to YUV conversion
140+
* - YUV to YUV conversion
141+
*
142+
* Color range support:
143+
* - Full range: 0-255 for both RGB and YUV
144+
* - Limited range: RGB 16-240, YUV Y:16-240, U-V:16-235
145+
*
146+
* @param hal CAM HAL context pointer
147+
* @param config Color conversion configuration. If NULL, default config is used.
148+
*/
149+
void cam_hal_color_format_convert(cam_hal_context_t *hal,
150+
const cam_ctlr_format_conv_config_t *config)
151+
{
152+
// Use provided config or default
153+
const cam_ctlr_format_conv_config_t *cfg = config;
154+
if (cfg == NULL) {
155+
static const cam_ctlr_format_conv_config_t default_config = CAM_HAL_DEFAULT_FORMAT_CONV_CONFIG;
156+
cfg = &default_config;
157+
}
158+
159+
cam_ll_enable_rgb_yuv_convert(hal->hw, false);
160+
161+
// Extract color space from source and destination formats
162+
color_space_t src_space = COLOR_SPACE_TYPE(cfg->src_format);
163+
color_space_t dst_space = COLOR_SPACE_TYPE(cfg->dst_format);
164+
165+
// Configure conversion based on color space types
166+
if (src_space == COLOR_SPACE_YUV && dst_space == COLOR_SPACE_RGB) {
167+
// YUV to RGB conversion
168+
color_pixel_yuv_format_t yuv_format = COLOR_PIXEL_FORMAT(cfg->src_format);
169+
cam_ll_set_convert_mode_yuv_to_rgb(hal->hw, yuv_format);
170+
} else if (src_space == COLOR_SPACE_RGB && dst_space == COLOR_SPACE_YUV) {
171+
// RGB to YUV conversion
172+
color_pixel_yuv_format_t yuv_format = COLOR_PIXEL_FORMAT(cfg->dst_format);
173+
cam_ll_set_convert_mode_rgb_to_yuv(hal->hw, yuv_format);
174+
} else if (src_space == COLOR_SPACE_YUV && dst_space == COLOR_SPACE_YUV) {
175+
// YUV to YUV conversion
176+
color_pixel_yuv_format_t src_yuv_format = COLOR_PIXEL_FORMAT(cfg->src_format);
177+
color_pixel_yuv_format_t dst_yuv_format = COLOR_PIXEL_FORMAT(cfg->dst_format);
178+
cam_ll_set_convert_mode_yuv_to_yuv(hal->hw, src_yuv_format, dst_yuv_format);
179+
}
180+
181+
// Common configuration for all conversion types
182+
cam_ll_set_yuv_convert_std(hal->hw, cfg->conv_std);
183+
cam_ll_set_convert_data_width(hal->hw, cfg->data_width);
184+
cam_ll_set_input_color_range(hal->hw, cfg->input_range);
185+
cam_ll_set_output_color_range(hal->hw, cfg->output_range);
186+
187+
cam_ll_enable_rgb_yuv_convert(hal->hw, true);
188+
}

components/hal/include/hal/cam_ctlr_types.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -39,6 +39,18 @@ typedef enum {
3939
CAM_CTLR_DATA_WIDTH_16 = 16, ///< 16-bit data width
4040
} cam_ctlr_data_width_t;
4141

42+
/**
43+
* @brief Camera Controller format conversion configuration
44+
*/
45+
typedef struct {
46+
cam_ctlr_color_t src_format; /*!< Source format */
47+
cam_ctlr_color_t dst_format; /*!< Destination format */
48+
color_conv_std_rgb_yuv_t conv_std; /*!< Conversion standard */
49+
uint32_t data_width; /*!< Data width in bits */
50+
color_range_t input_range; /*!< Input color range */
51+
color_range_t output_range; /*!< Output color range */
52+
} cam_ctlr_format_conv_config_t;
53+
4254
#ifdef __cplusplus
4355
}
4456
#endif

components/hal/include/hal/cam_hal.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -68,6 +68,24 @@ void cam_hal_start_streaming(cam_hal_context_t *hal);
6868
*/
6969
void cam_hal_stop_streaming(cam_hal_context_t *hal);
7070

71+
/**
72+
* @brief Configure color format conversion
73+
*
74+
* This function handles all types of color format conversions:
75+
* - YUV to RGB conversion
76+
* - RGB to YUV conversion
77+
* - YUV to YUV conversion
78+
*
79+
* Color range support:
80+
* - Full range: 0-255 for both RGB and YUV
81+
* - Limited range: RGB 16-240, YUV Y:16-240, U-V:16-235
82+
*
83+
* @param hal CAM HAL context pointer
84+
* @param config Color conversion configuration. If NULL, default config is used.
85+
*/
86+
void cam_hal_color_format_convert(cam_hal_context_t *hal,
87+
const cam_ctlr_format_conv_config_t *config);
88+
7189
#ifdef __cplusplus
7290
}
7391
#endif

docs/en/api-reference/peripherals/camera_driver.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ Camera controller driver can be implemented in one of following ways:
119119

120120
After calling :cpp:func:`esp_cam_new_dvp_ctlr`, you should allocate a camera buffer that meets the alignment constraints, or call :cpp:func:`esp_cam_ctlr_alloc_buffer` to automatically allocate.
121121

122+
You can call :cpp:func:`esp_cam_ctlr_format_conversion` to configure format conversion. The driver supports the following conversion types:
123+
124+
* YUV to RGB conversion
125+
* RGB to YUV conversion
126+
* YUV to YUV conversion
127+
128+
Color range support:
129+
* Full range: 0-255 for both RGB and YUV
130+
* Limited range: RGB 16-240, YUV Y:16-240, U-V:16-235
131+
122132
.. code:: c
123133
124134
esp_cam_ctlr_handle_t cam_handle = NULL;
@@ -153,6 +163,16 @@ Camera controller driver can be implemented in one of following ways:
153163
154164
ESP_ERROR_CHECK(esp_cam_new_dvp_ctlr(&dvp_config, &cam_handle));
155165
166+
const cam_ctlr_format_conv_config_t conv_cfg = {
167+
.src_format = CAM_CTLR_COLOR_YUV422, // Source format: YUV422
168+
.dst_format = CAM_CTLR_COLOR_RGB565, // Destination format: RGB565
169+
.conv_std = COLOR_CONV_STD_RGB_YUV_BT601,
170+
.data_width = 8,
171+
.input_range = COLOR_RANGE_LIMIT,
172+
.output_range = COLOR_RANGE_LIMIT,
173+
};
174+
ESP_ERROR_CHECK(esp_cam_ctlr_format_conversion(cam_handle, &conv_cfg));
175+
156176
Uninstall Camera Controller Driver
157177
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158178

0 commit comments

Comments
 (0)