Files
2023-05-14 11:44:44 +00:00

332 lines
10 KiB
C++

#include "camera_capture.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "aiqtool"
void process_image(struct capture_info* cap_info, const void* p, int size)
{
static int image_index = 0;
LOG_DEBUG("image_index %d\n", image_index++);
if (cap_info->out_fp) {
fwrite(p, size, 1, cap_info->out_fp);
fflush(cap_info->out_fp);
}
}
int read_frame(struct capture_info* cap_info)
{
struct v4l2_buffer buf;
unsigned int i, bytesused;
switch (cap_info->io) {
case IO_METHOD_READ:
if (-1 == read(cap_info->dev_fd, cap_info->buffers[0].start, cap_info->buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_debug("read");
}
}
process_image(cap_info, cap_info->buffers[0].start, cap_info->buffers[0].length);
break;
case IO_METHOD_MMAP:
CLEAR(buf);
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_MMAP;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (device_dqbuf(cap_info->dev_fd, &buf) == -1)
break;
assert(buf.index < cap_info->n_buffers);
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
bytesused = buf.m.planes[0].bytesused;
} else {
bytesused = buf.bytesused;
}
process_image(cap_info, cap_info->buffers[buf.index].start, bytesused);
device_qbuf(cap_info->dev_fd, &buf);
break;
case IO_METHOD_USERPTR:
CLEAR(buf);
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_USERPTR;
if (device_dqbuf(cap_info->dev_fd, &buf) == -1)
break;
for (i = 0; i < cap_info->n_buffers; ++i) {
if (buf.m.userptr == (unsigned long)cap_info->buffers[i].start &&
buf.length == cap_info->buffers[i].length) {
break;
}
}
assert(i < cap_info->n_buffers);
process_image(cap_info, (void*)buf.m.userptr, buf.bytesused);
device_qbuf(cap_info->dev_fd, &buf);
break;
}
return 1;
}
int read_frame(int handler, int index, struct capture_info* cap_info, CaptureCallBack callback)
{
struct v4l2_buffer buf;
unsigned int i, bytesused;
switch (cap_info->io) {
case IO_METHOD_READ:
if (-1 == read(cap_info->dev_fd, cap_info->buffers[0].start, cap_info->buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_debug("read");
}
}
if (callback)
callback(handler, index, cap_info->buffers[0].start, cap_info->buffers[0].length);
break;
case IO_METHOD_MMAP:
CLEAR(buf);
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_MMAP;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
if (device_dqbuf(cap_info->dev_fd, &buf) == -1)
break;
assert(buf.index < cap_info->n_buffers);
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
bytesused = buf.m.planes[0].bytesused;
} else {
bytesused = buf.bytesused;
}
if (callback) {
callback(handler, index, cap_info->buffers[buf.index].start, bytesused);
}
memset(cap_info->buffers[buf.index].start, 0, bytesused);
device_qbuf(cap_info->dev_fd, &buf);
break;
case IO_METHOD_USERPTR:
CLEAR(buf);
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_USERPTR;
if (device_dqbuf(cap_info->dev_fd, &buf) == -1)
break;
for (i = 0; i < cap_info->n_buffers; ++i)
if (buf.m.userptr == (unsigned long)cap_info->buffers[i].start &&
buf.length == cap_info->buffers[i].length) {
break;
}
assert(i < cap_info->n_buffers);
if (callback) {
callback(handler, index, (void*)buf.m.userptr, buf.bytesused);
}
device_qbuf(cap_info->dev_fd, &buf);
break;
}
return 1;
}
void stop_capturing(struct capture_info* cap_info)
{
enum v4l2_buf_type type;
switch (cap_info->io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = cap_info->capture_buf_type;
device_streamoff(cap_info->dev_fd, &type);
break;
}
}
void start_capturing(struct capture_info* cap_info)
{
unsigned int i;
enum v4l2_buf_type type;
LOG_DEBUG("#### start_capturing, cap_info.dev_name:%s\n", cap_info->dev_name);
switch (cap_info->io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
LOG_DEBUG("IO_METHOD_MMAP, buffer number:%d\n", cap_info->n_buffers);
for (i = 0; i < cap_info->n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
struct v4l2_plane planes[FMT_NUM_PLANES];
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
device_qbuf(cap_info->dev_fd, &buf);
}
type = cap_info->capture_buf_type;
device_streamon(cap_info->dev_fd, &type);
break;
case IO_METHOD_USERPTR:
for (i = 0; i < cap_info->n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = cap_info->capture_buf_type;
buf.memory = V4L2_MEMORY_USERPTR;
buf.index = i;
buf.m.userptr = (unsigned long)cap_info->buffers[i].start;
buf.length = cap_info->buffers[i].length;
if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) {
struct v4l2_plane planes[FMT_NUM_PLANES];
planes[0].m.userptr = (unsigned long)cap_info->buffers[i].start;
planes[0].length = cap_info->buffers[i].length;
buf.m.planes = planes;
buf.length = FMT_NUM_PLANES;
}
device_qbuf(cap_info->dev_fd, &buf);
}
type = cap_info->capture_buf_type;
device_streamon(cap_info->dev_fd, &type);
break;
}
}
void uninit_device(struct capture_info* cap_info)
{
unsigned int i;
switch (cap_info->io) {
case IO_METHOD_READ:
free(cap_info->buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < cap_info->n_buffers; ++i)
if (-1 == munmap(cap_info->buffers[i].start, cap_info->buffers[i].length)) {
errno_debug("munmap");
}
break;
case IO_METHOD_USERPTR:
for (i = 0; i < cap_info->n_buffers; ++i) {
free(cap_info->buffers[i].start);
}
break;
}
free(cap_info->buffers);
device_close(cap_info->dev_fd);
cap_info->dev_fd = -1;
}
int init_device(struct capture_info* cap_info)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
int ret;
cap_info->dev_fd = device_open(cap_info->dev_name);
if (-1 != device_querycap(cap_info->dev_fd, &cap)) {
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
LOG_ERROR("%s is no video capture device\n", cap_info->dev_name);
return -1;
}
}
if (-1 == check_io_method(cap_info->io, cap.capabilities)) {
return -1;
}
CLEAR(cropcap);
cropcap.type = cap_info->capture_buf_type;
crop.type = cap_info->capture_buf_type;
// crop.c = cropcap.defrect; /* reset to default */
crop.c.left = 0;
crop.c.top = 0;
crop.c.width = cap_info->width;
crop.c.height = cap_info->height;
if (cap_info->link == link_to_isp) {
device_cropcap(cap_info->dev_fd, &cropcap, &crop);
}
CLEAR(fmt);
if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
cap_info->capture_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
} else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) {
cap_info->capture_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
}
if (cap_info->format) {
fmt.type = cap_info->capture_buf_type;
fmt.fmt.pix.width = cap_info->width;
fmt.fmt.pix.height = cap_info->height;
fmt.fmt.pix.pixelformat = cap_info->format;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ret = device_setformat(cap_info->dev_fd, &fmt);
if (ret) {
LOG_ERROR("%s set format failed\n", cap_info->dev_name);
} else {
LOG_INFO("%s set format success\n", cap_info->dev_name);
}
} else {
device_getformat(cap_info->dev_fd, &fmt);
}
/* Buggy driver paranoia. */
min = fmt.fmt.pix.width * 2;
if (fmt.fmt.pix.bytesperline < min) {
fmt.fmt.pix.bytesperline = min;
}
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
if (fmt.fmt.pix.sizeimage < min) {
fmt.fmt.pix.sizeimage = min;
}
init_io_method(cap_info, fmt.fmt.pix.sizeimage);
return 0;
}