|
|
|
|
@ -1,22 +1,42 @@
|
|
|
|
|
|
|
|
|
|
#define _LARGEFILE64_SOURCE 1
|
|
|
|
|
#define _FILE_OFFSET_BITS 64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "miniwebcam.h"
|
|
|
|
|
#include "video.h"
|
|
|
|
|
#include "convert.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
#ifdef BUILD_WINDOWS
|
|
|
|
|
#include <winsock2.h>
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
|
#else
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VideoDevice::VideoDevice() {
|
|
|
|
|
debug ("");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VideoDevice::~VideoDevice() {
|
|
|
|
|
|
|
|
|
|
debug ("");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************************************/
|
|
|
|
|
|
|
|
|
|
VideoDevice_V4L2::VideoDevice_V4L2() {
|
|
|
|
|
debug ("");
|
|
|
|
|
conf_height = 0;
|
|
|
|
|
conf_width = 0;
|
|
|
|
|
conf_videodev = "";
|
|
|
|
|
@ -27,6 +47,7 @@ VideoDevice_V4L2::VideoDevice_V4L2() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VideoDevice_V4L2::~VideoDevice_V4L2() {
|
|
|
|
|
debug ("");
|
|
|
|
|
if (fd != 0) Stop();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -301,7 +322,7 @@ int VideoDevice_V4L2::UnInit() {
|
|
|
|
|
int VideoDevice_V4L2::Start() {
|
|
|
|
|
enum v4l2_buf_type type;
|
|
|
|
|
|
|
|
|
|
debug ("");
|
|
|
|
|
debug ("V4L2");
|
|
|
|
|
|
|
|
|
|
if (Open() == 0) {
|
|
|
|
|
debug ("VideoDevice_V4L2::Start Open Device Failed.");
|
|
|
|
|
@ -515,3 +536,323 @@ void VideoDevice_V4L2::PrintFmt(struct v4l2_format *f) {
|
|
|
|
|
printf (" fmt.pix.bytesperline : %d\n", f->fmt.pix.bytesperline);
|
|
|
|
|
printf (" fmt.pix.sizeimage : %d\n", f->fmt.pix.sizeimage);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************************************/
|
|
|
|
|
|
|
|
|
|
VideoDevice_Dump::VideoDevice_Dump() {
|
|
|
|
|
debug ("");
|
|
|
|
|
filesize = 0;
|
|
|
|
|
filepos = 0;
|
|
|
|
|
fd = -1;
|
|
|
|
|
w = 0;
|
|
|
|
|
h = 0;
|
|
|
|
|
pixformat = 0;
|
|
|
|
|
inframe = NULL;
|
|
|
|
|
inframe_size = 0;
|
|
|
|
|
inframe_maxsize = 0;
|
|
|
|
|
inframe_nexttime = 0;
|
|
|
|
|
fixedframesize = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VideoDevice_Dump::~VideoDevice_Dump() {
|
|
|
|
|
debug ("");
|
|
|
|
|
Stop();
|
|
|
|
|
Close();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Open Device
|
|
|
|
|
// prepare the buffer, InitMMAP and read all controls
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::Open() {
|
|
|
|
|
debug ("OPEN");
|
|
|
|
|
if (config.vdev_device == "") return 0;
|
|
|
|
|
|
|
|
|
|
VideoDevCtrl vctl;
|
|
|
|
|
uint32_t inbuf[3];
|
|
|
|
|
int i;
|
|
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
|
|
std::string fname = config.vdev_dumpfile;
|
|
|
|
|
|
|
|
|
|
printf ("%s:%d %s file %s\n", __FILE__, __LINE__, __FUNCTION__, fname.c_str());
|
|
|
|
|
|
|
|
|
|
if (fd >= 0) close (fd);
|
|
|
|
|
fd = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// read filesize
|
|
|
|
|
if (stat (fname.c_str(), &s) != 0) {
|
|
|
|
|
printf ("%s:%d %s could not read stat of file '%s'. Error:%s\n", __FILE__, __LINE__, __FUNCTION__,
|
|
|
|
|
fname.c_str(), strerror(errno));
|
|
|
|
|
Close();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
filesize = s.st_size;
|
|
|
|
|
|
|
|
|
|
#ifdef BUILD_WINDOWS
|
|
|
|
|
if ((fd = open(fname.c_str(), O_RDONLY | O_BINARY)) == -1)
|
|
|
|
|
#else
|
|
|
|
|
if ((fd = open(fname.c_str(), O_RDONLY)) == -1)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
printf ("%s:%d could not open file '%s' error:%s\n", __FILE__, __LINE__, fname.c_str(), strerror(errno));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// read header
|
|
|
|
|
if (read (fd, inbuf, 12) != 12) {
|
|
|
|
|
printf ("%s:%d could not read all header data.\n", __FILE__, __LINE__);
|
|
|
|
|
close (fd);
|
|
|
|
|
fd = -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
i = 0;
|
|
|
|
|
filepos = 12;
|
|
|
|
|
conf_width = w = ntohl(inbuf[i++]);
|
|
|
|
|
conf_height = h = ntohl(inbuf[i++]);
|
|
|
|
|
conf_videofmt = ntohl(inbuf[i++]);
|
|
|
|
|
|
|
|
|
|
vidctrls.clear();
|
|
|
|
|
vctl.name = "FilePosition";
|
|
|
|
|
vctl.id = 1;
|
|
|
|
|
vctl.min = 0;
|
|
|
|
|
vctl.max = 255;
|
|
|
|
|
vctl.value = 0;
|
|
|
|
|
vidctrls.push_back(vctl);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Close Device
|
|
|
|
|
// Free videobuffer
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::Close() {
|
|
|
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
|
|
if (fd >= 0) {
|
|
|
|
|
close(fd);
|
|
|
|
|
fd = -1;
|
|
|
|
|
filesize = 0;
|
|
|
|
|
filepos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// send the start capture signal to the cam
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::Start() {
|
|
|
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
|
|
Close();
|
|
|
|
|
if (Open() != 1) return 0;
|
|
|
|
|
gettimeofday(&starttv, NULL);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int VideoDevice_Dump::Stop() {
|
|
|
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
|
|
|
|
|
|
|
|
if (fd >= 0) {
|
|
|
|
|
close(fd);
|
|
|
|
|
fd = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inframe != NULL) {
|
|
|
|
|
free (inframe);
|
|
|
|
|
inframe_size = 0;
|
|
|
|
|
inframe = NULL;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// try to grab one frame and convert it into RGB32.
|
|
|
|
|
// If something goes wrong return an error code.
|
|
|
|
|
// Return code VDEV_STATUS_AGAIN is not an error. There was no video image ready to read.
|
|
|
|
|
//
|
|
|
|
|
#define SIZE_FRAMEHEADER 8
|
|
|
|
|
#define SIZE_DUMPHEADER 12
|
|
|
|
|
int VideoDevice_Dump::GetFrame(VideoFrame *destframe) {
|
|
|
|
|
struct timeval curtv;
|
|
|
|
|
unsigned int diff = 0;
|
|
|
|
|
std::list<VideoDevCtrl>::iterator ctrl;
|
|
|
|
|
|
|
|
|
|
if (fd == -1) return 0;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// is it time?
|
|
|
|
|
do {
|
|
|
|
|
gettimeofday(&curtv, NULL);
|
|
|
|
|
diff = 1000 * (curtv.tv_sec - starttv.tv_sec) +
|
|
|
|
|
(curtv.tv_usec - starttv.tv_usec) / 1000;
|
|
|
|
|
|
|
|
|
|
if (diff < inframe_nexttime)
|
|
|
|
|
usleep ((inframe_nexttime-diff)*1000);
|
|
|
|
|
} while (diff < inframe_nexttime);
|
|
|
|
|
|
|
|
|
|
ReadFrame();
|
|
|
|
|
Convert(&cdata, destframe, inframe, inframe_size,
|
|
|
|
|
conf_videofmt, w, h);
|
|
|
|
|
|
|
|
|
|
ctrl = vidctrls.begin();
|
|
|
|
|
if (ctrl->value == 0) {
|
|
|
|
|
// fixed framesize -> calculate frames
|
|
|
|
|
switch (pixformat) {
|
|
|
|
|
case(V4L2_PIX_FMT_RGB24):
|
|
|
|
|
case(V4L2_PIX_FMT_BGR24):
|
|
|
|
|
fixedframesize = 3 * w * h;
|
|
|
|
|
break;
|
|
|
|
|
case(V4L2_PIX_FMT_RGB32):
|
|
|
|
|
case(V4L2_PIX_FMT_BGR32):
|
|
|
|
|
fixedframesize = 4 * w * h;
|
|
|
|
|
break;
|
|
|
|
|
case(V4L2_PIX_FMT_SGRBG8):
|
|
|
|
|
fixedframesize = 1 * w * h;
|
|
|
|
|
break;
|
|
|
|
|
case(V4L2_PIX_FMT_SGRBG16):
|
|
|
|
|
fixedframesize = 2 * w * h;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ctrl->max = 0;
|
|
|
|
|
ctrl->value = -1;
|
|
|
|
|
fixedframesize = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (fixedframesize > 0)
|
|
|
|
|
ctrl->max = (filesize-SIZE_DUMPHEADER) / (fixedframesize + SIZE_FRAMEHEADER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ctrl->value != -1) ctrl->value++;
|
|
|
|
|
|
|
|
|
|
ReadFrame();
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Read Frame
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::ReadFrame() {
|
|
|
|
|
uint32_t inbuf[2];
|
|
|
|
|
|
|
|
|
|
if (fd < 0) return 0;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// check position, if end of file restart from beginning
|
|
|
|
|
if (filepos == filesize) {
|
|
|
|
|
printf ("%s:%d end of file start with first frame\n", __FILE__, __LINE__);
|
|
|
|
|
std::list<VideoDevCtrl>::iterator ctrl;
|
|
|
|
|
ctrl = vidctrls.begin();
|
|
|
|
|
ctrl->value = 0;
|
|
|
|
|
if (lseek(fd, 12, SEEK_SET) != 12) {
|
|
|
|
|
printf ("%s:%d %s lseek returned: %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno));
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
else { // reset filepos and starttime
|
|
|
|
|
filepos = 12;
|
|
|
|
|
gettimeofday(&starttv, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// read frame
|
|
|
|
|
if (read (fd, inbuf, 4*2) != 4*2) {
|
|
|
|
|
printf ("%s:%d could not read frame header: %s\n", __FILE__, __LINE__, strerror(errno));
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
filepos += (4*2);
|
|
|
|
|
inframe_size = ntohl(inbuf[0]);
|
|
|
|
|
inframe_nexttime = ntohl(inbuf[1]);
|
|
|
|
|
|
|
|
|
|
// read header
|
|
|
|
|
if (inframe == NULL) {
|
|
|
|
|
inframe = (unsigned char*) malloc (inframe_size);
|
|
|
|
|
inframe_maxsize = inframe_size;
|
|
|
|
|
}
|
|
|
|
|
else if (inframe_maxsize < inframe_size) {
|
|
|
|
|
inframe = (unsigned char*) realloc (inframe, inframe_size);
|
|
|
|
|
inframe_maxsize = inframe_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// allocate memory and read frame
|
|
|
|
|
if (inframe == NULL) {
|
|
|
|
|
Close();
|
|
|
|
|
printf ("%s:%d could not allocate enough memory\n", __FILE__, __LINE__);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (read (fd, inframe, inframe_size) != inframe_size) {
|
|
|
|
|
printf ("%s:%d could not read frame: %s\n", __FILE__, __LINE__, strerror(errno));
|
|
|
|
|
Close();
|
|
|
|
|
}
|
|
|
|
|
filepos += inframe_size;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// set video control identified by id
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::SetDevCtrl(unsigned int id, int value) {
|
|
|
|
|
std::list<VideoDevCtrl>::iterator ctrl;
|
|
|
|
|
int framerest;
|
|
|
|
|
off_t newfilepos = 0;
|
|
|
|
|
printf ("%s:%d VideoDev_Dumpfile::SetDevCtrl Set Offset to %d id:%d fixedframesize:%d\n", __FILE__, __LINE__, value, id, fixedframesize);
|
|
|
|
|
struct timeval curtv;
|
|
|
|
|
|
|
|
|
|
if (id == 1) {
|
|
|
|
|
ctrl = vidctrls.begin();
|
|
|
|
|
if (value != ctrl->value && value < ctrl->max) {
|
|
|
|
|
filepos = SIZE_DUMPHEADER + ((off_t)value * (SIZE_FRAMEHEADER + (off_t)fixedframesize));
|
|
|
|
|
printf ("%s:%d filepos:%ld\n", __FILE__, __LINE__, filepos);
|
|
|
|
|
|
|
|
|
|
if ((newfilepos = lseek (fd, filepos, SEEK_SET)) < 0) {
|
|
|
|
|
printf ("%s:%d ******* lseek error:%s\n", __FILE__, __LINE__, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
framerest = (newfilepos - SIZE_DUMPHEADER)%(SIZE_FRAMEHEADER + fixedframesize);
|
|
|
|
|
ctrl->value = (newfilepos - SIZE_DUMPHEADER)/(SIZE_FRAMEHEADER + fixedframesize);
|
|
|
|
|
if (ctrl->value != value || framerest != 0) {
|
|
|
|
|
printf ("%s:%d could not set file to correct position. ctrl->value:%d value:%d Framerest:%d\n", __FILE__, __LINE__, ctrl->value, value, framerest);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
//
|
|
|
|
|
// read first frame
|
|
|
|
|
ReadFrame();
|
|
|
|
|
gettimeofday(&curtv, NULL);
|
|
|
|
|
starttv.tv_sec = curtv.tv_sec - (inframe_nexttime/1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// else printf ("%s:%d could not set video position (ctrl->value:%d value:%d max:%d)\n",
|
|
|
|
|
// __FILE__, __LINE__, ctrl->value, value, ctrl->max);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// get video control identified by id
|
|
|
|
|
//
|
|
|
|
|
int VideoDevice_Dump::GetDevCtrl(unsigned int id, int *value) {
|
|
|
|
|
return 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|