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.
SimpleSkyCam/videodev.cc

237 lines
5.6 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;
};