- Package:
- libv4l-dev
- Source:
- v4l-utils
- Description:
- Collection of video4linux support libraries (development files)
- Submitter:
- william
- Date:
- 2021-02-04 21:33:05 UTC
- Severity:
- normal
- Tags:
Dear Maintainer,
* What led up to the situation?
Attempted to open access to a second device (camera)
* What exactly did you do (or not do) that was effective (or
ineffective)?
wrote the attached program which minimally opens the stream from the second camera
* What was the outcome of this action?
The program reportes that although the first camera was accessible, identical code opening a stream for a second camera was not successful
* What outcome did you expect instead?
Expected ioctl to return r==0, indicating successful system call
// v4l2_test.c
// compile as $ gcc v4l2_test.c -o v4l2_test
#define MMAP_BUFFERS 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <libv4l2.h>
struct v4l2_capability lcap, rcap;
struct v4l2_format lfmt, rfmt;
int xioctl(int fh, int request, void *arg){
int r;
do {
r = ioctl(fh, request, arg);
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
return r;
}
int main(int argc, char **argv){
char *left_camera, *right_camera;
int lfd, rfd, i, r;
struct v4l2_buffer lbuf, rbuf;
left_camera = "/dev/video1";
right_camera = "/dev/video3";
// Open the device
lfd = open(left_camera, O_RDWR | O_NONBLOCK, 0);
if (lfd < 0) {
printf("Failed to open left camera\n");
exit(EXIT_FAILURE);
}
rfd = open(right_camera, O_RDWR | O_NONBLOCK, 0);
if (rfd < 0) {
printf("Failed to open right camera\n");
exit(EXIT_FAILURE);
}
if (-1 == xioctl(lfd, VIDIOC_QUERYCAP, &lcap)) {
printf("Left ERROR: %s\n", strerror(errno));
if(lcap.capabilities != V4L2_CAP_VIDEO_CAPTURE)
printf("ERROR Left camera deficient capability\n");
exit(EXIT_FAILURE);
}
if (-1 == xioctl(rfd, VIDIOC_QUERYCAP, &rcap)) {
printf("Right ERROR: %s\n", strerror(errno));
if(rcap.capabilities != V4L2_CAP_VIDEO_CAPTURE)
printf("ERROR Right camera deficient capability\n");
exit(EXIT_FAILURE);
}
// poll fd for device format
lfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // == 1
if(-1 == xioctl(lfd, VIDIOC_G_FMT, &lfmt)){
printf("ERROR getting info from %s\n", left_camera);
return 1;
}
// poll fd for device format
rfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // == 1
if(-1 == xioctl(rfd, VIDIOC_G_FMT, &rfmt)){
printf("ERROR getting info from %s\n", right_camera);
return 1;
}
// Request N buffers that are memory mapped between
// our application space and the device
struct v4l2_requestbuffers l_request, r_request;
l_request.count = r_request.count = MMAP_BUFFERS;
l_request.type = r_request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
l_request.memory = r_request.memory = V4L2_MEMORY_MMAP;
if(r = xioctl(lfd, VIDIOC_REQBUFS, &l_request) < 0){
printf("ERROR Request l buffer failed\n");
}
if(r = xioctl(rfd, VIDIOC_REQBUFS, &r_request) < 0){
printf("ERROR Request r buffer failed\n");
}
if(l_request.count != r_request.count)
printf("ERROR in request count match\n");
printf("request count = %d\n", l_request.count);
// Queue the buffers, i.e. indicate to the device
// that they are available for writing now.
for (i = 0; i < l_request.count; ++i) {
// struct v4l2_buffer buf; - declared at head of main()
lbuf.type = rbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
lbuf.memory = rbuf.memory = V4L2_MEMORY_MMAP;
lbuf.index = rbuf.index = i;
if(r = xioctl(lfd, VIDIOC_QBUF, &lbuf) < 0)
printf("ERROR Failed to QBUF left camera\n");
if(r = xioctl(rfd, VIDIOC_QBUF, &rbuf) < 0)
printf("ERROR Failed to QBUF right camera\n");
}
// Start stream v4l_buf_type
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
r = xioctl(lfd, VIDIOC_STREAMON, &type);
if(r < 0)printf("ERROR Failed to STREAMON left camera\n");
r = xioctl(rfd, VIDIOC_STREAMON, &type);
if(r < 0)printf("ERROR Failed to STREAMON right camera\n");
}
// v4l2_test.c
// compile as $ gcc v4l2_test.c -o v4l2_test
#define MMAP_BUFFERS 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <libv4l2.h>
struct v4l2_capability lcap, rcap;
struct v4l2_format lfmt, rfmt;
int xioctl(int fh, int request, void *arg){
int r;
do {
r = ioctl(fh, request, arg);
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
return r;
}
int main(int argc, char **argv){
char *left_camera, *right_camera;
int lfd, rfd, i, r;
struct v4l2_buffer lbuf, rbuf;
left_camera = "/dev/video1";
right_camera = "/dev/video3";
// Open the device
lfd = open(left_camera, O_RDWR | O_NONBLOCK, 0);
if (lfd < 0) {
printf("Failed to open left camera\n");
exit(EXIT_FAILURE);
}
rfd = open(right_camera, O_RDWR | O_NONBLOCK, 0);
if (rfd < 0) {
printf("Failed to open right camera\n");
exit(EXIT_FAILURE);
}
if (-1 == xioctl(lfd, VIDIOC_QUERYCAP, &lcap)) {
printf("Left ERROR: %s\n", strerror(errno));
if(lcap.capabilities != V4L2_CAP_VIDEO_CAPTURE)
printf("ERROR Left camera deficient capability\n");
exit(EXIT_FAILURE);
}
if (-1 == xioctl(rfd, VIDIOC_QUERYCAP, &rcap)) {
printf("Right ERROR: %s\n", strerror(errno));
if(rcap.capabilities != V4L2_CAP_VIDEO_CAPTURE)
printf("ERROR Right camera deficient capability\n");
exit(EXIT_FAILURE);
}
// poll fd for device format
lfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // == 1
if(-1 == xioctl(lfd, VIDIOC_G_FMT, &lfmt)){
printf("ERROR getting info from %s\n", left_camera);
return 1;
}
// poll fd for device format
rfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // == 1
if(-1 == xioctl(rfd, VIDIOC_G_FMT, &rfmt)){
printf("ERROR getting info from %s\n", right_camera);
return 1;
}
// Request N buffers that are memory mapped between
// our application space and the device
struct v4l2_requestbuffers l_request, r_request;
l_request.count = r_request.count = MMAP_BUFFERS;
l_request.type = r_request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
l_request.memory = r_request.memory = V4L2_MEMORY_MMAP;
if(r = xioctl(lfd, VIDIOC_REQBUFS, &l_request) < 0){
printf("ERROR Request l buffer failed\n");
}
if(r = xioctl(lfd, VIDIOC_REQBUFS, &r_request) < 0){
printf("ERROR Request r buffer failed\n");
}
if(l_request.count != r_request.count)
printf("ERROR in request count match\n");
printf("request count = %d\n", l_request.count);
// Queue the buffers, i.e. indicate to the device
// that they are available for writing now.
for (i = 0; i < l_request.count; ++i) {
// struct v4l2_buffer buf; - declared at head of main()
lbuf.type = rbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
lbuf.memory = rbuf.memory = V4L2_MEMORY_MMAP;
lbuf.index = rbuf.index = i;
if(r = xioctl(lfd, VIDIOC_QBUF, &lbuf) < 0)
printf("ERROR Failed to QBUF left camera\n");
if(r = xioctl(rfd, VIDIOC_QBUF, &rbuf) < 0)
printf("ERROR Failed to QBUF right camera\n");
}
// Start stream v4l_buf_type
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
r = xioctl(lfd, VIDIOC_STREAMON, &type);
if(r < 0)printf("ERROR Failed to STREAMON left camera\n");
r = xioctl(rfd, VIDIOC_STREAMON, &type);
if(r < 0)printf("ERROR Failed to STREAMON right camera\n");
}
Control: severity -1 normal Control: tags -1 moreinfo I'm afraid that this bug reports lacks a lot of information and does not qualify as release critical. Does the second camera work if you switch ports? Also this package does not implement handling of the ioctl, so this bug would need to be assigned elsewhere. Cheers