| /* |
| * Copyright (c) 2019 Linaro Limited |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr.h> |
| #include <device.h> |
| |
| #include <drivers/video.h> |
| |
| #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL |
| #include <logging/log.h> |
| LOG_MODULE_REGISTER(main); |
| |
| #define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" |
| |
| #if defined(CONFIG_VIDEO_MCUX_CSI) |
| #define VIDEO_DEV DT_LABEL(DT_INST(0, nxp_imx_csi)) |
| #endif |
| |
| void main(void) |
| { |
| struct video_buffer *buffers[2], *vbuf; |
| struct video_format fmt; |
| struct video_caps caps; |
| struct device *video; |
| unsigned int frame = 0; |
| size_t bsize; |
| int i = 0; |
| |
| /* Default to software video pattern generator */ |
| video = device_get_binding(VIDEO_DEV_SW); |
| if (video == NULL) { |
| LOG_ERR("Video device %s not found", VIDEO_DEV_SW); |
| return; |
| } |
| |
| /* But would be better to use a real video device if any */ |
| #ifdef VIDEO_DEV |
| { |
| struct device *dev = device_get_binding(VIDEO_DEV); |
| |
| if (dev == NULL) { |
| LOG_ERR("Video device %s not found, " |
| "fallback to software generator.", VIDEO_DEV); |
| } else { |
| video = dev; |
| } |
| } |
| #endif |
| |
| printk("- Device name: %s\n", VIDEO_DEV); |
| |
| /* Get capabilities */ |
| if (video_get_caps(video, VIDEO_EP_OUT, &caps)) { |
| LOG_ERR("Unable to retrieve video capabilities"); |
| return; |
| } |
| |
| printk("- Capabilities:\n"); |
| while (caps.format_caps[i].pixelformat) { |
| const struct video_format_cap *fcap = &caps.format_caps[i]; |
| /* fourcc to string */ |
| printk(" %c%c%c%c width [%u; %u; %u] height [%u; %u; %u]\n", |
| (char)fcap->pixelformat, |
| (char)(fcap->pixelformat >> 8), |
| (char)(fcap->pixelformat >> 16), |
| (char)(fcap->pixelformat >> 24), |
| fcap->width_min, fcap->width_max, fcap->width_step, |
| fcap->height_min, fcap->height_max, fcap->height_step); |
| i++; |
| } |
| |
| /* Get default/native format */ |
| if (video_get_format(video, VIDEO_EP_OUT, &fmt)) { |
| LOG_ERR("Unable to retrieve video format"); |
| return; |
| } |
| |
| printk("- Default format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat, |
| (char)(fmt.pixelformat >> 8), |
| (char)(fmt.pixelformat >> 16), |
| (char)(fmt.pixelformat >> 24), |
| fmt.width, fmt.height); |
| |
| /* Size to allocate for each buffer */ |
| bsize = fmt.pitch * fmt.height; |
| |
| /* Alloc video buffers and enqueue for capture */ |
| for (i = 0; i < ARRAY_SIZE(buffers); i++) { |
| buffers[i] = video_buffer_alloc(bsize); |
| if (buffers[i] == NULL) { |
| LOG_ERR("Unable to alloc video buffer"); |
| return; |
| } |
| |
| video_enqueue(video, VIDEO_EP_OUT, buffers[i]); |
| } |
| |
| /* Start video capture */ |
| if (video_stream_start(video)) { |
| LOG_ERR("Unable to start capture (interface)"); |
| return; |
| } |
| |
| printk("Capture started\n"); |
| |
| /* Grab video frames */ |
| while (1) { |
| int err; |
| |
| err = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_FOREVER); |
| if (err) { |
| LOG_ERR("Unable to dequeue video buf"); |
| return; |
| } |
| |
| printk("\rGot frame %u! size: %u; timestamp %u ms", |
| frame++, vbuf->bytesused, vbuf->timestamp); |
| |
| err = video_enqueue(video, VIDEO_EP_OUT, vbuf); |
| if (err) { |
| LOG_ERR("Unable to requeue video buf"); |
| return; |
| } |
| } |
| } |