Created
July 2, 2014 12:41
-
-
Save TIS-Edgar/10f04501f49b6b3bf75e to your computer and use it in GitHub Desktop.
v4l2_openvc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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