Skip to content

Commit

Permalink
Make video_capture test use ALLOCATE_GUARD etc
Browse files Browse the repository at this point in the history
  • Loading branch information
rocallahan committed Dec 28, 2024
1 parent 6f8244f commit a3bbf7e
Showing 1 changed file with 110 additions and 82 deletions.
192 changes: 110 additions & 82 deletions src/test/video_capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static void no_v4l2(void) {
}

static int open_device(void) {
struct v4l2_capability cap;
struct v4l2_capability* cap;
int fd = open("/dev/video0", O_RDWR);
int ret;

Expand All @@ -31,7 +31,9 @@ static int open_device(void) {
}
test_assert(fd >= 0);

ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
ALLOCATE_GUARD(cap, 'a');
ret = ioctl(fd, VIDIOC_QUERYCAP, cap);
VERIFY_GUARD(cap);
if (ret < 0 && errno == EINVAL) {
atomic_printf("%s is not a V4L2 device; aborting test\n", device_name);
no_v4l2();
Expand All @@ -40,83 +42,95 @@ static int open_device(void) {
atomic_printf("%s is not accessible; aborting test\n", device_name);
no_v4l2();
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
if (!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
atomic_printf("%s is not a V4L2 capture device; aborting test\n",
device_name);
no_v4l2();
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
if (!(cap->capabilities & V4L2_CAP_STREAMING)) {
atomic_printf("%s does not support streaming; aborting test\n",
device_name);
no_v4l2();
}

uint32_t input = 0xdeadbeef;
ret = ioctl(fd, VIDIOC_G_INPUT, &input);
uint32_t* input;
ALLOCATE_GUARD(input, 'b');
ret = ioctl(fd, VIDIOC_G_INPUT, input);
VERIFY_GUARD(input);
if (ret < 0) {
atomic_printf("%s does not support VIDIOC_G_INPUT\n", device_name);
} else {
atomic_printf("%s VIDIOC_G_INPUT returns %d\n", device_name, input);
atomic_printf("%s VIDIOC_G_INPUT returns %d\n", device_name, *input);
}

#ifdef VIDIOC_QUERY_EXT_CTRL
struct v4l2_query_ext_ctrl qec;
memset(&qec, 0, sizeof(qec));
qec.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
ret = ioctl(fd, VIDIOC_QUERY_EXT_CTRL, &qec);
struct v4l2_query_ext_ctrl* qec;
ALLOCATE_GUARD(qec, 'c');
memset(qec, 0, sizeof(*qec));
qec->id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
ret = ioctl(fd, VIDIOC_QUERY_EXT_CTRL, qec);
VERIFY_GUARD(qec);
if (ret < 0) {
atomic_printf("%s does not support VIDIOC_QUERY_EXT_CTRL\n", device_name);
} else {
atomic_printf("%s VIDIOC_QUERY_EXT_CTRL returns id=%d, type=%d, name=%s\n",
device_name, qec.id, qec.type, qec.name);
device_name, qec->id, qec->type, qec->name);
}
#endif

enum v4l2_priority prio = V4L2_PRIORITY_UNSET;
ret = ioctl(fd, VIDIOC_G_PRIORITY, &prio);
enum v4l2_priority* prio;
ALLOCATE_GUARD(prio, 'd');
ret = ioctl(fd, VIDIOC_G_PRIORITY, prio);
VERIFY_GUARD(prio);
if (ret < 0) {
atomic_printf("%s does not support VIDIOC_G_PRIORITY\n", device_name);
} else {
atomic_printf("%s VIDIOC_G_PRIORITY returns prio=%d\n", device_name, prio);
atomic_printf("%s VIDIOC_G_PRIORITY returns prio=%d\n", device_name, *prio);
}

struct v4l2_queryctrl qc;
memset(&qc, 0, sizeof(qc));
qc.id = V4L2_CTRL_FLAG_NEXT_CTRL;
ret = ioctl(fd, VIDIOC_QUERYCTRL, &qc);
struct v4l2_queryctrl* qc;
ALLOCATE_GUARD(qc, 'e');
memset(qc, 0, sizeof(*qc));
qc->id = V4L2_CTRL_FLAG_NEXT_CTRL;
ret = ioctl(fd, VIDIOC_QUERYCTRL, qc);
VERIFY_GUARD(qc);
if (ret < 0) {
atomic_printf("%s does not support VIDIOC_QUERYCTRL\n", device_name);
} else {
atomic_printf("%s VIDIOC_QUERYCTRL returns id=%d, type=%d, name=%s\n",
device_name, qc.id, qc.type, qc.name);
device_name, qc->id, qc->type, qc->name);
}

return fd;
}

static void init_device(int fd) {
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_format* fmt;
struct v4l2_requestbuffers* req;
int ret;
size_t i;
enum v4l2_buf_type type;
enum v4l2_buf_type* type;

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
ALLOCATE_GUARD(fmt, 'a');
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_G_FMT, fmt);
VERIFY_GUARD(fmt);
if (ret < 0 && errno == EINVAL) {
// v4l2_loopback doesn't support G_FMT
atomic_printf("%s does not support G_FMT; aborting test\n",
device_name);
no_v4l2();
}
test_assert(0 == ret);
atomic_printf("%s returning %dx%d frames\n", device_name, fmt.fmt.pix.width,
fmt.fmt.pix.height);

req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_REQBUFS, &req);
atomic_printf("%s returning %dx%d frames\n", device_name, fmt->fmt.pix.width,
fmt->fmt.pix.height);

ALLOCATE_GUARD(req, 'b');
req->count = 4;
req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req->memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_REQBUFS, req);
VERIFY_GUARD(req);
if (ret < 0 && errno == EINVAL) {
atomic_printf("%s does not support memory mapping; aborting test\n",
device_name);
Expand All @@ -127,11 +141,11 @@ static void init_device(int fd) {
no_v4l2();
}
test_assert(0 == ret);
if (req.count < 2) {
if (req->count < 2) {
atomic_printf("%s only supports one buffer; aborting test\n", device_name);
no_v4l2();
}
buffer_count = req.count;
buffer_count = req->count;

for (i = 0; i < buffer_count; ++i) {
struct buffer* buf = buffers + i;
Expand All @@ -147,8 +161,10 @@ static void init_device(int fd) {
(long long)buf->vbuf.length);
test_assert(0 == ioctl(fd, VIDIOC_QBUF, &buf->vbuf));
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
test_assert(0 == ioctl(fd, VIDIOC_STREAMON, &type));
ALLOCATE_GUARD(type, 'c');
*type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
test_assert(0 == ioctl(fd, VIDIOC_STREAMON, type));
VERIFY_GUARD(type);
}

static void print_fourcc(int v) {
Expand All @@ -165,63 +181,69 @@ static double fract_to_fps(struct v4l2_fract* f) {
}

static void dump_sizes(int fd) {
struct v4l2_fmtdesc fmt;
struct v4l2_fmtdesc* fmt;

fmt.index = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ALLOCATE_GUARD(fmt, 'a');
fmt->index = 0;
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while (1) {
struct v4l2_frmsizeenum size;
int ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt);
struct v4l2_frmsizeenum* size;
int ret = ioctl(fd, VIDIOC_ENUM_FMT, fmt);
VERIFY_GUARD(fmt);
if (ret < 0) {
test_assert(errno == EINVAL);
break;
}
++fmt.index;

atomic_printf("Format %d fourcc ", fmt.index);
print_fourcc(fmt.pixelformat);
atomic_printf(" name '%s'\n", fmt.description);
atomic_printf("Format %d fourcc ", fmt->index);
print_fourcc(fmt->pixelformat);
++fmt->index;
atomic_printf(" name '%s'\n", fmt->description);

size.index = 0;
size.pixel_format = fmt.pixelformat;
ALLOCATE_GUARD(size, 'b');
size->index = 0;
size->pixel_format = fmt->pixelformat;
while (1) {
ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &size);
ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, size);
VERIFY_GUARD(size);
if (ret < 0) {
test_assert(errno == EINVAL);
break;
}
++size.index;

if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
struct v4l2_frmivalenum interval;
atomic_printf(" Frame size %dx%d\n", size.discrete.width,
size.discrete.height);
interval.index = 0;
interval.pixel_format = fmt.pixelformat;
interval.width = size.discrete.width;
interval.height = size.discrete.height;
++size->index;

if (size->type == V4L2_FRMSIZE_TYPE_DISCRETE) {
struct v4l2_frmivalenum* interval;
ALLOCATE_GUARD(interval, 'c');
atomic_printf(" Frame size %dx%d\n", size->discrete.width,
size->discrete.height);
interval->index = 0;
interval->pixel_format = fmt->pixelformat;
interval->width = size->discrete.width;
interval->height = size->discrete.height;
while (1) {
ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &interval);
ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, interval);
VERIFY_GUARD(interval);
if (ret < 0) {
test_assert(errno == EINVAL);
break;
}
++interval.index;
++interval->index;

if (interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
atomic_printf(" %f fps\n", fract_to_fps(&interval.discrete));
} else if (interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
if (interval->type == V4L2_FRMIVAL_TYPE_DISCRETE) {
atomic_printf(" %f fps\n", fract_to_fps(&interval->discrete));
} else if (interval->type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
interval->type == V4L2_FRMIVAL_TYPE_STEPWISE) {
atomic_printf(" %f-%f fps\n",
fract_to_fps(&interval.stepwise.min),
fract_to_fps(&interval.stepwise.max));
fract_to_fps(&interval->stepwise.min),
fract_to_fps(&interval->stepwise.max));
}
}
} else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
} else if (size->type == V4L2_FRMSIZE_TYPE_STEPWISE) {
atomic_printf(" Frame size %dx%d to %dx%d step %dx%d\n",
size.stepwise.min_width, size.stepwise.min_height,
size.stepwise.max_width, size.stepwise.max_height,
size.stepwise.step_width, size.stepwise.step_height);
size->stepwise.min_width, size->stepwise.min_height,
size->stepwise.max_width, size->stepwise.max_height,
size->stepwise.step_width, size->stepwise.step_height);
}
}
}
Expand All @@ -231,20 +253,22 @@ static void read_frames(int fd) {
size_t i, j;

for (i = 0; i < buffer_count * 2; ++i) {
struct v4l2_buffer buf;
struct v4l2_buffer* buf;
int ret;
size_t bytes;
struct buffer* buffer;

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
ALLOCATE_GUARD(buf, 'a');
buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf->memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, buf);
VERIFY_GUARD(buf);
test_assert(ret == 0);
test_assert(buf.index < buffer_count);
test_assert(buf->index < buffer_count);

bytes = buf.length < 16 ? buf.length : 16;
buffer = &buffers[buf.index];
atomic_printf("Frame %d, buffer %d, addr %p: ", (int)i, (int)buf.index,
bytes = buf->length < 16 ? buf->length : 16;
buffer = &buffers[buf->index];
atomic_printf("Frame %d, buffer %d, addr %p: ", (int)i, (int)buf->index,
buffer->mmap_data);
for (j = 0; j < bytes; ++j) {
atomic_printf("%2x ", buffer->mmap_data[j]);
Expand All @@ -259,15 +283,19 @@ static void read_frames(int fd) {
fd, buffer->vbuf.m.offset);
test_assert(buffer->mmap_data != MAP_FAILED);

test_assert(0 == ioctl(fd, VIDIOC_QBUF, &buf));
test_assert(0 == ioctl(fd, VIDIOC_QBUF, buf));
VERIFY_GUARD(buf);
FREE_GUARD(buf);
}
}

static void close_device(int fd) {
enum v4l2_buf_type type;
enum v4l2_buf_type* type;

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
test_assert(0 == ioctl(fd, VIDIOC_STREAMOFF, &type));
ALLOCATE_GUARD(type, 'a');
*type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
test_assert(0 == ioctl(fd, VIDIOC_STREAMOFF, type));
VERIFY_GUARD(type);
}

int main(void) {
Expand Down

0 comments on commit a3bbf7e

Please sign in to comment.