Skip to content
Merged
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
25 changes: 25 additions & 0 deletions drivers/video/video_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,28 @@ 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;
break;
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;
break;
}

return 0;
}
12 changes: 9 additions & 3 deletions 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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok for this part. However I think similar one is missing in the init function of this driver since doing a get_fmt without a set first will lead just read copy the fmt structure initialized during the init, into which only pitch is set. Hence video_estimate_fmt_size can simply be called during the _init function instead of the existing fmt->pitch set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it lacks a call in init(), will add it, but we still need to call video_estimate_fmt_size() in each set_format() because the call in init() is only for the default format.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes agree. I just used this part to comment since I couldn't point the _init section of course ;)

if (ret < 0) {
return ret;
}

data->fmt = *fmt;

return 0;
Expand Down Expand Up @@ -218,8 +222,10 @@ int emul_rx_init(const struct device *dev)
return ret;
}

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

k_fifo_init(&data->fifo_in);
k_fifo_init(&data->fifo_out);
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
7 changes: 2 additions & 5 deletions drivers/video/video_mcux_csi.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt
fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV;
break;
}

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

Expand Down Expand Up @@ -168,6 +166,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 All @@ -181,7 +180,7 @@ static int video_mcux_csi_get_fmt(const struct device *dev, struct video_format
video_pix_fmt_convert(fmt, true);
#endif

return 0;
return video_estimate_fmt_size(fmt);
}

return -EIO;
Expand Down Expand Up @@ -323,8 +322,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
Loading