Optimise usage of videodev2.h header

This commit is contained in:
Kamil Trzcinski 2022-04-10 14:41:00 +02:00
parent b21ddd2519
commit cae3087116
32 changed files with 131 additions and 158 deletions

View File

@ -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 <signal.h>

View File

@ -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));

View File

@ -3,7 +3,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <linux/videodev2.h>
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;

View File

@ -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)
{

View File

@ -2,7 +2,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <linux/videodev2.h>
typedef struct buffer_s buffer_t;
typedef struct device_s device_t;

View File

@ -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)
{

View File

@ -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 <pthread.h>
@ -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) {

View File

@ -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)
{

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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) {

View File

@ -2,7 +2,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <linux/videodev2.h>
typedef struct buffer_s buffer_t;
typedef struct buffer_list_s buffer_list_t;

View File

@ -1,28 +0,0 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <linux/v4l2-subdev.h>
#include "opts/log.h"
typedef struct {
char buf[10];
} fourcc_string;
fourcc_string fourcc_to_string(unsigned format);

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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 <unistd.h>
#include <dirent.h>

View File

@ -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 <ctype.h>

View File

@ -1,59 +1,26 @@
#include "device/v4l2/v4l2.h"
#include "v4l2.h"
#include "device/device.h"
#include <linux/videodev2.h>
#include <linux/v4l2-subdev.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,
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);
}

View File

@ -1,7 +1,9 @@
#pragma once
// TODO: temporary
#include "device/hw/v4l2.h"
#include <linux/videodev2.h>
#include <linux/v4l2-subdev.h>
#include <stdbool.h>
#include <stdint.h>
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)

View File

@ -11,7 +11,7 @@
#include <signal.h>
#include "http/http.h"
#include "device/hw/v4l2.h"
#include "opts/log.h"
#define BUFSIZE 256

View File

@ -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) {

View File

@ -1,4 +1,4 @@
#include "v4l2.h"
#include "fourcc.h"
fourcc_string fourcc_to_string(unsigned format)
{

9
opts/fourcc.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <linux/videodev2.h>
typedef struct {
char buf[10];
} fourcc_string;
fourcc_string fourcc_to_string(unsigned format);

View File

@ -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;
}

View File

@ -1,11 +1,25 @@
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#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)

View File

@ -1,5 +1,5 @@
#include "opts.h"
#include "device/hw/v4l2.h"
#include "opts/log.h"
#include <stddef.h>
#include <stdio.h>