Skip to content

Instantly share code, notes, and snippets.

@TIS-Edgar
Created July 2, 2014 12:41
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TIS-Edgar/10f04501f49b6b3bf75e to your computer and use it in GitHub Desktop.
Save TIS-Edgar/10f04501f49b6b3bf75e to your computer and use it in GitHub Desktop.
v4l2_openvc
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include "v4ldevice.h"
using namespace cv;
void ShowImage(char* Name, IplImage* Img, int Attribute )
{
cvNamedWindow(Name, Attribute );
cvShowImage( Name, Img );
cvWaitKey(0);
cvDestroyWindow( Name );
}
int main ()
{
IplImage* pOpenCVImage;
IplImage* pColorCVImage;
CvSize ImageSize;
unsigned char* ImageBuffer = NULL;
int wKey = -1;
ImageSize.width = 640;
ImageSize.height = 480;
cvNamedWindow( (char*)"Camera", 1 );
printf("Program started\n");
pOpenCVImage = cvCreateImage(ImageSize , IPL_DEPTH_8U, 1 ); // Grayscale
pColorCVImage = cvCreateImage(ImageSize , IPL_DEPTH_8U, 3 ); // Color image
open_device((char*)"/dev/video0");
init_device(ImageSize.width, ImageSize.height);
printf("Start capturing\n");
start_capturing();
while(wKey == -1 )
{
ImageBuffer = snapFrame();
if( ImageBuffer != NULL )
{
memcpy( pOpenCVImage->imageData, ImageBuffer, pOpenCVImage->imageSize);
cvCvtColor(pOpenCVImage,pColorCVImage,CV_BayerGB2RGB); // Create a color image from the raw data
cvShowImage( (char*)"Camera",pColorCVImage);
wKey = cvWaitKey(10);
}
else
{
printf("No image buffer retrieved.\n");
break;
}
}
cvDestroyWindow( (char*)"Camera" );
stop_capturing();
uninit_device();
close_device();
printf("Program ended\n");
return 0;
}
all: opencv-test
opencv-test: main.cpp v4ldevice.cpp
$(CXX) -Wall -g -O0 -o opencv-test main.cpp v4ldevice.cpp $(shell pkg-config --libs-only-l opencv libv4l2)
clean:
$(RM) *.o
$(RM) opencv-test
/*
* V4L2 video capture example
*
* This program can be used and distributed without restrictions.
*
* This program is provided with the V4L2 API
* see http://linuxtv.org/docs.php for more information
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define CLEAR(x) memset(&(x), 0, sizeof(x))
enum io_method
{
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
};
struct buffer
{
void *start;
size_t length;
};
struct v4l2_buffer buf;
char dev_name[1024];
enum io_method io = IO_METHOD_MMAP;
int fd = -1;
struct buffer *buffers;
unsigned int n_buffers;
int out_buf;
int force_format = 1;
int frame_count = 10;
void errno_exit (const char *s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
int xioctl (int fh, int request, void *arg)
{
int r;
do
{
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
int read_frame (void)
{
//struct v4l2_buffer buf;
unsigned int i;
switch (io)
{
case IO_METHOD_READ:
{
if (-1 == read(fd, buffers[0].start, buffers[0].length))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("read");
}
}
break;
}
case IO_METHOD_MMAP:
{
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("VIDIOC_DQBUF");
}
}
assert(buf.index < n_buffers);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
break;
}
case IO_METHOD_USERPTR:
{
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
{
errno_exit("VIDIOC_DQBUF");
}
}
}
for (i = 0; i < n_buffers; ++i)
{
if (buf.m.userptr == (unsigned long)buffers[i].start
&& buf.length == buffers[i].length)
break;
}
assert(i < n_buffers);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
errno_exit("VIDIOC_QBUF");
}
break;
}
}
return 1;
}
unsigned char* snapFrame()
{
//printf("Start snapFrame\n");
for (;;)
{
fd_set fds;
struct timeval tv;
int r;
FD_ZERO(&fds);
FD_SET(fd, &fds);
/* Timeout. */
tv.tv_sec = 2;
tv.tv_usec = 0;
r = select(fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r)
{
if (EINTR == errno)
continue;
errno_exit("select");
}
if (0 == r)
{
fprintf(stderr, "select timeout\n");
exit(EXIT_FAILURE);
}
if (read_frame())
break;
/* EAGAIN - continue select loop. */
}
//printf("End snapFrame\n");
// v4l2_buffer* pI = ((v4l2_buffer*)buffers[buf.index].start);
//return pI;
return (unsigned char*)buffers[buf.index].start;
}
void stop_capturing (void)
{
enum v4l2_buf_type type;
switch (io)
{
case IO_METHOD_READ:
{
/* Nothing to do. */
break;
}
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
{
errno_exit("VIDIOC_STREAMOFF");
}
break;
}
}
void start_capturing (void)
{
unsigned int i;
enum v4l2_buf_type type;
switch (io)
{
case IO_METHOD_READ:
{
/* Nothing to do. */
break;
}
case IO_METHOD_MMAP:
{
for (i = 0; i < n_buffers; ++i)
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
errno_exit("VIDIOC_QBUF");
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
{
errno_exit("VIDIOC_STREAMON");
}
break;
}
case IO_METHOD_USERPTR:
{
for (i = 0; i < n_buffers; ++i)
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.index = i;
buf.m.userptr = (unsigned long)buffers[i].start;
buf.length = buffers[i].length;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
errno_exit("VIDIOC_QBUF");
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
{
errno_exit("VIDIOC_STREAMON");
}
break;
}
}
}
void uninit_device (void)
{
unsigned int i;
switch (io)
{
case IO_METHOD_READ:
free(buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap(buffers[i].start, buffers[i].length))
errno_exit("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i)
free(buffers[i].start);
break;
}
free(buffers);
}
void init_read (unsigned int buffer_size)
{
buffers = (buffer*)(calloc(1, sizeof(*buffers)));
if (!buffers)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
buffers[0].length = buffer_size;
buffers[0].start = malloc(buffer_size);
if (!buffers[0].start)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
void init_mmap (void)
{
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
if (EINVAL == errno)
{
fprintf(stderr, "%s does not support "
"memory mapping\n", dev_name);
exit(EXIT_FAILURE);
}
else
{
errno_exit("VIDIOC_REQBUFS");
}
}
if (req.count < 2) \
{
fprintf(stderr, "Insufficient buffer memory on %s\n",
dev_name);
exit(EXIT_FAILURE);
}
buffers = (buffer*)calloc(req.count, sizeof(*buffers));
if (!buffers)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
errno_exit("VIDIOC_QUERYBUF");
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start =
mmap(NULL /* start anywhere */,
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
errno_exit("mmap");
}
}
void init_userp (unsigned int buffer_size)
{
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
if (EINVAL == errno)
{
fprintf(stderr, "%s does not support "
"user pointer i/o\n", dev_name);
exit(EXIT_FAILURE);
}
else
{
errno_exit("VIDIOC_REQBUFS");
}
}
buffers = (buffer*)calloc(4, sizeof(*buffers));
if (!buffers)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < 4; ++n_buffers)
{
buffers[n_buffers].length = buffer_size;
buffers[n_buffers].start = malloc(buffer_size);
if (!buffers[n_buffers].start)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
}
void init_device ( int width,int height)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap))
{
if (EINVAL == errno)
{
fprintf(stderr,
"%s is no V4L2 device\n",
dev_name);
exit(EXIT_FAILURE);
}
else
{
errno_exit("VIDIOC_QUERYCAP");
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
fprintf(stderr,
"%s is no video capture device\n",
dev_name);
exit(EXIT_FAILURE);
}
switch (io)
{
case IO_METHOD_READ:
{
if (!(cap.capabilities & V4L2_CAP_READWRITE))
{
fprintf(stderr,
"%s does not support read i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
break;
}
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
{
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr, "%s does not support streaming i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
break;
}
}
/* Select video input, video standard and tune here. */
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap))
{
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect; /* reset to default */
if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop))
{
switch (errno)
{
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
}
else
{
/* Errors ignored. */
}
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (force_format)
{
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
errno_exit("VIDIOC_S_FMT");
/* Note VIDIOC_S_FMT may change width and height. */
}
else
{
/* Preserve original settings as set by v4l2-ctl for example */
if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
errno_exit("VIDIOC_G_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;
switch (io)
{
case IO_METHOD_READ:
init_read(fmt.fmt.pix.sizeimage);
break;
case IO_METHOD_MMAP:
init_mmap();
break;
case IO_METHOD_USERPTR:
init_userp(fmt.fmt.pix.sizeimage);
break;
}
}
void close_device(void)
{
if (-1 == close(fd))
errno_exit("close");
fd = -1;
}
void open_device(char* devicename)
{
struct stat st;
strcpy( dev_name,devicename);
if (-1 == stat(dev_name, &st)) {
fprintf(stderr, "Cannot identify '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (!S_ISCHR(st.st_mode)) {
fprintf(stderr, "%s is no device\n", dev_name);
exit(EXIT_FAILURE);
}
fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
void open_device(char* devicename);
void close_device(void);
void init_device (int width, int height );
void init_userp (unsigned int buffer_size);
void init_mmap (void);
void init_read (unsigned int buffer_size);
void uninit_device (void);
void start_capturing (void);
void stop_capturing (void);
int read_frame (void);
void errno_exit (const char *s);
int xioctl (int fh, int request, void *arg);
unsigned char* snapFrame();
@VasylVarvolik
Copy link

I have a problem with building this simple:
Building target: Connect_camera
Invoking: NVCC Linker
/usr/local/cuda-8.0/bin/nvcc --cudart static --relocatable-device-code=false -gencode arch=compute_60,code=compute_60 -gencode arch=compute_60,code=sm_60 -m64 -link -o "Connect_camera" ./main.o ./v4ldevice.o -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dpm -lopencv_face -lopencv_photo -lopencv_freetype -lopencv_fuzzy -lopencv_img_hash -lopencv_line_descriptor -lopencv_optflow -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot -lopencv_xfeatures2d -lopencv_shape -lopencv_video -lopencv_ml -lopencv_ximgproc -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_flann -lopencv_xobjdetect -lopencv_imgcodecs -lopencv_objdetect -lopencv_xphoto -lopencv_imgproc -lopencv_core
./main.o: In function cv::String::~String()': /usr/local/include/opencv2/core/cvstd.hpp:648: undefined reference to cv::String::deallocate()'
./main.o: In function cv::String::operator=(cv::String const&)': makefile:58: recipe for target 'Connect_camera' failed /usr/local/include/opencv2/core/cvstd.hpp:656: undefined reference to cv::String::deallocate()'
collect2: error: ld returned 1 exit status
make: *** [Connect_camera] Error 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment