From cae3087116d751ee785ad926dfcffbf10bde3881 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Sun, 10 Apr 2022 14:41:00 +0200 Subject: [PATCH] Optimise usage of `videodev2.h` header --- cmd/camera_stream.c | 1 + device/buffer.c | 2 +- device/buffer.h | 5 +- device/buffer_list.c | 2 +- device/buffer_list.h | 1 - device/buffer_lock.c | 2 +- device/buffer_queue.c | 6 +-- device/camera/camera.c | 3 +- device/camera/camera_decoder.c | 3 +- device/camera/camera_direct.c | 3 +- device/camera/camera_isp.c | 3 +- device/camera/camera_legacy_isp.c | 3 +- device/device.c | 2 +- device/device.h | 1 - device/hw/v4l2.h | 28 ----------- device/links.c | 2 +- device/v4l2/buffer.c | 8 +++- device/v4l2/buffer_list.c | 4 +- device/v4l2/debug.c | 3 +- device/v4l2/device.c | 4 +- device/v4l2/device_hw.c | 27 ----------- device/v4l2/device_media.c | 5 +- device/v4l2/device_options.c | 4 +- device/v4l2/v4l2.c | 77 +++++++++---------------------- device/v4l2/v4l2.h | 21 ++------- http/http.c | 2 +- http/http_h264.c | 2 +- device/hw/v4l2.c => opts/fourcc.c | 2 +- opts/fourcc.h | 9 ++++ opts/log.c | 24 ++++++++++ opts/log.h | 28 +++++++++++ opts/opts.c | 2 +- 32 files changed, 131 insertions(+), 158 deletions(-) delete mode 100644 device/hw/v4l2.h delete mode 100644 device/v4l2/device_hw.c rename device/hw/v4l2.c => opts/fourcc.c (95%) create mode 100644 opts/fourcc.h diff --git a/cmd/camera_stream.c b/cmd/camera_stream.c index 0370e59..beb516a 100644 --- a/cmd/camera_stream.c +++ b/cmd/camera_stream.c @@ -1,6 +1,7 @@ #include "http/http.h" #include "opts/opts.h" #include "opts/log.h" +#include "opts/fourcc.h" #include "device/camera/camera.h" #include diff --git a/device/buffer.c b/device/buffer.c index d33154b..85fdf32 100644 --- a/device/buffer.c +++ b/device/buffer.c @@ -1,7 +1,7 @@ #include "device/buffer.h" #include "device/buffer_list.h" #include "device/device.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { buffer_t *buf = calloc(1, sizeof(buffer_t)); diff --git a/device/buffer.h b/device/buffer.h index 4505746..f4585f1 100644 --- a/device/buffer.h +++ b/device/buffer.h @@ -3,7 +3,6 @@ #include #include #include -#include typedef struct buffer_s buffer_t; typedef struct buffer_list_s buffer_list_t; @@ -19,6 +18,10 @@ typedef struct buffer_s { size_t length; int dma_fd; + struct { + bool is_keyframe : 1; + } flags; + struct { unsigned flags; } v4l2; diff --git a/device/buffer_list.c b/device/buffer_list.c index 22ead2f..99d3439 100644 --- a/device/buffer_list.c +++ b/device/buffer_list.c @@ -1,7 +1,7 @@ #include "device/buffer.h" #include "device/buffer_list.h" #include "device/device.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, bool do_capture, bool do_mmap) { diff --git a/device/buffer_list.h b/device/buffer_list.h index c6d5b31..bbddd94 100644 --- a/device/buffer_list.h +++ b/device/buffer_list.h @@ -2,7 +2,6 @@ #include #include -#include typedef struct buffer_s buffer_t; typedef struct device_s device_t; diff --git a/device/buffer_lock.c b/device/buffer_lock.c index 62affc1..c67254c 100644 --- a/device/buffer_lock.c +++ b/device/buffer_lock.c @@ -1,7 +1,7 @@ #include "device/buffer_lock.h" #include "device/buffer_list.h" #include "device/buffer.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" bool buffer_lock_is_used(buffer_lock_t *buf_lock) { diff --git a/device/buffer_queue.c b/device/buffer_queue.c index afcc635..a245d5f 100644 --- a/device/buffer_queue.c +++ b/device/buffer_queue.c @@ -1,7 +1,7 @@ #include "device/buffer.h" #include "device/buffer_list.h" #include "device/device.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #include @@ -102,9 +102,7 @@ int buffer_list_enqueue(buffer_list_t *buf_list, buffer_t *dma_buf) return 0; } - buf->v4l2.flags = 0; - buf->v4l2.flags &= ~V4L2_BUF_FLAG_KEYFRAME; - buf->v4l2.flags |= dma_buf->v4l2.flags & V4L2_BUF_FLAG_KEYFRAME; + buf->flags = dma_buf->flags; buf->captured_time_us = dma_buf->captured_time_us; if (buf_list->do_mmap) { diff --git a/device/camera/camera.c b/device/camera/camera.c index fe45fd8..6beb0bf 100644 --- a/device/camera/camera.c +++ b/device/camera/camera.c @@ -3,7 +3,8 @@ #include "device/device.h" #include "device/buffer_list.h" #include "device/links.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" +#include "opts/fourcc.h" void camera_init(camera_t *camera) { diff --git a/device/camera/camera_decoder.c b/device/camera/camera_decoder.c index b0f749e..6c79963 100644 --- a/device/camera/camera_decoder.c +++ b/device/camera/camera_decoder.c @@ -4,7 +4,8 @@ #include "device/buffer_list.h" #include "device/device.h" #include "device/links.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" +#include "opts/fourcc.h" #include "device/buffer_list.h" #include "http/http.h" diff --git a/device/camera/camera_direct.c b/device/camera/camera_direct.c index c5a7f8d..f6bf96c 100644 --- a/device/camera/camera_direct.c +++ b/device/camera/camera_direct.c @@ -4,7 +4,8 @@ #include "device/buffer_list.h" #include "device/device.h" #include "device/links.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" +#include "opts/fourcc.h" #include "device/buffer_list.h" #include "http/http.h" diff --git a/device/camera/camera_isp.c b/device/camera/camera_isp.c index 409e144..b6887bf 100644 --- a/device/camera/camera_isp.c +++ b/device/camera/camera_isp.c @@ -4,7 +4,8 @@ #include "device/buffer_list.h" #include "device/device.h" #include "device/links.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" +#include "opts/fourcc.h" #include "device/buffer_list.h" #include "http/http.h" diff --git a/device/camera/camera_legacy_isp.c b/device/camera/camera_legacy_isp.c index d07c732..3a9e9e5 100644 --- a/device/camera/camera_legacy_isp.c +++ b/device/camera/camera_legacy_isp.c @@ -4,7 +4,8 @@ #include "device/buffer_list.h" #include "device/device.h" #include "device/links.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" +#include "opts/fourcc.h" #include "device/buffer_list.h" #include "http/http.h" diff --git a/device/device.c b/device/device.c index cafb5cd..1f31133 100644 --- a/device/device.c +++ b/device/device.c @@ -1,7 +1,7 @@ #include "device/device.h" #include "device/buffer.h" #include "device/buffer_list.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #include "opts/opts.h" device_t *device_open(const char *name, const char *path, device_hw_t *hw) { diff --git a/device/device.h b/device/device.h index c91f8b0..c2bec29 100644 --- a/device/device.h +++ b/device/device.h @@ -2,7 +2,6 @@ #include #include -#include typedef struct buffer_s buffer_t; typedef struct buffer_list_s buffer_list_t; diff --git a/device/hw/v4l2.h b/device/hw/v4l2.h deleted file mode 100644 index 1dd0f4d..0000000 --- a/device/hw/v4l2.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "opts/log.h" - -typedef struct { - char buf[10]; -} fourcc_string; - -fourcc_string fourcc_to_string(unsigned format); diff --git a/device/links.c b/device/links.c index 48a82be..645dd20 100644 --- a/device/links.c +++ b/device/links.c @@ -2,7 +2,7 @@ #include "device/device.h" #include "device/buffer.h" #include "device/buffer_list.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #define N_FDS 50 #define QUEUE_ON_CAPTURE // seems to provide better latency diff --git a/device/v4l2/buffer.c b/device/v4l2/buffer.c index e27d853..162365c 100644 --- a/device/v4l2/buffer.c +++ b/device/v4l2/buffer.c @@ -1,7 +1,8 @@ -#include "device/v4l2/v4l2.h" +#include "v4l2.h" #include "device/buffer.h" #include "device/buffer_list.h" #include "device/device.h" +#include "opts/log.h" int v4l2_buffer_open(buffer_t *buf) { @@ -78,7 +79,9 @@ int v4l2_buffer_enqueue(buffer_t *buf, const char *who) v4l2_buf.type = buf->buf_list->v4l2.type; v4l2_buf.index = buf->index; - v4l2_buf.flags = buf->v4l2.flags; + v4l2_buf.flags = 0; + if (buf->flags.is_keyframe) + v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME; if (buf->buf_list->do_mmap) { assert(buf->dma_source == NULL); @@ -154,6 +157,7 @@ int v4l2_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp) } buf->v4l2.flags = v4l2_buf.flags; + buf->flags.is_keyframe = (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) != 0; buf->captured_time_us = get_time_us(CLOCK_FROM_PARAMS, NULL, &v4l2_buf.timestamp, 0); return 0; diff --git a/device/v4l2/buffer_list.c b/device/v4l2/buffer_list.c index d329051..d62d2ed 100644 --- a/device/v4l2/buffer_list.c +++ b/device/v4l2/buffer_list.c @@ -1,7 +1,9 @@ -#include "device/v4l2/v4l2.h" +#include "v4l2.h" #include "device/buffer.h" #include "device/buffer_list.h" #include "device/device.h" +#include "opts/log.h" +#include "opts/fourcc.h" int v4l2_buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline) { diff --git a/device/v4l2/debug.c b/device/v4l2/debug.c index 775cb57..9fb44bb 100644 --- a/device/v4l2/debug.c +++ b/device/v4l2/debug.c @@ -1,6 +1,7 @@ -#include "device/v4l2/v4l2.h" +#include "v4l2.h" #include "device/buffer_list.h" #include "device/device.h" +#include "opts/log.h" int v4l2_buffer_list_refresh_states(buffer_list_t *buf_list) { diff --git a/device/v4l2/device.c b/device/v4l2/device.c index e722565..faf39ac 100644 --- a/device/v4l2/device.c +++ b/device/v4l2/device.c @@ -1,6 +1,6 @@ -#include "device/v4l2/v4l2.h" -#include "device/hw/v4l2.h" +#include "v4l2.h" #include "device/device.h" +#include "opts/log.h" int v4l2_device_open(device_t *dev) { diff --git a/device/v4l2/device_hw.c b/device/v4l2/device_hw.c deleted file mode 100644 index 12287ed..0000000 --- a/device/v4l2/device_hw.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "device/v4l2/v4l2.h" -#include "device/hw/v4l2.h" -#include "device/device.h" - -device_hw_t v4l2_device_hw = { - .device_open = v4l2_device_open, - .device_close = v4l2_device_close, - .device_set_decoder_start = v4l2_device_set_decoder_start, - .device_video_force_key = v4l2_device_video_force_key, - .device_set_fps = v4l2_device_set_fps, - .device_set_option = v4l2_device_set_option, - - .buffer_open = v4l2_buffer_open, - .buffer_close = v4l2_buffer_close, - .buffer_enqueue = v4l2_buffer_enqueue, - - .buffer_list_dequeue = v4l2_buffer_list_dequeue, - .buffer_list_pollfd = v4l2_buffer_list_pollfd, - .buffer_list_set_format = v4l2_buffer_list_set_format, - .buffer_list_set_buffers = v4l2_buffer_list_set_buffers, - .buffer_list_set_stream = v4l2_buffer_list_set_stream -}; - -device_t *device_v4l2_open(const char *name, const char *path) -{ - return device_open(name, path, &v4l2_device_hw); -} diff --git a/device/v4l2/device_media.c b/device/v4l2/device_media.c index fe94332..41b6614 100644 --- a/device/v4l2/device_media.c +++ b/device/v4l2/device_media.c @@ -1,6 +1,7 @@ -#include "device/v4l2/v4l2.h" +#include "v4l2.h" + #include "device/device.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #include #include diff --git a/device/v4l2/device_options.c b/device/v4l2/device_options.c index e92fa91..8324859 100644 --- a/device/v4l2/device_options.c +++ b/device/v4l2/device_options.c @@ -1,6 +1,6 @@ -#include "device/v4l2/v4l2.h" -#include "device/hw/v4l2.h" +#include "v4l2.h" #include "device/device.h" +#include "opts/log.h" #include diff --git a/device/v4l2/v4l2.c b/device/v4l2/v4l2.c index e602d2d..a164b48 100644 --- a/device/v4l2/v4l2.c +++ b/device/v4l2/v4l2.c @@ -1,59 +1,26 @@ -#include "device/v4l2/v4l2.h" +#include "v4l2.h" +#include "device/device.h" -#include -#include +device_hw_t v4l2_device_hw = { + .device_open = v4l2_device_open, + .device_close = v4l2_device_close, + .device_set_decoder_start = v4l2_device_set_decoder_start, + .device_video_force_key = v4l2_device_video_force_key, + .device_set_fps = v4l2_device_set_fps, + .device_set_option = v4l2_device_set_option, -int xioctl(const char *name, int fd, int request, void *arg) + .buffer_open = v4l2_buffer_open, + .buffer_close = v4l2_buffer_close, + .buffer_enqueue = v4l2_buffer_enqueue, + + .buffer_list_dequeue = v4l2_buffer_list_dequeue, + .buffer_list_pollfd = v4l2_buffer_list_pollfd, + .buffer_list_set_format = v4l2_buffer_list_set_format, + .buffer_list_set_buffers = v4l2_buffer_list_set_buffers, + .buffer_list_set_stream = v4l2_buffer_list_set_stream +}; + +device_t *device_v4l2_open(const char *name, const char *path) { - int retries = XIOCTL_RETRIES; - int retval = -1; - - do { - retval = ioctl(fd, request, arg); - } while ( - retval - && retries-- - && ( - errno == EINTR - || errno == EAGAIN - || errno == ETIMEDOUT - ) - ); - - // cppcheck-suppress knownConditionTrueFalse - if (retval && retries <= 0) { - E_LOG_PERROR(NULL, "%s: ioctl(%08x) retried %u times; giving up", name, request, XIOCTL_RETRIES); - } - return retval; -} - -static size_t align_size(size_t size, size_t to) -{ - return ((size + (to - 1)) & ~(to - 1)); -} - -unsigned fourcc_to_stride(unsigned width, unsigned format) -{ - switch (format) { - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_RGB565: - return align_size(width * 2, 32); - - case V4L2_PIX_FMT_YUV420: - return align_size(width * 3 / 2, 32); - - case V4L2_PIX_FMT_RGB24: - return align_size(width * 3, 32); - - case V4L2_PIX_FMT_SRGGB10P: - return align_size(width * 5 / 4, 32); - - case V4L2_PIX_FMT_JPEG: - case V4L2_PIX_FMT_H264: - return 0; - - default: - E_LOG_PERROR(NULL, "Unknown format: %s", fourcc_to_string(format).buf); - } + return device_open(name, path, &v4l2_device_hw); } diff --git a/device/v4l2/v4l2.h b/device/v4l2/v4l2.h index e1fb125..ce6ef9a 100644 --- a/device/v4l2/v4l2.h +++ b/device/v4l2/v4l2.h @@ -1,7 +1,9 @@ #pragma once -// TODO: temporary -#include "device/hw/v4l2.h" +#include +#include +#include +#include typedef struct buffer_s buffer_t; typedef struct buffer_list_s buffer_list_t; @@ -29,18 +31,3 @@ int v4l2_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on); int v4l2_device_open_media_device(device_t *dev); int v4l2_device_open_v4l2_subdev(device_t *dev, int subdev); int v4l2_device_set_pad_format(device_t *dev, unsigned width, unsigned height, unsigned format); - -#ifndef CFG_XIOCTL_RETRIES -# define CFG_XIOCTL_RETRIES 4 -#endif -#define XIOCTL_RETRIES ((unsigned)(CFG_XIOCTL_RETRIES)) - -unsigned fourcc_to_stride(unsigned width, unsigned format); -int xioctl(const char *name, int fd, int request, void *arg); - -#define E_XIOCTL(dev, _fd, _request, _value, _msg, ...) do { \ - int ret; \ - if ((ret = xioctl(dev_name(dev), _fd, _request, _value)) < 0) { \ - E_LOG_ERROR(dev, "xioctl(ret=%d): " _msg, ret, ##__VA_ARGS__); \ - } \ - } while(0) diff --git a/http/http.c b/http/http.c index 10ce25c..05e504a 100644 --- a/http/http.c +++ b/http/http.c @@ -11,7 +11,7 @@ #include #include "http/http.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #define BUFSIZE 256 diff --git a/http/http_h264.c b/http/http_h264.c index 4200bf9..5a18ddf 100644 --- a/http/http_h264.c +++ b/http/http_h264.c @@ -52,7 +52,7 @@ bool h264_is_key_frame(buffer_t *buf) { unsigned char *data = buf->start; - if (buf->v4l2.flags & V4L2_BUF_FLAG_KEYFRAME) { + if (buf->flags.is_keyframe) { E_LOG_DEBUG(buf, "Got key frame (from V4L2)!"); return true; } else if (buf->used >= 5 && (data[4] & 0x1F) == 0x07) { diff --git a/device/hw/v4l2.c b/opts/fourcc.c similarity index 95% rename from device/hw/v4l2.c rename to opts/fourcc.c index bf7027a..b92ba5b 100644 --- a/device/hw/v4l2.c +++ b/opts/fourcc.c @@ -1,4 +1,4 @@ -#include "v4l2.h" +#include "fourcc.h" fourcc_string fourcc_to_string(unsigned format) { diff --git a/opts/fourcc.h b/opts/fourcc.h new file mode 100644 index 0000000..524d109 --- /dev/null +++ b/opts/fourcc.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +typedef struct { + char buf[10]; +} fourcc_string; + +fourcc_string fourcc_to_string(unsigned format); diff --git a/opts/log.c b/opts/log.c index 54bbdd1..ea161ea 100644 --- a/opts/log.c +++ b/opts/log.c @@ -82,3 +82,27 @@ uint64_t get_monotonic_time_us(struct timespec *ts, struct timeval *tv) { return get_time_us(CLOCK_MONOTONIC, ts, tv, 0); } + +int xioctl(const char *name, int fd, int request, void *arg) +{ + int retries = XIOCTL_RETRIES; + int retval = -1; + + do { + retval = ioctl(fd, request, arg); + } while ( + retval + && retries-- + && ( + errno == EINTR + || errno == EAGAIN + || errno == ETIMEDOUT + ) + ); + + // cppcheck-suppress knownConditionTrueFalse + if (retval && retries <= 0) { + E_LOG_PERROR(NULL, "%s: ioctl(%08x) retried %u times; giving up", name, request, XIOCTL_RETRIES); + } + return retval; +} diff --git a/opts/log.h b/opts/log.h index 3b3ae94..575b620 100644 --- a/opts/log.h +++ b/opts/log.h @@ -1,11 +1,25 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include +#include +#include #define __FILENAME__ __FILE__ @@ -35,3 +49,17 @@ bool filter_log(const char *filename); uint64_t get_monotonic_time_us(struct timespec *ts, struct timeval *tv); uint64_t get_time_us(clockid_t clock, struct timespec *ts, struct timeval *tv, int64_t delays_us); int shrink_to_block(int size, int block); + +#ifndef CFG_XIOCTL_RETRIES +# define CFG_XIOCTL_RETRIES 4 +#endif +#define XIOCTL_RETRIES ((unsigned)(CFG_XIOCTL_RETRIES)) + +int xioctl(const char *name, int fd, int request, void *arg); + +#define E_XIOCTL(dev, _fd, _request, _value, _msg, ...) do { \ + int ret; \ + if ((ret = xioctl(dev_name(dev), _fd, _request, _value)) < 0) { \ + E_LOG_ERROR(dev, "xioctl(ret=%d): " _msg, ret, ##__VA_ARGS__); \ + } \ + } while(0) diff --git a/opts/opts.c b/opts/opts.c index 79a6bd8..523dbea 100644 --- a/opts/opts.c +++ b/opts/opts.c @@ -1,5 +1,5 @@ #include "opts.h" -#include "device/hw/v4l2.h" +#include "opts/log.h" #include #include