Introduce buffer_format_t and use it for buffer_list_open

This commit is contained in:
Kamil Trzcinski 2022-04-11 20:48:09 +02:00
parent a3e8ef1e24
commit 5a9e871484
14 changed files with 117 additions and 104 deletions

View File

@ -4,18 +4,20 @@
#include "opts/log.h" #include "opts/log.h"
#include "opts/fourcc.h" #include "opts/fourcc.h"
buffer_list_t *buffer_list_open(const char *name, const char *path, struct device_s *dev, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs, bool do_capture, bool do_mmap) buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, const char *path, buffer_format_t fmt, bool do_capture, bool do_mmap)
{ {
buffer_list_t *buf_list = calloc(1, sizeof(buffer_list_t)); buffer_list_t *buf_list = calloc(1, sizeof(buffer_list_t));
buf_list->dev = dev; buf_list->dev = dev;
buf_list->name = strdup(name); buf_list->name = strdup(name);
if (path) if (path) {
buf_list->path = strdup(path); buf_list->path = strdup(path);
}
buf_list->do_capture = do_capture; buf_list->do_capture = do_capture;
buf_list->do_mmap = do_mmap; buf_list->do_mmap = do_mmap;
buf_list->fmt = fmt;
int got_bufs = dev->hw->buffer_list_open(buf_list, path, width, height, format, bytesperline, nbufs); int got_bufs = dev->hw->buffer_list_open(buf_list);
if (got_bufs <= 0) { if (got_bufs <= 0) {
goto error; goto error;
} }
@ -23,13 +25,14 @@ buffer_list_t *buffer_list_open(const char *name, const char *path, struct devic
LOG_INFO( LOG_INFO(
buf_list, buf_list,
"Using: %ux%u/%s, bytesperline=%d", "Using: %ux%u/%s, bytesperline=%d",
buf_list->fmt_width, buf_list->fmt.width,
buf_list->fmt_height, buf_list->fmt.height,
fourcc_to_string(buf_list->fmt_format).buf, fourcc_to_string(buf_list->fmt.format).buf,
buf_list->fmt_bytesperline buf_list->fmt.bytesperline
); );
buf_list->bufs = calloc(got_bufs, sizeof(buffer_t*)); buf_list->bufs = calloc(got_bufs, sizeof(buffer_t*));
buf_list->fmt.nbufs = got_bufs;
buf_list->nbufs = got_bufs; buf_list->nbufs = got_bufs;
for (unsigned i = 0; i < buf_list->nbufs; i++) { for (unsigned i = 0; i < buf_list->nbufs; i++) {

View File

@ -7,6 +7,12 @@ typedef struct buffer_s buffer_t;
typedef struct device_s device_t; typedef struct device_s device_t;
struct pollfd; struct pollfd;
typedef struct buffer_format_s {
unsigned width, height, format, bytesperline;
unsigned nbufs;
unsigned interval_us;
} buffer_format_t;
typedef struct buffer_list_s { typedef struct buffer_list_s {
char *name; char *name;
char *path; char *path;
@ -14,7 +20,8 @@ typedef struct buffer_list_s {
buffer_t **bufs; buffer_t **bufs;
int nbufs; int nbufs;
bool do_mmap, do_capture; buffer_format_t fmt;
bool do_mmap, do_capture, do_timestamps;
union { union {
struct buffer_list_v4l2_s *v4l2; struct buffer_list_v4l2_s *v4l2;
@ -22,16 +29,12 @@ typedef struct buffer_list_s {
struct buffer_list_libcamera_s *libcamera; struct buffer_list_libcamera_s *libcamera;
}; };
unsigned fmt_width, fmt_height, fmt_format, fmt_bytesperline, fmt_interval_us;
bool do_timestamps;
uint64_t last_enqueued_us, last_dequeued_us; uint64_t last_enqueued_us, last_dequeued_us;
bool streaming; bool streaming;
int frames; int frames;
} buffer_list_t; } buffer_list_t;
buffer_list_t *buffer_list_open(const char *name, const char *path, struct device_s *dev, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs, bool do_capture, bool do_mmap); buffer_list_t *buffer_list_open(const char *name, struct device_s *dev, const char *path, buffer_format_t fmt, bool do_capture, bool do_mmap);
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);

View File

@ -31,7 +31,7 @@ int camera_configure_decoder(camera_t *camera)
src = camera->decoder->capture_list; src = camera->decoder->capture_list;
if (camera_src->fmt_format != V4L2_PIX_FMT_MJPEG && camera_src->fmt_format != V4L2_PIX_FMT_JPEG) { if (camera_src->fmt.format != V4L2_PIX_FMT_MJPEG && camera_src->fmt.format != V4L2_PIX_FMT_JPEG) {
camera->codec_jpeg = device_v4l2_open("JPEG", "/dev/video31"); camera->codec_jpeg = device_v4l2_open("JPEG", "/dev/video31");
if (device_open_buffer_list_output(camera->codec_jpeg, src) < 0 || if (device_open_buffer_list_output(camera->codec_jpeg, src) < 0 ||
@ -40,7 +40,7 @@ int camera_configure_decoder(camera_t *camera)
} }
} }
if (camera_src->fmt_format != V4L2_PIX_FMT_H264) { if (camera_src->fmt.format != V4L2_PIX_FMT_H264) {
camera->codec_h264 = device_v4l2_open("H264", "/dev/video11"); camera->codec_h264 = device_v4l2_open("H264", "/dev/video11");
if (device_open_buffer_list_output(camera->codec_h264, src) < 0 || if (device_open_buffer_list_output(camera->codec_h264, src) < 0 ||
@ -51,11 +51,11 @@ int camera_configure_decoder(camera_t *camera)
link_t *links = camera->links; link_t *links = camera->links;
if (camera_src->fmt_format == V4L2_PIX_FMT_MJPEG || camera_src->fmt_format == V4L2_PIX_FMT_JPEG) { if (camera_src->fmt.format == V4L2_PIX_FMT_MJPEG || camera_src->fmt.format == V4L2_PIX_FMT_JPEG) {
*links++ = (link_t){ camera->camera->capture_list, { camera->decoder->output_list }, { http_jpeg_capture, http_jpeg_needs_buffer } }; *links++ = (link_t){ camera->camera->capture_list, { camera->decoder->output_list }, { http_jpeg_capture, http_jpeg_needs_buffer } };
*links++ = (link_t){ camera->decoder->capture_list, { camera->codec_h264->output_list } }; *links++ = (link_t){ camera->decoder->capture_list, { camera->codec_h264->output_list } };
*links++ = (link_t){ camera->codec_h264->capture_list, { }, { http_h264_capture, http_h264_needs_buffer } }; *links++ = (link_t){ camera->codec_h264->capture_list, { }, { http_h264_capture, http_h264_needs_buffer } };
} else if (camera_src->fmt_format == V4L2_PIX_FMT_H264) { } else if (camera_src->fmt.format == V4L2_PIX_FMT_H264) {
*links++ = (link_t){ camera->camera->capture_list, { camera->decoder->output_list }, { http_h264_capture, http_h264_needs_buffer }}; *links++ = (link_t){ camera->camera->capture_list, { camera->decoder->output_list }, { http_h264_capture, http_h264_needs_buffer }};
*links++ = (link_t){ camera->decoder->capture_list, { camera->codec_jpeg->output_list } }; *links++ = (link_t){ camera->decoder->capture_list, { camera->codec_jpeg->output_list } };
*links++ = (link_t){ camera->codec_jpeg->capture_list, { }, { http_jpeg_capture, http_jpeg_needs_buffer } }; *links++ = (link_t){ camera->codec_jpeg->capture_list, { }, { http_jpeg_capture, http_jpeg_needs_buffer } };

View File

@ -22,7 +22,7 @@ int camera_configure_libcamera(camera_t *camera)
camera->camera->capture_list->do_timestamps = true; camera->camera->capture_list->do_timestamps = true;
if (camera->options.fps > 0) { if (camera->options.fps > 0) {
camera->camera->capture_list->fmt_interval_us = 1000 * 1000 / camera->options.fps; camera->camera->capture_list->fmt.interval_us = 1000 * 1000 / camera->options.fps;
} }
if (camera_configure_direct(camera) < 0) { if (camera_configure_direct(camera) < 0) {

View File

@ -27,10 +27,10 @@ int camera_configure_v4l2(camera_t *camera)
camera->camera->capture_list->do_timestamps = true; camera->camera->capture_list->do_timestamps = true;
if (camera->options.fps > 0) { if (camera->options.fps > 0) {
camera->camera->capture_list->fmt_interval_us = 1000 * 1000 / camera->options.fps; camera->camera->capture_list->fmt.interval_us = 1000 * 1000 / camera->options.fps;
} }
switch (camera->camera->capture_list->fmt_format) { switch (camera->camera->capture_list->fmt.format) {
case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU: case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_VYUY:
@ -64,7 +64,7 @@ int camera_configure_v4l2(camera_t *camera)
default: default:
LOG_ERROR(camera, "Unsupported camera format=%s", LOG_ERROR(camera, "Unsupported camera format=%s",
fourcc_to_string(camera->camera->capture_list->fmt_format).buf); fourcc_to_string(camera->camera->capture_list->fmt.format).buf);
break; break;
} }

View File

@ -75,7 +75,15 @@ int device_open_buffer_list(device_t *dev, bool do_capture, unsigned width, unsi
sprintf(name, "%s:output", dev->name); sprintf(name, "%s:output", dev->name);
} }
*buf_list = buffer_list_open(name, NULL, dev, width, height, format, bytesperline, nbufs, do_capture, do_mmap); buffer_format_t fmt = {
.width = width,
.height = height,
.format = format,
.bytesperline = bytesperline,
.nbufs = nbufs
};
*buf_list = buffer_list_open(name, dev, NULL, fmt, do_capture, do_mmap);
if (!*buf_list) { if (!*buf_list) {
goto error; goto error;
} }
@ -91,8 +99,8 @@ error:
int device_open_buffer_list_output(device_t *dev, buffer_list_t *capture_list) int device_open_buffer_list_output(device_t *dev, buffer_list_t *capture_list)
{ {
return device_open_buffer_list(dev, false, return device_open_buffer_list(dev, false,
capture_list->fmt_width, capture_list->fmt_height, capture_list->fmt.width, capture_list->fmt.height,
capture_list->fmt_format, capture_list->fmt_bytesperline, capture_list->fmt.format, capture_list->fmt.bytesperline,
capture_list->nbufs, capture_list->nbufs,
capture_list->dev->opts.allow_dma ? !capture_list->do_mmap : true); capture_list->dev->opts.allow_dma ? !capture_list->do_mmap : true);
} }
@ -107,7 +115,7 @@ int device_open_buffer_list_capture(device_t *dev, buffer_list_t *output_list, f
} }
return device_open_buffer_list(dev, true, return device_open_buffer_list(dev, true,
output_list->fmt_width / div, output_list->fmt_height / div, output_list->fmt.width / div, output_list->fmt.height / div,
format, 0, output_list->nbufs, do_mmap); format, 0, output_list->nbufs, do_mmap);
} }

View File

@ -22,7 +22,7 @@ typedef struct device_hw_s {
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_open)(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs); int (*buffer_list_open)(buffer_list_t *buf_list);
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);
} device_hw_t; } device_hw_t;

View File

@ -3,7 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
int dummy_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs) int dummy_buffer_list_open(buffer_list_t *buf_list)
{ {
buf_list->dummy = calloc(1, sizeof(buffer_list_dummy_t)); buf_list->dummy = calloc(1, sizeof(buffer_list_dummy_t));
return 0; return 0;

View File

@ -30,7 +30,7 @@ int dummy_buffer_enqueue(buffer_t *buf, const char *who);
int dummy_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp); int dummy_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp);
int dummy_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue); int dummy_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue);
int dummy_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs); int dummy_buffer_list_open(buffer_list_t *buf_list);
void dummy_buffer_list_close(buffer_list_t *buf_list); void dummy_buffer_list_close(buffer_list_t *buf_list);
int dummy_buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs); int dummy_buffer_list_set_buffers(buffer_list_t *buf_list, int nbufs);
int dummy_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on); int dummy_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on);

View File

@ -1,10 +1,8 @@
#ifdef USE_LIBCAMERA #ifdef USE_LIBCAMERA
#include "libcamera.hh" #include "libcamera.hh"
int libcamera_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs) int libcamera_buffer_list_open(buffer_list_t *buf_list)
{ {
int got_bufs = 0;
if (!buf_list->do_capture) { if (!buf_list->do_capture) {
LOG_INFO(buf_list, "Only capture mode is supported."); LOG_INFO(buf_list, "Only capture mode is supported.");
return -1; return -1;
@ -29,13 +27,13 @@ int libcamera_buffer_list_open(buffer_list_t *buf_list, const char *path, unsign
{ libcamera::StreamRole::Viewfinder }); { libcamera::StreamRole::Viewfinder });
auto &configuration = buf_list->libcamera->configuration->at(0); auto &configuration = buf_list->libcamera->configuration->at(0);
configuration.size = libcamera::Size(width, height); configuration.size = libcamera::Size(buf_list->fmt.width, buf_list->fmt.height);
configuration.pixelFormat = libcamera::PixelFormat(format); configuration.pixelFormat = libcamera::PixelFormat(buf_list->fmt.format);
if (bytesperline > 0) { if (buf_list->fmt.bytesperline > 0) {
configuration.stride = bytesperline; configuration.stride = buf_list->fmt.bytesperline;
} }
if (nbufs > 0) { if (buf_list->fmt.nbufs > 0) {
configuration.bufferCount = nbufs; configuration.bufferCount = buf_list->fmt.nbufs;
} }
if (buf_list->libcamera->configuration->validate() == libcamera::CameraConfiguration::Invalid) { if (buf_list->libcamera->configuration->validate() == libcamera::CameraConfiguration::Invalid) {
LOG_ERROR(buf_list, "Camera configuration invalid"); LOG_ERROR(buf_list, "Camera configuration invalid");
@ -45,15 +43,15 @@ int libcamera_buffer_list_open(buffer_list_t *buf_list, const char *path, unsign
LOG_ERROR(buf_list, "Failed to configure camera"); LOG_ERROR(buf_list, "Failed to configure camera");
} }
buf_list->fmt_width = configuration.size.width; buf_list->fmt.width = configuration.size.width;
buf_list->fmt_height = configuration.size.height; buf_list->fmt.height = configuration.size.height;
buf_list->fmt_format = configuration.pixelFormat.fourcc(); buf_list->fmt.format = configuration.pixelFormat.fourcc();
buf_list->fmt_bytesperline = configuration.stride; buf_list->fmt.bytesperline = configuration.stride;
buf_list->fmt.nbufs = configuration.bufferCount;
buf_list->libcamera->allocator = std::make_shared<libcamera::FrameBufferAllocator>( buf_list->libcamera->allocator = std::make_shared<libcamera::FrameBufferAllocator>(
buf_list->dev->libcamera->camera); buf_list->dev->libcamera->camera);
got_bufs = configuration.bufferCount;
for (libcamera::StreamConfiguration &stream_config : *buf_list->libcamera->configuration) { for (libcamera::StreamConfiguration &stream_config : *buf_list->libcamera->configuration) {
if (buf_list->libcamera->allocator->allocate(stream_config.stream()) < 0) { if (buf_list->libcamera->allocator->allocate(stream_config.stream()) < 0) {
@ -62,10 +60,10 @@ int libcamera_buffer_list_open(buffer_list_t *buf_list, const char *path, unsign
int allocated = buf_list->libcamera->allocator->buffers( int allocated = buf_list->libcamera->allocator->buffers(
stream_config.stream()).size(); stream_config.stream()).size();
got_bufs = std::min(got_bufs, allocated); buf_list->fmt.nbufs = std::min<unsigned>(buf_list->fmt.nbufs, allocated);
} }
return got_bufs; return buf_list->fmt.nbufs;
error: error:
return -1; return -1;

View File

@ -67,7 +67,7 @@ void libcamera_buffer_list_dequeued(buffer_list_t *buf_list, libcamera::Request
int libcamera_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp); int libcamera_buffer_list_dequeue(buffer_list_t *buf_list, buffer_t **bufp);
int libcamera_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue); int libcamera_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_dequeue);
int libcamera_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs); int libcamera_buffer_list_open(buffer_list_t *buf_list);
void libcamera_buffer_list_close(buffer_list_t *buf_list); void libcamera_buffer_list_close(buffer_list_t *buf_list);
int libcamera_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on); int libcamera_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on);
#endif // USE_LIBCAMERA #endif // USE_LIBCAMERA

View File

@ -202,18 +202,18 @@ int links_step(link_t *all_links, int timeout_now_ms, int *timeout_next_ms)
buffer_t *buf; buffer_t *buf;
#ifdef QUEUE_ON_CAPTURE #ifdef QUEUE_ON_CAPTURE
if (buf_list->fmt_interval_us > 0 && now_us - buf_list->last_enqueued_us < buf_list->fmt_interval_us) { if (buf_list->fmt.interval_us > 0 && now_us - buf_list->last_enqueued_us < buf_list->fmt.interval_us) {
*timeout_next_ms = MIN(*timeout_next_ms, (buf_list->last_enqueued_us + buf_list->fmt_interval_us - now_us) / 1000); *timeout_next_ms = MIN(*timeout_next_ms, (buf_list->last_enqueued_us + buf_list->fmt.interval_us - now_us) / 1000);
LOG_DEBUG(buf_list, "skipping dequeue: %.1f / %.1f. enqueued=%d", LOG_DEBUG(buf_list, "skipping dequeue: %.1f / %.1f. enqueued=%d",
(now_us - buf_list->last_enqueued_us) / 1000.0f, (now_us - buf_list->last_enqueued_us) / 1000.0f,
buf_list->fmt_interval_us / 1000.0f, buf_list->fmt.interval_us / 1000.0f,
buffer_list_count_enqueued(buf_list)); buffer_list_count_enqueued(buf_list));
continue; continue;
} else if (buf_list->fmt_interval_us > 0) { } else if (buf_list->fmt.interval_us > 0) {
LOG_DEBUG(buf_list, "since last: %.1f / %.1f. enqueued=%d", LOG_DEBUG(buf_list, "since last: %.1f / %.1f. enqueued=%d",
(now_us - buf_list->last_enqueued_us) / 1000.0f, (now_us - buf_list->last_enqueued_us) / 1000.0f,
buf_list->fmt_interval_us / 1000.0f, buf_list->fmt.interval_us / 1000.0f,
buffer_list_count_enqueued(buf_list)); buffer_list_count_enqueued(buf_list));
} }
#else #else

View File

@ -5,7 +5,7 @@
#include "opts/log.h" #include "opts/log.h"
#include "opts/fourcc.h" #include "opts/fourcc.h"
int v4l2_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs) int v4l2_buffer_list_open(buffer_list_t *buf_list)
{ {
device_t *dev = buf_list->dev; device_t *dev = buf_list->dev;
@ -45,95 +45,95 @@ int v4l2_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned wi
strcat(buf_list->name, MPLANE_SUFFIX); strcat(buf_list->name, MPLANE_SUFFIX);
} }
struct v4l2_format fmt = { 0 }; struct v4l2_format v4l2_fmt = { 0 };
fmt.type = buf_list->v4l2->type; v4l2_fmt.type = buf_list->v4l2->type;
unsigned orig_width = width; buffer_format_t fmt = buf_list->fmt;
unsigned orig_height = height;
// 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")) {
width = shrink_to_block(width, 32); buffer_format_t org_fmt = buf_list->fmt;
height = shrink_to_block(height, 32); fmt.width = shrink_to_block(fmt.width, 32);
LOG_VERBOSE(buf_list, "Adapting size to 32x32 block: %dx%d vs %dx%d", orig_width, orig_height, width, height); fmt.height = shrink_to_block(fmt.height, 32);
LOG_VERBOSE(buf_list, "Adapting size to 32x32 block: %dx%d vs %dx%d", org_fmt.width, org_fmt.height, fmt.width, fmt.height);
} }
if (format == V4L2_PIX_FMT_H264) { if (fmt.format == V4L2_PIX_FMT_H264) {
bytesperline = 0; fmt.bytesperline = 0;
} }
LOG_DEBUG(buf_list, "Get current format ..."); LOG_DEBUG(buf_list, "Get current format ...");
ERR_IOCTL(buf_list, buf_list->v4l2->dev_fd, VIDIOC_G_FMT, &fmt, "Can't set format"); ERR_IOCTL(buf_list, buf_list->v4l2->dev_fd, VIDIOC_G_FMT, &v4l2_fmt, "Can't set format");
if (buf_list->v4l2->do_mplanes) { if (buf_list->v4l2->do_mplanes) {
fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG; v4l2_fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG;
if (width) if (fmt.width)
fmt.fmt.pix_mp.width = width; v4l2_fmt.fmt.pix_mp.width = fmt.width;
if (height) if (fmt.height)
fmt.fmt.pix_mp.height = height; v4l2_fmt.fmt.pix_mp.height = fmt.height;
if (format) if (fmt.format)
fmt.fmt.pix_mp.pixelformat = format; v4l2_fmt.fmt.pix_mp.pixelformat = fmt.format;
fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; v4l2_fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
fmt.fmt.pix_mp.num_planes = 1; v4l2_fmt.fmt.pix_mp.num_planes = 1;
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = bytesperline; v4l2_fmt.fmt.pix_mp.plane_fmt[0].bytesperline = fmt.bytesperline;
//fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bytesperline * orig_height; //v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bytesperline * orig_height;
} else { } else {
fmt.fmt.pix.colorspace = V4L2_COLORSPACE_RAW; v4l2_fmt.fmt.pix.colorspace = V4L2_COLORSPACE_RAW;
if (width) if (fmt.width)
fmt.fmt.pix.width = width; v4l2_fmt.fmt.pix.width = fmt.width;
if (height) if (fmt.height)
fmt.fmt.pix.height = height; v4l2_fmt.fmt.pix.height = fmt.height;
if (format) if (fmt.format)
fmt.fmt.pix.pixelformat = format; v4l2_fmt.fmt.pix.pixelformat = fmt.format;
fmt.fmt.pix.field = V4L2_FIELD_ANY; v4l2_fmt.fmt.pix.field = V4L2_FIELD_ANY;
fmt.fmt.pix.bytesperline = bytesperline; v4l2_fmt.fmt.pix.bytesperline = fmt.bytesperline;
//fmt.fmt.pix.sizeimage = bytesperline * orig_height; //v4l2_fmt.fmt.pix.sizeimage = bytesperline * orig_height;
} }
LOG_DEBUG(buf_list, "Configuring format (%s)...", fourcc_to_string(format).buf); LOG_DEBUG(buf_list, "Configuring format (%s)...", fourcc_to_string(fmt.format).buf);
ERR_IOCTL(buf_list, buf_list->v4l2->dev_fd, VIDIOC_S_FMT, &fmt, "Can't set format"); ERR_IOCTL(buf_list, buf_list->v4l2->dev_fd, VIDIOC_S_FMT, &v4l2_fmt, "Can't set format");
if (buf_list->v4l2->do_mplanes) { if (buf_list->v4l2->do_mplanes) {
buf_list->fmt_width = fmt.fmt.pix_mp.width; buf_list->fmt.width = v4l2_fmt.fmt.pix_mp.width;
buf_list->fmt_height = fmt.fmt.pix_mp.height; buf_list->fmt.height = v4l2_fmt.fmt.pix_mp.height;
buf_list->fmt_format = fmt.fmt.pix_mp.pixelformat; buf_list->fmt.format = v4l2_fmt.fmt.pix_mp.pixelformat;
buf_list->fmt_bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; buf_list->fmt.bytesperline = v4l2_fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
} else { } else {
buf_list->fmt_width = fmt.fmt.pix.width; buf_list->fmt.width = v4l2_fmt.fmt.pix.width;
buf_list->fmt_height = fmt.fmt.pix.height; buf_list->fmt.height = v4l2_fmt.fmt.pix.height;
buf_list->fmt_format = fmt.fmt.pix.pixelformat; buf_list->fmt.format = v4l2_fmt.fmt.pix.pixelformat;
buf_list->fmt_bytesperline = fmt.fmt.pix.bytesperline; buf_list->fmt.bytesperline = v4l2_fmt.fmt.pix.bytesperline;
} }
if (buf_list->fmt_width != width || buf_list->fmt_height != height) { if (buf_list->fmt.width != fmt.width || buf_list->fmt.height != fmt.height) {
if (bytesperline) { if (fmt.bytesperline) {
LOG_ERROR(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u.", LOG_ERROR(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u.",
width, height, buf_list->fmt_width, buf_list->fmt_height); fmt.width, fmt.height, buf_list->fmt.width, buf_list->fmt.height);
} else { } else {
LOG_INFO(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u. Accepted", LOG_INFO(buf_list, "Requested resolution=%ux%u is unavailable. Got %ux%u. Accepted",
width, height, buf_list->fmt_width, buf_list->fmt_height); fmt.width, fmt.height, buf_list->fmt.width, buf_list->fmt.height);
} }
} }
if (format && buf_list->fmt_format != format) { if (fmt.format && buf_list->fmt.format != fmt.format) {
LOG_ERROR(buf_list, "Could not obtain the requested format=%s; driver gave us %s", LOG_ERROR(buf_list, "Could not obtain the requested format=%s; driver gave us %s",
fourcc_to_string(format).buf, fourcc_to_string(fmt.format).buf,
fourcc_to_string(buf_list->fmt_format).buf); fourcc_to_string(buf_list->fmt.format).buf);
} }
if (bytesperline > 0 && buf_list->fmt_bytesperline != bytesperline) { if (fmt.bytesperline > 0 && buf_list->fmt.bytesperline != fmt.bytesperline) {
LOG_ERROR(buf_list, "Requested bytesperline=%u. Got %u.", LOG_ERROR(buf_list, "Requested bytesperline=%u. Got %u.",
bytesperline, buf_list->fmt_bytesperline); fmt.bytesperline, buf_list->fmt.bytesperline);
} }
// Some devices require setting pad size via media-controller // Some devices require setting pad size via media-controller
if (buf_list->do_capture) { if (buf_list->do_capture) {
v4l2_device_set_pad_format(dev, width, height, format); v4l2_device_set_pad_format(dev, fmt.width, fmt.height, fmt.format);
} }
struct v4l2_requestbuffers v4l2_req = {0}; struct v4l2_requestbuffers v4l2_req = {0};
v4l2_req.count = nbufs; v4l2_req.count = fmt.nbufs;
v4l2_req.type = buf_list->v4l2->type; v4l2_req.type = buf_list->v4l2->type;
v4l2_req.memory = buf_list->do_mmap ? V4L2_MEMORY_MMAP : V4L2_MEMORY_DMABUF; v4l2_req.memory = buf_list->do_mmap ? V4L2_MEMORY_MMAP : V4L2_MEMORY_DMABUF;
@ -145,6 +145,7 @@ int v4l2_buffer_list_open(buffer_list_t *buf_list, const char *path, unsigned wi
} }
LOG_DEBUG(buf_list, "Got %u buffers", v4l2_req.count); LOG_DEBUG(buf_list, "Got %u buffers", v4l2_req.count);
buf_list->fmt.nbufs = v4l2_req.count;
return v4l2_req.count; return v4l2_req.count;
error: error:

View File

@ -46,7 +46,7 @@ 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_open(buffer_list_t *buf_list, const char *path, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs); int v4l2_buffer_list_open(buffer_list_t *buf_list);
void v4l2_buffer_list_close(buffer_list_t *buf_list); void v4l2_buffer_list_close(buffer_list_t *buf_list);
int v4l2_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);