From 932c32576bf1227414f7b19a81ad23b986fb5f78 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 4 Apr 2022 19:48:08 +0200 Subject: [PATCH] WIP --- buffer.h | 1 + buffer_list.c | 10 ++++ buffer_queue.c | 14 +++++ device.h | 2 +- links.c | 141 ++++++++++++++++++++++++++----------------------- links.h | 10 ++-- main.c | 62 ++++++++++++++++++---- 7 files changed, 160 insertions(+), 80 deletions(-) diff --git a/buffer.h b/buffer.h index 7c0457f..dc58631 100644 --- a/buffer.h +++ b/buffer.h @@ -22,4 +22,5 @@ typedef struct buffer_s { buffer_t *buffer_open(const char *name, struct buffer_list_s *buf_list, int buffer); void buffer_close(buffer_t *buf); +bool buffer_use(buffer_t *buf); bool buffer_consumed(buffer_t *buf); diff --git a/buffer_list.c b/buffer_list.c index 2fd01c9..85f5a67 100644 --- a/buffer_list.c +++ b/buffer_list.c @@ -154,11 +154,21 @@ error: int buffer_list_stream(buffer_list_t *buf_list, bool do_on) { + if (!buf_list) { + return -1; + } + + if (buf_list->streaming == do_on) { + return 0; + } + enum v4l2_buf_type type = buf_list->type; E_XIOCTL(buf_list, buf_list->device->fd, do_on ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type, "Cannot set streaming state"); buf_list->streaming = do_on; + E_LOG_DEBUG(buf_list, "Streaming %s...", do_on ? "started" : "stopped"); + return 0; error: diff --git a/buffer_queue.c b/buffer_queue.c index 8a20fe4..23ef493 100644 --- a/buffer_queue.c +++ b/buffer_queue.c @@ -2,6 +2,16 @@ #include "buffer_list.h" #include "device.h" +bool buffer_use(buffer_t *buf) +{ + if (buf->enqueued) { + return false; + } + + buf->mmap_reflinks += 1; + return true; +} + bool buffer_consumed(buffer_t *buf) { if (buf->mmap_reflinks > 0) { @@ -35,6 +45,10 @@ bool buffer_consumed(buffer_t *buf) return true; error: + if (buf->mmap_source) { + buffer_consumed(buf->mmap_source); + buf->mmap_source = NULL; + } return false; } diff --git a/device.h b/device.h index c000582..f13c00a 100644 --- a/device.h +++ b/device.h @@ -12,7 +12,7 @@ typedef struct device_s { struct buffer_list_s *capture_list; struct buffer_list_s *output_list; - struct device_s *upstream_device; + struct device_s *output_device; } device_t; device_t *device_open(const char *name, const char *path); diff --git a/links.c b/links.c index db50591..8e008f5 100644 --- a/links.c +++ b/links.c @@ -72,8 +72,8 @@ int links_step(link_t *all_links, int timeout) buffer_list_enqueue(link->outputs[j]->output_list, buf); } - if (link->on_buffer) { - link->on_buffer(buf); + if (link->callbacks.on_buffer) { + link->callbacks.on_buffer(buf); } buffer_consumed(buf); @@ -89,73 +89,25 @@ int links_step(link_t *all_links, int timeout) 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"); - } + int n; - for (int j = 0; all_links[i].outputs[j]; j++) { - if (device_stream(all_links[i].outputs[j], true) < 0) { - E_LOG_ERROR(all_links[i].outputs[j], "Failed to start streaming"); - } - } - } + for (n = 0; all_links[n].capture; n++); - return 0; - -error: - return -1; -} - -int links_open_buffer_list_from(device_t *dev, bool do_capture, buffer_list_t *parent_buffer, unsigned format) -{ - if (!parent_buffer) { - return -1; - } - - return device_open_buffer_list( - dev, - do_capture, - parent_buffer->fmt_width, - parent_buffer->fmt_height, - format ? format : parent_buffer->fmt_format, - parent_buffer->nbufs - ); -} - -int links_init(link_t *all_links) -{ - // create all outputs (sinks) - for (int i = 0; all_links[i].capture; i++) { + for (int i = n; --i >= 0; ) { + bool streaming = true; link_t *link = &all_links[i]; - - if (!link->capture) { - E_LOG_ERROR(NULL, "Missing link capture."); + + if (link->callbacks.check_streaming) { + streaming = link->callbacks.check_streaming(); } - if (link->capture_format) { - int ret = links_open_buffer_list_from( - link->capture, - true, - link->capture->upstream_device ? link->capture->upstream_device->output_list : link->capture->output_list, - link->capture_format - ); - - if (ret < 0) { - E_LOG_ERROR(link->capture, "Failed to create capture_list."); - } - } - - if (!link->capture->capture_list) { - E_LOG_ERROR(link->capture, "Missing capture device."); + if (buffer_list_stream(link->capture->capture_list, streaming) < 0) { + E_LOG_ERROR(link->capture, "Failed to start streaming"); } for (int j = 0; link->outputs[j]; j++) { - device_t *output = link->outputs[j]; - - int ret = links_open_buffer_list_from(output, false, link->capture->capture_list, 0); - if (ret < 0) { - E_LOG_ERROR(output, "Failed to create output_list."); + if (buffer_list_stream(link->outputs[j]->output_list, streaming) < 0) { + E_LOG_ERROR(link->outputs[j], "Failed to start streaming"); } } } @@ -166,15 +118,74 @@ error: return -1; } +// int links_open_buffer_list_from(device_t *dev, bool do_capture, buffer_list_t *parent_buffer, unsigned format) +// { +// if (!parent_buffer) { +// return -1; +// } + +// return device_open_buffer_list( +// dev, +// do_capture, +// parent_buffer->fmt_width, +// parent_buffer->fmt_height, +// format ? format : parent_buffer->fmt_format, +// parent_buffer->nbufs +// ); +// } + +// 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_format) { +// int ret = links_open_buffer_list_from( +// link->capture, +// true, +// link->capture->upstream_device ? link->capture->upstream_device->output_list : link->capture->output_list, +// link->capture_format +// ); + +// if (ret < 0) { +// E_LOG_ERROR(link->capture, "Failed to create capture_list."); +// } +// } + +// 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]; + +// int ret = links_open_buffer_list_from(output, false, link->capture->capture_list, 0); +// if (ret < 0) { +// E_LOG_ERROR(output, "Failed to create output_list."); +// } +// } +// } + +// 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_stream(all_links, true) < 0) { + return -1; + } + if (links_step(all_links, 1000) < 0) { links_stream(all_links, false); return -1; diff --git a/links.h b/links.h index aaa8961..fd152ba 100644 --- a/links.h +++ b/links.h @@ -2,12 +2,16 @@ #include "v4l2.h" +typedef void (*link_on_buffer)(struct buffer_s *buf); +typedef bool (*link_check_streaming)(); + typedef struct link_s { struct device_s *capture; // capture_list struct device_s *outputs[10]; - void (*on_buffer)(struct buffer_s *buf); - - unsigned capture_format; + struct { + link_on_buffer on_buffer; + link_check_streaming check_streaming; + } callbacks; } link_t; int links_init(link_t *all_links); diff --git a/main.c b/main.c index a215065..f4c5bd7 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ device_t *isp_srgb = NULL; device_t *isp_yuuv = NULL; device_t *isp_yuuv_low = NULL; device_t *codec_jpeg = NULL; +device_t *codec_h264 = NULL; int open_isp(buffer_list_t *src, const char *srgb_path, const char *yuuv_path, const char *yuuv_low_path) { @@ -38,6 +39,16 @@ int open_jpeg(buffer_list_t *src, const char *tmp) return 0; } +int open_h264(buffer_list_t *src, const char *tmp) +{ + if (device_open_buffer_list(codec_h264, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs) < 0 || + device_open_buffer_list(codec_h264, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_H264, camera_nbufs) < 0) { + return -1; + } + + return 0; +} + void write_jpeg(buffer_t *buf) { FILE *fp = fopen("/tmp/capture.jpg.tmp", "wb"); @@ -49,6 +60,22 @@ void write_jpeg(buffer_t *buf) rename("/tmp/capture.jpg.tmp", "/tmp/capture.jpg"); } +bool check_streaming() +{ + return true; +} + +void write_h264(buffer_t *buf) +{ + FILE *fp = fopen("/tmp/capture.h264.tmp", "wb"); + if (fp) { + fwrite(buf->start, 1, buf->used, fp); + fclose(fp); + E_LOG_DEBUG(buf, "Wrote H264: %d", buf->used); + } + rename("/tmp/capture.h264.tmp", "/tmp/capture.h264"); +} + int main(int argc, char *argv[]) { camera = device_open("CAMERA", "/dev/video0"); @@ -60,11 +87,13 @@ int main(int argc, char *argv[]) isp_srgb = device_open("ISP-SRGB", "/dev/video13"); //isp_srgb->allow_dma = false; isp_yuuv = device_open("ISP-YUUV", "/dev/video14"); - isp_yuuv->upstream_device = isp_srgb; + isp_yuuv->output_device = isp_srgb; isp_yuuv_low = device_open("ISP-YUUV-LOW", "/dev/video15"); - isp_yuuv_low->upstream_device = isp_srgb; + isp_yuuv_low->output_device = isp_srgb; codec_jpeg = device_open("JPEG", "/dev/video31"); codec_jpeg->allow_dma = false; + codec_h264 = device_open("H264", "/dev/video11"); + codec_h264->allow_dma = false; if (open_isp(camera->capture_list, "/dev/video13", "/dev/video14", "/dev/video15") < 0) { goto error; @@ -72,30 +101,41 @@ int main(int argc, char *argv[]) if (open_jpeg(camera_use_low ? isp_yuuv_low->capture_list : isp_yuuv->capture_list, "/dev/video31") < 0) { goto error; } + if (open_h264(camera_use_low ? isp_yuuv_low->capture_list : isp_yuuv->capture_list, "/dev/video11") < 0) { + goto error; + } link_t links[] = { { camera, { isp_srgb }, - NULL + { NULL, NULL } }, { isp_yuuv, - { camera_use_low ? NULL : codec_jpeg }, - NULL, - V4L2_PIX_FMT_YUYV + { + camera_use_low ? NULL : codec_jpeg, + camera_use_low ? NULL : codec_h264, + }, + { NULL, NULL } }, { isp_yuuv_low, - { camera_use_low ? codec_jpeg : NULL }, - NULL, - V4L2_PIX_FMT_YUYV + { + camera_use_low ? codec_jpeg : NULL, + camera_use_low ? codec_h264 : NULL, + }, + { NULL, NULL } }, { codec_jpeg, { }, - write_jpeg, - V4L2_PIX_FMT_JPEG + { write_jpeg, check_streaming } + }, + { + codec_h264, + { }, + { write_h264, check_streaming } }, { NULL } };