diff --git a/ChangeLog b/ChangeLog index f8e4e95..8d365a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2021-10-25: +- adding support for different resolution and pixelformat - adding position/movement vector in the top left corner - saving/loading the default config is working now - saving and recalling presetbuttons are working diff --git a/video.cc b/video.cc index 58a58b7..387c940 100644 --- a/video.cc +++ b/video.cc @@ -269,21 +269,32 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) { std::list list; std::list::iterator iter; 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")); GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); GtkWidget *gridchild = NULL; - int i; + int i, w, h; - GtkWidget *cbdevice = gtk_bin_get_child(GTK_BIN(cbox)); + // + // read values from GUI elements std::string device = gtk_entry_get_text(GTK_ENTRY(cbdevice)); device = device.substr (0, device.find(' ')); + std::string format = gtk_entry_get_text(GTK_ENTRY(cbfmtentry)); + std::string resolution = gtk_entry_get_text(GTK_ENTRY(cbresentry)); + w = h = -1; + if (resolution.compare ("MAX") != 0) sscanf (resolution.c_str(), "%dx%d", &w, &h); + printf ("%s:%d %s open device: '%s'\n", __FILE__, __LINE__, __FUNCTION__, device.c_str()); gtk_widget_set_sensitive(btnstart, false); gtk_widget_set_sensitive(btnstop, true); - videodev.Start(device, cb_thread_video); + videodev.Start(device, w, h, format, cb_thread_video); videodev.GetCtrlList(&list); // @@ -332,6 +343,13 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) { gtk_widget_show (scale); gtk_widget_show (entry); } + + // + // read video information + videodev.GetVideoInfo(&w, &h, &format); + resolution = std::to_string(w) + "x" + std::to_string(h); + gtk_entry_set_text (GTK_ENTRY(cbresentry), resolution.c_str()); + gtk_entry_set_text (GTK_ENTRY(cbfmtentry), format.c_str()); }; diff --git a/video.h b/video.h index 18792a5..7812501 100644 --- a/video.h +++ b/video.h @@ -72,6 +72,9 @@ class VideoDev { private: std::string conf_device; std::string conf_devicename; + std::string conf_format; + int conf_width; + int conf_height; gboolean (*callback)(gpointer data); int running; GMutex mutex; @@ -99,7 +102,8 @@ private: int CaptureStop(); int UnInit(); - int Convert (VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch); + int Convert (VideoFrame *dest, unsigned char *ptrsrc, int srcsize, + uint32_t pixelformat, int srcw, int srch); int OpenInit (); int Close (); @@ -113,9 +117,11 @@ public: void Thread(); - int Start(std::string dev, gboolean (*callback_func)(gpointer data)); // will start a new thread + int Start(std::string dev, int w, int h, std::string format, gboolean (*callback_func)(gpointer data)); int Stop(); // stop video processing and stop the pthread + void GetVideoInfo(int *w, int *h, std::string *format); + int GetDeviceList(std::list *list); int GetCtrlList(std::list *list); int GetCtrlMinMaxValue(std::string name, int *min, int *max, int *value); diff --git a/videodev.cc b/videodev.cc index f1597c3..b9228f1 100644 --- a/videodev.cc +++ b/videodev.cc @@ -83,6 +83,11 @@ VideoDev::VideoDev() { inbuffer[i].size = 0; inbuffer[i].data = NULL; } + conf_device = ""; + conf_devicename = ""; + conf_format = ""; + conf_height = -1; + conf_width = -1; vf.data = NULL; vf.h = 0; vf.w = 0; @@ -205,11 +210,14 @@ int VideoDev::SetCtrlValue(std::string name, int value) { // start the video, start capturing, start thread // after return of this function we can call the Ctrl thread // -int VideoDev::Start(std::string dev, gboolean (*callback_func)(gpointer data)) { +int VideoDev::Start(std::string dev, int w, int h, std::string format, gboolean (*callback_func)(gpointer data)) { if (running != 0 || thread != NULL) return VDEV_STATUS_ERROR; running = 1; conf_device = dev; + conf_format = format; + conf_width = w; + conf_height = h; callback = callback_func; // @@ -246,6 +254,13 @@ int VideoDev::Stop() { }; +void VideoDev::GetVideoInfo(int *w, int *h, std::string *format) { + *format = conf_format; + *w = conf_width; + *h = conf_height; +} + + // // try to read a video every 0.05ms (25hz) // running = 2 ... thread is running normaly @@ -407,6 +422,7 @@ int VideoDev::OpenInit() { int i; struct v4l2_capability vcap; VideoDevCtrl vctl; + char txt[32]; printf ("%s:%d %s Device: '%s'\n", __FILE__, __LINE__, __FUNCTION__, conf_device.c_str()); if (fd != -1) return VDEV_STATUS_ERROR; @@ -465,14 +481,30 @@ int VideoDev::OpenInit() { } } + // + // prepare resolution and pixelformat CLEAR (fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = 1920; - fmt.fmt.pix.height = 1080; -// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - fmt.fmt.pix.field = V4L2_FIELD_NONE; + if (conf_height != -1 && conf_width != -1) { // resolution + fmt.fmt.pix.width = conf_width; + fmt.fmt.pix.height = conf_height; + } + else { + fmt.fmt.pix.width = 1920; + 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; + } + fmt.fmt.pix.field = V4L2_FIELD_NONE; if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) { fprintf (stderr, "VIDIOC_S_FMT : %s", strerror (errno)); return VDEV_STATUS_ERROR; @@ -486,6 +518,13 @@ int VideoDev::OpenInit() { min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; if (fmt.fmt.pix.sizeimage < min) fmt.fmt.pix.sizeimage = min; + conf_width = fmt.fmt.pix.width; + conf_height = fmt.fmt.pix.height; + snprintf (txt, 32, "%c%c%c%c", ((char*)&fmt.fmt.pix.pixelformat)[0], + ((char*)&fmt.fmt.pix.pixelformat)[1], + ((char*)&fmt.fmt.pix.pixelformat)[2], + ((char*)&fmt.fmt.pix.pixelformat)[3]); + conf_format = txt; PrintFmt (&fmt); // init buffers