소스 정리
parent
1709e4ad2f
commit
4ef17a44ef
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
src/*.o
|
||||
*.a
|
||||
*.cmake
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
libv4l2cpptest
|
||||
Makefile
|
||||
@ -1,14 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# set project name from current directory
|
||||
get_filename_component(BASENAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||
project(${BASENAME})
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
aux_source_directory(src SRC_FILES)
|
||||
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/inc")
|
||||
|
||||
add_executable (${PROJECT_NAME}test main.cpp)
|
||||
target_link_libraries (${PROJECT_NAME}test ${PROJECT_NAME})
|
||||
@ -1,43 +0,0 @@
|
||||
|
||||
libv4l2cpp
|
||||
====================
|
||||
|
||||
It is a C++ wrapper for V4L2
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
- liblog4cpp5-dev (optional)
|
||||
|
||||
V4L2 Capture
|
||||
-------------
|
||||
- create a V4L2 Capture interface using MMAP interface:
|
||||
|
||||
V4L2DeviceParameters param("/dev/video0", V4L2_PIX_FMT_*, width, height, fps, IOTYPE_MMAP);
|
||||
V4l2Capture* videoCapture = V4l2Capture::create(param);
|
||||
|
||||
- data are available :
|
||||
|
||||
timeval timeout;
|
||||
bool isReadable = videoCapture->isReadable(&timeout);
|
||||
|
||||
- read data :
|
||||
|
||||
size_t nb = videoCapture->read(buffer, bufferSize);
|
||||
|
||||
|
||||
V4L2 Output
|
||||
-------------
|
||||
|
||||
- To create a V4L2 Output interface using MMAP interface:
|
||||
|
||||
V4L2DeviceParameters param("/dev/video0", V4L2_PIX_FMT_*, width, height, fps, IOTYPE_MMAP);
|
||||
V4l2Output* videoOutput = V4l2Output::create(param);
|
||||
|
||||
- data could be written :
|
||||
|
||||
timeval timeout;
|
||||
bool isWritable = videoOutput->isWritable(&timeout);
|
||||
|
||||
- write data :
|
||||
|
||||
size_t nb = videoOutput->write(buffer, bufferSize);
|
||||
@ -1,24 +0,0 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
@ -1,48 +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.
|
||||
**
|
||||
** V4l2Access.h
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "V4l2Device.h"
|
||||
|
||||
class V4l2Access
|
||||
{
|
||||
public:
|
||||
explicit V4l2Access(V4l2Device* device);
|
||||
virtual ~V4l2Access();
|
||||
|
||||
int getFd() { return m_device->getFd(); }
|
||||
unsigned int getBufferSize() { return m_device->getBufferSize(); }
|
||||
unsigned int getFormat() { return m_device->getFormat(); }
|
||||
unsigned int getWidth() { return m_device->getWidth(); }
|
||||
unsigned int getHeight() { return m_device->getHeight(); }
|
||||
|
||||
void queryFormat() { m_device->queryFormat(); }
|
||||
int setFormat(unsigned int format, unsigned int width, unsigned int height) {
|
||||
return m_device->setFormat(format, width, height);
|
||||
}
|
||||
int setFps(int fps) {
|
||||
return m_device->setFps(fps);
|
||||
}
|
||||
|
||||
int isReady() { return m_device->isReady(); }
|
||||
int start() { return m_device->start(); }
|
||||
int stop() { return m_device->stop(); }
|
||||
|
||||
private:
|
||||
V4l2Access(const V4l2Access&);
|
||||
V4l2Access & operator=(const V4l2Access&);
|
||||
|
||||
protected:
|
||||
V4l2Device* m_device;
|
||||
};
|
||||
|
||||
@ -1,33 +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 Capture wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "V4l2Access.h"
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Capture
|
||||
// ---------------------------------
|
||||
class V4l2Capture : public V4l2Access
|
||||
{
|
||||
protected:
|
||||
explicit V4l2Capture(V4l2Device* device);
|
||||
|
||||
public:
|
||||
static V4l2Capture* create(const V4L2DeviceParameters & param);
|
||||
virtual ~V4l2Capture();
|
||||
|
||||
size_t read(char* buffer, size_t bufferSize);
|
||||
bool isReadable(timeval* tv);
|
||||
};
|
||||
|
||||
|
||||
@ -1,124 +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.
|
||||
**
|
||||
** V4l2Device.h
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <linux/videodev2.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef V4L2_PIX_FMT_VP8
|
||||
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0')
|
||||
#endif
|
||||
#ifndef V4L2_PIX_FMT_VP9
|
||||
#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0')
|
||||
#endif
|
||||
#ifndef V4L2_PIX_FMT_HEVC
|
||||
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
|
||||
#endif
|
||||
|
||||
enum V4l2IoType
|
||||
{
|
||||
IOTYPE_READWRITE,
|
||||
IOTYPE_MMAP
|
||||
};
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Device parameters
|
||||
// ---------------------------------
|
||||
struct V4L2DeviceParameters
|
||||
{
|
||||
V4L2DeviceParameters(const char* devname, const std::list<unsigned int> & formatList, unsigned int width, unsigned int height, int fps, V4l2IoType ioType = IOTYPE_MMAP, int openFlags = O_RDWR | O_NONBLOCK) :
|
||||
m_devName(devname), m_formatList(formatList), m_width(width), m_height(height), m_fps(fps), m_iotype(ioType), m_openFlags(openFlags) {}
|
||||
|
||||
V4L2DeviceParameters(const char* devname, unsigned int format, unsigned int width, unsigned int height, int fps, V4l2IoType ioType = IOTYPE_MMAP, int openFlags = O_RDWR | O_NONBLOCK) :
|
||||
m_devName(devname), m_width(width), m_height(height), m_fps(fps), m_iotype(ioType), m_openFlags(openFlags) {
|
||||
if (format) {
|
||||
m_formatList.push_back(format);
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_devName;
|
||||
std::list<unsigned int> m_formatList;
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
int m_fps;
|
||||
V4l2IoType m_iotype;
|
||||
int m_verbose;
|
||||
int m_openFlags;
|
||||
};
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Device
|
||||
// ---------------------------------
|
||||
class V4l2Device
|
||||
{
|
||||
friend class V4l2Capture;
|
||||
friend class V4l2Output;
|
||||
|
||||
protected:
|
||||
void close();
|
||||
|
||||
int initdevice(const char *dev_name, unsigned int mandatoryCapabilities);
|
||||
int checkCapabilities(int fd, unsigned int mandatoryCapabilities);
|
||||
int configureFormat(int fd);
|
||||
int configureFormat(int fd, unsigned int format, unsigned int width, unsigned int height);
|
||||
int configureParam(int fd, int fps);
|
||||
|
||||
virtual bool init(unsigned int mandatoryCapabilities);
|
||||
virtual size_t writeInternal(char*, size_t) { return -1; }
|
||||
virtual bool startPartialWrite() { return false; }
|
||||
virtual size_t writePartialInternal(char*, size_t) { return -1; }
|
||||
virtual bool endPartialWrite() { return false; }
|
||||
virtual size_t readInternal(char*, size_t) { return -1; }
|
||||
|
||||
public:
|
||||
V4l2Device(const V4L2DeviceParameters& params, v4l2_buf_type deviceType);
|
||||
virtual ~V4l2Device();
|
||||
|
||||
virtual bool isReady() { return (m_fd != -1); }
|
||||
virtual bool start() { return true; }
|
||||
virtual bool stop() { return true; }
|
||||
|
||||
unsigned int getBufferSize() { return m_bufferSize; }
|
||||
unsigned int getFormat() { return m_format; }
|
||||
unsigned int getWidth() { return m_width; }
|
||||
unsigned int getHeight() { return m_height; }
|
||||
int getFd() { return m_fd; }
|
||||
void queryFormat();
|
||||
|
||||
int setFormat(unsigned int format, unsigned int width, unsigned int height) {
|
||||
return this->configureFormat(m_fd, format, width, height);
|
||||
}
|
||||
int setFps(int fps) {
|
||||
return this->configureParam(m_fd, fps);
|
||||
}
|
||||
|
||||
static std::string fourcc(unsigned int format);
|
||||
static unsigned int fourcc(const char* format);
|
||||
|
||||
protected:
|
||||
V4L2DeviceParameters m_params;
|
||||
int m_fd;
|
||||
v4l2_buf_type m_deviceType;
|
||||
|
||||
unsigned int m_bufferSize;
|
||||
unsigned int m_format;
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
|
||||
struct v4l2_buffer m_partialWriteBuf;
|
||||
bool m_partialWriteInProgress;
|
||||
};
|
||||
|
||||
|
||||
@ -1,48 +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.
|
||||
**
|
||||
** V4l2MmapDevice.h
|
||||
**
|
||||
** V4L2 source using mmap API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "V4l2Device.h"
|
||||
|
||||
#define V4L2MMAP_NBBUFFER 10
|
||||
|
||||
class V4l2MmapDevice : public V4l2Device
|
||||
{
|
||||
protected:
|
||||
size_t writeInternal(char* buffer, size_t bufferSize);
|
||||
bool startPartialWrite();
|
||||
size_t writePartialInternal(char*, size_t);
|
||||
bool endPartialWrite();
|
||||
size_t readInternal(char* buffer, size_t bufferSize);
|
||||
|
||||
public:
|
||||
V4l2MmapDevice(const V4L2DeviceParameters & params, v4l2_buf_type deviceType);
|
||||
virtual ~V4l2MmapDevice();
|
||||
|
||||
virtual bool init(unsigned int mandatoryCapabilities);
|
||||
virtual bool isReady() { return ((m_fd != -1)&& (n_buffers != 0)); }
|
||||
virtual bool start();
|
||||
virtual bool stop();
|
||||
|
||||
protected:
|
||||
unsigned int n_buffers;
|
||||
|
||||
struct buffer
|
||||
{
|
||||
void * start;
|
||||
size_t length;
|
||||
};
|
||||
buffer m_buffer[V4L2MMAP_NBBUFFER];
|
||||
};
|
||||
|
||||
|
||||
@ -1,35 +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.
|
||||
**
|
||||
** V4l2Output.h
|
||||
**
|
||||
** V4L2 Output wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "V4l2Access.h"
|
||||
|
||||
// ---------------------------------
|
||||
// V4L2 Output
|
||||
// ---------------------------------
|
||||
class V4l2Output : public V4l2Access
|
||||
{
|
||||
protected:
|
||||
explicit V4l2Output(V4l2Device* device);
|
||||
|
||||
public:
|
||||
static V4l2Output* create(const V4L2DeviceParameters & param);
|
||||
virtual ~V4l2Output();
|
||||
|
||||
size_t write(char* buffer, size_t bufferSize);
|
||||
bool isWritable(timeval* tv);
|
||||
bool startPartialWrite();
|
||||
size_t writePartial(char* buffer, size_t bufferSize);
|
||||
bool endPartialWrite();
|
||||
};
|
||||
|
||||
@ -1,29 +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.
|
||||
**
|
||||
** V4l2ReadWriteDevice.h
|
||||
**
|
||||
** V4L2 source using read/write API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "V4l2Device.h"
|
||||
|
||||
|
||||
class V4l2ReadWriteDevice : public V4l2Device
|
||||
{
|
||||
protected:
|
||||
virtual size_t writeInternal(char* buffer, size_t bufferSize);
|
||||
virtual size_t readInternal(char* buffer, size_t bufferSize);
|
||||
|
||||
public:
|
||||
V4l2ReadWriteDevice(const V4L2DeviceParameters& params, v4l2_buf_type deviceType);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,112 +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.
|
||||
**
|
||||
** logger.h
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
#ifdef HAVE_LOG4CPP
|
||||
#include "log4cpp/Category.hh"
|
||||
#include "log4cpp/FileAppender.hh"
|
||||
#include "log4cpp/PatternLayout.hh"
|
||||
|
||||
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << __FILENAME__ << ":" << __LINE__ << "\n\t"
|
||||
|
||||
|
||||
inline int getLogLevel() {
|
||||
log4cpp::Category &log = log4cpp::Category::getRoot();
|
||||
return log.getPriority();
|
||||
}
|
||||
|
||||
inline void setLogLevel(int verbose) {
|
||||
log4cpp::Category &log = log4cpp::Category::getRoot();
|
||||
switch (verbose)
|
||||
{
|
||||
case 2: log.setPriority(log4cpp::Priority::DEBUG); break;
|
||||
case 1: log.setPriority(log4cpp::Priority::INFO); break;
|
||||
default: log.setPriority(log4cpp::Priority::NOTICE); break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void initLogger(int verbose)
|
||||
{
|
||||
// initialize log4cpp
|
||||
log4cpp::Category &log = log4cpp::Category::getRoot();
|
||||
log4cpp::Appender *app = new log4cpp::FileAppender("root", fileno(stdout));
|
||||
if (app)
|
||||
{
|
||||
log4cpp::PatternLayout *plt = new log4cpp::PatternLayout();
|
||||
if (plt)
|
||||
{
|
||||
plt->setConversionPattern("%d [%-6p] - %m%n");
|
||||
app->setLayout(plt);
|
||||
}
|
||||
log.addAppender(app);
|
||||
}
|
||||
|
||||
setLogLevel(verbose);
|
||||
|
||||
LOG(INFO) << "level:" << log4cpp::Priority::getPriorityName(log.getPriority());
|
||||
}
|
||||
#else
|
||||
|
||||
typedef enum {EMERG = 0,
|
||||
FATAL = 0,
|
||||
ALERT = 100,
|
||||
CRIT = 200,
|
||||
ERROR = 300,
|
||||
WARN = 400,
|
||||
NOTICE = 500,
|
||||
INFO = 600,
|
||||
DEBUG = 700,
|
||||
NOTSET = 800
|
||||
} PriorityLevel;
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
extern int LogLevel;
|
||||
inline std::string getLevel(const char* level) {
|
||||
std::stringstream ss;
|
||||
ss << "[" << level << "]";
|
||||
return ss.str();
|
||||
}
|
||||
inline std::string getFilename(const char* filename, int line) {
|
||||
std::stringstream ss;
|
||||
ss << "(" << filename << ":" << line << ")";
|
||||
return ss.str();
|
||||
}
|
||||
#define LOG(__level) if (__level<=LogLevel) std::cout << "\n" << std::setw(8) << std::left << getLevel(#__level) << " " << std::setw(30) << std::left << getFilename(__FILENAME__, __LINE__) << "\t"
|
||||
|
||||
|
||||
inline int getLogLevel() {
|
||||
return LogLevel;
|
||||
}
|
||||
|
||||
inline void setLogLevel(int verbose) {
|
||||
switch (verbose)
|
||||
{
|
||||
case 2: LogLevel=DEBUG; break;
|
||||
case 1: LogLevel=INFO; break;
|
||||
default: LogLevel=NOTICE; break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void initLogger(int verbose)
|
||||
{
|
||||
setLogLevel(verbose);
|
||||
std::cout << "log level:" << LogLevel << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,130 +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.
|
||||
**
|
||||
** main.cpp
|
||||
**
|
||||
** test V4L2 capture device
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include "V4l2Capture.h"
|
||||
|
||||
int stop=0;
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
** SIGINT handler
|
||||
** -------------------------------------------------------------------------*/
|
||||
void sighandler(int)
|
||||
{
|
||||
printf("SIGINT\n");
|
||||
stop =1;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
** main
|
||||
** -------------------------------------------------------------------------*/
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int verbose = 0;
|
||||
const char *in_devname = "/dev/video0";
|
||||
V4l2IoType ioTypeIn = IOTYPE_MMAP;
|
||||
int format = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int fps = 0;
|
||||
int framecount = 0;
|
||||
int c = 0;
|
||||
while ((c = getopt (argc, argv, "x:hv:" "G:f:r")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'v': verbose = 1; if (optarg && *optarg=='v') verbose++; break;
|
||||
case 'r': ioTypeIn = IOTYPE_READWRITE ; break;
|
||||
case 'G': sscanf(optarg,"%dx%dx%d", &width, &height, &fps) ; break;
|
||||
case 'f': format = V4l2Device::fourcc(optarg) ; break;
|
||||
case 'x': sscanf(optarg,"%d", &framecount) ; break;
|
||||
case 'h':
|
||||
{
|
||||
std::cout << argv[0] << " [-v[v]] [-G <width>x<height>x<fps>] [-f format] [device] [-r]" << std::endl;
|
||||
std::cout << "\t -G <width>x<height>x<fps> : set capture resolution" << std::endl;
|
||||
std::cout << "\t -v : verbose " << std::endl;
|
||||
std::cout << "\t -vv : very verbose " << std::endl;
|
||||
std::cout << "\t -r : V4L2 capture using read interface (default use memory mapped buffers)" << std::endl;
|
||||
std::cout << "\t -x <count> : read <count> frames and save them in current dir." << std::endl;
|
||||
std::cout << "\t device : V4L2 capture device (default "<< in_devname << ")" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (optind<argc)
|
||||
{
|
||||
in_devname = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
|
||||
// initialize log4cpp
|
||||
initLogger(verbose);
|
||||
|
||||
// init V4L2 capture interface
|
||||
V4L2DeviceParameters param(in_devname, format, width, height, fps, ioTypeIn);
|
||||
V4l2Capture* videoCapture = V4l2Capture::create(param);
|
||||
|
||||
if (videoCapture == NULL)
|
||||
{
|
||||
LOG(WARN) << "Cannot reading from V4L2 capture interface for device:" << in_devname;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeval tv;
|
||||
|
||||
LOG(NOTICE) << "Start reading from " << in_devname;
|
||||
signal(SIGINT,sighandler);
|
||||
while (!stop)
|
||||
{
|
||||
tv.tv_sec=1;
|
||||
tv.tv_usec=0;
|
||||
int ret = videoCapture->isReadable(&tv);
|
||||
if (ret == 1)
|
||||
{
|
||||
char buffer[videoCapture->getBufferSize()];
|
||||
int rsize = videoCapture->read(buffer, sizeof(buffer));
|
||||
if (rsize == -1)
|
||||
{
|
||||
LOG(NOTICE) << "stop " << strerror(errno);
|
||||
stop=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(NOTICE) << "size:" << rsize;
|
||||
static int stop_count = 0;
|
||||
if(framecount and stop_count < framecount){
|
||||
std::string filename = "Frame" + std::to_string(stop_count) + '.' + V4l2Device::fourcc(videoCapture->getFormat());
|
||||
stop_count++;
|
||||
FILE *fp = fopen(filename.c_str(), "wb");
|
||||
fwrite(buffer, 1, rsize, fp);
|
||||
fclose(fp);
|
||||
LOG(NOTICE) << "saved:\t" << filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ret == -1)
|
||||
{
|
||||
LOG(NOTICE) << "stop " << strerror(errno);
|
||||
stop=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete videoCapture;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,20 +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.
|
||||
**
|
||||
** V4l2Access.cpp
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include "V4l2Access.h"
|
||||
|
||||
V4l2Access::V4l2Access(V4l2Device* device) : m_device(device) {
|
||||
}
|
||||
|
||||
V4l2Access::~V4l2Access() {
|
||||
delete m_device;
|
||||
}
|
||||
|
||||
@ -1,90 +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
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
// project
|
||||
#include "logger.h"
|
||||
#include "V4l2Capture.h"
|
||||
#include "V4l2MmapDevice.h"
|
||||
#include "V4l2ReadWriteDevice.h"
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
// create video capture interface
|
||||
// -----------------------------------------
|
||||
V4l2Capture* V4l2Capture::create(const V4L2DeviceParameters & param)
|
||||
{
|
||||
V4l2Capture* videoCapture = NULL;
|
||||
V4l2Device* videoDevice = NULL;
|
||||
int caps = V4L2_CAP_VIDEO_CAPTURE;
|
||||
switch (param.m_iotype)
|
||||
{
|
||||
case IOTYPE_MMAP:
|
||||
videoDevice = new V4l2MmapDevice(param, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
caps |= V4L2_CAP_STREAMING;
|
||||
break;
|
||||
case IOTYPE_READWRITE:
|
||||
videoDevice = new V4l2ReadWriteDevice(param, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
caps |= V4L2_CAP_READWRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (videoDevice && !videoDevice->init(caps))
|
||||
{
|
||||
delete videoDevice;
|
||||
videoDevice=NULL;
|
||||
}
|
||||
|
||||
if (videoDevice)
|
||||
{
|
||||
videoCapture = new V4l2Capture(videoDevice);
|
||||
}
|
||||
return videoCapture;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// constructor
|
||||
// -----------------------------------------
|
||||
V4l2Capture::V4l2Capture(V4l2Device* device) : V4l2Access(device)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// destructor
|
||||
// -----------------------------------------
|
||||
V4l2Capture::~V4l2Capture()
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// check readability
|
||||
// -----------------------------------------
|
||||
bool V4l2Capture::isReadable(timeval* tv)
|
||||
{
|
||||
int fd = m_device->getFd();
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
return (select(fd+1, &fdset, NULL, NULL, tv) == 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// read from V4l2Device
|
||||
// -----------------------------------------
|
||||
size_t V4l2Capture::read(char* buffer, size_t bufferSize)
|
||||
{
|
||||
return m_device->readInternal(buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
@ -1,253 +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.
|
||||
**
|
||||
** V4l2Device.cpp
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include "V4l2Device.h"
|
||||
|
||||
std::string V4l2Device::fourcc(unsigned int format) {
|
||||
char formatArray[] = { (char)(format&0xff), (char)((format>>8)&0xff), (char)((format>>16)&0xff), (char)((format>>24)&0xff), 0 };
|
||||
return std::string(formatArray, strlen(formatArray));
|
||||
}
|
||||
|
||||
unsigned int V4l2Device::fourcc(const char* format) {
|
||||
char fourcc[4];
|
||||
memset(&fourcc, 0, sizeof(fourcc));
|
||||
if (format != NULL)
|
||||
{
|
||||
strncpy(fourcc, format, 4);
|
||||
}
|
||||
return v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// V4L2Device
|
||||
// -----------------------------------------
|
||||
V4l2Device::V4l2Device(const V4L2DeviceParameters& params, v4l2_buf_type deviceType) : m_params(params), m_fd(-1), m_deviceType(deviceType), m_bufferSize(0), m_format(0)
|
||||
{
|
||||
}
|
||||
|
||||
V4l2Device::~V4l2Device()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
|
||||
void V4l2Device::close()
|
||||
{
|
||||
if (m_fd != -1)
|
||||
::close(m_fd);
|
||||
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
// query current format
|
||||
void V4l2Device::queryFormat()
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
memset(&fmt,0,sizeof(fmt));
|
||||
fmt.type = m_deviceType;
|
||||
if (0 == ioctl(m_fd,VIDIOC_G_FMT,&fmt))
|
||||
{
|
||||
m_format = fmt.fmt.pix.pixelformat;
|
||||
m_width = fmt.fmt.pix.width;
|
||||
m_height = fmt.fmt.pix.height;
|
||||
m_bufferSize = fmt.fmt.pix.sizeimage;
|
||||
|
||||
LOG(DEBUG) << m_params.m_devName << ":" << fourcc(m_format) << " size:" << m_width << "x" << m_height << " bufferSize:" << m_bufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
// intialize the V4L2 connection
|
||||
bool V4l2Device::init(unsigned int mandatoryCapabilities)
|
||||
{
|
||||
struct stat sb;
|
||||
if ( (stat(m_params.m_devName.c_str(), &sb)==0) && ((sb.st_mode & S_IFMT) == S_IFCHR) )
|
||||
{
|
||||
if (initdevice(m_params.m_devName.c_str(), mandatoryCapabilities) == -1)
|
||||
{
|
||||
LOG(ERROR) << "Cannot init device:" << m_params.m_devName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// open a normal file
|
||||
m_fd = open(m_params.m_devName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
|
||||
}
|
||||
return (m_fd!=-1);
|
||||
}
|
||||
|
||||
// intialize the V4L2 device
|
||||
int V4l2Device::initdevice(const char *dev_name, unsigned int mandatoryCapabilities)
|
||||
{
|
||||
m_fd = open(dev_name, m_params.m_openFlags);
|
||||
if (m_fd < 0)
|
||||
{
|
||||
LOG(ERROR) << "Cannot open device:" << m_params.m_devName << " " << strerror(errno);
|
||||
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, m_params.m_fps) !=0)
|
||||
{
|
||||
this->close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
// check needed V4L2 capabilities
|
||||
int V4l2Device::checkCapabilities(int fd, unsigned int mandatoryCapabilities)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
memset(&(cap), 0, sizeof(cap));
|
||||
if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap))
|
||||
{
|
||||
LOG(ERROR) << "Cannot get capabilities for device:" << m_params.m_devName << " " << strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
LOG(INFO) << "driver:" << cap.driver << " capabilities:" << std::hex << cap.capabilities << " mandatory:" << mandatoryCapabilities << std::dec;
|
||||
|
||||
if ((cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) LOG(DEBUG) << m_params.m_devName << " support output";
|
||||
if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) LOG(DEBUG) << m_params.m_devName << " support capture";
|
||||
|
||||
if ((cap.capabilities & V4L2_CAP_READWRITE)) LOG(DEBUG) << m_params.m_devName << " support read/write";
|
||||
if ((cap.capabilities & V4L2_CAP_STREAMING)) LOG(DEBUG) << m_params.m_devName << " support streaming";
|
||||
|
||||
if ((cap.capabilities & V4L2_CAP_TIMEPERFRAME)) LOG(DEBUG) << m_params.m_devName << " support timeperframe";
|
||||
|
||||
if ( (cap.capabilities & mandatoryCapabilities) != mandatoryCapabilities )
|
||||
{
|
||||
LOG(ERROR) << "Mandatory capability not available for device:" << m_params.m_devName;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// configure capture format
|
||||
int V4l2Device::configureFormat(int fd)
|
||||
{
|
||||
// get current configuration
|
||||
this->queryFormat();
|
||||
|
||||
unsigned int width = m_width;
|
||||
unsigned int height = m_height;
|
||||
if (m_params.m_width != 0) {
|
||||
width= m_params.m_width;
|
||||
}
|
||||
if (m_params.m_height != 0) {
|
||||
height= m_params.m_height;
|
||||
}
|
||||
if ( (m_params.m_formatList.size()==0) && (m_format != 0) ) {
|
||||
m_params.m_formatList.push_back(m_format);
|
||||
}
|
||||
|
||||
// try to set format, widht, height
|
||||
std::list<unsigned int>::iterator it;
|
||||
for (it = m_params.m_formatList.begin(); it != m_params.m_formatList.end(); ++it) {
|
||||
unsigned int format = *it;
|
||||
if (this->configureFormat(fd, format, width, height)==0) {
|
||||
// format has been set
|
||||
// get the format again because calling SET-FMT return a bad buffersize using v4l2loopback
|
||||
this->queryFormat();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// configure capture format
|
||||
int V4l2Device::configureFormat(int fd, unsigned int format, unsigned int width, unsigned int height)
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
memset(&(fmt), 0, sizeof(fmt));
|
||||
fmt.type = m_deviceType;
|
||||
if (ioctl(m_fd,VIDIOC_G_FMT,&fmt) == -1)
|
||||
{
|
||||
LOG(ERROR) << m_params.m_devName << ": Cannot get format " << strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
if (width != 0) {
|
||||
fmt.fmt.pix.width = width;
|
||||
}
|
||||
if (height != 0) {
|
||||
fmt.fmt.pix.height = height;
|
||||
}
|
||||
if (format != 0) {
|
||||
fmt.fmt.pix.pixelformat = format;
|
||||
}
|
||||
|
||||
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)
|
||||
{
|
||||
LOG(ERROR) << m_params.m_devName << ": Cannot set format:" << fourcc(format) << " " << strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
if (fmt.fmt.pix.pixelformat != format)
|
||||
{
|
||||
LOG(ERROR) << m_params.m_devName << ": Cannot set pixelformat to:" << fourcc(format) << " format is:" << fourcc(fmt.fmt.pix.pixelformat);
|
||||
return -1;
|
||||
}
|
||||
if ((fmt.fmt.pix.width != width) || (fmt.fmt.pix.height != height))
|
||||
{
|
||||
LOG(WARN) << m_params.m_devName << ": Cannot set size to:" << width << "x" << height << " size is:" << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height;
|
||||
}
|
||||
|
||||
m_format = fmt.fmt.pix.pixelformat;
|
||||
m_width = fmt.fmt.pix.width;
|
||||
m_height = fmt.fmt.pix.height;
|
||||
m_bufferSize = fmt.fmt.pix.sizeimage;
|
||||
|
||||
LOG(INFO) << m_params.m_devName << ":" << fourcc(m_format) << " size:" << m_width << "x" << m_height << " bufferSize:" << m_bufferSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// configure capture FPS
|
||||
int V4l2Device::configureParam(int fd, int fps)
|
||||
{
|
||||
if (fps!=0)
|
||||
{
|
||||
struct v4l2_streamparm param;
|
||||
memset(&(param), 0, sizeof(param));
|
||||
param.type = m_deviceType;
|
||||
param.parm.capture.timeperframe.numerator = 1;
|
||||
param.parm.capture.timeperframe.denominator = fps;
|
||||
|
||||
if (ioctl(fd, VIDIOC_S_PARM, ¶m) == -1)
|
||||
{
|
||||
LOG(WARN) << "Cannot set param for device:" << m_params.m_devName << " " << strerror(errno);
|
||||
}
|
||||
|
||||
LOG(INFO) << "fps:" << param.parm.capture.timeperframe.numerator << "/" << param.parm.capture.timeperframe.denominator;
|
||||
LOG(INFO) << "nbBuffer:" << param.parm.capture.readbuffers;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,311 +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.
|
||||
**
|
||||
** V4l2MmapDevice.cpp
|
||||
**
|
||||
** V4L2 source using mmap API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
// project
|
||||
#include "logger.h"
|
||||
#include "V4l2MmapDevice.h"
|
||||
|
||||
V4l2MmapDevice::V4l2MmapDevice(const V4L2DeviceParameters & params, v4l2_buf_type deviceType) : V4l2Device(params, deviceType), n_buffers(0)
|
||||
{
|
||||
memset(&m_buffer, 0, sizeof(m_buffer));
|
||||
}
|
||||
|
||||
bool V4l2MmapDevice::init(unsigned int mandatoryCapabilities)
|
||||
{
|
||||
bool ret = V4l2Device::init(mandatoryCapabilities);
|
||||
if (ret)
|
||||
{
|
||||
ret = this->start();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
V4l2MmapDevice::~V4l2MmapDevice()
|
||||
{
|
||||
this->stop();
|
||||
}
|
||||
|
||||
|
||||
bool V4l2MmapDevice::start()
|
||||
{
|
||||
LOG(INFO) << "Device " << m_params.m_devName;
|
||||
|
||||
bool success = true;
|
||||
struct v4l2_requestbuffers req;
|
||||
memset (&req, 0, sizeof(req));
|
||||
req.count = V4L2MMAP_NBBUFFER;
|
||||
req.type = m_deviceType;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_REQBUFS, &req))
|
||||
{
|
||||
if (EINVAL == errno)
|
||||
{
|
||||
LOG(ERROR) << "Device " << m_params.m_devName << " does not support memory mapping";
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("VIDIOC_REQBUFS");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "Device " << m_params.m_devName << " nb buffer:" << 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 = m_deviceType;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = n_buffers;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_QUERYBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QUERYBUF");
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "Device " << m_params.m_devName << " buffer idx:" << n_buffers << " size:" << buf.length << " offset:" << buf.m.offset;
|
||||
m_buffer[n_buffers].length = buf.length;
|
||||
if (!m_buffer[n_buffers].length) {
|
||||
m_buffer[n_buffers].length = buf.bytesused;
|
||||
}
|
||||
m_buffer[n_buffers].start = mmap ( NULL /* start anywhere */,
|
||||
m_buffer[n_buffers].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 = m_deviceType;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = i;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// start stream
|
||||
int type = m_deviceType;
|
||||
if (-1 == ioctl(m_fd, VIDIOC_STREAMON, &type))
|
||||
{
|
||||
perror("VIDIOC_STREAMON");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool V4l2MmapDevice::stop()
|
||||
{
|
||||
LOG(INFO) << "Device " << m_params.m_devName;
|
||||
|
||||
bool success = true;
|
||||
|
||||
int type = m_deviceType;
|
||||
if (-1 == ioctl(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 = m_deviceType;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
if (-1 == ioctl(m_fd, VIDIOC_REQBUFS, &req))
|
||||
{
|
||||
perror("VIDIOC_REQBUFS");
|
||||
success = false;
|
||||
}
|
||||
|
||||
n_buffers = 0;
|
||||
return success;
|
||||
}
|
||||
|
||||
size_t V4l2MmapDevice::readInternal(char* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t size = 0;
|
||||
if (n_buffers > 0)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
buf.type = m_deviceType;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
if (errno == EAGAIN) {
|
||||
size = 0;
|
||||
} else {
|
||||
perror("VIDIOC_DQBUF");
|
||||
size = -1;
|
||||
}
|
||||
}
|
||||
else if (buf.index < n_buffers)
|
||||
{
|
||||
size = buf.bytesused;
|
||||
if (size > bufferSize)
|
||||
{
|
||||
size = bufferSize;
|
||||
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << bufferSize << " needed:" << buf.bytesused;
|
||||
}
|
||||
memcpy(buffer, m_buffer[buf.index].start, size);
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
size = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t V4l2MmapDevice::writeInternal(char* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t size = 0;
|
||||
if (n_buffers > 0)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
buf.type = m_deviceType;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_DQBUF");
|
||||
size = -1;
|
||||
}
|
||||
else if (buf.index < n_buffers)
|
||||
{
|
||||
size = bufferSize;
|
||||
if (size > buf.length)
|
||||
{
|
||||
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << buf.length << " needed:" << size;
|
||||
size = buf.length;
|
||||
}
|
||||
memcpy(m_buffer[buf.index].start, buffer, size);
|
||||
buf.bytesused = size;
|
||||
|
||||
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &buf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
size = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool V4l2MmapDevice::startPartialWrite()
|
||||
{
|
||||
if (n_buffers <= 0)
|
||||
return false;
|
||||
if (m_partialWriteInProgress)
|
||||
return false;
|
||||
memset(&m_partialWriteBuf, 0, sizeof(m_partialWriteBuf));
|
||||
m_partialWriteBuf.type = m_deviceType;
|
||||
m_partialWriteBuf.memory = V4L2_MEMORY_MMAP;
|
||||
if (-1 == ioctl(m_fd, VIDIOC_DQBUF, &m_partialWriteBuf))
|
||||
{
|
||||
perror("VIDIOC_DQBUF");
|
||||
return false;
|
||||
}
|
||||
m_partialWriteBuf.bytesused = 0;
|
||||
m_partialWriteInProgress = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t V4l2MmapDevice::writePartialInternal(char* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t new_size = 0;
|
||||
size_t size = 0;
|
||||
if ((n_buffers > 0) && m_partialWriteInProgress)
|
||||
{
|
||||
if (m_partialWriteBuf.index < n_buffers)
|
||||
{
|
||||
new_size = m_partialWriteBuf.bytesused + bufferSize;
|
||||
if (new_size > m_partialWriteBuf.length)
|
||||
{
|
||||
LOG(WARN) << "Device " << m_params.m_devName << " buffer truncated available:" << m_partialWriteBuf.length << " needed:" << new_size;
|
||||
new_size = m_partialWriteBuf.length;
|
||||
}
|
||||
size = new_size - m_partialWriteBuf.bytesused;
|
||||
memcpy(&((char *)m_buffer[m_partialWriteBuf.index].start)[m_partialWriteBuf.bytesused], buffer, size);
|
||||
|
||||
m_partialWriteBuf.bytesused += size;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool V4l2MmapDevice::endPartialWrite()
|
||||
{
|
||||
if (!m_partialWriteInProgress)
|
||||
return false;
|
||||
if (n_buffers <= 0)
|
||||
{
|
||||
m_partialWriteInProgress = false; // abort partial write
|
||||
return true;
|
||||
}
|
||||
if (-1 == ioctl(m_fd, VIDIOC_QBUF, &m_partialWriteBuf))
|
||||
{
|
||||
perror("VIDIOC_QBUF");
|
||||
m_partialWriteInProgress = false; // abort partial write
|
||||
return true;
|
||||
}
|
||||
m_partialWriteInProgress = false;
|
||||
return true;
|
||||
}
|
||||
@ -1,106 +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.
|
||||
**
|
||||
** V4l2Output.cpp
|
||||
**
|
||||
** V4L2 wrapper
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// libv4l2
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
// project
|
||||
#include "logger.h"
|
||||
|
||||
#include "V4l2Output.h"
|
||||
#include "V4l2MmapDevice.h"
|
||||
#include "V4l2ReadWriteDevice.h"
|
||||
|
||||
// -----------------------------------------
|
||||
// create video output interface
|
||||
// -----------------------------------------
|
||||
V4l2Output* V4l2Output::create(const V4L2DeviceParameters & param)
|
||||
{
|
||||
V4l2Output* videoOutput = NULL;
|
||||
V4l2Device* videoDevice = NULL;
|
||||
int caps = V4L2_CAP_VIDEO_OUTPUT;
|
||||
switch (param.m_iotype)
|
||||
{
|
||||
case IOTYPE_MMAP:
|
||||
videoDevice = new V4l2MmapDevice(param, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||
caps |= V4L2_CAP_STREAMING;
|
||||
break;
|
||||
case IOTYPE_READWRITE:
|
||||
videoDevice = new V4l2ReadWriteDevice(param, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||
caps |= V4L2_CAP_READWRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (videoDevice && !videoDevice->init(caps))
|
||||
{
|
||||
delete videoDevice;
|
||||
videoDevice=NULL;
|
||||
}
|
||||
|
||||
if (videoDevice)
|
||||
{
|
||||
videoOutput = new V4l2Output(videoDevice);
|
||||
}
|
||||
return videoOutput;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// constructor
|
||||
// -----------------------------------------
|
||||
V4l2Output::V4l2Output(V4l2Device* device) : V4l2Access(device)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// destructor
|
||||
// -----------------------------------------
|
||||
V4l2Output::~V4l2Output()
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// check writability
|
||||
// -----------------------------------------
|
||||
bool V4l2Output::isWritable(timeval* tv)
|
||||
{
|
||||
int fd = m_device->getFd();
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
return (select(fd+1, NULL, &fdset, NULL, tv) == 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// write to V4l2Device
|
||||
// -----------------------------------------
|
||||
size_t V4l2Output::write(char* buffer, size_t bufferSize)
|
||||
{
|
||||
return m_device->writeInternal(buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
bool V4l2Output::startPartialWrite()
|
||||
{
|
||||
return m_device->startPartialWrite();
|
||||
}
|
||||
|
||||
size_t V4l2Output::writePartial(char* buffer, size_t bufferSize)
|
||||
{
|
||||
return m_device->writePartialInternal(buffer, bufferSize);
|
||||
}
|
||||
|
||||
bool V4l2Output::endPartialWrite()
|
||||
{
|
||||
return m_device->endPartialWrite();
|
||||
}
|
||||
|
||||
@ -1,29 +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.
|
||||
**
|
||||
** V4l2ReadWriteDevice.cpp
|
||||
**
|
||||
** V4L2 source using read/write API
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "V4l2ReadWriteDevice.h"
|
||||
|
||||
V4l2ReadWriteDevice::V4l2ReadWriteDevice(const V4L2DeviceParameters& params, v4l2_buf_type deviceType) : V4l2Device(params, deviceType) {
|
||||
}
|
||||
|
||||
|
||||
size_t V4l2ReadWriteDevice::writeInternal(char* buffer, size_t bufferSize) {
|
||||
return ::write(m_fd, buffer, bufferSize);
|
||||
}
|
||||
|
||||
size_t V4l2ReadWriteDevice::readInternal(char* buffer, size_t bufferSize) {
|
||||
return ::read(m_fd, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,14 +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.
|
||||
**
|
||||
** logger.cpp
|
||||
**
|
||||
** -------------------------------------------------------------------------*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#ifndef HAVE_LOG4CPP
|
||||
int LogLevel=NOTICE;
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue