SVG5/sv4l2device.cpp
2025-10-12 13:55:56 +09:00

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++;
}