From c6359755007d866c5802d459c1a8253322a5d52b Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Sun, 30 Oct 2022 23:06:20 +0100 Subject: [PATCH] adding automatic format detection, fixing control display. Adding rudimentary support for controls to SVBONY driver --- ChangeLog | 5 ++ Makefile | 7 +- Makefile.rules.linux | 6 +- configuration.cc | 1 - convert.cc | 31 +++++++++ convert.h | 5 ++ gui.h | 3 + main.cc | 1 + simpleskycam.ui | 3 +- video.cc | 157 ++++++++++++++++++++++++++++++++----------- videodev-dummy.h | 2 + videodev-svbcam.cc | 152 ++++++++++++++++++++++++++++++++++++++--- videodev-svbcam.h | 2 + videodev-v4l2.cc | 61 +++++++++++++---- videodev-v4l2.h | 2 + videodev.cc | 6 +- videodev.h | 3 + 17 files changed, 378 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2ae2543..56149bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2022-10-30: +- fixing many bugs check change log. + controls are back working, automatic format detection. + adding alot FIXMEs to the code. + 2021-11-17: - adding basic support for SBVcams like SV-305 diff --git a/Makefile b/Makefile index 9bddcee..0f9baa8 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,12 @@ APP = simpleskycam OBJECTS := $(OBJECTS) gui.oo main.oo video.oo videoframe.oo videodev.oo videodev-v4l2.oo convert.oo filter.oo detect.oo json.oo configuration.oo DISTNAME=simpleskycam-$(VERSION) + ifeq ($(TARGET),) -noconfig: help +noconfig: configlinux help endif + all: Makefile.rules $(TARGET) help: @@ -34,6 +36,7 @@ config: Makefile.rules echo "#define _CONFIG_H_" >> config.h echo "" >> config.h echo "#define VERSION \"$(VERSION)\"" >> config.h + echo "#define USE_SVBONY" >> config.h echo "" >> config.h echo "#endif" >> config.h @@ -53,6 +56,8 @@ clean: rm -rf *.dll rm -rf *.exe rm -rf Makefile.rules + rm -rf U2SM200C-AST_Cfg_A.bin + rm -rf U2SM200C-AST_Cfg_SAVE.bin dist: clean rm -rf $(DISTNAME) diff --git a/Makefile.rules.linux b/Makefile.rules.linux index 6c197f1..5be2262 100644 --- a/Makefile.rules.linux +++ b/Makefile.rules.linux @@ -12,9 +12,9 @@ OBJECTS = # # Uncomment to enable support for SVBONY Cammeras. # -# CPPFLAGS := $(CPPFLAGS) -DUSE_SVBONY -I/usr/local/include -# LDFLAGS := $(LDFLAGS) -lSVBCameraSDK -L/usr/local/lib -# OBJECTS := $(OBJECTS) videodev-svbcam.oo +CPPFLAGS := $(CPPFLAGS) -I/usr/local/include +LDFLAGS := $(LDFLAGS) -lSVBCameraSDK -L/usr/local/lib +OBJECTS := $(OBJECTS) videodev-svbcam.oo # diff --git a/configuration.cc b/configuration.cc index 30e5c60..80ad0ee 100644 --- a/configuration.cc +++ b/configuration.cc @@ -143,7 +143,6 @@ void Configuration::LoadConfig(std::string filename) { GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev")); GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); gtk_entry_set_text(GTK_ENTRY(cbdevice), vstr.c_str()); - cb_video_btnrec (NULL, NULL); } // diff --git a/convert.cc b/convert.cc index 097083b..c4a0a42 100644 --- a/convert.cc +++ b/convert.cc @@ -4,6 +4,17 @@ #include "gui.h" #include "video.h" +uint32_t convert_pixelformats [] = { + V4L2_PIX_FMT_MJPEG, + V4L2_PIX_FMT_YUYV, + V4L2_PIX_FMT_RGB32, + V4L2_PIX_FMT_RGB24, + V4L2_PIX_FMT_BGR32, + V4L2_PIX_FMT_UYVY, + 0 +}; + + /* * helper part for converting different video types @@ -243,6 +254,8 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr break; default: + printf ("%s:%d Error no default possible, need to finish\n", __FILE__, __LINE__); + exit (-1); break; } @@ -251,3 +264,21 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr +std::string convert_from_pixelformat (uint32_t fmt) { + char txt[5]; + + snprintf (txt, 5, "%c%c%c%c", ((char*)&fmt)[0], ((char*)&fmt)[1], ((char*)&fmt)[2], ((char*)&fmt)[3]); + return txt; +}; + + +uint32_t convert_to_pixelformat(std::string s) { + uint32_t u = 0; + + u = ((unsigned char) s[0]) + ((unsigned char) s[1] << 8) + + ((unsigned char) s[2] << 16) + ((unsigned char) s[3] << 24); + + return u; +}; + + diff --git a/convert.h b/convert.h index 90800ea..aa7f36b 100644 --- a/convert.h +++ b/convert.h @@ -21,4 +21,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr int ConvertStart(ConvertData *cdata, uint32_t pixelformat); int ConvertStop(ConvertData *cdata, uint32_t pixelformat); +extern uint32_t convert_pixelformats[]; +std::string convert_from_pixelformat (uint32_t fmt); +uint32_t convert_to_pixelformat(std::string s); + + #endif diff --git a/gui.h b/gui.h index b109e7c..5a747a3 100644 --- a/gui.h +++ b/gui.h @@ -57,6 +57,8 @@ G_MODULE_EXPORT gboolean cb_window_delete_event (GtkWidget *widget, // // video and video devices +G_MODULE_EXPORT void cb_video_cbox_videodev (GtkWidget *widget, gpointer data); + G_MODULE_EXPORT void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_video_btnrec (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_video_btnstop (GtkWidget *widget, gpointer data); @@ -69,6 +71,7 @@ G_MODULE_EXPORT void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_vidctrl_scale_change (GtkRange *range, gpointer data); gboolean videoctrl_update(gpointer data); +// preset buttons G_MODULE_EXPORT void cb_video_pre_click (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_video_pre_pressed (GtkWidget *widget, gpointer data); gboolean video_pre_long(gpointer data); diff --git a/main.cc b/main.cc index 6f6cc44..5947b4e 100644 --- a/main.cc +++ b/main.cc @@ -11,6 +11,7 @@ #include "gui.h" #include "filter.h" #include "detect.h" +#include "convert.h" /************************************************************************** * global variables diff --git a/simpleskycam.ui b/simpleskycam.ui index 0291e9e..ff48336 100644 --- a/simpleskycam.ui +++ b/simpleskycam.ui @@ -1,5 +1,5 @@ - + @@ -82,6 +82,7 @@ True False True + False diff --git a/video.cc b/video.cc index aee4791..d6504e6 100644 --- a/video.cc +++ b/video.cc @@ -34,6 +34,49 @@ extern position_2d video_enterdata_pos; extern detect_movement detectedpos_data; extern Configuration config; + +/* + * stop video recording + */ +void video_stoprecord() { + GtkWidget *btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec")); + GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); + + if (videodev == NULL) return; + + videodev->Stop(); + gtk_widget_set_sensitive(btnstart, true); + gtk_widget_set_sensitive(btnstop, false); + + if (videodev_thread != NULL) g_thread_join (videodev_thread); + videodev_thread = NULL; + + delete videodev; + videodev = NULL; +} + + +/* + * return selected driver and device from GUI + */ +void video_get_driverdevice(std::string *driver, std::string *device) { + GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev")); + GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); + + if (driver == NULL || device == NULL) return; + + // read values from GUI elements, and start videodev with the correct driver + int i; + *device = gtk_entry_get_text(GTK_ENTRY(cbdevice)); + + i = device->find(' '); + *driver = device->substr (0, i); + *device = device->substr (i+1, std::string::npos); + *device = device->substr (0, device->find(' ')); +} + + + gboolean videoctrl_update(gpointer data) { GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); GtkWidget *scale = NULL; @@ -242,6 +285,7 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) +// fixme: refresh format list. /* * refresh the possible devices */ @@ -291,43 +335,25 @@ gpointer videodev_threadprocess_wrapper (gpointer data) { * with all elements. Also connect the signals to the callback functions. */ void cb_video_btnrec (GtkWidget *widget, gpointer data) { - GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev")); - GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); GtkWidget *cbres = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videores")); GtkWidget *cbresentry = gtk_bin_get_child(GTK_BIN(cbres)); GtkWidget *cbfmt = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videofmt")); GtkWidget *cbfmtentry = gtk_bin_get_child(GTK_BIN(cbfmt)); GtkWidget *btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec")); GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); - int i, w, h; + int w, h; - // - // read values from GUI elements, and start videodev with the correct driver - std::string device = gtk_entry_get_text(GTK_ENTRY(cbdevice)); - std::string driver; + // get device and driver information + std::string device, driver; std::string parameter; + video_get_driverdevice(&driver, &device); - i = device.find(' '); - driver = device.substr (0, i); - device = device.substr (i+1, std::string::npos); - device = device.substr (0, device.find(' ')); - - if (videodev != NULL) { - // - // before we can delete this object we must stop the thread. - // - videodev->Stop(); - if (videodev_thread != NULL) g_thread_join (videodev_thread); - videodev_thread = NULL; - - delete videodev; - videodev = NULL; - } + // stop recording + video_stoprecord(); // // load the selected driver if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2; - #ifdef USE_SVBONY else if (driver.compare("SVBCAM") == 0) videodev = new VideoDev_SVBCam; #endif @@ -431,21 +457,8 @@ void video_refreshctrls () { * we need to wait for the thread to complete and then we can delete this object. */ void cb_video_btnstop (GtkWidget *widget, gpointer data) { - GtkWidget *btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec")); - GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); - printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); - if (videodev == NULL) return; - - videodev->Stop(); - gtk_widget_set_sensitive(btnstart, true); - gtk_widget_set_sensitive(btnstop, false); - - if (videodev_thread != NULL) g_thread_join (videodev_thread); - videodev_thread = NULL; - - delete videodev; - videodev = NULL; + video_stoprecord(); }; @@ -459,9 +472,14 @@ gboolean cb_thread_video (gpointer data) { VideoDevThreadData *cbdata = (VideoDevThreadData*) data; VideoFrame *vf = NULL; +// printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + if (cbdata != NULL) { vf = &cbdata->vf; - if (cbdata->running == 1) video_refreshctrls(); + if (cbdata->running == 1) { + video_refreshctrls(); + cbdata->running = 2; + } if (vf->w <= 0 || vf->h <= 0 || vf->data == NULL) vf = NULL; } if (videodev == NULL) return false; @@ -616,6 +634,7 @@ struct { struct timeval tv; guint timer; } presetbtn; + void cb_video_pre_click (GtkWidget *widget, gpointer data) { float pushtime = get_cycletime(&presetbtn.tv); std::string s; @@ -702,3 +721,63 @@ gboolean video_pre_long(gpointer data) { }; +/* + * videodevice changed + */ +void cb_video_cbox_videodev (GtkWidget *widget, gpointer data) { + +// GtkWidget *cbres = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videores")); +// GtkWidget *cbresentry = gtk_bin_get_child(GTK_BIN(cbres)); + GtkWidget *cbfmt = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videofmt")); + GtkWidget *cbfmtentry = gtk_bin_get_child(GTK_BIN(cbfmt)); + GtkListStore *model; + std::list lst_format; + std::list lst_resolution; + std::list::iterator iter; + std::string device, driver; + std::string parameter; + + + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + video_stoprecord(); + + // + // open device + video_get_driverdevice(&driver, &device); + + // + // load the selected driver + if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2; +#ifdef USE_SVBONY + else if (driver.compare("SVBCAM") == 0) videodev = new VideoDev_SVBCam; +#endif + else if (driver.compare("DUMMY") == 0) videodev = new VideoDev; + else videodev = new VideoDev; + + videodev->GetDeviceFormats(device, &lst_format); + model = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(cbfmt))); + gtk_list_store_clear(GTK_LIST_STORE(model)); + gtk_entry_set_text (GTK_ENTRY(cbfmtentry), ""); + for (iter = lst_format.begin(); iter != lst_format.end(); iter++) { + gtk_list_store_insert_with_values(GTK_LIST_STORE(model), NULL, -1, + 0, iter->c_str(), + -1); + } + + videodev->GetDeviceResolutions(device, &lst_format); + + + // + // get resolution + + // + // get controls + + // + // close device + + delete videodev; + videodev = NULL; +}; + diff --git a/videodev-dummy.h b/videodev-dummy.h index 3181b66..4a2f14b 100644 --- a/videodev-dummy.h +++ b/videodev-dummy.h @@ -49,6 +49,8 @@ public: VideoDev_Dummy(); ~VideoDev_Dummy(); int GetDeviceList(std::list *list); + int GetDeviceFormats(string device, std::list *formats) { return VDEV_STATUS_OK; }; + int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; }; #endif diff --git a/videodev-svbcam.cc b/videodev-svbcam.cc index 00206ae..de8f71e 100644 --- a/videodev-svbcam.cc +++ b/videodev-svbcam.cc @@ -4,6 +4,8 @@ * SUBSYSTEMS=="usb", ATTRS{idVendor}=="f266", ATTRS{idProduct}=="9a0a", GROUP="plugdev", MODE="0660" */ +#include "config.h" + #ifdef USE_SVBONY #include @@ -56,7 +58,6 @@ void VideoDev_SVBCam::print_error(int err) { printf ("unknown %d\n", err); break; } - exit (0); }; @@ -113,7 +114,7 @@ int VideoDev_SVBCam::Open() { } printf ("%s:%d %s height: %ld width: %ld\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight, camprop.MaxWidth); - for(int i=0; i < 8 && camprop.SupportedVideoFormat[i] == SVB_IMG_END; i++) { + for(int i=0; i < 8 && camprop.SupportedVideoFormat[i] != SVB_IMG_END; i++) { printf ("%s:%d %s VideoFormat Index:%d ", __FILE__, __LINE__, __FUNCTION__, i); switch (camprop.SupportedVideoFormat[i]) { case SVB_IMG_RAW8: @@ -172,8 +173,8 @@ int VideoDev_SVBCam::Open() { print_error(err); return VDEV_STATUS_ERROR; } - printf ("%s:%d %s Got Control idx: %d name:%s desc:%s\n", __FILE__, __LINE__, __FUNCTION__, - i, camcontrols[i].Name, camcontrols[i].Description); + printf ("%s:%d %s Got Control idx: %d name:%s desc:%s [%ld - %ld]\n", __FILE__, __LINE__, __FUNCTION__, + i, camcontrols[i].Name, camcontrols[i].Description, (long)camcontrols[i].MinValue, (long)camcontrols[i].MaxValue); vctl.name = (char*)camcontrols[i].Name; vctl.id = i; vctl.min = camcontrols[i].MinValue; @@ -194,11 +195,30 @@ int VideoDev_SVBCam::Open() { print_error(err); return VDEV_STATUS_ERROR; } - if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) { - print_error(err); - return VDEV_STATUS_ERROR; + + switch (convert_to_pixelformat(conf_format)) { + case (V4L2_PIX_FMT_RGB32): + if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB32)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + break; + case (V4L2_PIX_FMT_RGB24): + if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + break; + default: + conf_format = convert_from_pixelformat(V4L2_PIX_FMT_RGB24); + if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + break; } + // // preprare buffer LockMutex(); @@ -266,6 +286,7 @@ int VideoDev_SVBCam::CaptureStop() { * 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. */ +// FIXME: SVBGetVideoData needs to be outside of Lock/UnLockMutex - using inside thread inbuffer int VideoDev_SVBCam::Grab(VideoFrame *vf) { int err; @@ -283,6 +304,96 @@ int VideoDev_SVBCam::Grab(VideoFrame *vf) { } +int VideoDev_SVBCam::GetDeviceFormats(string device, std::list *formats) { + int camid_; + std::string result = ""; + int err; + SVB_CAMERA_PROPERTY camprop; + VideoDevCtrl vctl; + + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + LockMutex(); + + if (camid == -1) { + camid_ = atoi (device.c_str()); + printf ("%s:%d %s opening cam %d\n", __FILE__, __LINE__, __FUNCTION__, camid_); + + if ((err = SVBOpenCamera(camid_)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + } + else camid_ = camid; + + // + // get cam property + if ((err = SVBGetCameraProperty(camid_, &camprop)) != SVB_SUCCESS) { + print_error(err); + Close(); + return VDEV_STATUS_ERROR; + } + printf ("%s:%d %s height: %ld width: %ld\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight, camprop.MaxWidth); + + for(int i=0; i < 8 && camprop.SupportedVideoFormat[i] != SVB_IMG_END; i++) { + printf ("%s:%d %s VideoFormat Index:%d ", __FILE__, __LINE__, __FUNCTION__, i); + switch (camprop.SupportedVideoFormat[i]) { + case SVB_IMG_RAW8: + printf("\t\tSVB_IMG_RAW8\n"); + break; + case SVB_IMG_RAW10: + printf("\t\tSVB_IMG_RAW10\n"); + break; + case SVB_IMG_RAW12: + printf("\t\tSVB_IMG_RAW12\n"); + break; + case SVB_IMG_RAW14: + printf("\t\tSVB_IMG_RAW14\n"); + break; + case SVB_IMG_RAW16: + printf("\t\tSVB_IMG_RAW16\n"); + break; + case SVB_IMG_Y8: + printf("\t\tSVB_IMG_Y8\n"); + break; + case SVB_IMG_Y10: + printf("\t\tSVB_IMG_Y10\n"); + break; + case SVB_IMG_Y12: + printf("\t\tSVB_IMG_Y12\n"); + break; + case SVB_IMG_Y14: + printf("\t\tSVB_IMG_Y14\n"); + break; + case SVB_IMG_Y16: + printf("\t\tSVB_IMG_Y16\n"); + break; + case SVB_IMG_RGB24: + printf("\t\tSVB_IMG_RGB24\n"); + formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_RGB24)); + break; + case SVB_IMG_RGB32: + printf("\t\tSVB_IMG_RGB32\n"); + formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_RGB32)); + break; + case SVB_IMG_END: + printf("\t\tSVB_IMG_END\n"); + break; + default: + printf ("\t\tunbekannt\n"); + break; + } + } + + if (camid == -1) { + if ((err = SVBCloseCamera(camid_)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + } + + UnLockMutex(); + return VDEV_STATUS_OK; +} @@ -294,6 +405,23 @@ int VideoDev_SVBCam::Grab(VideoFrame *vf) { * set video control identified by id */ int VideoDev_SVBCam::SetDevCtrl(unsigned int id, int value) { + int err; + int oldv; + + if (value < 0) { // enable auto + GetDevCtrl (id, &oldv); + if ((err = SVBSetControlValue(camid, static_cast(id), oldv, SVB_TRUE)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + } + else { + if ((err = SVBSetControlValue(camid, static_cast(id), value, SVB_FALSE)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + } + return VDEV_STATUS_OK; }; @@ -302,7 +430,15 @@ int VideoDev_SVBCam::SetDevCtrl(unsigned int id, int value) { * get video control identified by id */ int VideoDev_SVBCam::GetDevCtrl(unsigned int id, int *value) { - *value = 0; + int err; + long pvalue; + SVB_BOOL ctlauto; + + if ((err = SVBGetControlValue(camid, static_cast(id), &pvalue, &ctlauto)) != SVB_SUCCESS) { + print_error(err); + return VDEV_STATUS_ERROR; + } + *value = (int) pvalue; return VDEV_STATUS_OK; }; diff --git a/videodev-svbcam.h b/videodev-svbcam.h index a4828fb..77e5784 100644 --- a/videodev-svbcam.h +++ b/videodev-svbcam.h @@ -47,6 +47,8 @@ public: VideoDev_SVBCam(); ~VideoDev_SVBCam(); int GetDeviceList(std::list *list); + int GetDeviceFormats(string device, std::list *formats); + int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; }; #endif diff --git a/videodev-v4l2.cc b/videodev-v4l2.cc index 7be4ef7..ff7b4ee 100644 --- a/videodev-v4l2.cc +++ b/videodev-v4l2.cc @@ -108,10 +108,10 @@ void VideoDev_V4L2::PrintFmt(struct v4l2_format *f) { printf (" type : %u\n", f->type); printf (" fmt.pix.width : %d\n", f->fmt.pix.width); printf (" fmt.pix.height : %d\n", f->fmt.pix.height); - printf (" fmt.fmt.pix.pixelformat : %c%c%c%c\n", ((char*)&fmt.fmt.pix.pixelformat)[0], - ((char*)&fmt.fmt.pix.pixelformat)[1], - ((char*)&fmt.fmt.pix.pixelformat)[2], - ((char*)&fmt.fmt.pix.pixelformat)[3]); + printf (" fmt.fmt.pix.pixelformat : %c%c%c%c\n", ((char*)&f->fmt.pix.pixelformat)[0], + ((char*)&f->fmt.pix.pixelformat)[1], + ((char*)&f->fmt.pix.pixelformat)[2], + ((char*)&f->fmt.pix.pixelformat)[3]); printf (" fmt.pix.field : %d\n", f->fmt.pix.field); printf (" fmt.pix.bytesperline : %d\n", f->fmt.pix.bytesperline); printf (" fmt.pix.sizeimage : %d\n", f->fmt.pix.sizeimage); @@ -199,16 +199,8 @@ int VideoDev_V4L2::Open() { fmt.fmt.pix.height = 1080; } - if (conf_format.length() > 0) { // pixelformat - if (conf_format.compare("MJPG") == 0) fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - else if (conf_format.compare("YUYV") == 0) fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - else if (conf_format.compare("RGB4") == 0) fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; - else fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - } - else { - // fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - } + // fixme: hardcoded video format????? + fmt.fmt.pix.pixelformat = convert_to_pixelformat(conf_format); fmt.fmt.pix.field = V4L2_FIELD_NONE; if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) { fprintf (stderr, "%s:%d VIDIOC_S_FMT : %s\n", __FILE__, __LINE__, strerror (errno)); @@ -500,6 +492,47 @@ int VideoDev_V4L2::Grab(VideoFrame *vf) { } +int VideoDev_V4L2::GetDeviceFormats(string device, std::list *formats) { + int i, fd_; + struct v4l2_format format = {0}; + std::string result = ""; + + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + LockMutex(); + + if (fd == -1){ + // + // open device and get device name and capabilities | O_NONBLOCK + if((fd_ = open(device.c_str(), O_RDWR)) == -1) { + printf ("%s could not open device %s: %s\n", __FUNCTION__, device.c_str(), strerror(errno)); + return VDEV_STATUS_ERROR; + } + } + else fd_ = fd; + + for(i = 0; convert_pixelformats[i] != 0; i++){ + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.width = -1; + format.fmt.pix.height = -1; + format.fmt.pix.pixelformat = convert_pixelformats[i]; + if(xioctl(fd_, VIDIOC_S_FMT, &format) != -1) { + if (format.fmt.pix.pixelformat == convert_pixelformats[i]) { + formats->push_back(convert_from_pixelformat(format.fmt.pix.pixelformat)); + } + } + else { + printf ("error: %s\n", strerror(errno)); + } + } + + if (fd == -1) { + close (fd_); + } + + UnLockMutex(); + return VDEV_STATUS_OK; +} + diff --git a/videodev-v4l2.h b/videodev-v4l2.h index b8392e5..2b0cd3d 100644 --- a/videodev-v4l2.h +++ b/videodev-v4l2.h @@ -66,6 +66,8 @@ public: VideoDev_V4L2(); ~VideoDev_V4L2(); int GetDeviceList(std::list *list); + int GetDeviceFormats(string device, std::list *formats); + int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; }; #endif diff --git a/videodev.cc b/videodev.cc index f63bec4..34b3f40 100644 --- a/videodev.cc +++ b/videodev.cc @@ -163,9 +163,11 @@ void VideoDev::ThreadProcess() { Close(); running = 0; } - threaddata.running = 1; + + threaddata.running = 1; // prevent reading all controlls every time. + // will be set to 2 in callback function if (callback) gdk_threads_add_idle(callback, &threaddata); - threaddata.running = 2; +// threaddata.running = 2; while (running) { i = Grab(&threaddata.vf); diff --git a/videodev.h b/videodev.h index dc6144a..4287128 100644 --- a/videodev.h +++ b/videodev.h @@ -16,6 +16,7 @@ #include "video.h" #include "videoframe.h" + enum { VDEV_STATUS_UNKNOWN, VDEV_STATUS_OK, @@ -141,6 +142,8 @@ public: /* fills the list with all found device */ virtual int GetDeviceList(std::list *list) { return VDEV_STATUS_OK; }; + virtual int GetDeviceFormats(string device, std::list *formats) { return VDEV_STATUS_OK; }; + virtual int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; int GetCtrlList(std::list *list);