Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/releases/migration-guide-4.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ PTP Clock
ratio adjusting based on nominal frequency. Drivers implementing :c:func:`ptp_clock_rate_adjust`
should be adjusted to account for the new behavior.

Video
*****

* The ``min_line_count`` and ``max_line_count`` fields have been removed from :c:struct:`video_caps`.
Application should base on the new :c:member:`video_format.size` to allocate buffers.

Other subsystems
****************

Expand Down
1 change: 1 addition & 0 deletions doc/releases/release-notes-4.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ New APIs and options
* Video

* :c:member:`video_format.size` field
* :c:func:`video_estimate_fmt_size`

.. zephyr-keep-sorted-stop
Expand Down
23 changes: 23 additions & 0 deletions drivers/video/video_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,26 @@ int64_t video_get_csi_link_freq(const struct device *dev, uint8_t bpp, uint8_t l
/* CSI D-PHY is using a DDR data bus so bitrate is twice the frequency */
return ctrl.val64 * bpp / (2 * lane_nb);
}

int video_estimate_fmt_size(struct video_format *fmt)
{
if (fmt == NULL) {
return -EINVAL;
}

switch (fmt->pixelformat) {
case VIDEO_PIX_FMT_JPEG:
/* Rough estimate for the worst case (quality = 100) */
fmt->pitch = 0;
fmt->size = fmt->width * fmt->height * 2;
return 0;
default:
/* Uncompressed format */
fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
if (fmt->pitch == 0) {
return -ENOTSUP;
}
fmt->size = fmt->pitch * fmt->height;
return 0;
}
}
6 changes: 5 additions & 1 deletion drivers/video/video_emul_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ static int emul_rx_set_fmt(const struct device *const dev, struct video_format *
}

/* Cache the format selected locally to use it for getting the size of the buffer */
fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

data->fmt = *fmt;

return 0;
Expand Down
13 changes: 8 additions & 5 deletions drivers/video/video_esp32_dvp.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,6 @@ static int video_esp32_get_caps(const struct device *dev, struct video_caps *cap
/* Two buffers are needed to perform transfers */
caps->min_vbuf_count = 2;

/* ESP32 produces full frames */
caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;

/* Forward the message to the source device */
return video_get_caps(config->source_dev, caps);
}
Expand All @@ -268,7 +265,10 @@ static int video_esp32_get_fmt(const struct device *dev, struct video_format *fm
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

return 0;
}
Expand All @@ -284,7 +284,10 @@ static int video_esp32_set_fmt(const struct device *dev, struct video_format *fm
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

data->video_format = *fmt;

Expand Down
5 changes: 2 additions & 3 deletions drivers/video/video_mcux_csi.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt
break;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
video_estimate_fmt_size(fmt);
}
#endif

Expand Down Expand Up @@ -168,6 +168,7 @@ static int video_mcux_csi_set_fmt(const struct device *dev, struct video_format
}

fmt->pitch = data->csi_config.linePitch_Bytes;
fmt->size = fmt->pitch * fmt->height;

return 0;
}
Expand Down Expand Up @@ -323,8 +324,6 @@ static int video_mcux_csi_get_caps(const struct device *dev, struct video_caps *

/* NXP MCUX CSI request at least 2 buffer before starting */
caps->min_vbuf_count = 2;
/* CSI only operates on buffers of full frame size */
caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;

/* no source dev */
return err;
Expand Down
4 changes: 2 additions & 2 deletions drivers/video/video_mcux_smartdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ static int nxp_video_sdma_set_format(const struct device *dev, struct video_form
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
fmt->size = fmt->pitch * SDMA_LINE_COUNT;

return 0;
}
Expand Down Expand Up @@ -271,6 +272,7 @@ static int nxp_video_sdma_get_format(const struct device *dev, struct video_form
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
fmt->size = fmt->pitch * SDMA_LINE_COUNT;

return 0;
}
Expand All @@ -279,8 +281,6 @@ static int nxp_video_sdma_get_caps(const struct device *dev, struct video_caps *
{
/* SmartDMA needs at least two buffers allocated before starting */
caps->min_vbuf_count = 2;
/* Firmware reads 30 lines per queued vbuf */
caps->min_line_count = caps->max_line_count = SDMA_LINE_COUNT;
caps->format_caps = fmts;
return 0;
}
Expand Down
11 changes: 5 additions & 6 deletions drivers/video/video_renesas_ra_ceu.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,7 @@ static int video_renesas_ra_ceu_get_format(const struct device *dev, struct vide
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;

return 0;
return video_estimate_fmt_size(fmt);
}

static int video_renesas_ra_ceu_set_format(const struct device *dev, struct video_format *fmt)
Expand Down Expand Up @@ -169,7 +167,10 @@ static int video_renesas_ra_ceu_set_format(const struct device *dev, struct vide
return -EIO;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

memcpy(&data->fmt, fmt, sizeof(struct video_format));

Expand All @@ -181,8 +182,6 @@ static int video_renesas_ra_ceu_get_caps(const struct device *dev, struct video_
const struct video_renesas_ra_ceu_config *config = dev->config;

caps->min_vbuf_count = 1;
caps->min_line_count = LINE_COUNT_HEIGHT;
caps->max_line_count = LINE_COUNT_HEIGHT;

return video_get_caps(config->source_dev, caps);
}
Expand Down
2 changes: 0 additions & 2 deletions drivers/video/video_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,6 @@ static int video_shell_print_caps(const struct shell *sh, const struct device *d
int ret;

shell_print(sh, "min vbuf count: %u", caps->min_vbuf_count);
shell_print(sh, "min line count: %u", caps->min_line_count);
shell_print(sh, "max line count: %u", caps->max_line_count);

for (size_t i = 0; caps->format_caps[i].pixelformat != 0; i++) {
ret = video_shell_print_format_cap(sh, dev, caps->type, &caps->format_caps[i], i);
Expand Down
3 changes: 0 additions & 3 deletions drivers/video/video_st_mipid02.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,6 @@ static int mipid02_get_caps(const struct device *dev, struct video_caps *caps)
}

caps->format_caps = drv_data->caps;
caps->min_vbuf_count = 1;
caps->min_line_count = LINE_COUNT_HEIGHT;
caps->max_line_count = LINE_COUNT_HEIGHT;

return 0;
}
Expand Down
13 changes: 8 additions & 5 deletions drivers/video/video_stm32_dcmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ static int video_stm32_dcmi_set_fmt(const struct device *dev, struct video_forma
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

data->fmt = *fmt;

Expand All @@ -213,7 +216,10 @@ static int video_stm32_dcmi_get_fmt(const struct device *dev, struct video_forma
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

data->fmt = *fmt;

Expand Down Expand Up @@ -309,9 +315,6 @@ static int video_stm32_dcmi_get_caps(const struct device *dev, struct video_caps
/* 2 buffers are needed for DCMI_MODE_CONTINUOUS */
caps->min_vbuf_count = 2;

/* DCMI produces full frames */
caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;

/* Forward the message to the sensor device */
return video_get_caps(config->sensor_dev, caps);
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/video/video_stm32_dcmipp.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,9 @@ static inline void stm32_dcmipp_compute_fmt_pitch(uint32_t pipe_id, struct video
fmt->pitch = ROUND_UP(fmt->pitch, 16);
}
#endif

/* Update the corresponding fmt->size */
fmt->size = fmt->pitch * fmt->height;
}

static int stm32_dcmipp_set_fmt(const struct device *dev, struct video_format *fmt)
Expand Down Expand Up @@ -1370,8 +1373,6 @@ static int stm32_dcmipp_get_caps(const struct device *dev, struct video_caps *ca
ret = video_get_caps(config->source_dev, caps);

caps->min_vbuf_count = 1;
caps->min_line_count = LINE_COUNT_HEIGHT;
caps->max_line_count = LINE_COUNT_HEIGHT;

return ret;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/video/video_stm32_venc.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,6 @@ static int stm32_venc_get_caps(const struct device *dev, struct video_caps *caps
}

/* VENC produces full frames */
caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;
caps->min_vbuf_count = 1;

return 0;
Expand Down
9 changes: 5 additions & 4 deletions drivers/video/video_sw_generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ static int video_sw_generator_set_fmt(const struct device *dev, struct video_for
return ret;
}

fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
ret = video_estimate_fmt_size(fmt);
if (ret < 0) {
return ret;
}

data->fmt = *fmt;
return 0;
Expand Down Expand Up @@ -365,9 +368,6 @@ static int video_sw_generator_get_caps(const struct device *dev, struct video_ca
caps->format_caps = fmts;
caps->min_vbuf_count = 1;

/* SW generator produces full frames */
caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT;

return 0;
}

Expand Down Expand Up @@ -477,6 +477,7 @@ static int video_sw_generator_init(const struct device *dev)
.fmt.height = 160, \
.fmt.pitch = 320 * 2, \
.fmt.pixelformat = VIDEO_PIX_FMT_RGB565, \
.fmt.size = 320 * 2 * 160, \
.frame_rate = DEFAULT_FRAME_RATE, \
}; \
\
Expand Down
38 changes: 16 additions & 22 deletions include/zephyr/drivers/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@
extern "C" {
#endif

/*
* Flag used by @ref video_caps structure to indicate endpoint operates on
* buffers the size of the video frame
*/
#define LINE_COUNT_HEIGHT (-1)

struct video_control;

/**
Expand Down Expand Up @@ -128,22 +122,6 @@ struct video_caps {
* the stream.
*/
uint8_t min_vbuf_count;
/** Denotes minimum line count of a video buffer that this endpoint
* can fill or process. Each line is expected to consume the number
* of bytes the selected video format's pitch uses, so the video
* buffer must be at least `pitch` * `min_line_count` bytes.
* `LINE_COUNT_HEIGHT` is a special value, indicating the endpoint
* only supports video buffers with at least enough bytes to store
* a full video frame
*/
int16_t min_line_count;
/**
* Denotes maximum line count of a video buffer that this endpoint
* can fill or process. Similar constraints to `min_line_count`,
* but `LINE_COUNT_HEIGHT` indicates that the endpoint will never
* fill or process more than a full video frame in one video buffer.
*/
int16_t max_line_count;
};

/**
Expand Down Expand Up @@ -988,6 +966,22 @@ void video_closest_frmival(const struct device *dev, struct video_frmival_enum *
*/
int64_t video_get_csi_link_freq(const struct device *dev, uint8_t bpp, uint8_t lane_nb);

/**
* @brief Estimate the size and pitch in bytes of a @ref video_format
*
* This helper should only be used by drivers that support the whole image frame.
*
* For uncompressed formats, it gives the actual size and pitch of the
* whole raw image without any padding.
*
* For compressed formats, it gives a rough estimate size of a complete
* compressed frame.
*
* @param fmt Pointer to the video format structure
* @return 0 on success, otherwise a negative errno code
*/
int video_estimate_fmt_size(struct video_format *fmt);

/**
* @defgroup video_pixel_formats Video pixel formats
* The '|' characters separate the pixels or logical blocks, and spaces separate the bytes.
Expand Down
12 changes: 2 additions & 10 deletions samples/drivers/video/capture/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ int main(void)
};
#endif
unsigned int frame = 0;
size_t bsize;
int i = 0;
int err;

Expand Down Expand Up @@ -276,16 +275,9 @@ int main(void)
}
#endif

/* Size to allocate for each buffer */
if (caps.min_line_count == LINE_COUNT_HEIGHT) {
bsize = fmt.pitch * fmt.height;
} else {
bsize = fmt.pitch * caps.min_line_count;
}

/* Alloc video buffers and enqueue for capture */
if (caps.min_vbuf_count > CONFIG_VIDEO_BUFFER_POOL_NUM_MAX ||
bsize > CONFIG_VIDEO_BUFFER_POOL_SZ_MAX) {
fmt.size > CONFIG_VIDEO_BUFFER_POOL_SZ_MAX) {
LOG_ERR("Not enough buffers or memory to start streaming");
return 0;
}
Expand All @@ -295,7 +287,7 @@ int main(void)
* For some hardwares, such as the PxP used on i.MX RT1170 to do image rotation,
* buffer alignment is needed in order to achieve the best performance
*/
vbuf = video_buffer_aligned_alloc(bsize, CONFIG_VIDEO_BUFFER_POOL_ALIGN,
vbuf = video_buffer_aligned_alloc(fmt.size, CONFIG_VIDEO_BUFFER_POOL_ALIGN,
K_FOREVER);
if (vbuf == NULL) {
LOG_ERR("Unable to alloc video buffer");
Expand Down
Loading