313 lines
7.1 KiB
C++
313 lines
7.1 KiB
C++
#include "sv4l2device.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <fcntl.h> /* low-level i/o */
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h> // strerrno
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
//#include <stdexcept>
|
|
#include <sys/klog.h>
|
|
#include <linux/videodev2.h>
|
|
|
|
#include <libv4l2.h>
|
|
|
|
#include "mainwindow.h"
|
|
#include "commondata.h"
|
|
|
|
#include <QElapsedTimer>
|
|
|
|
int SV4L2Device::m_nDeviceID = -1;
|
|
|
|
SV4L2Device::SV4L2Device()
|
|
{
|
|
m_nVideoWidth = 3840;
|
|
m_nVideoHeight = 2160;
|
|
|
|
m_nDeviceID = 0;
|
|
}
|
|
|
|
SV4L2Device::~SV4L2Device()
|
|
{
|
|
|
|
}
|
|
|
|
bool SV4L2Device::CheckDevice(QString strDevice)
|
|
{
|
|
bool bCheck = false;
|
|
|
|
return bCheck;
|
|
}
|
|
|
|
int SV4L2Device::xioctl(int fh, unsigned long int request, void *arg)
|
|
{
|
|
int r = 0;
|
|
|
|
int nCount = 0;
|
|
|
|
do {
|
|
r = ioctl(fh, request, arg);
|
|
nCount++;
|
|
} while (-1 == r && EINTR == errno && nCount<50);
|
|
|
|
if(nCount>=50)
|
|
{
|
|
r = -1;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
int SV4L2Device::open_device(QString strDevice)
|
|
{
|
|
//m_nDeviceID = v4l2_open(strDevice.toStdString().c_str(), O_RDWR | O_NONBLOCK, 0);
|
|
|
|
struct stat st;
|
|
int fd = 0;
|
|
|
|
if (-1 == stat(strDevice.toStdString().c_str(), &st)) {
|
|
return -1;
|
|
}
|
|
|
|
if (!S_ISCHR(st.st_mode)) {
|
|
return -2;
|
|
}
|
|
|
|
fd = open(strDevice.toStdString().c_str(), O_RDWR | O_NONBLOCK, 0);
|
|
|
|
if (-1 == fd) {
|
|
return -3;
|
|
}
|
|
|
|
m_nDeviceID = fd;
|
|
|
|
v4l2_format format = {0};
|
|
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
format.fmt.pix.width = m_nVideoWidth;
|
|
format.fmt.pix.height = m_nVideoHeight;
|
|
format.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;//V4L2_PIX_FMT_YUYV //V4L2_PIX_FMT_RGB24
|
|
format.fmt.pix.field = V4L2_FIELD_NONE; //V4L2_FIELD_NONE
|
|
xioctl(m_nDeviceID, VIDIOC_S_FMT, &format);
|
|
|
|
memset(&m_RequestBuffer, 0, sizeof(v4l2_requestbuffers));
|
|
m_RequestBuffer.count = 1;
|
|
m_RequestBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
m_RequestBuffer.memory = V4L2_MEMORY_MMAP;
|
|
//xioctl(m_nDeviceID, VIDIOC_REQBUFS, &m_RequestBuffer);
|
|
ioctl(m_nDeviceID, VIDIOC_REQBUFS, &m_RequestBuffer);
|
|
|
|
///mapping buffers
|
|
unsigned int i;
|
|
m_pBufferLMS = (LMSBBB_buffer*) calloc(m_RequestBuffer.count, sizeof(*m_pBufferLMS));
|
|
for (i = 0; i < m_RequestBuffer.count; i++) {
|
|
clear_memmory(&(m_Buffer));
|
|
|
|
(m_Buffer).type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
(m_Buffer).memory = V4L2_MEMORY_MMAP;
|
|
(m_Buffer).index = i;
|
|
|
|
xioctl(m_nDeviceID, VIDIOC_QUERYBUF, &m_Buffer);
|
|
|
|
m_pBufferLMS[i].length = (m_Buffer).length;
|
|
printf("A buff has a len of: %i\n",m_pBufferLMS[i].length);
|
|
m_pBufferLMS[i].start = v4l2_mmap(NULL, (m_Buffer).length, PROT_READ | PROT_WRITE, MAP_SHARED, m_nDeviceID, (m_Buffer).m.offset);
|
|
|
|
if (MAP_FAILED == m_pBufferLMS[i].start) {
|
|
perror("Can not map the m_pBufferLMS.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < m_RequestBuffer.count; i++) {
|
|
clear_memmory(&(m_Buffer));
|
|
(m_Buffer).type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
(m_Buffer).memory = V4L2_MEMORY_MMAP;
|
|
(m_Buffer).index = i;
|
|
ioctl(m_nDeviceID,VIDIOC_QBUF, &(m_Buffer));
|
|
}
|
|
|
|
|
|
|
|
return m_nDeviceID;
|
|
|
|
/*
|
|
struct stat st;
|
|
int fd = 0;
|
|
|
|
if (-1 == stat(strDevice.c_str(), &st)) {
|
|
return -1;
|
|
}
|
|
|
|
if (!S_ISCHR(st.st_mode)) {
|
|
return -2;
|
|
}
|
|
|
|
fd = open(strDevice.c_str(), O_RDWR | O_NONBLOCK, 0);
|
|
|
|
if (-1 == fd) {
|
|
return -3;
|
|
}
|
|
|
|
return fd;
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
template <typename typeXX>
|
|
void SV4L2Device::clear_memmory(typeXX* x)
|
|
{
|
|
memset(x, 0, sizeof(*x));
|
|
}
|
|
|
|
|
|
void SV4L2Device::StreamOn()
|
|
{
|
|
v4l2_buf_type type;
|
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
ioctl(m_nDeviceID, VIDIOC_STREAMON, &type);
|
|
|
|
|
|
int pic_count=0;
|
|
///CAPTURE
|
|
fd_set fds;
|
|
struct timeval tv;
|
|
int r;
|
|
char out_name[256];
|
|
FILE* fout;
|
|
|
|
|
|
|
|
do
|
|
{
|
|
FD_ZERO(&fds);
|
|
FD_SET(m_nDeviceID, &fds);
|
|
|
|
// Timeout.
|
|
tv.tv_sec = 2;
|
|
tv.tv_usec = 16;
|
|
|
|
r = select(m_nDeviceID + 1, &fds, NULL, NULL, &tv);
|
|
} while ((r == -1 && (errno = EINTR)));
|
|
|
|
if (r == -1) {
|
|
perror("select");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int i=0;
|
|
vector<uint8_t*> listData;
|
|
|
|
for(i=0 ; i<60 ; i++)
|
|
{
|
|
uint8_t* pData = new uint8_t[3840*2160*2];
|
|
memcpy(pData, m_pBufferLMS[(m_Buffer).index].start, (m_Buffer).bytesused);
|
|
listData.push_back(pData);
|
|
}
|
|
|
|
QElapsedTimer timeCheck;
|
|
|
|
QElapsedTimer timeCheckTotal;
|
|
|
|
timeCheck.restart();
|
|
timeCheckTotal.restart();
|
|
|
|
int nReceivedCount = 0;
|
|
int nStoreCount = 0;
|
|
|
|
|
|
for(i=0 ; i<600 ; i++)
|
|
{
|
|
|
|
|
|
|
|
clear_memmory(&(m_Buffer));
|
|
(m_Buffer).type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
(m_Buffer).memory = V4L2_MEMORY_MMAP;
|
|
//(m_Buffer).index = i%10;
|
|
|
|
int nRetry = 0;
|
|
do{
|
|
//xioctl(m_nDeviceID, VIDIOC_DQBUF, &(m_Buffer));
|
|
ioctl(m_nDeviceID, VIDIOC_DQBUF, &(m_Buffer));
|
|
nRetry++;
|
|
}while((m_Buffer).bytesused==0);
|
|
|
|
//qDebug() << nRetry;
|
|
|
|
ioctl(m_nDeviceID,VIDIOC_QBUF, &(m_Buffer));
|
|
|
|
/*
|
|
|
|
printf("Buff index: %i\n",(m_Buffer).index);
|
|
sprintf(out_name, "image%03d_%03d_%x.ppm",pic_count, (m_Buffer).index, m_pBufferLMS[(m_Buffer).index].start);
|
|
fout = fopen(out_name, "w");
|
|
if (!fout) {
|
|
perror("Cannot open image");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(fout, "P6\n%d %d 255\n",m_nVideoWidth, m_nVideoHeight);
|
|
fwrite(m_pBufferLMS[(m_Buffer).index].start, (m_Buffer).bytesused, 1, fout);
|
|
fclose(fout);
|
|
|
|
*/
|
|
|
|
timeCheck.restart();
|
|
uint8_t* pData = listData[i%60];
|
|
memcpy(pData, m_pBufferLMS[(m_Buffer).index].start, (m_Buffer).bytesused);
|
|
usleep(10);
|
|
|
|
int nTime = timeCheck.elapsed();
|
|
qDebug() << nTime;
|
|
|
|
|
|
|
|
pic_count++;
|
|
|
|
}
|
|
|
|
int nTimeTotal = timeCheckTotal.elapsed();
|
|
qDebug() << nTimeTotal;
|
|
|
|
pic_count = 0;
|
|
for(i=0 ; i<listData.size() ; i++)
|
|
{
|
|
uint8_t* pData = listData[i];
|
|
sprintf(out_name, "image%03d.ppm",pic_count);
|
|
fout = fopen(out_name, "w");
|
|
if (!fout) {
|
|
perror("Cannot open image");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(fout, "P6\n%d %d 255\n",m_nVideoWidth, m_nVideoHeight);
|
|
fwrite(pData, 3840*2160*2, 1, fout);
|
|
fclose(fout);
|
|
pic_count++;
|
|
}
|
|
|
|
|
|
clear_memmory(&(m_Buffer));
|
|
(m_Buffer).type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
(m_Buffer).memory = V4L2_MEMORY_MMAP;
|
|
xioctl(m_nDeviceID, VIDIOC_DQBUF, &(m_Buffer));
|
|
printf("Buff index: %i\n",(m_Buffer).index);
|
|
sprintf(out_name, "image%03d.ppm",pic_count);
|
|
fout = fopen(out_name, "w");
|
|
if (!fout) {
|
|
perror("Cannot open image");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(fout, "P6\n%d %d 255\n",m_nVideoWidth, m_nVideoHeight);
|
|
fwrite(m_pBufferLMS[(m_Buffer).index].start, (m_Buffer).bytesused, 1, fout);
|
|
fclose(fout);
|
|
pic_count++;
|
|
|
|
|
|
}
|