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