You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
6.1 KiB
265 lines
6.1 KiB
/***************************************************************************************
|
|
*
|
|
* videodev.cc is part of SimpleSkyCam.
|
|
*
|
|
*****************************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/time.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <jpeglib.h>
|
|
|
|
#include <list>
|
|
#include <string>
|
|
#include <setjmp.h>
|
|
|
|
#include "simpleskycam.h"
|
|
#include "gui.h"
|
|
#include "video.h"
|
|
#include "videoframe.h"
|
|
#include "videodev.h"
|
|
#include "convert.h"
|
|
|
|
|
|
|
|
VideoDev::VideoDev() {
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
conf_device = "";
|
|
conf_devicename = "";
|
|
conf_format = "";
|
|
conf_parameter = "";
|
|
conf_height = 800;
|
|
conf_width = 600;
|
|
running = 0;
|
|
callback = NULL;
|
|
pixelformat = 0x0;
|
|
g_mutex_init (&mutex);
|
|
};
|
|
|
|
|
|
#define THREAD_WAITWARNING_TO 10000000
|
|
VideoDev::~VideoDev() {
|
|
int to = 0;
|
|
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
|
|
if (running) Stop();
|
|
while (running > 0) {
|
|
if (--to <= 0) {
|
|
to = THREAD_WAITWARNING_TO;
|
|
printf ("%s:%d %s still waiting for complete\n", __FILE__, __LINE__, __FUNCTION__);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* fill the list with all found controls.
|
|
*/
|
|
int VideoDev::GetCtrlList(std::list<std::string> *list) {
|
|
std::list<VideoDevCtrl>::iterator iter;
|
|
if (list == NULL) return VDEV_STATUS_ERROR;
|
|
|
|
list->clear();
|
|
LockMutex();
|
|
|
|
for (iter = vidctrls.begin(); iter != vidctrls.end(); iter++) {
|
|
list->push_back ((*iter).name);
|
|
}
|
|
|
|
UnLockMutex();
|
|
|
|
return VDEV_STATUS_OK;
|
|
};
|
|
|
|
|
|
/*
|
|
* if the control is found, fill out all the fields and return with VDEV_STATUS_OK,
|
|
* on error VDEV_STATUS_UNKNOWN. In case he control have not been found.
|
|
*/
|
|
int VideoDev::GetCtrlMinMaxValue(std::string name, int *min, int *max, int *value) {
|
|
std::list<VideoDevCtrl>::iterator iter;
|
|
LockMutex();
|
|
for (iter = vidctrls.begin(); iter != vidctrls.end(); iter++)
|
|
if (iter->name.compare(name) == 0) {
|
|
GetDevCtrl(iter->id, &(iter->value));
|
|
if (value != NULL) *value = iter->value;
|
|
if (min != NULL) *min = iter->min;
|
|
if (max != NULL) *max = iter->max;
|
|
break;
|
|
}
|
|
UnLockMutex();
|
|
if (iter == vidctrls.end()) return VDEV_STATUS_ERROR;
|
|
return VDEV_STATUS_OK;
|
|
};
|
|
|
|
|
|
//
|
|
// set the value for an control, on error VDEV_STATUS_UNKNOWN
|
|
//
|
|
int VideoDev::SetCtrlValue(std::string name, int value) {
|
|
std::list<VideoDevCtrl>::iterator iter;
|
|
LockMutex();
|
|
for (iter = vidctrls.begin(); iter != vidctrls.end(); iter++)
|
|
if (iter->name.compare(name) == 0) {
|
|
SetDevCtrl(iter->id, value);
|
|
break;
|
|
}
|
|
UnLockMutex();
|
|
if (iter == vidctrls.end()) return VDEV_STATUS_ERROR;
|
|
return VDEV_STATUS_OK;
|
|
};
|
|
|
|
|
|
/*
|
|
* before is it possible to Start the VideoGrabbing it is mandatory to set up some values
|
|
*/
|
|
void VideoDev::SetConfig(std::string dev, int w, int h, std::string format, std::string parameter, gboolean (*callback_func)(gpointer data)) {
|
|
conf_device = dev;
|
|
conf_format = format;
|
|
conf_parameter = parameter;
|
|
conf_width = w;
|
|
conf_height = h;
|
|
callback = callback_func;
|
|
};
|
|
|
|
|
|
/*
|
|
* start the video, start capturing, start thread
|
|
* after return of this function we can call the Ctrl thread
|
|
* this function should onyl be called after everything is setup with SetConfig(..)
|
|
*/
|
|
#define CYCLETIME 0.050
|
|
void VideoDev::ThreadProcess() {
|
|
struct timeval cycle_timestamp;
|
|
int numframes = 0;
|
|
int lastsec = 0;
|
|
float cycle_time = 0.0;
|
|
float cycle_wait = 0.0;
|
|
int i;
|
|
|
|
printf ("%s:%d %s Enter\n", __FILE__, __LINE__, __FUNCTION__);
|
|
cycle_time = get_cycletime(&cycle_timestamp); // just start counting
|
|
|
|
running = 1;
|
|
|
|
//
|
|
// open and init device buffers device
|
|
if (Open() != VDEV_STATUS_OK) {
|
|
Close();
|
|
running = 0;
|
|
}
|
|
|
|
//
|
|
// start capturing
|
|
if (CaptureStart() != VDEV_STATUS_OK) {
|
|
Close();
|
|
running = 0;
|
|
}
|
|
|
|
if (running) {
|
|
ConvertStart(&cdata, pixelformat);
|
|
}
|
|
|
|
threaddata.running = 1; // prevent reading all controlls every time.
|
|
// will be set to 2 in callback function, after the first frame
|
|
// is read and all controls a loaded.
|
|
if (callback) gdk_threads_add_idle(callback, &threaddata);
|
|
|
|
while (running) {
|
|
i = Grab(&threaddata.vfr);
|
|
Convert(&cdata, &threaddata.vf, threaddata.vfr.data, threaddata.vfr.size, threaddata.vfr.pixfmt, threaddata.vfr.w, threaddata.vfr.h);
|
|
switch (i) {
|
|
case VDEV_STATUS_OK:
|
|
numframes++;
|
|
if (callback) gdk_threads_add_idle(callback, &threaddata);
|
|
break;
|
|
|
|
case VDEV_STATUS_AGAIN:
|
|
break;
|
|
|
|
default:
|
|
running = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// keep 25fps, write every second a message
|
|
cycle_time = get_cycletime(&cycle_timestamp);
|
|
cycle_wait = (CYCLETIME - cycle_time) + cycle_wait;
|
|
if (lastsec != cycle_timestamp.tv_sec) {
|
|
printf ("%s:%d %s Loop: cycle_time:%f Freq:%f Hz Frames:%d \n", __FILE__, __LINE__, __FUNCTION__, cycle_time, (1.0/cycle_time), numframes);
|
|
lastsec = cycle_timestamp.tv_sec;
|
|
numframes = 0;
|
|
}
|
|
if (cycle_wait > 0.0 && cycle_wait < 1.0 ) usleep ((int)(cycle_wait * 1000000.0));
|
|
}
|
|
|
|
//
|
|
// stop capturing
|
|
if (callback) gdk_threads_add_idle(callback, NULL);
|
|
ConvertStop(&cdata, pixelformat);
|
|
CaptureStop();
|
|
Close();
|
|
|
|
printf ("%s:%d %s Exit Thread\n", __FILE__, __LINE__, __FUNCTION__);
|
|
|
|
return;
|
|
};
|
|
|
|
|
|
void VideoDev::Stop() {
|
|
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
|
|
if (running == 1) running = 0;
|
|
return;
|
|
};
|
|
|
|
|
|
void VideoDev::GetVideoInfo(int *w, int *h, std::string *format) {
|
|
if (format != NULL) *format = conf_format;
|
|
if (w != NULL) *w = conf_width;
|
|
if (h != NULL) *h = conf_height;
|
|
}
|
|
|
|
|
|
list<VideoDevCtrl> VideoDev::GetCtrlsMinMaxValue() {
|
|
return vidctrls;
|
|
};
|
|
|
|
|
|
int VideoDev::get_bytesperpixel (uint32_t pixfmt) {
|
|
int bytesperpixel = 4;
|
|
|
|
switch (pixfmt) {
|
|
case (V4L2_PIX_FMT_SGRBG8):
|
|
bytesperpixel = 1;
|
|
break;
|
|
case (V4L2_PIX_FMT_SGRBG16):
|
|
bytesperpixel = 2;
|
|
break;
|
|
case (V4L2_PIX_FMT_BGR32):
|
|
case (V4L2_PIX_FMT_RGB32):
|
|
bytesperpixel = 4;
|
|
break;
|
|
case (V4L2_PIX_FMT_BGR24):
|
|
case (V4L2_PIX_FMT_RGB24):
|
|
bytesperpixel = 3;
|
|
break;
|
|
default:
|
|
errorexit((char*)"%s:%d unsupported pixelformat %s\n", convert_from_pixelformat(pixfmt).c_str());
|
|
break;
|
|
}
|
|
return bytesperpixel;
|
|
}
|
|
|
|
|