From fcbb56f7fa51f83b9ccd078cee6174f7cdc7fcb0 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 4 Apr 2022 17:13:44 +0200 Subject: [PATCH] Add links --- Makefile | 2 +- buffer_list.c | 4 +-- links.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++- links.h | 4 ++- main.c | 75 ++++++++++++++++++++++----------------------------- v4l2.c | 2 +- 6 files changed, 111 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index 261bebb..a1c0e28 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ camera_stream: *.c *.h - gcc -o camera_stream *.c \ No newline at end of file + gcc -g -o camera_stream *.c \ No newline at end of file diff --git a/buffer_list.c b/buffer_list.c index 8a77e37..76b9adc 100644 --- a/buffer_list.c +++ b/buffer_list.c @@ -90,8 +90,8 @@ int buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned hei E_LOG_DEBUG(buf_list, "Configuring format ..."); E_XIOCTL(buf_list, buf_list->device->fd, VIDIOC_S_FMT, fmt, "Can't set format"); - if (fmt->fmt.pix.width != width || fmt->fmt.pix.height != height) { - E_LOG_INFO(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u.", + if (fmt->fmt.pix.width != width || fmt->fmt.pix.height < height) { + E_LOG_ERROR(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u.", width, height, fmt->fmt.pix.width, fmt->fmt.pix.height); } diff --git a/links.c b/links.c index 7eaf36b..1e9be4e 100644 --- a/links.c +++ b/links.c @@ -46,7 +46,7 @@ int _build_fds(link_t *all_links, struct pollfd *fds, link_t **links, buffer_lis return n; } -int handle_links(link_t *all_links, int timeout) +int links_step(link_t *all_links, int timeout) { struct pollfd fds[N_FDS] = {0}; link_t *links[N_FDS]; @@ -85,3 +85,74 @@ int handle_links(link_t *all_links, int timeout) } return 0; } + +int links_stream(link_t *all_links, bool do_stream) +{ + for (int i = 0; all_links[i].capture; i++) { + if (device_stream(all_links[i].capture, true) < 0) { + E_LOG_ERROR(all_links[i].capture, "Failed to start streaming"); + } + } + + return 0; + +error: + return -1; +} + +int links_init(link_t *all_links) +{ + // create all outputs (sinks) + for (int i = 0; all_links[i].capture; i++) { + link_t *link = &all_links[i]; + + if (!link->capture) { + E_LOG_ERROR(NULL, "Missing link capture."); + } + if (!link->capture->capture_list) { + E_LOG_ERROR(link->capture, "Missing capture device."); + } + + for (int j = 0; link->outputs[j]; j++) { + device_t *output = link->outputs[j]; + + if (output->output_list) { + E_LOG_ERROR(output, "Device already has output created. Duplicate?"); + } + + int ret = device_open_buffer_list(output, false, + link->capture->capture_list->fmt_width, + link->capture->capture_list->fmt_height, + link->capture->capture_list->fmt_format, + link->capture->capture_list->nbufs, + true + ); + + if (ret < 0) { + E_LOG_ERROR(output, "Failed to create capture."); + } + } + } + + return 0; + +error: + return -1; +} + +int links_loop(link_t *all_links, bool *running) +{ + if (links_stream(all_links, true) < 0) { + return -1; + } + + *running = true; + + while(*running) { + if (links_step(all_links, 1000) < 0) { + return -1; + } + } + + return 0; +} \ No newline at end of file diff --git a/links.h b/links.h index 4990113..a3ad92c 100644 --- a/links.h +++ b/links.h @@ -8,4 +8,6 @@ typedef struct link_s { void (*on_buffer)(struct buffer_s *buf); } link_t; -int handle_links(link_t *all_links, int timeout); +int links_init(link_t *all_links); +int links_step(link_t *all_links, int timeout); +int links_loop(link_t *all_links, bool *running); diff --git a/main.c b/main.c index ea4707a..2077e4a 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ int camera_width = 1920; int camera_height = 1080; int camera_format = V4L2_PIX_FMT_SRGGB10P; int camera_nbufs = 4; +bool camera_use_low = false; device_t *camera = NULL; device_t *isp_srgb = NULL; @@ -17,11 +18,6 @@ device_t *codec_jpeg = NULL; int open_camera(const char *path) { - camera = device_open("CAMERA", path); - if (!camera) { - return -1; - } - if (device_open_buffer_list(camera, true, camera_width, camera_height, camera_format, camera_nbufs, true) < 0) { return -1; } @@ -31,14 +27,6 @@ int open_camera(const char *path) int open_isp(buffer_list_t *src, const char *srgb_path, const char *yuuv_path, const char *yuuv_low_path) { - isp_srgb = device_open("ISP-SRGB", srgb_path); - isp_yuuv = device_open("ISP-YUUV", yuuv_path); - isp_yuuv_low = device_open("ISP-YUUV-LOW", yuuv_low_path); - - if (!isp_srgb || !isp_yuuv || !isp_yuuv_low) { - return -1; - } - if (device_open_buffer_list(isp_srgb, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs, true) < 0 || device_open_buffer_list(isp_yuuv, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_YUYV, camera_nbufs, true) < 0 || device_open_buffer_list(isp_yuuv_low, true, src->fmt_width / 2, src->fmt_height / 2, V4L2_PIX_FMT_YUYV, camera_nbufs, true) < 0) { @@ -48,13 +36,8 @@ int open_isp(buffer_list_t *src, const char *srgb_path, const char *yuuv_path, c return 0; } -int open_jpeg(buffer_list_t *src, const char *jpeg_codec) +int open_jpeg(buffer_list_t *src, const char *tmp) { - codec_jpeg = device_open("JPEG", jpeg_codec); - if (!codec_jpeg) { - return -1; - } - if (device_open_buffer_list(codec_jpeg, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs, false) < 0 || device_open_buffer_list(codec_jpeg, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_JPEG, camera_nbufs, false) < 0) { return -1; @@ -63,31 +46,36 @@ int open_jpeg(buffer_list_t *src, const char *jpeg_codec) return 0; } +void write_jpeg(buffer_t *buf) +{ + FILE *fp = fopen("/tmp/capture.jpg.tmp", "wb"); + if (fp) { + fwrite(buf->start, 1, buf->used, fp); + fclose(fp); + E_LOG_DEBUG(buf, "Wrote JPEG: %d", buf->used); + } + rename("/tmp/capture.jpg.tmp", "/tmp/capture.jpg"); +} + int main(int argc, char *argv[]) { + camera = device_open("CAMERA", "/dev/video0"); + isp_srgb = device_open("ISP-SRGB", "/dev/video13"); + isp_yuuv = device_open("ISP-YUUV", "/dev/video14"); + isp_yuuv_low = device_open("ISP-YUUV-LOW", "/dev/video15"); + codec_jpeg = device_open("JPEG", "/dev/video31"); + + if (device_open_buffer_list(camera, true, camera_width, camera_height, camera_format, camera_nbufs, true) < 0) { + return -1; + } + if (open_camera("/dev/video0") < 0) { goto error; } if (open_isp(camera->capture_list, "/dev/video13", "/dev/video14", "/dev/video15") < 0) { goto error; } - if (open_jpeg(isp_yuuv->capture_list, "/dev/video31") < 0) { - goto error; - } - - if (device_stream(camera, true) < 0) { - goto error; - } - if (device_stream(isp_srgb, true) < 0) { - goto error; - } - if (device_stream(isp_yuuv, true) < 0) { - goto error; - } - if (device_stream(isp_yuuv_low, true) < 0) { - goto error; - } - if (device_stream(codec_jpeg, true) < 0) { + if (open_jpeg(camera_use_low ? isp_yuuv_low->capture_list : isp_yuuv->capture_list, "/dev/video31") < 0) { goto error; } @@ -99,28 +87,29 @@ int main(int argc, char *argv[]) }, { isp_yuuv, - {codec_jpeg}, + { camera_use_low ? NULL : codec_jpeg }, NULL }, { isp_yuuv_low, - {}, + { camera_use_low ? codec_jpeg : NULL }, NULL }, { codec_jpeg, {}, - NULL + write_jpeg }, { NULL } }; - while(true) { - handle_links(links, 100); - - usleep(10*1000); + if (links_init(links) < 0) { + return -1; } + bool running = false; + links_loop(links, &running); + error: device_close(isp_yuuv_low); device_close(isp_yuuv); diff --git a/v4l2.c b/v4l2.c index 7f5cd9c..ad4af62 100644 --- a/v4l2.c +++ b/v4l2.c @@ -64,6 +64,6 @@ unsigned fourcc_to_stride(unsigned width, unsigned format) return align_size(width * 5 / 4, 32); default: - E_LOG_PERROR(NULL, "Unknown format: %s", fourcc_to_string(format)); + E_LOG_PERROR(NULL, "Unknown format: %s", fourcc_to_string(format).buf); } }