1 /**
2  * @file
3  *
4  * @brief Public APIs for Video.
5  */
6 
7 /*
8  * Copyright (c) 2019 Linaro Limited.
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 #ifndef ZEPHYR_INCLUDE_VIDEO_H_
13 #define ZEPHYR_INCLUDE_VIDEO_H_
14 
15 /**
16  * @brief Video Interface
17  * @defgroup video_interface Video Interface
18  * @since 2.1
19  * @version 1.0.0
20  * @ingroup io_interfaces
21  * @{
22  */
23 
24 #include <zephyr/device.h>
25 #include <stddef.h>
26 #include <zephyr/kernel.h>
27 
28 #include <zephyr/types.h>
29 
30 #include <zephyr/drivers/video-controls.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 
37 /**
38  * @struct video_format
39  * @brief Video format structure
40  *
41  * Used to configure frame format.
42  */
43 struct video_format {
44 	/** FourCC pixel format value (\ref video_pixel_formats) */
45 	uint32_t pixelformat;
46 	/** frame width in pixels. */
47 	uint32_t width;
48 	/** frame height in pixels. */
49 	uint32_t height;
50 	/**
51 	 * @brief line stride.
52 	 *
53 	 * This is the number of bytes that needs to be added to the address in the
54 	 * first pixel of a row in order to go to the address of the first pixel of
55 	 * the next row (>=width).
56 	 */
57 	uint32_t pitch;
58 };
59 
60 
61 /**
62  * @struct video_format_cap
63  * @brief Video format capability
64  *
65  * Used to describe a video endpoint format capability.
66  */
67 struct video_format_cap {
68 	/** FourCC pixel format value (\ref video_pixel_formats). */
69 	uint32_t pixelformat;
70 	/** minimum supported frame width in pixels. */
71 	uint32_t width_min;
72 	/** maximum supported frame width in pixels. */
73 	uint32_t width_max;
74 	/** minimum supported frame height in pixels. */
75 	uint32_t height_min;
76 	/** maximum supported frame height in pixels. */
77 	uint32_t height_max;
78 	/** width step size in pixels. */
79 	uint16_t width_step;
80 	/** height step size in pixels. */
81 	uint16_t height_step;
82 };
83 
84 /**
85  * @struct video_caps
86  * @brief Video format capabilities
87  *
88  * Used to describe video endpoint capabilities.
89  */
90 struct video_caps {
91 	/** list of video format capabilities (zero terminated). */
92 	const struct video_format_cap *format_caps;
93 	/** minimal count of video buffers to enqueue before being able to start
94 	 * the stream.
95 	 */
96 	uint8_t min_vbuf_count;
97 };
98 
99 /**
100  * @struct video_buffer
101  * @brief Video buffer structure
102  *
103  * Represent a video frame.
104  */
105 struct video_buffer {
106 	/** pointer to driver specific data. */
107 	void *driver_data;
108 	/** pointer to the start of the buffer. */
109 	uint8_t *buffer;
110 	/** size of the buffer in bytes. */
111 	uint32_t size;
112 	/** number of bytes occupied by the valid data in the buffer. */
113 	uint32_t bytesused;
114 	/** time reference in milliseconds at which the last data byte was
115 	 * actually received for input endpoints or to be consumed for output
116 	 * endpoints.
117 	 */
118 	uint32_t timestamp;
119 };
120 
121 /**
122  * @brief video_endpoint_id enum
123  *
124  * Identify the video device endpoint.
125  */
126 enum video_endpoint_id {
127 	VIDEO_EP_NONE,
128 	VIDEO_EP_ANY,
129 	VIDEO_EP_IN,
130 	VIDEO_EP_OUT,
131 };
132 
133 /**
134  * @brief video_event enum
135  *
136  * Identify video event.
137  */
138 enum video_signal_result {
139 	VIDEO_BUF_DONE,
140 	VIDEO_BUF_ABORTED,
141 	VIDEO_BUF_ERROR,
142 };
143 
144 /**
145  * @typedef video_api_set_format_t
146  * @brief Set video format
147  *
148  * See video_set_format() for argument descriptions.
149  */
150 typedef int (*video_api_set_format_t)(const struct device *dev,
151 				      enum video_endpoint_id ep,
152 				      struct video_format *fmt);
153 
154 /**
155  * @typedef video_api_get_format_t
156  * @brief Get current video format
157  *
158  * See video_get_format() for argument descriptions.
159  */
160 typedef int (*video_api_get_format_t)(const struct device *dev,
161 				      enum video_endpoint_id ep,
162 				      struct video_format *fmt);
163 
164 /**
165  * @typedef video_api_enqueue_t
166  * @brief Enqueue a buffer in the driver’s incoming queue.
167  *
168  * See video_enqueue() for argument descriptions.
169  */
170 typedef int (*video_api_enqueue_t)(const struct device *dev,
171 				   enum video_endpoint_id ep,
172 				   struct video_buffer *buf);
173 
174 /**
175  * @typedef video_api_dequeue_t
176  * @brief Dequeue a buffer from the driver’s outgoing queue.
177  *
178  * See video_dequeue() for argument descriptions.
179  */
180 typedef int (*video_api_dequeue_t)(const struct device *dev,
181 				   enum video_endpoint_id ep,
182 				   struct video_buffer **buf,
183 				   k_timeout_t timeout);
184 
185 /**
186  * @typedef video_api_flush_t
187  * @brief Flush endpoint buffers, buffer are moved from incoming queue to
188  *        outgoing queue.
189  *
190  * See video_flush() for argument descriptions.
191  */
192 typedef int (*video_api_flush_t)(const struct device *dev,
193 				 enum video_endpoint_id ep,
194 				 bool cancel);
195 
196 /**
197  * @typedef video_api_stream_start_t
198  * @brief Start the capture or output process.
199  *
200  * See video_stream_start() for argument descriptions.
201  */
202 typedef int (*video_api_stream_start_t)(const struct device *dev);
203 
204 /**
205  * @typedef video_api_stream_stop_t
206  * @brief Stop the capture or output process.
207  *
208  * See video_stream_stop() for argument descriptions.
209  */
210 typedef int (*video_api_stream_stop_t)(const struct device *dev);
211 
212 /**
213  * @typedef video_api_set_ctrl_t
214  * @brief Set a video control value.
215  *
216  * See video_set_ctrl() for argument descriptions.
217  */
218 typedef int (*video_api_set_ctrl_t)(const struct device *dev,
219 				    unsigned int cid,
220 				    void *value);
221 
222 /**
223  * @typedef video_api_get_ctrl_t
224  * @brief Get a video control value.
225  *
226  * See video_get_ctrl() for argument descriptions.
227  */
228 typedef int (*video_api_get_ctrl_t)(const struct device *dev,
229 				    unsigned int cid,
230 				    void *value);
231 
232 /**
233  * @typedef video_api_get_caps_t
234  * @brief Get capabilities of a video endpoint.
235  *
236  * See video_get_caps() for argument descriptions.
237  */
238 typedef int (*video_api_get_caps_t)(const struct device *dev,
239 				    enum video_endpoint_id ep,
240 				    struct video_caps *caps);
241 
242 /**
243  * @typedef video_api_set_signal_t
244  * @brief Register/Unregister poll signal for buffer events.
245  *
246  * See video_set_signal() for argument descriptions.
247  */
248 typedef int (*video_api_set_signal_t)(const struct device *dev,
249 				      enum video_endpoint_id ep,
250 				      struct k_poll_signal *signal);
251 
252 __subsystem struct video_driver_api {
253 	/* mandatory callbacks */
254 	video_api_set_format_t set_format;
255 	video_api_get_format_t get_format;
256 	video_api_stream_start_t stream_start;
257 	video_api_stream_stop_t stream_stop;
258 	video_api_get_caps_t get_caps;
259 	/* optional callbacks */
260 	video_api_enqueue_t enqueue;
261 	video_api_dequeue_t dequeue;
262 	video_api_flush_t flush;
263 	video_api_set_ctrl_t set_ctrl;
264 	video_api_set_ctrl_t get_ctrl;
265 	video_api_set_signal_t set_signal;
266 };
267 
268 /**
269  * @brief Set video format.
270  *
271  * Configure video device with a specific format.
272  *
273  * @param dev Pointer to the device structure for the driver instance.
274  * @param ep Endpoint ID.
275  * @param fmt Pointer to a video format struct.
276  *
277  * @retval 0 Is successful.
278  * @retval -EINVAL If parameters are invalid.
279  * @retval -ENOTSUP If format is not supported.
280  * @retval -EIO General input / output error.
281  */
video_set_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)282 static inline int video_set_format(const struct device *dev,
283 				   enum video_endpoint_id ep,
284 				   struct video_format *fmt)
285 {
286 	const struct video_driver_api *api =
287 		(const struct video_driver_api *)dev->api;
288 
289 	if (api->set_format == NULL) {
290 		return -ENOSYS;
291 	}
292 
293 	return api->set_format(dev, ep, fmt);
294 }
295 
296 /**
297  * @brief Get video format.
298  *
299  * Get video device current video format.
300  *
301  * @param dev Pointer to the device structure for the driver instance.
302  * @param ep Endpoint ID.
303  * @param fmt Pointer to video format struct.
304  *
305  * @retval pointer to video format
306  */
video_get_format(const struct device * dev,enum video_endpoint_id ep,struct video_format * fmt)307 static inline int video_get_format(const struct device *dev,
308 				   enum video_endpoint_id ep,
309 				   struct video_format *fmt)
310 {
311 	const struct video_driver_api *api =
312 		(const struct video_driver_api *)dev->api;
313 
314 	if (api->get_format == NULL) {
315 		return -ENOSYS;
316 	}
317 
318 	return api->get_format(dev, ep, fmt);
319 }
320 
321 /**
322  * @brief Enqueue a video buffer.
323  *
324  * Enqueue an empty (capturing) or filled (output) video buffer in the driver’s
325  * endpoint incoming queue.
326  *
327  * @param dev Pointer to the device structure for the driver instance.
328  * @param ep Endpoint ID.
329  * @param buf Pointer to the video buffer.
330  *
331  * @retval 0 Is successful.
332  * @retval -EINVAL If parameters are invalid.
333  * @retval -EIO General input / output error.
334  */
video_enqueue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer * buf)335 static inline int video_enqueue(const struct device *dev,
336 				enum video_endpoint_id ep,
337 				struct video_buffer *buf)
338 {
339 	const struct video_driver_api *api =
340 		(const struct video_driver_api *)dev->api;
341 
342 	if (api->enqueue == NULL) {
343 		return -ENOSYS;
344 	}
345 
346 	return api->enqueue(dev, ep, buf);
347 }
348 
349 /**
350  * @brief Dequeue a video buffer.
351  *
352  * Dequeue a filled (capturing) or displayed (output) buffer from the driver’s
353  * endpoint outgoing queue.
354  *
355  * @param dev Pointer to the device structure for the driver instance.
356  * @param ep Endpoint ID.
357  * @param buf Pointer a video buffer pointer.
358  * @param timeout Timeout
359  *
360  * @retval 0 Is successful.
361  * @retval -EINVAL If parameters are invalid.
362  * @retval -EIO General input / output error.
363  */
video_dequeue(const struct device * dev,enum video_endpoint_id ep,struct video_buffer ** buf,k_timeout_t timeout)364 static inline int video_dequeue(const struct device *dev,
365 				enum video_endpoint_id ep,
366 				struct video_buffer **buf,
367 				k_timeout_t timeout)
368 {
369 	const struct video_driver_api *api =
370 		(const struct video_driver_api *)dev->api;
371 
372 	if (api->dequeue == NULL) {
373 		return -ENOSYS;
374 	}
375 
376 	return api->dequeue(dev, ep, buf, timeout);
377 }
378 
379 
380 /**
381  * @brief Flush endpoint buffers.
382  *
383  * A call to flush finishes when all endpoint buffers have been moved from
384  * incoming queue to outgoing queue. Either because canceled or fully processed
385  * through the video function.
386  *
387  * @param dev Pointer to the device structure for the driver instance.
388  * @param ep Endpoint ID.
389  * @param cancel If true, cancel buffer processing instead of waiting for
390  *        completion.
391  *
392  * @retval 0 Is successful, -ERRNO code otherwise.
393  */
video_flush(const struct device * dev,enum video_endpoint_id ep,bool cancel)394 static inline int video_flush(const struct device *dev,
395 			      enum video_endpoint_id ep,
396 			      bool cancel)
397 {
398 	const struct video_driver_api *api =
399 		(const struct video_driver_api *)dev->api;
400 
401 	if (api->flush == NULL) {
402 		return -ENOSYS;
403 	}
404 
405 	return api->flush(dev, ep, cancel);
406 }
407 
408 /**
409  * @brief Start the video device function.
410  *
411  * video_stream_start is called to enter ‘streaming’ state (capture, output...).
412  * The driver may receive buffers with video_enqueue() before video_stream_start
413  * is called. If driver/device needs a minimum number of buffers before being
414  * able to start streaming, then driver set the min_vbuf_count to the related
415  * endpoint capabilities.
416  *
417  * @retval 0 Is successful.
418  * @retval -EIO General input / output error.
419  */
video_stream_start(const struct device * dev)420 static inline int video_stream_start(const struct device *dev)
421 {
422 	const struct video_driver_api *api =
423 		(const struct video_driver_api *)dev->api;
424 
425 	if (api->stream_start == NULL) {
426 		return -ENOSYS;
427 	}
428 
429 	return api->stream_start(dev);
430 }
431 
432 /**
433  * @brief Stop the video device function.
434  *
435  * On video_stream_stop, driver must stop any transactions or wait until they
436  * finish.
437  *
438  * @retval 0 Is successful.
439  * @retval -EIO General input / output error.
440  */
video_stream_stop(const struct device * dev)441 static inline int video_stream_stop(const struct device *dev)
442 {
443 	const struct video_driver_api *api =
444 		(const struct video_driver_api *)dev->api;
445 	int ret;
446 
447 	if (api->stream_stop == NULL) {
448 		return -ENOSYS;
449 	}
450 
451 	ret = api->stream_stop(dev);
452 	video_flush(dev, VIDEO_EP_ANY, true);
453 
454 	return ret;
455 }
456 
457 /**
458  * @brief Get the capabilities of a video endpoint.
459  *
460  * @param dev Pointer to the device structure for the driver instance.
461  * @param ep Endpoint ID.
462  * @param caps Pointer to the video_caps struct to fill.
463  *
464  * @retval 0 Is successful, -ERRNO code otherwise.
465  */
video_get_caps(const struct device * dev,enum video_endpoint_id ep,struct video_caps * caps)466 static inline int video_get_caps(const struct device *dev,
467 				 enum video_endpoint_id ep,
468 				 struct video_caps *caps)
469 {
470 	const struct video_driver_api *api =
471 		(const struct video_driver_api *)dev->api;
472 
473 	if (api->get_caps == NULL) {
474 		return -ENOSYS;
475 	}
476 
477 	return api->get_caps(dev, ep, caps);
478 }
479 
480 /**
481  * @brief Set the value of a control.
482  *
483  * This set the value of a video control, value type depends on control ID, and
484  * must be interpreted accordingly.
485  *
486  * @param dev Pointer to the device structure for the driver instance.
487  * @param cid Control ID.
488  * @param value Pointer to the control value.
489  *
490  * @retval 0 Is successful.
491  * @retval -EINVAL If parameters are invalid.
492  * @retval -ENOTSUP If format is not supported.
493  * @retval -EIO General input / output error.
494  */
video_set_ctrl(const struct device * dev,unsigned int cid,void * value)495 static inline int video_set_ctrl(const struct device *dev, unsigned int cid,
496 				 void *value)
497 {
498 	const struct video_driver_api *api =
499 		(const struct video_driver_api *)dev->api;
500 
501 	if (api->set_ctrl == NULL) {
502 		return -ENOSYS;
503 	}
504 
505 	return api->set_ctrl(dev, cid, value);
506 }
507 
508 /**
509  * @brief Get the current value of a control.
510  *
511  * This retrieve the value of a video control, value type depends on control ID,
512  * and must be interpreted accordingly.
513  *
514  * @param dev Pointer to the device structure for the driver instance.
515  * @param cid Control ID.
516  * @param value Pointer to the control value.
517  *
518  * @retval 0 Is successful.
519  * @retval -EINVAL If parameters are invalid.
520  * @retval -ENOTSUP If format is not supported.
521  * @retval -EIO General input / output error.
522  */
video_get_ctrl(const struct device * dev,unsigned int cid,void * value)523 static inline int video_get_ctrl(const struct device *dev, unsigned int cid,
524 				 void *value)
525 {
526 	const struct video_driver_api *api =
527 		(const struct video_driver_api *)dev->api;
528 
529 	if (api->get_ctrl == NULL) {
530 		return -ENOSYS;
531 	}
532 
533 	return api->get_ctrl(dev, cid, value);
534 }
535 
536 /**
537  * @brief Register/Unregister k_poll signal for a video endpoint.
538  *
539  * Register a poll signal to the endpoint, which will be signaled on frame
540  * completion (done, aborted, error). Registering a NULL poll signal
541  * unregisters any previously registered signal.
542  *
543  * @param dev Pointer to the device structure for the driver instance.
544  * @param ep Endpoint ID.
545  * @param signal Pointer to k_poll_signal
546  *
547  * @retval 0 Is successful, -ERRNO code otherwise.
548  */
video_set_signal(const struct device * dev,enum video_endpoint_id ep,struct k_poll_signal * signal)549 static inline int video_set_signal(const struct device *dev,
550 				   enum video_endpoint_id ep,
551 				   struct k_poll_signal *signal)
552 {
553 	const struct video_driver_api *api =
554 		(const struct video_driver_api *)dev->api;
555 
556 	if (api->set_signal == NULL) {
557 		return -ENOSYS;
558 	}
559 
560 	return api->set_signal(dev, ep, signal);
561 }
562 
563 /**
564  * @brief Allocate aligned video buffer.
565  *
566  * @param size Size of the video buffer (in bytes).
567  * @param align Alignment of the requested memory, must be a power of two.
568  *
569  * @retval pointer to allocated video buffer
570  */
571 struct video_buffer *video_buffer_aligned_alloc(size_t size, size_t align);
572 
573 /**
574  * @brief Allocate video buffer.
575  *
576  * @param size Size of the video buffer (in bytes).
577  *
578  * @retval pointer to allocated video buffer
579  */
580 struct video_buffer *video_buffer_alloc(size_t size);
581 
582 /**
583  * @brief Release a video buffer.
584  *
585  * @param buf Pointer to the video buffer to release.
586  */
587 void video_buffer_release(struct video_buffer *buf);
588 
589 
590 /* fourcc - four-character-code */
591 #define video_fourcc(a, b, c, d)\
592 	((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
593 
594 
595 /**
596  * @defgroup video_pixel_formats Video pixel formats
597  * @{
598  */
599 
600 /**
601  * @name Bayer formats
602  * @{
603  */
604 
605 /** BGGR8 pixel format */
606 #define VIDEO_PIX_FMT_BGGR8  video_fourcc('B', 'G', 'G', 'R') /*  8  BGBG.. GRGR.. */
607 /** GBRG8 pixel format */
608 #define VIDEO_PIX_FMT_GBRG8  video_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
609 /** GRBG8 pixel format */
610 #define VIDEO_PIX_FMT_GRBG8  video_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
611 /** RGGB8 pixel format */
612 #define VIDEO_PIX_FMT_RGGB8  video_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
613 
614 /**
615  * @}
616  */
617 
618 /**
619  * @name RGB formats
620  * @{
621  */
622 
623 /** RGB565 pixel format */
624 #define VIDEO_PIX_FMT_RGB565 video_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5 */
625 
626 /** XRGB32 pixel format */
627 #define VIDEO_PIX_FMT_XRGB32 video_fourcc('B', 'X', '2', '4') /* 32  XRGB-8-8-8-8 */
628 
629 /**
630  * @}
631  */
632 
633 /**
634  * @name YUV formats
635  * @{
636  */
637 
638 /** YUYV pixel format */
639 #define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16  Y0-Cb0 Y1-Cr0 */
640 
641 /** XYUV32 pixel format */
642 #define VIDEO_PIX_FMT_XYUV32 video_fourcc('X', 'Y', 'U', 'V') /* 32  XYUV-8-8-8-8 */
643 
644 /**
645  *
646  * @}
647  */
648 
649 /**
650  * @name JPEG formats
651  * @{
652  */
653 
654 /** JPEG pixel format */
655 #define VIDEO_PIX_FMT_JPEG   video_fourcc('J', 'P', 'E', 'G') /*  8  JPEG */
656 
657 /**
658  * @}
659  */
660 
661 /**
662  * @}
663  */
664 
665 #ifdef __cplusplus
666 }
667 #endif
668 
669 /**
670  * @}
671  */
672 
673 #endif /* ZEPHYR_INCLUDE_VIDEO_H_ */
674