Make device/buffer_list* be generic

This commit is contained in:
Kamil Trzcinski 2022-04-10 11:24:25 +02:00
parent fd2f19270c
commit 33b7062bf1
21 changed files with 134 additions and 104 deletions

View File

@ -1,5 +1,5 @@
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"

View File

@ -1,5 +1,5 @@
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"

94
device/buffer_list.c Normal file
View File

@ -0,0 +1,94 @@
#include "device/buffer.h"
#include "device/buffer_list.h"
#include "device/hw/device.h"
#include "device/hw/v4l2.h"
buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, bool do_capture, bool do_mmap)
{
buffer_list_t *buf_list = calloc(1, sizeof(buffer_list_t));
buf_list->device = dev;
buf_list->name = strdup(name);
buf_list->do_capture = do_capture;
buf_list->do_mmap = do_mmap;
return buf_list;
error:
buffer_list_close(buf_list);
return NULL;
}
void buffer_list_close(buffer_list_t *buf_list)
{
if (!buf_list) {
return;
}
if (buf_list->bufs) {
for (int i = 0; i < buf_list->nbufs; i++) {
buffer_close(buf_list->bufs[i]);
}
free(buf_list->bufs);
buf_list->bufs = NULL;
buf_list->nbufs = 0;
}
free(buf_list->name);
free(buf_list);
}
int buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline)
{
return buf_list->device->hw->buffer_list_set_format(buf_list, width, height, format, bytesperline);
}
int buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs)
{
int got_bufs = buf_list->device->hw->buffer_list_set_buffers(buf_list, nbufs);
if (got_bufs <= 0) {
goto error;
}
buf_list->bufs = calloc(got_bufs, sizeof(buffer_t*));
buf_list->nbufs = got_bufs;
for (unsigned i = 0; i < buf_list->nbufs; i++) {
char name[64];
sprintf(name, "%s:buf%d", buf_list->name, i);
buffer_t *buf = buffer_open(name, buf_list, i);
if (!buf) {
E_LOG_ERROR(buf_list, "Cannot open buffer: %u", i);
goto error;
}
buf_list->bufs[i] = buf;
}
E_LOG_DEBUG(buf_list, "Opened %u buffers", buf_list->nbufs);
return 0;
error:
return -1;
}
int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on)
{
if (!buf_list) {
return -1;
}
if (buf_list->streaming == do_on) {
return 0;
}
if (buf_list->device->hw->buffer_list_set_stream(buf_list, do_on) < 0) {
goto error;
}
buf_list->streaming = do_on;
int enqueued = buffer_list_count_enqueued(buf_list);
E_LOG_DEBUG(buf_list, "Streaming %s... Was %d of %d enqueud", do_on ? "started" : "stopped", enqueued, buf_list->nbufs);
return 0;
error:
return -1;
}

View File

@ -14,7 +14,7 @@ typedef struct buffer_list_s {
buffer_t **bufs; buffer_t **bufs;
int nbufs; int nbufs;
bool do_mmap, do_dma, do_capture; bool do_mmap, do_capture;
struct { struct {
bool do_mplanes; bool do_mplanes;
@ -34,7 +34,7 @@ buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, bool do_
void buffer_list_close(buffer_list_t *buf_list); void buffer_list_close(buffer_list_t *buf_list);
int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on); int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on);
int buffer_list_set_format(buffer_list_t *buffer_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline); int buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline);
int buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs); int buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs);
int buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue); int buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue);

View File

@ -1,5 +1,5 @@
#include "device/buffer_lock.h" #include "device/buffer_lock.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"

View File

@ -1,5 +1,5 @@
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#include <pthread.h> #include <pthread.h>

View File

@ -1,7 +1,7 @@
#include "camera.h" #include "camera.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"

View File

@ -1,11 +1,11 @@
#include "camera.h" #include "camera.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "http/http.h" #include "http/http.h"
int camera_configure_decoder(camera_t *camera) int camera_configure_decoder(camera_t *camera)

View File

@ -1,11 +1,11 @@
#include "camera.h" #include "camera.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "http/http.h" #include "http/http.h"
int camera_configure_direct(camera_t *camera) int camera_configure_direct(camera_t *camera)

View File

@ -1,11 +1,11 @@
#include "camera.h" #include "camera.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "http/http.h" #include "http/http.h"
void write_yuvu(buffer_t *buffer); void write_yuvu(buffer_t *buffer);

View File

@ -1,11 +1,11 @@
#include "camera.h" #include "camera.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/links.h" #include "device/links.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "http/http.h" #include "http/http.h"
void write_yuvu(buffer_t *buffer) void write_yuvu(buffer_t *buffer)

View File

@ -1,6 +1,6 @@
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
device_t *device_open(const char *name, const char *path, device_hw_t *hw) { device_t *device_open(const char *name, const char *path, device_hw_t *hw) {

View File

@ -15,6 +15,10 @@ typedef struct device_hw_s {
int (*buffer_enqueue)(buffer_t *buf, const char *who); int (*buffer_enqueue)(buffer_t *buf, const char *who);
int (*buffer_list_dequeue)(buffer_list_t *buf_list, buffer_t **bufp); int (*buffer_list_dequeue)(buffer_list_t *buf_list, buffer_t **bufp);
int (*buffer_list_pollfd)(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue); int (*buffer_list_pollfd)(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue);
int (*buffer_list_set_format)(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline);
int (*buffer_list_set_buffers)(buffer_list_t *buf_list, int nbufs);
int (*buffer_list_set_stream)(buffer_list_t *buf_list, bool do_on);
} device_hw_t; } device_hw_t;
typedef struct device_s { typedef struct device_s {

View File

@ -1,7 +1,7 @@
#include "device/links.h" #include "device/links.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/v4l2.h" #include "device/hw/v4l2.h"
#define N_FDS 50 #define N_FDS 50

View File

@ -1,6 +1,6 @@
#include "device/v4l2/v4l2.h" #include "device/v4l2/v4l2.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
int v4l2_buffer_open(buffer_t *buf) int v4l2_buffer_open(buffer_t *buf)
@ -43,9 +43,7 @@ int v4l2_buffer_open(buffer_t *buf)
if (buf->start == MAP_FAILED) { if (buf->start == MAP_FAILED) {
goto error; goto error;
} }
}
if (buf_list->do_dma) {
struct v4l2_exportbuffer v4l2_exp = {0}; struct v4l2_exportbuffer v4l2_exp = {0};
v4l2_exp.type = v4l2_buf.type; v4l2_exp.type = v4l2_buf.type;
v4l2_exp.index = buf->index; v4l2_exp.index = buf->index;

View File

@ -1,42 +1,30 @@
#include "device/v4l2/v4l2.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "device/hw/v4l2.h"
buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, bool do_capture, bool do_mmap) int v4l2_buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline)
{ {
buffer_list_t *buf_list = calloc(1, sizeof(buffer_list_t)); device_t *dev = buf_list->device;
buf_list->device = dev;
buf_list->name = strdup(name);
buf_list->do_capture = do_capture;
struct v4l2_capability v4l2_cap; struct v4l2_capability v4l2_cap;
E_XIOCTL(dev, dev->fd, VIDIOC_QUERYCAP, &v4l2_cap, "Can't query device capabilities"); E_XIOCTL(dev, dev->fd, VIDIOC_QUERYCAP, &v4l2_cap, "Can't query device capabilities");
if (do_capture) { if (buf_list->do_capture) {
if (v4l2_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { if (v4l2_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf_list->do_dma = do_mmap;
buf_list->do_mmap = do_mmap;
} else if (v4l2_cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) { } else if (v4l2_cap.capabilities & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) {
buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf_list->v4l2.do_mplanes = true; buf_list->v4l2.do_mplanes = true;
buf_list->do_dma = do_mmap;
buf_list->do_mmap = do_mmap;
} else { } else {
E_LOG_ERROR(dev, "Video capture is not supported by device: %08x", v4l2_cap.capabilities); E_LOG_ERROR(dev, "Video capture is not supported by device: %08x", v4l2_cap.capabilities);
} }
} else { } else {
if (v4l2_cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) { if (v4l2_cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) {
buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf_list->do_mmap = do_mmap;
buf_list->do_dma = do_mmap;
} else if (v4l2_cap.capabilities & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) { } else if (v4l2_cap.capabilities & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_VIDEO_M2M_MPLANE)) {
buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; buf_list->v4l2.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
buf_list->v4l2.do_mplanes = true; buf_list->v4l2.do_mplanes = true;
buf_list->do_mmap = do_mmap;
buf_list->do_dma = do_mmap;
} else { } else {
E_LOG_ERROR(dev, "Video output is not supported by device: %08x", v4l2_cap.capabilities); E_LOG_ERROR(dev, "Video output is not supported by device: %08x", v4l2_cap.capabilities);
} }
@ -49,43 +37,12 @@ buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, bool do_
strcat(buf_list->name, MPLANE_SUFFIX); strcat(buf_list->name, MPLANE_SUFFIX);
} }
return buf_list;
error:
buffer_list_close(buf_list);
return NULL;
}
void buffer_list_close(buffer_list_t *buf_list)
{
if (!buf_list) {
return;
}
if (buf_list->bufs) {
for (int i = 0; i < buf_list->nbufs; i++) {
buffer_close(buf_list->bufs[i]);
}
free(buf_list->bufs);
buf_list->bufs = NULL;
buf_list->nbufs = 0;
}
free(buf_list->name);
free(buf_list);
}
int buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline)
{
struct v4l2_format fmt = { 0 }; struct v4l2_format fmt = { 0 };
fmt.type = buf_list->v4l2.type; fmt.type = buf_list->v4l2.type;
unsigned orig_width = width; unsigned orig_width = width;
unsigned orig_height = height; unsigned orig_height = height;
retry:
// JPEG is in 16x16 blocks (shrink image to fit) (but adapt to 32x32) // JPEG is in 16x16 blocks (shrink image to fit) (but adapt to 32x32)
// And ISP output // And ISP output
if (strstr(buf_list->name, "JPEG") || strstr(buf_list->name, "H264") || buf_list->do_capture && strstr(buf_list->name, "ISP")) { if (strstr(buf_list->name, "JPEG") || strstr(buf_list->name, "H264") || buf_list->do_capture && strstr(buf_list->name, "ISP")) {
@ -177,7 +134,7 @@ error:
return -1; return -1;
} }
int buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs) int v4l2_buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs)
{ {
struct v4l2_requestbuffers v4l2_req = {0}; struct v4l2_requestbuffers v4l2_req = {0};
v4l2_req.count = nbufs; v4l2_req.count = nbufs;
@ -192,48 +149,18 @@ int buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs)
} }
E_LOG_DEBUG(buf_list, "Got %u buffers", v4l2_req.count); E_LOG_DEBUG(buf_list, "Got %u buffers", v4l2_req.count);
return v4l2_req.count;
buf_list->bufs = calloc(v4l2_req.count, sizeof(buffer_t*));
buf_list->nbufs = v4l2_req.count;
for (unsigned i = 0; i < buf_list->nbufs; i++) {
char name[64];
sprintf(name, "%s:buf%d", buf_list->name, i);
buffer_t *buf = buffer_open(name, buf_list, i);
if (!buf) {
E_LOG_ERROR(buf_list, "Cannot open buffer: %u", i);
goto error;
}
buf_list->bufs[i] = buf;
}
E_LOG_DEBUG(buf_list, "Opened %u buffers", buf_list->nbufs);
return 0;
error: error:
return -1; return -1;
} }
int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on) int v4l2_buffer_list_set_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->v4l2.type; enum v4l2_buf_type type = buf_list->v4l2.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;
int enqueued = buffer_list_count_enqueued(buf_list);
E_LOG_DEBUG(buf_list, "Streaming %s... Was %d of %d enqueud", do_on ? "started" : "stopped", enqueued, buf_list->nbufs);
return 0; return 0;
error: error:
return -1; return -1;
} }

View File

@ -1,5 +1,5 @@
#include "device/v4l2/v4l2.h" #include "device/v4l2/v4l2.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
int v4l2_buffer_list_refresh_states(buffer_list_t *buf_list) int v4l2_buffer_list_refresh_states(buffer_list_t *buf_list)

View File

@ -8,6 +8,9 @@ device_hw_t v4l2_device_hw = {
.buffer_enqueue = v4l2_buffer_enqueue, .buffer_enqueue = v4l2_buffer_enqueue,
.buffer_list_dequeue = v4l2_buffer_list_dequeue, .buffer_list_dequeue = v4l2_buffer_list_dequeue,
.buffer_list_pollfd = v4l2_buffer_list_pollfd, .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) device_t *device_v4l2_open(const char *name, const char *path)

View File

@ -13,3 +13,7 @@ int v4l2_buffer_enqueue(buffer_t *buf, const char *who);
int v4l2_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp); int v4l2_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp);
int v4l2_buffer_list_refresh_states(buffer_list_t *buf_list); int v4l2_buffer_list_refresh_states(buffer_list_t *buf_list);
int v4l2_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue); int v4l2_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue);
int v4l2_buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline);
int v4l2_buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs);
int v4l2_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on);

View File

@ -5,7 +5,7 @@
#include "http/http.h" #include "http/http.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/buffer_lock.h" #include "device/buffer_lock.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
#include "ffmpeg/remuxer.h" #include "ffmpeg/remuxer.h"

View File

@ -5,7 +5,7 @@
#include "http/http.h" #include "http/http.h"
#include "device/buffer.h" #include "device/buffer.h"
#include "device/buffer_lock.h" #include "device/buffer_lock.h"
#include "device/hw/buffer_list.h" #include "device/buffer_list.h"
#include "device/hw/device.h" #include "device/hw/device.h"
DEFINE_BUFFER_LOCK(http_h264, 0); DEFINE_BUFFER_LOCK(http_h264, 0);