blob: 84b5558390e85e4b484adbf307d7e97523c86483 [file] [log] [blame]
/**
* @file
*
* @brief Public APIs for Video.
*/
/*
* Copyright (c) 2019 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_VIDEO_H_
#define ZEPHYR_INCLUDE_VIDEO_H_
/**
* @brief Video Interface
* @defgroup video_interface Video Interface
* @since 2.1
* @version 1.0.0
* @ingroup io_interfaces
* @{
*/
#include <zephyr/device.h>
#include <stddef.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <zephyr/drivers/video-controls.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @struct video_format
* @brief Video format structure
*
* Used to configure frame format.
*/
struct video_format {
/** FourCC pixel format value (\ref video_pixel_formats) */
uint32_t pixelformat;
/** frame width in pixels. */
uint32_t width;
/** frame height in pixels. */
uint32_t height;
/**
* @brief line stride.
*
* This is the number of bytes that needs to be added to the address in the
* first pixel of a row in order to go to the address of the first pixel of
* the next row (>=width).
*/
uint32_t pitch;
};
/**
* @struct video_format_cap
* @brief Video format capability
*
* Used to describe a video endpoint format capability.
*/
struct video_format_cap {
/** FourCC pixel format value (\ref video_pixel_formats). */
uint32_t pixelformat;
/** minimum supported frame width in pixels. */
uint32_t width_min;
/** maximum supported frame width in pixels. */
uint32_t width_max;
/** minimum supported frame height in pixels. */
uint32_t height_min;
/** maximum supported frame height in pixels. */
uint32_t height_max;
/** width step size in pixels. */
uint16_t width_step;
/** height step size in pixels. */
uint16_t height_step;
};
/**
* @struct video_caps
* @brief Video format capabilities
*
* Used to describe video endpoint capabilities.
*/
struct video_caps {
/** 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
* the stream.
*/
uint8_t min_vbuf_count;
};
/**
* @struct video_buffer
* @brief Video buffer structure
*
* Represent a video frame.
*/
struct video_buffer {
/** pointer to driver specific data. */
void *driver_data;
/** pointer to the start of the buffer. */
uint8_t *buffer;
/** size of the buffer in bytes. */
uint32_t size;
/** number of bytes occupied by the valid data in the buffer. */
uint32_t bytesused;
/** time reference in milliseconds at which the last data byte was
* actually received for input endpoints or to be consumed for output
* endpoints.
*/
uint32_t timestamp;
};
/**
* @brief video_endpoint_id enum
*
* Identify the video device endpoint.
*/
enum video_endpoint_id {
VIDEO_EP_NONE,
VIDEO_EP_ANY,
VIDEO_EP_IN,
VIDEO_EP_OUT,
};
/**
* @brief video_event enum
*
* Identify video event.
*/
enum video_signal_result {
VIDEO_BUF_DONE,
VIDEO_BUF_ABORTED,
VIDEO_BUF_ERROR,
};
/**
* @typedef video_api_set_format_t
* @brief Set video format
*
* See video_set_format() for argument descriptions.
*/
typedef int (*video_api_set_format_t)(const struct device *dev,
enum video_endpoint_id ep,
struct video_format *fmt);
/**
* @typedef video_api_get_format_t
* @brief Get current video format
*
* See video_get_format() for argument descriptions.
*/
typedef int (*video_api_get_format_t)(const struct device *dev,
enum video_endpoint_id ep,
struct video_format *fmt);
/**
* @typedef video_api_enqueue_t
* @brief Enqueue a buffer in the driver’s incoming queue.
*
* See video_enqueue() for argument descriptions.
*/
typedef int (*video_api_enqueue_t)(const struct device *dev,
enum video_endpoint_id ep,
struct video_buffer *buf);
/**
* @typedef video_api_dequeue_t
* @brief Dequeue a buffer from the driver’s outgoing queue.
*
* See video_dequeue() for argument descriptions.
*/
typedef int (*video_api_dequeue_t)(const struct device *dev,
enum video_endpoint_id ep,
struct video_buffer **buf,
k_timeout_t timeout);
/**
* @typedef video_api_flush_t
* @brief Flush endpoint buffers, buffer are moved from incoming queue to
* outgoing queue.
*
* See video_flush() for argument descriptions.
*/
typedef int (*video_api_flush_t)(const struct device *dev,
enum video_endpoint_id ep,
bool cancel);
/**
* @typedef video_api_stream_start_t
* @brief Start the capture or output process.
*
* See video_stream_start() for argument descriptions.
*/
typedef int (*video_api_stream_start_t)(const struct device *dev);
/**
* @typedef video_api_stream_stop_t
* @brief Stop the capture or output process.
*
* See video_stream_stop() for argument descriptions.
*/
typedef int (*video_api_stream_stop_t)(const struct device *dev);
/**
* @typedef video_api_set_ctrl_t
* @brief Set a video control value.
*
* See video_set_ctrl() for argument descriptions.
*/
typedef int (*video_api_set_ctrl_t)(const struct device *dev,
unsigned int cid,
void *value);
/**
* @typedef video_api_get_ctrl_t
* @brief Get a video control value.
*
* See video_get_ctrl() for argument descriptions.
*/
typedef int (*video_api_get_ctrl_t)(const struct device *dev,
unsigned int cid,
void *value);
/**
* @typedef video_api_get_caps_t
* @brief Get capabilities of a video endpoint.
*
* See video_get_caps() for argument descriptions.
*/
typedef int (*video_api_get_caps_t)(const struct device *dev,
enum video_endpoint_id ep,
struct video_caps *caps);
/**
* @typedef video_api_set_signal_t
* @brief Register/Unregister poll signal for buffer events.
*
* See video_set_signal() for argument descriptions.
*/
typedef int (*video_api_set_signal_t)(const struct device *dev,
enum video_endpoint_id ep,
struct k_poll_signal *signal);
__subsystem struct video_driver_api {
/* mandatory callbacks */
video_api_set_format_t set_format;
video_api_get_format_t get_format;
video_api_stream_start_t stream_start;
video_api_stream_stop_t stream_stop;
video_api_get_caps_t get_caps;
/* optional callbacks */
video_api_enqueue_t enqueue;
video_api_dequeue_t dequeue;
video_api_flush_t flush;
video_api_set_ctrl_t set_ctrl;
video_api_set_ctrl_t get_ctrl;
video_api_set_signal_t set_signal;
};
/**
* @brief Set video format.
*
* Configure video device with a specific format.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param fmt Pointer to a video format struct.
*
* @retval 0 Is successful.
* @retval -EINVAL If parameters are invalid.
* @retval -ENOTSUP If format is not supported.
* @retval -EIO General input / output error.
*/
static inline int video_set_format(const struct device *dev,
enum video_endpoint_id ep,
struct video_format *fmt)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->set_format == NULL) {
return -ENOSYS;
}
return api->set_format(dev, ep, fmt);
}
/**
* @brief Get video format.
*
* Get video device current video format.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param fmt Pointer to video format struct.
*
* @retval pointer to video format
*/
static inline int video_get_format(const struct device *dev,
enum video_endpoint_id ep,
struct video_format *fmt)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->get_format == NULL) {
return -ENOSYS;
}
return api->get_format(dev, ep, fmt);
}
/**
* @brief Enqueue a video buffer.
*
* Enqueue an empty (capturing) or filled (output) video buffer in the driver’s
* endpoint incoming queue.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param buf Pointer to the video buffer.
*
* @retval 0 Is successful.
* @retval -EINVAL If parameters are invalid.
* @retval -EIO General input / output error.
*/
static inline int video_enqueue(const struct device *dev,
enum video_endpoint_id ep,
struct video_buffer *buf)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->enqueue == NULL) {
return -ENOSYS;
}
return api->enqueue(dev, ep, buf);
}
/**
* @brief Dequeue a video buffer.
*
* Dequeue a filled (capturing) or displayed (output) buffer from the driver’s
* endpoint outgoing queue.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param buf Pointer a video buffer pointer.
* @param timeout Timeout
*
* @retval 0 Is successful.
* @retval -EINVAL If parameters are invalid.
* @retval -EIO General input / output error.
*/
static inline int video_dequeue(const struct device *dev,
enum video_endpoint_id ep,
struct video_buffer **buf,
k_timeout_t timeout)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->dequeue == NULL) {
return -ENOSYS;
}
return api->dequeue(dev, ep, buf, timeout);
}
/**
* @brief Flush endpoint buffers.
*
* A call to flush finishes when all endpoint buffers have been moved from
* incoming queue to outgoing queue. Either because canceled or fully processed
* through the video function.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param cancel If true, cancel buffer processing instead of waiting for
* completion.
*
* @retval 0 Is successful, -ERRNO code otherwise.
*/
static inline int video_flush(const struct device *dev,
enum video_endpoint_id ep,
bool cancel)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->flush == NULL) {
return -ENOSYS;
}
return api->flush(dev, ep, cancel);
}
/**
* @brief Start the video device function.
*
* video_stream_start is called to enter ‘streaming’ state (capture, output...).
* The driver may receive buffers with video_enqueue() before video_stream_start
* is called. If driver/device needs a minimum number of buffers before being
* able to start streaming, then driver set the min_vbuf_count to the related
* endpoint capabilities.
*
* @retval 0 Is successful.
* @retval -EIO General input / output error.
*/
static inline int video_stream_start(const struct device *dev)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->stream_start == NULL) {
return -ENOSYS;
}
return api->stream_start(dev);
}
/**
* @brief Stop the video device function.
*
* On video_stream_stop, driver must stop any transactions or wait until they
* finish.
*
* @retval 0 Is successful.
* @retval -EIO General input / output error.
*/
static inline int video_stream_stop(const struct device *dev)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
int ret;
if (api->stream_stop == NULL) {
return -ENOSYS;
}
ret = api->stream_stop(dev);
video_flush(dev, VIDEO_EP_ANY, true);
return ret;
}
/**
* @brief Get the capabilities of a video endpoint.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param caps Pointer to the video_caps struct to fill.
*
* @retval 0 Is successful, -ERRNO code otherwise.
*/
static inline int video_get_caps(const struct device *dev,
enum video_endpoint_id ep,
struct video_caps *caps)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->get_caps == NULL) {
return -ENOSYS;
}
return api->get_caps(dev, ep, caps);
}
/**
* @brief Set the value of a control.
*
* This set the value of a video control, value type depends on control ID, and
* must be interpreted accordingly.
*
* @param dev Pointer to the device structure for the driver instance.
* @param cid Control ID.
* @param value Pointer to the control value.
*
* @retval 0 Is successful.
* @retval -EINVAL If parameters are invalid.
* @retval -ENOTSUP If format is not supported.
* @retval -EIO General input / output error.
*/
static inline int video_set_ctrl(const struct device *dev, unsigned int cid,
void *value)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->set_ctrl == NULL) {
return -ENOSYS;
}
return api->set_ctrl(dev, cid, value);
}
/**
* @brief Get the current value of a control.
*
* This retrieve the value of a video control, value type depends on control ID,
* and must be interpreted accordingly.
*
* @param dev Pointer to the device structure for the driver instance.
* @param cid Control ID.
* @param value Pointer to the control value.
*
* @retval 0 Is successful.
* @retval -EINVAL If parameters are invalid.
* @retval -ENOTSUP If format is not supported.
* @retval -EIO General input / output error.
*/
static inline int video_get_ctrl(const struct device *dev, unsigned int cid,
void *value)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->get_ctrl == NULL) {
return -ENOSYS;
}
return api->get_ctrl(dev, cid, value);
}
/**
* @brief Register/Unregister k_poll signal for a video endpoint.
*
* Register a poll signal to the endpoint, which will be signaled on frame
* completion (done, aborted, error). Registering a NULL poll signal
* unregisters any previously registered signal.
*
* @param dev Pointer to the device structure for the driver instance.
* @param ep Endpoint ID.
* @param signal Pointer to k_poll_signal
*
* @retval 0 Is successful, -ERRNO code otherwise.
*/
static inline int video_set_signal(const struct device *dev,
enum video_endpoint_id ep,
struct k_poll_signal *signal)
{
const struct video_driver_api *api =
(const struct video_driver_api *)dev->api;
if (api->set_signal == NULL) {
return -ENOSYS;
}
return api->set_signal(dev, ep, signal);
}
/**
* @brief Allocate aligned video buffer.
*
* @param size Size of the video buffer (in bytes).
* @param align Alignment of the requested memory, must be a power of two.
*
* @retval pointer to allocated video buffer
*/
struct video_buffer *video_buffer_aligned_alloc(size_t size, size_t align);
/**
* @brief Allocate video buffer.
*
* @param size Size of the video buffer (in bytes).
*
* @retval pointer to allocated video buffer
*/
struct video_buffer *video_buffer_alloc(size_t size);
/**
* @brief Release a video buffer.
*
* @param buf Pointer to the video buffer to release.
*/
void video_buffer_release(struct video_buffer *buf);
/* fourcc - four-character-code */
#define video_fourcc(a, b, c, d)\
((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
/**
* @defgroup video_pixel_formats Video pixel formats
* @{
*/
/**
* @name Bayer formats
* @{
*/
/** BGGR8 pixel format */
#define VIDEO_PIX_FMT_BGGR8 video_fourcc('B', 'G', 'G', 'R') /* 8 BGBG.. GRGR.. */
/** GBRG8 pixel format */
#define VIDEO_PIX_FMT_GBRG8 video_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
/** GRBG8 pixel format */
#define VIDEO_PIX_FMT_GRBG8 video_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */
/** RGGB8 pixel format */
#define VIDEO_PIX_FMT_RGGB8 video_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */
/**
* @}
*/
/**
* @name RGB formats
* @{
*/
/** RGB565 pixel format */
#define VIDEO_PIX_FMT_RGB565 video_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
/** XRGB32 pixel format */
#define VIDEO_PIX_FMT_XRGB32 video_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */
/**
* @}
*/
/**
* @name YUV formats
* @{
*/
/** YUYV pixel format */
#define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16 Y0-Cb0 Y1-Cr0 */
/** XYUV32 pixel format */
#define VIDEO_PIX_FMT_XYUV32 video_fourcc('X', 'Y', 'U', 'V') /* 32 XYUV-8-8-8-8 */
/**
*
* @}
*/
/**
* @name JPEG formats
* @{
*/
/** JPEG pixel format */
#define VIDEO_PIX_FMT_JPEG video_fourcc('J', 'P', 'E', 'G') /* 8 JPEG */
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_VIDEO_H_ */