drivers: video: Add video_buf_type

M2M devices like ISPs or PxP have two separate buffer queues, i.e.
incoming and outcoming queues. For each API, the driver needs to
distinguish on which queue it needs to take action.

Add video buffer type to support this kind of devices.

- get_caps(), set/get_format(), enqueue()/dequeue(): the buffer type
is embeded in the video_caps, video_format and video_buffer structs

- video_stream_start/stop() : buffer type needs is sent as a parameter

Signed-off-by: Phi Bang Nguyen <phibang.nguyen@nxp.com>
This commit is contained in:
Phi Bang Nguyen 2025-03-13 18:27:19 +01:00 committed by Benjamin Cabé
parent b63fb91622
commit 9fa1aeea32
20 changed files with 99 additions and 41 deletions

View File

@ -513,6 +513,12 @@ Video
* video_endpoint_id enum has been dropped. It is no longer a parameter in any video API.
* video_buf_type enum has been added. It is a required parameter in the following video APIs:
``set_stream``
``video_stream_start``
``video_stream_stop``
Other subsystems
****************

View File

@ -1093,7 +1093,7 @@ static int gc2145_get_fmt(const struct device *dev, struct video_format *fmt)
return 0;
}
static int gc2145_set_stream(const struct device *dev, bool enable)
static int gc2145_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
const struct gc2145_config *cfg = dev->config;

View File

@ -458,7 +458,7 @@ static int mt9m114_get_fmt(const struct device *dev, struct video_format *fmt)
return 0;
}
static int mt9m114_set_stream(const struct device *dev, bool enable)
static int mt9m114_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
return enable ? mt9m114_set_state(dev, MT9M114_SYS_STATE_START_STREAMING)
: mt9m114_set_state(dev, MT9M114_SYS_STATE_ENTER_SUSPEND);

View File

@ -880,7 +880,7 @@ static int ov2640_get_fmt(const struct device *dev, struct video_format *fmt)
return 0;
}
static int ov2640_set_stream(const struct device *dev, bool enable)
static int ov2640_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
return 0;
}

View File

@ -922,7 +922,7 @@ static int ov5640_get_caps(const struct device *dev, struct video_caps *caps)
return 0;
}
static int ov5640_set_stream(const struct device *dev, bool enable)
static int ov5640_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
const struct ov5640_config *cfg = dev->config;

View File

@ -573,7 +573,7 @@ static int ov7670_init(const struct device *dev)
return ov7670_init_controls(dev);
}
static int ov7670_set_stream(const struct device *dev, bool enable)
static int ov7670_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
return 0;
}

View File

@ -515,7 +515,7 @@ static int ov7725_get_fmt(const struct device *dev, struct video_format *fmt)
return 0;
}
static int ov7725_set_stream(const struct device *dev, bool enable)
static int ov7725_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
return 0;
}

View File

@ -317,7 +317,7 @@ static int emul_imager_get_caps(const struct device *dev, struct video_caps *cap
return 0;
}
static int emul_imager_set_stream(const struct device *dev, bool enable)
static int emul_imager_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
return emul_imager_write_reg(dev, EMUL_IMAGER_REG_CTRL, enable ? 1 : 0);
}

View File

@ -86,12 +86,13 @@ static int emul_rx_get_caps(const struct device *dev, struct video_caps *caps)
return video_get_caps(cfg->source_dev, caps);
}
static int emul_rx_set_stream(const struct device *dev, bool enable)
static int emul_rx_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
const struct emul_rx_config *cfg = dev->config;
/* A real hardware driver would first start / stop its own peripheral */
return enable ? video_stream_start(cfg->source_dev) : video_stream_stop(cfg->source_dev);
return enable ? video_stream_start(cfg->source_dev, type)
: video_stream_stop(cfg->source_dev, type);
}
static void emul_rx_worker(struct k_work *work)

View File

@ -136,7 +136,7 @@ void video_esp32_dma_rx_done(const struct device *dev, void *user_data, uint32_t
video_esp32_reload_dma(data);
}
static int video_esp32_set_stream(const struct device *dev, bool enable)
static int video_esp32_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
const struct video_esp32_config *cfg = dev->config;
struct video_esp32_data *data = dev->data;
@ -149,7 +149,7 @@ static int video_esp32_set_stream(const struct device *dev, bool enable)
if (!enable) {
LOG_DBG("Stop streaming");
if (video_stream_stop(cfg->source_dev)) {
if (video_stream_stop(cfg->source_dev, type)) {
return -EIO;
}
@ -233,7 +233,7 @@ static int video_esp32_set_stream(const struct device *dev, bool enable)
cam_hal_start_streaming(&data->hal);
if (video_stream_start(cfg->source_dev)) {
if (video_stream_start(cfg->source_dev, type)) {
return -EIO;
}
data->is_streaming = true;

View File

@ -194,7 +194,8 @@ static int video_mcux_csi_get_fmt(const struct device *dev, struct video_format
return -EIO;
}
static int video_mcux_csi_set_stream(const struct device *dev, bool enable)
static int video_mcux_csi_set_stream(const struct device *dev, bool enable,
enum video_buf_type type)
{
const struct video_mcux_csi_config *config = dev->config;
struct video_mcux_csi_data *data = dev->data;
@ -206,11 +207,11 @@ static int video_mcux_csi_set_stream(const struct device *dev, bool enable)
return -EIO;
}
if (config->source_dev && video_stream_start(config->source_dev)) {
if (config->source_dev && video_stream_start(config->source_dev, type)) {
return -EIO;
}
} else {
if (config->source_dev && video_stream_stop(config->source_dev)) {
if (config->source_dev && video_stream_stop(config->source_dev, type)) {
return -EIO;
}

View File

@ -141,7 +141,7 @@ static int mipi_csi2rx_get_fmt(const struct device *dev, struct video_format *fm
return 0;
}
static int mipi_csi2rx_set_stream(const struct device *dev, bool enable)
static int mipi_csi2rx_set_stream(const struct device *dev, bool enable, enum video_buf_type type)
{
const struct mipi_csi2rx_config *config = dev->config;
@ -149,11 +149,11 @@ static int mipi_csi2rx_set_stream(const struct device *dev, bool enable)
struct mipi_csi2rx_data *drv_data = dev->data;
CSI2RX_Init((MIPI_CSI2RX_Type *)config->base, &drv_data->csi2rxConfig);
if (video_stream_start(config->sensor_dev)) {
if (video_stream_start(config->sensor_dev, type)) {
return -EIO;
}
} else {
if (video_stream_stop(config->sensor_dev)) {
if (video_stream_stop(config->sensor_dev, type)) {
return -EIO;
}
CSI2RX_Deinit((MIPI_CSI2RX_Type *)config->base);

View File

@ -95,7 +95,8 @@ static void nxp_video_sdma_callback(const struct device *dev, void *user_data,
data->buf_reload_flag = !data->buf_reload_flag;
}
static int nxp_video_sdma_set_stream(const struct device *dev, bool enable)
static int nxp_video_sdma_set_stream(const struct device *dev, bool enable,
enum video_buf_type type)
{
const struct nxp_video_sdma_config *config = dev->config;
struct nxp_video_sdma_data *data = dev->data;
@ -162,7 +163,7 @@ static int nxp_video_sdma_enqueue(const struct device *dev, struct video_buffer
k_fifo_put(&data->fifo_in, vbuf);
if (data->stream_starved) {
/* Kick SmartDMA off */
nxp_video_sdma_set_stream(dev, true);
nxp_video_sdma_set_stream(dev, true, vbuf->type);
}
return 0;
}

View File

@ -250,14 +250,15 @@ static int video_stm32_dcmi_get_fmt(const struct device *dev, struct video_forma
(capture_rate) == 4 ? DCMI_CR_ALTERNATE_4_FRAME : \
DCMI_CR_ALL_FRAME)
static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable)
static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable,
enum video_buf_type type)
{
struct video_stm32_dcmi_data *data = dev->data;
const struct video_stm32_dcmi_config *config = dev->config;
int err;
if (!enable) {
err = video_stream_stop(config->sensor_dev);
err = video_stream_stop(config->sensor_dev, type);
if (err < 0) {
return err;
}
@ -292,7 +293,7 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable)
return -EIO;
}
return video_stream_start(config->sensor_dev);
return video_stream_start(config->sensor_dev, type);
}
static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffer *vbuf)

View File

@ -95,7 +95,8 @@ static int video_sw_generator_get_fmt(const struct device *dev, struct video_for
return 0;
}
static int video_sw_generator_set_stream(const struct device *dev, bool enable)
static int video_sw_generator_set_stream(const struct device *dev, bool enable,
enum video_buf_type type)
{
struct video_sw_generator_data *data = dev->data;

View File

@ -40,6 +40,21 @@ extern "C" {
struct video_control;
/**
* @brief video_buf_type enum
*
* Supported video buffer types of a video device.
* The direction (input or output) is defined from the device's point of view.
* Devices like cameras support only output type, encoders support only input
* types while m2m devices like ISP, PxP support both input and output types.
*/
enum video_buf_type {
/** input buffer type */
VIDEO_BUF_TYPE_INPUT,
/** output buffer type */
VIDEO_BUF_TYPE_OUTPUT,
};
/**
* @struct video_format
* @brief Video format structure
@ -47,6 +62,8 @@ struct video_control;
* Used to configure frame format.
*/
struct video_format {
/** type of the buffer */
enum video_buf_type type;
/** FourCC pixel format value (\ref video_pixel_formats) */
uint32_t pixelformat;
/** frame width in pixels. */
@ -93,6 +110,8 @@ struct video_format_cap {
* Used to describe video endpoint capabilities.
*/
struct video_caps {
/** type of the buffer */
enum video_buf_type type;
/** list of video format capabilities (zero terminated). */
const struct video_format_cap *format_caps;
/** minimal count of video buffers to enqueue before being able to start
@ -124,6 +143,8 @@ struct video_caps {
* Represent a video frame.
*/
struct video_buffer {
/** type of the buffer */
enum video_buf_type type;
/** pointer to driver specific data. */
void *driver_data;
/** pointer to the start of the buffer. */
@ -290,10 +311,12 @@ typedef int (*video_api_flush_t)(const struct device *dev, bool cancel);
*
* @param dev Pointer to the device structure.
* @param enable If true, start streaming, otherwise stop streaming.
* @param type The type of the buffers stream to start or stop.
*
* @retval 0 on success, otherwise a negative errno code.
*/
typedef int (*video_api_set_stream_t)(const struct device *dev, bool enable);
typedef int (*video_api_set_stream_t)(const struct device *dev, bool enable,
enum video_buf_type type);
/**
* @typedef video_api_ctrl_t
@ -545,10 +568,13 @@ static inline int video_flush(const struct device *dev, bool cancel)
* able to start streaming, then driver set the min_vbuf_count to the related
* endpoint capabilities.
*
* @param dev Pointer to the device structure.
* @param type The type of the buffers stream to start.
*
* @retval 0 Is successful.
* @retval -EIO General input / output error.
*/
static inline int video_stream_start(const struct device *dev)
static inline int video_stream_start(const struct device *dev, enum video_buf_type type)
{
const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
@ -556,7 +582,7 @@ static inline int video_stream_start(const struct device *dev)
return -ENOSYS;
}
return api->set_stream(dev, true);
return api->set_stream(dev, true, type);
}
/**
@ -565,10 +591,13 @@ static inline int video_stream_start(const struct device *dev)
* On video_stream_stop, driver must stop any transactions or wait until they
* finish.
*
* @param dev Pointer to the device structure.
* @param type The type of the buffers stream to stop.
*
* @retval 0 Is successful.
* @retval -EIO General input / output error.
*/
static inline int video_stream_stop(const struct device *dev)
static inline int video_stream_stop(const struct device *dev, enum video_buf_type type)
{
const struct video_driver_api *api = (const struct video_driver_api *)dev->api;
int ret;
@ -577,7 +606,7 @@ static inline int video_stream_stop(const struct device *dev)
return -ENOSYS;
}
ret = api->set_stream(dev, false);
ret = api->set_stream(dev, false, type);
video_flush(dev, true);
return ret;

View File

@ -95,6 +95,7 @@ int main(void)
struct video_caps caps;
struct video_frmival frmival;
struct video_frmival_enum fie;
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT;
unsigned int frame = 0;
size_t bsize;
int i = 0;
@ -119,6 +120,7 @@ int main(void)
LOG_INF("Video device: %s", video_dev->name);
/* Get capabilities */
caps.type = type;
if (video_get_caps(video_dev, &caps)) {
LOG_ERR("Unable to retrieve video capabilities");
return 0;
@ -136,6 +138,7 @@ int main(void)
}
/* Get default/native format */
fmt.type = type;
if (video_get_format(video_dev, &fmt)) {
LOG_ERR("Unable to retrieve video format");
return 0;
@ -238,12 +241,12 @@ int main(void)
LOG_ERR("Unable to alloc video buffer");
return 0;
}
buffers[i]->type = type;
video_enqueue(video_dev, buffers[i]);
}
/* Start video capture */
if (video_stream_start(video_dev)) {
if (video_stream_start(video_dev, type)) {
LOG_ERR("Unable to start capture (interface)");
return 0;
}
@ -251,6 +254,7 @@ int main(void)
LOG_INF("Capture started");
/* Grab video frames */
vbuf->type = type;
while (1) {
err = video_dequeue(video_dev, &vbuf, K_FOREVER);
if (err) {

View File

@ -23,6 +23,7 @@ int main(void)
const struct device *display_dev;
struct video_format fmt;
struct video_caps caps;
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT;
const struct device *video_dev;
size_t bsize;
int i = 0;
@ -50,6 +51,7 @@ int main(void)
LOG_INF("- Device name: %s", video_dev->name);
/* Get capabilities */
caps.type = type;
if (video_get_caps(video_dev, &caps)) {
LOG_ERR("Unable to retrieve video capabilities");
return 0;
@ -68,6 +70,7 @@ int main(void)
}
/* Get default/native format */
fmt.type = type;
if (video_get_format(video_dev, &fmt)) {
LOG_ERR("Unable to retrieve video format");
return 0;
@ -102,7 +105,7 @@ int main(void)
LOG_ERR("Unable to alloc video buffer");
return 0;
}
buffers[i]->type = type;
video_enqueue(video_dev, buffers[i]);
}
@ -119,7 +122,7 @@ int main(void)
}
/* Start video capture */
if (video_stream_start(video_dev)) {
if (video_stream_start(video_dev, type)) {
LOG_ERR("Unable to start capture (interface)");
return 0;
}
@ -139,6 +142,7 @@ int main(void)
LOG_INF("- Capture started");
/* Grab video frames */
vbuf->type = type;
while (1) {
int err;

View File

@ -42,6 +42,7 @@ int main(void)
int i, ret, sock, client;
struct video_format fmt;
struct video_caps caps;
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT;
#if DT_HAS_CHOSEN(zephyr_camera)
const struct device *const video = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
@ -83,12 +84,14 @@ int main(void)
}
/* Get capabilities */
caps.type = type;
if (video_get_caps(video, &caps)) {
LOG_ERR("Unable to retrieve video capabilities");
return 0;
}
/* Get default/native format */
fmt.type = type;
if (video_get_format(video, &fmt)) {
LOG_ERR("Unable to retrieve video format");
return 0;
@ -109,6 +112,7 @@ int main(void)
LOG_ERR("Unable to alloc video buffer");
return 0;
}
buffers[i]->type = type;
}
/* Connection loop */
@ -129,7 +133,7 @@ int main(void)
}
/* Start video capture */
if (video_stream_start(video)) {
if (video_stream_start(video, type)) {
LOG_ERR("Unable to start video");
return 0;
}
@ -138,6 +142,7 @@ int main(void)
/* Capture loop */
i = 0;
vbuf->type = type;
do {
ret = video_dequeue(video, &vbuf, K_FOREVER);
if (ret) {
@ -159,7 +164,7 @@ int main(void)
} while (!ret);
/* stop capture */
if (video_stream_stop(video)) {
if (video_stream_stop(video, type)) {
LOG_ERR("Unable to stop video");
return 0;
}

View File

@ -16,11 +16,11 @@ ZTEST(video_common, test_video_device)
zexpect_true(device_is_ready(rx_dev));
zexpect_true(device_is_ready(imager_dev));
zexpect_ok(video_stream_start(imager_dev));
zexpect_ok(video_stream_stop(imager_dev));
zexpect_ok(video_stream_start(imager_dev, VIDEO_BUF_TYPE_OUTPUT));
zexpect_ok(video_stream_stop(imager_dev, VIDEO_BUF_TYPE_OUTPUT));
zexpect_ok(video_stream_start(rx_dev));
zexpect_ok(video_stream_stop(rx_dev));
zexpect_ok(video_stream_start(rx_dev, VIDEO_BUF_TYPE_OUTPUT));
zexpect_ok(video_stream_stop(rx_dev, VIDEO_BUF_TYPE_OUTPUT));
}
ZTEST(video_common, test_video_format)
@ -148,8 +148,10 @@ ZTEST(video_common, test_video_vbuf)
struct video_caps caps;
struct video_format fmt;
struct video_buffer *vbuf = NULL;
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT;
/* Get a list of supported format */
caps.type = type;
zexpect_ok(video_get_caps(rx_dev, &caps));
/* Pick set first format, just to use something supported */
@ -157,6 +159,7 @@ ZTEST(video_common, test_video_vbuf)
fmt.width = caps.format_caps[0].width_max;
fmt.height = caps.format_caps[0].height_max;
fmt.pitch = fmt.width * 2;
fmt.type = type;
zexpect_ok(video_set_format(rx_dev, &fmt));
/* Allocate a buffer, assuming prj.conf gives enough memory for it */
@ -164,7 +167,9 @@ ZTEST(video_common, test_video_vbuf)
zexpect_not_null(vbuf);
/* Start the virtual hardware */
zexpect_ok(video_stream_start(rx_dev));
zexpect_ok(video_stream_start(rx_dev, type));
vbuf->type = type;
/* Enqueue a first buffer */
zexpect_ok(video_enqueue(rx_dev, vbuf));
@ -186,7 +191,7 @@ ZTEST(video_common, test_video_vbuf)
zexpect_equal(vbuf->bytesused, vbuf->size);
/* Nothing left in the queue, possible to stop */
zexpect_ok(video_stream_stop(rx_dev));
zexpect_ok(video_stream_stop(rx_dev, type));
/* Nothing tested, but this should not crash */
video_buffer_release(vbuf);