extract V4L2 wrapper
parent
b3010a157c
commit
812522473e
@ -0,0 +1,3 @@
|
||||
[submodule "v4l2wrapper"]
|
||||
path = v4l2wrapper
|
||||
url = https://github.com/mpromonet/v4l2wrapper
|
@ -1,76 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2Capture.h
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef V4L2_CAPTURE
|
||||
#define V4L2_CAPTURE
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Capture parameters
|
||||
// ---------------------------------
|
||||
struct V4L2DeviceParameters
|
||||
{
|
||||
V4L2DeviceParameters(const char* devname, unsigned int format, unsigned int width, unsigned int height, int fps, int verbose) :
|
||||
m_devName(devname), m_format(format), m_width(width), m_height(height), m_fps(fps), m_verbose(verbose) {};
|
||||
|
||||
std::string m_devName;
|
||||
unsigned int m_format;
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
int m_fps;
|
||||
int m_verbose;
|
||||
};
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Capture
|
||||
// ---------------------------------
|
||||
class V4l2Capture
|
||||
{
|
||||
protected:
|
||||
V4l2Capture(V4L2DeviceParameters params);
|
||||
|
||||
public:
|
||||
virtual ~V4l2Capture();
|
||||
|
||||
public:
|
||||
int getFd() { return m_fd; };
|
||||
int getBufferSize() { return m_bufferSize; };
|
||||
int getFormat() { return m_format; } ;
|
||||
void queryFormat();
|
||||
|
||||
protected:
|
||||
bool init(unsigned int mandatoryCapabilities);
|
||||
void close();
|
||||
|
||||
int initdevice(const char *dev_name, unsigned int mandatoryCapabilities);
|
||||
int checkCapabilities(int fd, unsigned int mandatoryCapabilities);
|
||||
int configureFormat(int fd);
|
||||
int configureParam(int fd);
|
||||
int xioctl(int fd, int request, void *arg);
|
||||
|
||||
public:
|
||||
virtual bool captureStart() = 0;
|
||||
virtual size_t read(char* buffer, size_t bufferSize) = 0;
|
||||
virtual bool captureStop() = 0;
|
||||
virtual bool isReady() = 0;
|
||||
|
||||
protected:
|
||||
V4L2DeviceParameters m_params;
|
||||
int m_fd;
|
||||
int m_bufferSize;
|
||||
int m_format;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2MmapCapture.h
|
||||
**
|
||||
** V4L2 source using mmap API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef V4L2_MMAP_CAPTURE
|
||||
#define V4L2_MMAP_CAPTURE
|
||||
|
||||
// project
|
||||
#include "V4l2Capture.h"
|
||||
|
||||
#define V4L2MMAP_NBBUFFER 10
|
||||
class V4l2MmapCapture : public V4l2Capture
|
||||
{
|
||||
public:
|
||||
static V4l2MmapCapture* createNew(V4L2DeviceParameters params);
|
||||
|
||||
protected:
|
||||
V4l2MmapCapture(V4L2DeviceParameters params) : V4l2Capture(params), n_buffers(0) {};
|
||||
|
||||
public:
|
||||
virtual bool captureStart();
|
||||
virtual size_t read(char* buffer, size_t bufferSize);
|
||||
virtual bool captureStop();
|
||||
virtual bool isReady() { return ((m_fd != -1)&& (n_buffers != 0)); };
|
||||
|
||||
protected:
|
||||
unsigned int n_buffers;
|
||||
|
||||
struct buffer
|
||||
{
|
||||
void * start;
|
||||
size_t length;
|
||||
};
|
||||
buffer m_buffer[V4L2MMAP_NBBUFFER];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2ReadCapture.h
|
||||
**
|
||||
** V4L2 source using read API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef V4L2_READ_CAPTURE
|
||||
#define V4L2_READ_CAPTURE
|
||||
|
||||
// project
|
||||
#include "V4l2Capture.h"
|
||||
|
||||
class V4l2ReadCapture : public V4l2Capture
|
||||
{
|
||||
public:
|
||||
static V4l2ReadCapture* createNew(V4L2DeviceParameters params);
|
||||
|
||||
protected:
|
||||
V4l2ReadCapture(V4L2DeviceParameters params) : V4l2Capture(params), m_counter(0) {};
|
||||
|
||||
public:
|
||||
virtual bool captureStart() { m_counter=1; return true; };
|
||||
virtual size_t read(char* buffer, size_t bufferSize);
|
||||
virtual bool captureStop() { m_counter=0; return true; };
|
||||
virtual bool isReady() { return ((m_fd != -1) && (m_counter>0)); };
|
||||
|
||||
protected:
|
||||
int m_counter;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,196 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2Capture.cpp
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
#include <libv4l2.h>
|
||||
|
||||
// project
|
||||
#include "V4l2Capture.h"
|
||||
|
||||
// Constructor
|
||||
V4l2Capture::V4l2Capture(V4L2DeviceParameters params) : m_params(params), m_fd(-1), m_bufferSize(0), m_format(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
V4l2Capture::~V4l2Capture()
|
||||
{
|
||||
if (m_fd !=-1) v4l2_close(m_fd);
|
||||
}
|
||||
|
||||
// intialize the V4L2 connection
|
||||
bool V4l2Capture::init(unsigned int mandatoryCapabilities)
|
||||
{
|
||||
if (initdevice(m_params.m_devName.c_str(), mandatoryCapabilities) == -1)
|
||||
{
|
||||
fprintf(stderr, "[%s] Init device:%s failure\n", __FILE__, m_params.m_devName.c_str());
|
||||
|
||||
}
|
||||
return (m_fd!=-1);
|
||||
}
|
||||
|
||||
// close the V4L2 connection
|
||||
void V4l2Capture::close()
|
||||
{
|
||||
if (m_fd != -1) v4l2_close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
// intialize the V4L2 device
|
||||
int V4l2Capture::initdevice(const char *dev_name, unsigned int mandatoryCapabilities)
|
||||
{
|
||||
m_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
|
||||
if (m_fd < 0)
|
||||
{
|
||||
perror("Cannot open device");
|
||||
this->close();
|
||||
return -1;
|
||||
}
|
||||
if (checkCapabilities(m_fd,mandatoryCapabilities) !=0)
|
||||
{
|
||||
this->close();
|
||||
return -1;
|
||||
}
|
||||
if (configureFormat(m_fd) !=0)
|
||||
{
|
||||
this->close();
|
||||
return -1;
|
||||
}
|
||||
if (configureParam(m_fd) !=0)
|
||||
{
|
||||
this->close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
// check needed V4L2 capabilities
|
||||
int V4l2Capture::checkCapabilities(int fd, unsigned int mandatoryCapabilities)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
memset(&(cap), 0, sizeof(cap));
|
||||
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap))
|
||||
{
|
||||
fprintf(stderr, "[%s] xioctl cannot get capabilities error %d, %s\n", __FILE__, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "driver:%s capabilities;%X\n", cap.driver, cap.capabilities);
|
||||
|
||||
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
{
|
||||
fprintf(stderr, "[%s] the device '%s' doesnot support capture\n", __FILE__, m_params.m_devName.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((cap.capabilities & V4L2_CAP_READWRITE)) fprintf(stderr, "%s support read i/o\n", m_params.m_devName.c_str());
|
||||
if ((cap.capabilities & V4L2_CAP_STREAMING)) fprintf(stderr, "%s support streaming i/o\n", m_params.m_devName.c_str());
|
||||
if ((cap.capabilities & V4L2_CAP_TIMEPERFRAME)) fprintf(stderr, "%s support timeperframe\n", m_params.m_devName.c_str());
|
||||
|
||||
if ( (cap.capabilities & mandatoryCapabilities) != mandatoryCapabilities )
|
||||
{
|
||||
fprintf(stderr, "%s mandatory capabilities not available\n", m_params.m_devName.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// configure capture format
|
||||
int V4l2Capture::configureFormat(int fd)
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
memset(&(fmt), 0, sizeof(fmt));
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.width = m_params.m_width;
|
||||
fmt.fmt.pix.height = m_params.m_height;
|
||||
fmt.fmt.pix.pixelformat = m_params.m_format;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
|
||||
if (xioctl(fd, VIDIOC_S_FMT, &fmt) == -1)
|
||||
{
|
||||
fprintf(stderr, "Cannot set format error %d, %s\n", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (fmt.fmt.pix.pixelformat != m_params.m_format)
|
||||
{
|
||||
printf("Error: format (%d) refused.\n", m_params.m_format);
|
||||
return -1;
|
||||
}
|
||||
if ((fmt.fmt.pix.width != m_params.m_width) || (fmt.fmt.pix.height != m_params.m_height))
|
||||
{
|
||||
printf("Warning: driver is sending image at %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.width);
|
||||
}
|
||||
|
||||
m_format = fmt.fmt.pix.pixelformat;
|
||||
m_bufferSize = fmt.fmt.pix.sizeimage;
|
||||
|
||||
fprintf(stderr, "[%s] bufferSize:%d\n", __FILE__, m_bufferSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// configure capture FPS
|
||||
int V4l2Capture::configureParam(int fd)
|
||||
{
|
||||
struct v4l2_streamparm param;
|
||||
memset(&(param), 0, sizeof(param));
|
||||
param.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
param.parm.capture.timeperframe.numerator = 1;
|
||||
param.parm.capture.timeperframe.denominator = m_params.m_fps;
|
||||
|
||||
if (xioctl(fd, VIDIOC_S_PARM, ¶m) == -1)
|
||||
{
|
||||
fprintf(stderr, "xioctl cannot set param error %d, %s\n", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "fps :%d/%d nbBuffer:%d\n", param.parm.capture.timeperframe.numerator, param.parm.capture.timeperframe.denominator, param.parm.capture.readbuffers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// query current format
|
||||
void V4l2Capture::queryFormat()
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
memset(&fmt,0,sizeof(fmt));
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (0 == ioctl(m_fd,VIDIOC_G_FMT,&fmt)) // don't understand why xioctl give a different result
|
||||
{
|
||||
m_format = fmt.fmt.pix.pixelformat;
|
||||
m_bufferSize = fmt.fmt.pix.sizeimage;
|
||||
}
|
||||
}
|
||||
|
||||
// ioctl encapsulation
|
||||
int V4l2Capture::xioctl(int fd, int request, void *arg)
|
||||
{
|
||||
int ret = -1;
|
||||
errno=0;
|
||||
do
|
||||
{
|
||||
ret = v4l2_ioctl(fd, request, arg);
|
||||
} while ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,192 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2MmapCapture.cpp
|
||||
**
|
||||
** V4L2 source using mmap API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
#include <libv4l2.h>
|
||||
|
||||
// project
|
||||
#include "V4l2MmapCapture.h"
|
||||
|
||||
V4l2MmapCapture* V4l2MmapCapture::createNew(V4L2DeviceParameters params)
|
||||
{
|
||||
V4l2MmapCapture* device = new V4l2MmapCapture(params);
|
||||
if (device && !device->init(V4L2_CAP_STREAMING))
|
||||
{
|
||||
delete device;
|
||||
device=NULL;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
bool V4l2MmapCapture::captureStart()
|
||||
{
|
||||
bool success = true;
|
||||
struct v4l2_requestbuffers req;
|
||||
memset (&req, 0, sizeof(req));
|
||||
req.count = V4L2MMAP_NBBUFFER;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == xioctl(m_fd, VIDIOC_REQBUFS, &req))
|
||||
{
|
||||
if (EINVAL == errno)
|
||||
{
|
||||
fprintf(stderr, "%s does not support memory mapping\n", m_params.m_devName.c_str());
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("VIDIOC_REQBUFS");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s memory mapping nb buffer:%d\n", m_params.m_devName.c_str(), req.count);
|
||||
|
||||
// allocate buffers
|
||||
memset(&m_buffer,0, sizeof(m_buffer));
|
||||
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = n_buffers;
|
||||
|
||||
if (-1 == xioctl(m_fd, VIDIOC_QUERYBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QUERYBUF");
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s memory mapping buffer:%d size:%d\n", m_params.m_devName.c_str(), n_buffers, buf.length);
|
||||
m_buffer[n_buffers].length = buf.length;
|
||||
m_buffer[n_buffers].start = mmap ( NULL /* start anywhere */,
|
||||
buf.length,
|
||||
PROT_READ | PROT_WRITE /* required */,
|
||||
MAP_SHARED /* recommended */,
|
||||
m_fd,
|
||||
buf.m.offset);
|
||||
|
||||
if (MAP_FAILED == m_buffer[n_buffers].start)
|
||||
{
|
||||
perror("mmap");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// queue buffers
|
||||
for (unsigned int i = 0; i < n_buffers; ++i)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = i;
|
||||
|
||||
if (-1 == xioctl(m_fd, VIDIOC_QBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// start stream
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == xioctl(m_fd, VIDIOC_STREAMON, &type))
|
||||
{
|
||||
perror("VIDIOC_STREAMON");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
size_t V4l2MmapCapture::read(char* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t size = 0;
|
||||
if (n_buffers > 0)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == xioctl(m_fd, VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_DQBUF");
|
||||
size = -1;
|
||||
}
|
||||
else if (buf.index < n_buffers)
|
||||
{
|
||||
size = buf.bytesused;
|
||||
if (size > bufferSize)
|
||||
{
|
||||
size = bufferSize;
|
||||
fprintf(stderr, "%s buffer truncated:%d size:%d\n", m_params.m_devName.c_str(), m_buffer[buf.index].length, bufferSize);
|
||||
}
|
||||
memcpy(buffer, m_buffer[buf.index].start, size);
|
||||
|
||||
if (-1 == xioctl(m_fd, VIDIOC_QBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
size = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool V4l2MmapCapture::captureStop()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == xioctl(m_fd, VIDIOC_STREAMOFF, &type))
|
||||
{
|
||||
perror("VIDIOC_STREAMOFF");
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < n_buffers; ++i)
|
||||
{
|
||||
if (-1 == munmap (m_buffer[i].start, m_buffer[i].length))
|
||||
{
|
||||
perror("munmap");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// free buffers
|
||||
struct v4l2_requestbuffers req;
|
||||
memset (&req, 0, sizeof(req));
|
||||
req.count = 0;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
if (-1 == xioctl(m_fd, VIDIOC_REQBUFS, &req))
|
||||
{
|
||||
perror("VIDIOC_REQBUFS");
|
||||
success = false;
|
||||
}
|
||||
|
||||
n_buffers = 0;
|
||||
return success;
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
/* ---------------------------------------------------------------------------
|
||||
** This software is in the public domain, furnished "as is", without technical
|
||||
** support, and with no warranty, express or implied, as to its usefulness for
|
||||
** any purpose.
|
||||
**
|
||||
** V4l2ReadCapture.cpp
|
||||
**
|
||||
** V4L2 source using read API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
#include <libv4l2.h>
|
||||
|
||||
// project
|
||||
#include "V4l2ReadCapture.h"
|
||||
|
||||
// Creator
|
||||
V4l2ReadCapture* V4l2ReadCapture::createNew(V4L2DeviceParameters params)
|
||||
{
|
||||
V4l2ReadCapture* device = new V4l2ReadCapture(params);
|
||||
if (device && !device->init(V4L2_CAP_READWRITE))
|
||||
{
|
||||
delete device;
|
||||
device=NULL;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
size_t V4l2ReadCapture::read(char* buffer, size_t bufferSize)
|
||||
{
|
||||
return v4l2_read(m_fd, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
Subproject commit 3582a9c9da4bd75a8347d4b09defd6babc008f6d
|
Loading…
Reference in New Issue