diff --git a/doc/releases/migration-guide-4.2.rst b/doc/releases/migration-guide-4.2.rst index 3d632a45bbd..1d440882e6e 100644 --- a/doc/releases/migration-guide-4.2.rst +++ b/doc/releases/migration-guide-4.2.rst @@ -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 **************** diff --git a/drivers/video/gc2145.c b/drivers/video/gc2145.c index 2725026353f..ad724a98983 100644 --- a/drivers/video/gc2145.c +++ b/drivers/video/gc2145.c @@ -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; diff --git a/drivers/video/mt9m114.c b/drivers/video/mt9m114.c index d690e327bc5..ec855474409 100644 --- a/drivers/video/mt9m114.c +++ b/drivers/video/mt9m114.c @@ -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); diff --git a/drivers/video/ov2640.c b/drivers/video/ov2640.c index ef02f73dea9..7a660cbb643 100644 --- a/drivers/video/ov2640.c +++ b/drivers/video/ov2640.c @@ -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; } diff --git a/drivers/video/ov5640.c b/drivers/video/ov5640.c index 76ecb764b77..9610a9ccaa4 100644 --- a/drivers/video/ov5640.c +++ b/drivers/video/ov5640.c @@ -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; diff --git a/drivers/video/ov7670.c b/drivers/video/ov7670.c index 8ecc733c32d..3b6ad6ac288 100644 --- a/drivers/video/ov7670.c +++ b/drivers/video/ov7670.c @@ -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; } diff --git a/drivers/video/ov7725.c b/drivers/video/ov7725.c index 49a83125a60..1f9834c7910 100644 --- a/drivers/video/ov7725.c +++ b/drivers/video/ov7725.c @@ -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; } diff --git a/drivers/video/video_emul_imager.c b/drivers/video/video_emul_imager.c index 9f73cb38522..43b4982a89f 100644 --- a/drivers/video/video_emul_imager.c +++ b/drivers/video/video_emul_imager.c @@ -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); } diff --git a/drivers/video/video_emul_rx.c b/drivers/video/video_emul_rx.c index 4e9c54f27a2..2a67559cb44 100644 --- a/drivers/video/video_emul_rx.c +++ b/drivers/video/video_emul_rx.c @@ -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) diff --git a/drivers/video/video_esp32_dvp.c b/drivers/video/video_esp32_dvp.c index 811927be930..d0eebe40b13 100644 --- a/drivers/video/video_esp32_dvp.c +++ b/drivers/video/video_esp32_dvp.c @@ -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; diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 9835950b1ff..38807290240 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -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; } diff --git a/drivers/video/video_mcux_mipi_csi2rx.c b/drivers/video/video_mcux_mipi_csi2rx.c index 84cd29af317..2e7bdd32a20 100644 --- a/drivers/video/video_mcux_mipi_csi2rx.c +++ b/drivers/video/video_mcux_mipi_csi2rx.c @@ -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); diff --git a/drivers/video/video_mcux_smartdma.c b/drivers/video/video_mcux_smartdma.c index d3254007f07..5a6e65f6ebf 100644 --- a/drivers/video/video_mcux_smartdma.c +++ b/drivers/video/video_mcux_smartdma.c @@ -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; } diff --git a/drivers/video/video_stm32_dcmi.c b/drivers/video/video_stm32_dcmi.c index 05faa79716f..f27a06da16b 100644 --- a/drivers/video/video_stm32_dcmi.c +++ b/drivers/video/video_stm32_dcmi.c @@ -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) diff --git a/drivers/video/video_sw_generator.c b/drivers/video/video_sw_generator.c index fca00ac1ab7..526a3549ee1 100644 --- a/drivers/video/video_sw_generator.c +++ b/drivers/video/video_sw_generator.c @@ -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; diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index c004e30fe75..d8d4594d6f2 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -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; diff --git a/samples/drivers/video/capture/src/main.c b/samples/drivers/video/capture/src/main.c index dfcf34513b1..f5afea59254 100644 --- a/samples/drivers/video/capture/src/main.c +++ b/samples/drivers/video/capture/src/main.c @@ -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) { diff --git a/samples/drivers/video/capture_to_lvgl/src/main.c b/samples/drivers/video/capture_to_lvgl/src/main.c index 85a1ae8de24..81883577ad8 100644 --- a/samples/drivers/video/capture_to_lvgl/src/main.c +++ b/samples/drivers/video/capture_to_lvgl/src/main.c @@ -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; diff --git a/samples/drivers/video/tcpserversink/src/main.c b/samples/drivers/video/tcpserversink/src/main.c index 90bec617ea0..85d321bf8e7 100644 --- a/samples/drivers/video/tcpserversink/src/main.c +++ b/samples/drivers/video/tcpserversink/src/main.c @@ -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; } diff --git a/tests/drivers/video/api/src/video_emul.c b/tests/drivers/video/api/src/video_emul.c index 0c4e4a8751c..3013ea84bef 100644 --- a/tests/drivers/video/api/src/video_emul.c +++ b/tests/drivers/video/api/src/video_emul.c @@ -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);