/*************************************************************************************** * * videodev.cc is part of SimpleSkyCam. * *****************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 *list) { std::list::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::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::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 VideoDev::GetCtrlsMinMaxValue() { return vidctrls; };