WIP
This commit is contained in:
		
							
								
								
									
										1
									
								
								buffer.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								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); | buffer_t *buffer_open(const char *name, struct buffer_list_s *buf_list, int buffer); | ||||||
| void buffer_close(buffer_t *buf); | void buffer_close(buffer_t *buf); | ||||||
|  |  | ||||||
|  | bool buffer_use(buffer_t *buf); | ||||||
| bool buffer_consumed(buffer_t *buf); | bool buffer_consumed(buffer_t *buf); | ||||||
|   | |||||||
| @@ -154,11 +154,21 @@ error: | |||||||
|  |  | ||||||
| int buffer_list_stream(buffer_list_t *buf_list, bool do_on) | 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; | 	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"); |   E_XIOCTL(buf_list, buf_list->device->fd, do_on ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type, "Cannot set streaming state"); | ||||||
|   buf_list->streaming = do_on; |   buf_list->streaming = do_on; | ||||||
|  |  | ||||||
|  |   E_LOG_DEBUG(buf_list, "Streaming %s...", do_on ? "started" : "stopped"); | ||||||
|  |  | ||||||
|   return 0; |   return 0; | ||||||
|  |  | ||||||
| error: | error: | ||||||
|   | |||||||
| @@ -2,6 +2,16 @@ | |||||||
| #include "buffer_list.h" | #include "buffer_list.h" | ||||||
| #include "device.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) | bool buffer_consumed(buffer_t *buf) | ||||||
| { | { | ||||||
|   if (buf->mmap_reflinks > 0) { |   if (buf->mmap_reflinks > 0) { | ||||||
| @@ -35,6 +45,10 @@ bool buffer_consumed(buffer_t *buf) | |||||||
|   return true; |   return true; | ||||||
|  |  | ||||||
| error: | error: | ||||||
|  |   if (buf->mmap_source) { | ||||||
|  |     buffer_consumed(buf->mmap_source); | ||||||
|  |     buf->mmap_source = NULL; | ||||||
|  |   } | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								device.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								device.h
									
									
									
									
									
								
							| @@ -12,7 +12,7 @@ typedef struct device_s { | |||||||
|   struct buffer_list_s *capture_list; |   struct buffer_list_s *capture_list; | ||||||
|   struct buffer_list_s *output_list; |   struct buffer_list_s *output_list; | ||||||
|  |  | ||||||
|   struct device_s *upstream_device; |   struct device_s *output_device; | ||||||
| } device_t; | } device_t; | ||||||
|  |  | ||||||
| device_t *device_open(const char *name, const char *path); | device_t *device_open(const char *name, const char *path); | ||||||
|   | |||||||
							
								
								
									
										137
									
								
								links.c
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								links.c
									
									
									
									
									
								
							| @@ -72,8 +72,8 @@ int links_step(link_t *all_links, int timeout) | |||||||
|           buffer_list_enqueue(link->outputs[j]->output_list, buf); |           buffer_list_enqueue(link->outputs[j]->output_list, buf); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (link->on_buffer) { |         if (link->callbacks.on_buffer) { | ||||||
|           link->on_buffer(buf); |           link->callbacks.on_buffer(buf); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         buffer_consumed(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) | int links_stream(link_t *all_links, bool do_stream) | ||||||
| { | { | ||||||
|   for (int i = 0; all_links[i].capture; i++) { |   int n; | ||||||
|     if (device_stream(all_links[i].capture, true) < 0) { |  | ||||||
|       E_LOG_ERROR(all_links[i].capture, "Failed to start streaming"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     for (int j = 0; all_links[i].outputs[j]; j++) { |   for (n = 0; all_links[n].capture; n++); | ||||||
|       if (device_stream(all_links[i].outputs[j], true) < 0) { |  | ||||||
|         E_LOG_ERROR(all_links[i].outputs[j], "Failed to start streaming"); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return 0; |   for (int i = n; --i >= 0; ) { | ||||||
|  |     bool streaming = true; | ||||||
| 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]; |     link_t *link = &all_links[i]; | ||||||
|      |      | ||||||
|     if (!link->capture) { |     if (link->callbacks.check_streaming) { | ||||||
|       E_LOG_ERROR(NULL, "Missing link capture."); |       streaming = link->callbacks.check_streaming(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (link->capture_format) { |     if (buffer_list_stream(link->capture->capture_list, streaming) < 0) { | ||||||
|       int ret = links_open_buffer_list_from( |       E_LOG_ERROR(link->capture, "Failed to start streaming"); | ||||||
|         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++) { |     for (int j = 0; link->outputs[j]; j++) { | ||||||
|       device_t *output = link->outputs[j]; |       if (buffer_list_stream(link->outputs[j]->output_list, streaming) < 0) { | ||||||
|  |         E_LOG_ERROR(link->outputs[j], "Failed to start streaming"); | ||||||
|       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."); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -166,15 +118,74 @@ error: | |||||||
|   return -1; |   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) | int links_loop(link_t *all_links, bool *running) | ||||||
| { | { | ||||||
|  |   *running = true; | ||||||
|  |  | ||||||
|  |   while(*running) { | ||||||
|     if (links_stream(all_links, true) < 0) { |     if (links_stream(all_links, true) < 0) { | ||||||
|       return -1; |       return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   *running = true; |  | ||||||
|  |  | ||||||
|   while(*running) { |  | ||||||
|     if (links_step(all_links, 1000) < 0) { |     if (links_step(all_links, 1000) < 0) { | ||||||
|       links_stream(all_links, false); |       links_stream(all_links, false); | ||||||
|       return -1; |       return -1; | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								links.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								links.h
									
									
									
									
									
								
							| @@ -2,12 +2,16 @@ | |||||||
|  |  | ||||||
| #include "v4l2.h" | #include "v4l2.h" | ||||||
|  |  | ||||||
|  | typedef void (*link_on_buffer)(struct buffer_s *buf); | ||||||
|  | typedef bool (*link_check_streaming)(); | ||||||
|  |  | ||||||
| typedef struct link_s { | typedef struct link_s { | ||||||
|   struct device_s *capture; // capture_list |   struct device_s *capture; // capture_list | ||||||
|   struct device_s *outputs[10]; |   struct device_s *outputs[10]; | ||||||
|   void (*on_buffer)(struct buffer_s *buf); |   struct { | ||||||
|  |     link_on_buffer on_buffer; | ||||||
|   unsigned capture_format; |     link_check_streaming check_streaming; | ||||||
|  |   } callbacks; | ||||||
| } link_t; | } link_t; | ||||||
|  |  | ||||||
| int links_init(link_t *all_links); | int links_init(link_t *all_links); | ||||||
|   | |||||||
							
								
								
									
										62
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								main.c
									
									
									
									
									
								
							| @@ -16,6 +16,7 @@ device_t *isp_srgb = NULL; | |||||||
| device_t *isp_yuuv = NULL; | device_t *isp_yuuv = NULL; | ||||||
| device_t *isp_yuuv_low = NULL; | device_t *isp_yuuv_low = NULL; | ||||||
| device_t *codec_jpeg = 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) | 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; |   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) | void write_jpeg(buffer_t *buf) | ||||||
| { | { | ||||||
|   FILE *fp = fopen("/tmp/capture.jpg.tmp", "wb"); |   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"); |   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[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|   camera = device_open("CAMERA", "/dev/video0"); |   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 = device_open("ISP-SRGB", "/dev/video13"); | ||||||
|   //isp_srgb->allow_dma = false; |   //isp_srgb->allow_dma = false; | ||||||
|   isp_yuuv = device_open("ISP-YUUV", "/dev/video14"); |   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 = 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 = device_open("JPEG", "/dev/video31"); | ||||||
|   codec_jpeg->allow_dma = false; |   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) { |   if (open_isp(camera->capture_list, "/dev/video13", "/dev/video14", "/dev/video15") < 0) { | ||||||
|     goto error; |     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) { |   if (open_jpeg(camera_use_low ? isp_yuuv_low->capture_list : isp_yuuv->capture_list, "/dev/video31") < 0) { | ||||||
|     goto error; |     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[] = { |   link_t links[] = { | ||||||
|     { |     { | ||||||
|       camera, |       camera, | ||||||
|       { isp_srgb }, |       { isp_srgb }, | ||||||
|       NULL |       { NULL, NULL } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       isp_yuuv, |       isp_yuuv, | ||||||
|       { camera_use_low ? NULL : codec_jpeg }, |       { | ||||||
|       NULL, |         camera_use_low ? NULL : codec_jpeg, | ||||||
|       V4L2_PIX_FMT_YUYV |         camera_use_low ? NULL : codec_h264, | ||||||
|  |       }, | ||||||
|  |       { NULL, NULL } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       isp_yuuv_low, |       isp_yuuv_low, | ||||||
|       { camera_use_low ? codec_jpeg : NULL }, |       { | ||||||
|       NULL, |         camera_use_low ? codec_jpeg : NULL, | ||||||
|       V4L2_PIX_FMT_YUYV |         camera_use_low ? codec_h264 : NULL, | ||||||
|  |       }, | ||||||
|  |       { NULL, NULL } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       codec_jpeg, |       codec_jpeg, | ||||||
|       { }, |       { }, | ||||||
|       write_jpeg, |       { write_jpeg, check_streaming } | ||||||
|       V4L2_PIX_FMT_JPEG |     }, | ||||||
|  |     { | ||||||
|  |       codec_h264, | ||||||
|  |       { }, | ||||||
|  |       { write_h264, check_streaming } | ||||||
|     }, |     }, | ||||||
|     { NULL } |     { NULL } | ||||||
|   }; |   }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Kamil Trzcinski
					Kamil Trzcinski