Optimise usage of videodev2.h
header
This commit is contained in:
parent
b21ddd2519
commit
cae3087116
@ -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>
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "http/http.h"
|
||||
#include "device/hw/v4l2.h"
|
||||
#include "opts/log.h"
|
||||
|
||||
#define BUFSIZE 256
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "v4l2.h"
|
||||
#include "fourcc.h"
|
||||
|
||||
fourcc_string fourcc_to_string(unsigned format)
|
||||
{
|
9
opts/fourcc.h
Normal file
9
opts/fourcc.h
Normal 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);
|
24
opts/log.c
24
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;
|
||||
}
|
||||
|
28
opts/log.h
28
opts/log.h
@ -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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "opts.h"
|
||||
#include "device/hw/v4l2.h"
|
||||
#include "opts/log.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user