#include "video.h" #include "videoframe.h" int convert_debug_fd = -1; struct timeval convert_debug_tv; int dumpframe_open(uint32_t pixelformat, int srcw, int srch) { time_t t = time(NULL); struct tm *tmptr; char fname[LEN_FILENAME]; char fullfname[LEN_FULLFILENAME]; printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); if (config.vdev_dumppath.length() == 0) return -1; // // check to create file, if not possible try creating the directory and create the file again tmptr = localtime(&t); strftime(fname, LEN_FILENAME, "%Y%m%d-%H%M%S", tmptr); snprintf (fullfname, LEN_FULLFILENAME, "%s/%s.videodump", config.vdev_dumppath.c_str(), fname); if ((convert_debug_fd = creat (fullfname, 0666)) == -1) { printf ("%s:%d could not create file '%s'. Error:%s\n", __FILE__, __LINE__, fullfname, strerror(errno)); printf ("%s:%d try to create folder\n", __FILE__, __LINE__); // create folder // FIXME: how to do thin on windows #ifdef BUILD_WINDOWS if ((mkdir (config.debugpath)) == -1) { #else if ((mkdir (config.vdev_dumppath.c_str(), 0777)) == -1) { #endif printf ("%s:%d could not create debug folder.\n", __FILE__, __LINE__); return -1; } if ((convert_debug_fd = creat (fullfname, 0666)) == -1) { printf ("%s:%d could again not create file '%s'. Error:%s\n", __FILE__, __LINE__, fullfname, strerror(errno)); return -1; } } // // file is open for writing, write header information uint32_t wwidth = htonl(srcw); uint32_t wheight = htonl(srch); uint32_t wpixfmt = htonl(pixelformat); write (convert_debug_fd, &wwidth, 4); write (convert_debug_fd, &wheight, 4); write (convert_debug_fd, &wpixfmt, 4); // // save start time, this is needed to calculate the time between the frames gettimeofday (&convert_debug_tv, NULL); return 0; } /* * if fd is not open open file and set up header */ void dumpframe(unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch) { struct timeval tv; uint32_t wts, ts; uint32_t wsize; if (ptrsrc == NULL) return; if (config.vdev_dumppath.length() == 0) return; if (convert_debug_fd == -1) if (dumpframe_open(pixelformat, srcw, srch) == -1) return; // // construct and write header wsize = htonl(srcsize); gettimeofday (&tv, NULL); ts = 1000 * (tv.tv_sec - convert_debug_tv.tv_sec) + (tv.tv_usec - convert_debug_tv.tv_usec) / 1000; wts = htonl(ts); write (convert_debug_fd, &wsize, 4); write (convert_debug_fd, &wts, 4); // // write frame write (convert_debug_fd, ptrsrc, srcsize); }; /* * close file and reset all data */ void dumpframe_close() { if (convert_debug_fd != -1) { close (convert_debug_fd); convert_debug_fd = -1; } } 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; pthread_mutex_init(&mtx, NULL); }; 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, VideoFrameFloat *destfloat) { struct timeval curtv; unsigned int diff = 0; std::list::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, destfloat, 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::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::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; };