Compare commits

..

1 Commits

7
.gitignore vendored

@ -6,11 +6,6 @@ config.h
*.oo
simpleskycam
*~
*.bkp
U2SM200C-AST_Cfg_A.bin
U2SM200C-AST_Cfg_SAVE.bin
gmon.out
*.log
*.exe
*.bz2
Makefile.config

@ -1,34 +1,3 @@
2023-02-16:
- fixed positioncontrol. made some misstakes in calculating the angle
of the axsis vectors.
- changed: convert function is now only presend in videodef class.
2023-02-07:
- position control is now working. has still some glitches
with negative Kp, Ki and Kd values. But in general it is working.
- fixed: set mode to POSCTL_MODE_OFF if an output error occured.
2022-12-07:
- dump files will continussly loop
- fixed: dumpfile is not setting the frame size to the videodev.conf_height
and width variable
2022-12-06:
- saving and restoring windows position and size on exit and startup
2022-12-04:
- RAW8 format support for SVB camera, also fixed RGB24 format
- many bug fixes for RGB conversions
- DNG and SER file format fixes
2022-11-29:
- Crash on invalid dumpfile solved.
- closing and reopening of windows is working now.
- RGB16 debayer mode simple/bilinear can now be choosen in the settings menu
2022-11-26:
- adding histogram
2022-11-10:
- support for DNG file export

@ -1,76 +1,26 @@
.SILENT: help
#
# all configuration is set in the Makefile.config file.
#
VERSION = 0.0.1
APP = simpleskycam
-include Makefile.config
-include Makefile.rules
OBJECTS := $(OBJECTS) gui.oo main.oo error.oo debug.oo \
OBJECTS := $(OBJECTS) gui.oo main.oo \
video.oo videoframe.oo \
videodev.oo videodev-dumpfile.oo videodev-simulation.oo \
convert.oo output.oo detect.oo histogram.oo pid.oo \
posctl.oo json.oo configuration.oo debayer.oo
videodev.oo videodev-v4l2.oo videodev-dumpfile.oo \
convert.oo filter.oo detect.oo json.oo configuration.oo ser.oo
DISTNAME=simpleskycam-$(VERSION)
#
# add configuration for debug_angles
#
ifeq ($(DEBUG_ANGLES),1)
CPPFLAGS := $(CPPFLAGS)
OBJECTS := $(OBJECTS) debug-angles.oo
endif
#
#
# compile and use DNG files
#
ifeq ($(USE_DNG),1)
LDFLAGS := $(LDFLAGS) -ltiff
OBJECTS := $(OBJECTS) dng.oo
endif
#
#
# compile and use DNG files
#
ifeq ($(USE_SER),1)
OBJECTS := $(OBJECTS) ser.oo
endif
#
ifeq ($(TARGET),)
noconfig: defaultconfig help
noconfig: configlinux help
endif
all: Makefile.rules $(TARGET)
defaultconfig:
ifeq ($(MAKEFILE_CONFIG),)
echo "MAKEFILE_CONFIG = 1" > Makefile.config
echo "" >> Makefile.config
echo "USE_SVBONY = 1" >> Makefile.config
echo "USE_DNG = 1" >> Makefile.config
echo "USE_SER = 1" >> Makefile.config
echo "" >> Makefile.config
echo "DEBUG_ANGLES = 0" >> Makefile.config
echo "DEBUG_POSCTL = 0" >> Makefile.config
endif
all: Makefile.rules $(TARGET)
help:
echo "set up configuration"
echo " make configlinux to generate the linix build"
echo " make configcross to generate the windows build using cross tools."
echo " make configwindows to generate the windows build using msys2."
echo " "
echo " make checkdumpfile to create a test tool for videodumps."
checkdumpfile: checkdumpfile.cc
@ -93,76 +43,20 @@ config: Makefile.rules
echo "#define _CONFIG_H_" >> config.h
echo "" >> config.h
echo "#define VERSION \"$(VERSION)\"" >> config.h
ifeq ($(USE_SVBONY),1)
echo "#define USE_SVBONY" >> config.h
endif
ifeq ($(USE_SER),1)
echo "#define USE_SER" >> config.h
endif
ifeq ($(USE_DNG),1)
echo "#define USE_DNG" >> config.h
endif
ifeq ($(USE_V4L2),1)
echo "#define USE_V4L2" >> config.h
endif
ifeq ($(USE_VFW),1)
echo "#define USE_VFW" >> config.h
endif
echo "" >> config.h
ifeq ($(DEBUG_ANGLES),1)
echo "#define DEBUG_ANGLES" >> config.h
endif
ifeq ($(DEBUG_POSCTL),1)
echo "#define DEBUG_POSCTL" >> config.h
endif
echo "#define USE_SVBONY" >> config.h
echo "" >> config.h
echo "#endif" >> config.h
buildwindows: clean
make configcross
make $(TARGET) -j 9
mkdir SimpleSkyCam-$(VERSION)
cp *.exe SimpleSkyCam-$(VERSION)/
cp simpleskycam.ui SimpleSkyCam-$(VERSION)/
cp README.md SimpleSkyCam-$(VERSION)/
cp ChangeLog SimpleSkyCam-$(VERSION)/
cp LICENSE SimpleSkyCam-$(VERSION)/
./copydlls.sh
./copydlls.sh
./copyshare.sh
mv *.dll SimpleSkyCam-$(VERSION)/
mv share SimpleSkyCam-$(VERSION)/
cp /usr/lib/gcc/x86_64-w64-mingw32/12-win32/*.dll SimpleSkyCam-$(VERSION)/
cp /opt/W64-cross-compile/lib/libtiff4.dll SimpleSkyCam-$(VERSION)/libtiff-6.dll
cp /opt/W64-cross-compile/lib/SVBCamera* SimpleSkyCam-$(VERSION)/
packwindows:
rm -rf SimpleSkyCam-$(VERSION) *.bz2
mkdir SimpleSkyCam-$(VERSION)
cp *.exe SimpleSkyCam-$(VERSION)/
cp simpleskycam.ui SimpleSkyCam-$(VERSION)/
cp README.md SimpleSkyCam-$(VERSION)/
cp ChangeLog SimpleSkyCam-$(VERSION)/
cp LICENSE SimpleSkyCam-$(VERSION)/
for i in `ldd simpleskycam.exe |grep -vi "/c/windows" | cut -d" " -f3`; do cp $$i SimpleSkyCam-$(VERSION)/; done
tar cvohif SimpleSkyCam-0.0.1-win64.tar.bz2 SimpleSkyCam-0.0.1/
$(TARGET): $(OBJECTS)
$(CPP) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LIBS)
.SUFFIXES:
.SUFFIXES: .c .cc .C .cpp .oo
-include $(DEPENDFILE)
.cc.oo : $(INCLUDES)
$(CPP) -o $@ -c $(CPPFLAGS) $<
cleanall: clean
rm -rf Makefile.config
clean:
rm -f *.o *.oo *.c~ *.h~ *.cc~ *.ui~ $(APP) Makefile~
rm -rf config.h
@ -172,9 +66,8 @@ clean:
rm -rf checkdumpfile
rm -rf U2SM200C-AST_Cfg_A.bin
rm -rf U2SM200C-AST_Cfg_SAVE.bin
rm -rf SimpleSkyCam-$(VERSION)
dist: cleanall
dist: clean
rm -rf $(DISTNAME)
mkdir $(DISTNAME)
cp Makefile* $(DISTNAME)
@ -187,6 +80,11 @@ dist: cleanall
tar cvzf $(DISTNAME).tgz $(DISTNAME)
rm -rf $(DISTNAME)
dep:
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
-include $(DEPENDFILE)
.PHONY: all
.PHONY: count
.PHONY: clean

@ -1,32 +0,0 @@
include Makefile.config
USE_VFW = 1
TARGET = $(APP).exe
CROSSENV = /opt/W64-cross-compile/
CPP = /usr/bin/x86_64-w64-mingw32-g++
CPPFLAGS = -ggdb -Wall -O0 `PKG_CONFIG_PATH=$(CROSSENV)/lib/pkgconfig pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -DBUILD_WINDOWS=1 -Wdeprecated -D_POSIX_C_SOURCE=200112L
INCLUDES =
LDFLAGS = -lws2_32 -ljpeg
LIBS = `PKG_CONFIG_PATH=$(CROSSENV)/lib/pkgconfig pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib -mwindows
OBJECTS := $(OBJECTS) windows.oo
#
# add makefile configuration for svbony cams
#
ifeq ($(USE_SVBONY),1)
CPPFLAGS := $(CPPFLAGS)
LDFLAGS := $(LDFLAGS) -lSVBCameraSDK
OBJECTS := $(OBJECTS) videodev-svbcam.oo
endif
#
#
# add makefile configuration for vfw cams
#
ifeq ($(USE_VFW),1)
OBJECTS := $(OBJECTS) videodev-vfw.oo
LDFLAGS := $(LDFLAGS) -lvfw32
endif
#

@ -1,34 +1,20 @@
include Makefile.config
USE_V4L2 = 1
TARGET = $(APP)
CPP = c++
CPPFLAGS = -std=c++11 -pg -ggdb -Wall -Werror -O0 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -I/usr/include -DBUILD_LINUX=1
CPPFLAGS = -std=c++11 -ggdb -Wall -Werror -O0 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -I/usr/include -DBUILD_LINUX=1
INCLUDES =
LDFLAGS =
LIBS = `pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib -ljpeg -pg
LIBS = `pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib -ljpeg
OBJECTS =
#
# add makefile configuration for svbony cams
# Uncomment to enable support for SVBONY Cammeras.
#
ifeq ($(USE_SVBONY),1)
CPPFLAGS := $(CPPFLAGS) -I/usr/local/include
LDFLAGS := $(LDFLAGS) -lSVBCameraSDK -L/usr/local/lib `pkg-config --libs libusb-1.0`
LDFLAGS := $(LDFLAGS) -lSVBCameraSDK -L/usr/local/lib
OBJECTS := $(OBJECTS) videodev-svbcam.oo
endif
#
#
# add makefile configuration for svbony cams
#
ifeq ($(USE_V4L2),1)
OBJECTS := $(OBJECTS) videodev-v4l2.oo
endif
#
#

@ -1,32 +0,0 @@
include Makefile.config
USE_VFW = 1
TARGET = $(APP).exe
CPP = g++
CPPFLAGS = -ggdb -Wall -O0 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -DBUILD_WINDOWS=1 -Wdeprecated -D_POSIX_C_SOURCE=200112L
#CPPFLAGS = -Wall -O3 `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` -Wl,--export-dynamic -DBUILD_WINDOWS=1 -Wdeprecated -D_POSIX_C_SOURCE=200112L
INCLUDES =
LDFLAGS = -lws2_32 -ljpeg
LIBS = `pkg-config --libs gtk+-3.0 gmodule-export-2.0` -L/usr/lib -mwindows
OBJECTS := $(OBJECTS) windows.oo
#
# add makefile configuration for svbony cams
#
ifeq ($(USE_SVBONY),1)
CPPFLAGS := $(CPPFLAGS) -I/usr/local/include
LDFLAGS := $(LDFLAGS) -lSVBCameraSDK -L/usr/local/lib
OBJECTS := $(OBJECTS) videodev-svbcam.oo
endif
#
#
# add makefile configuration for vfw cams
#
ifeq ($(USE_VFW),1)
OBJECTS := $(OBJECTS) videodev-vfw.oo
LDFLAGS := $(LDFLAGS) -lvfw32
endif
#

@ -1,20 +1,6 @@
# SimpleSkyCam
Simple application to create images using a teleskope and a cameramodul.
We have basic support for follow any object seen by the cammera.
One SER sample Outputfile can be found in the SampleOutput folder.
# Command Line Options
-d <debugpath> destination for video debugging path
-dd disable debugging path
-rd <debugpath> read video from dumpfile folder
If the video debugging path is set, all videodata received by the video adapter will be written to disc. Be carefull with this option. Some RAW formats can take serval GB within seconds.
# Screenshots
![Screenshot](https://steffen.gulpe.de/gitea/steffen/SimpleSkyCam/raw/branch/master/SampleOutput/screenshot-2024_04_13.png)
Screenshots and other stuff can be found at: <https://steffen.gulpe.de/progs/SimpleSkyCam>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 KiB

@ -2,19 +2,12 @@
* tool to check and gain some basic information about videodum-files
*/
/* enable files > 2GB on 32 bit systems */
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef BUILD_WINDOWS
#else
#include <arpa/inet.h>
#endif
#include <string>
@ -27,142 +20,25 @@ std::string convert_from_pixelformat (uint32_t fmt) {
int fixfile(char *src, char *dest) {
int fd, fd2;
int main(int argc, char **argv) {
int fd;
int cnt = 0;
char *inbuf = NULL;
int inbufsize = 0;
int frmcnt = 0;
uint32_t i;
uint32_t size, size2;
printf ("fix file:'%s' output file:'%s'\n", src, dest);
if ((fd = open (src, O_RDONLY)) < 0) {
printf ("could not open input file: %s\n", strerror(errno));
return -1;
}
if ((fd2 = open (dest, O_WRONLY | O_CREAT | O_TRUNC), S_IRUSR | S_IWUSR) < 0) {
printf ("could not open output file: %s\n", strerror(errno));
close (fd);
return -1;
}
//
// read header w, h, pixfmt
if (read (fd, &i, 4) != 4) {
printf ("could not read all bytes.\n");
close (fd);
return -1;
}
if (write (fd2, &i, 4) != 4) {
printf ("could not write all bytes.\n");
close (fd2);
close (fd);
return -1;
}
printf (" Width: %d\n", ntohl(i));
if (read (fd, &i, 4) != 4) {
printf ("could not read all bytes.\n");
close (fd);
return -1;
}
if (write (fd2, &i, 4) != 4) {
printf ("could not write all bytes.\n");
close (fd2);
close (fd);
return -1;
}
printf (" Height: %d\n", ntohl(i));
uint32_t size;
if (read (fd, &i, 4) != 4) {
printf ("could not read all bytes.\n");
close (fd);
if (argc != 2) {
printf ("please give a file name as parameter.\n");
printf ("checkdumpfile FILE\n");
printf ("\n");
return -1;
}
if (write (fd2, &i, 4) != 4) {
printf ("could not write all bytes.\n");
close (fd2);
close (fd);
return -1;
}
printf(" Pixfmt: %s\n", convert_from_pixelformat(ntohl(i)).c_str());
//
// read frame
while (read (fd, &size, 4) == 4) {
size = ntohl(size);
size2 = htonl(size / 2);
if (write (fd2, &size2, 4) != 4) {
printf ("could not write framesize of frame %d.\n", frmcnt);
close (fd2);
close (fd);
return -1;
}
if (read (fd, &i, 4) != 4) {
printf ("could not read all bytes.\n");
close (fd);
return -1;
}
if (write (fd2, &i, 4) != 4) {
printf ("could not write timestamp of frame %d.\n", frmcnt);
close (fd2);
close (fd);
return -1;
}
i = ntohl(i);
if (inbuf == NULL){
inbuf = (char*) malloc (size);
inbufsize = size;
}
else if (inbufsize < size) {
inbuf = (char*)realloc(inbuf, size);
inbufsize = size;
}
if (inbuf == NULL) {
printf ("Error could not allocate enough memory\n");
close (fd);
return -1;
}
if (read (fd, inbuf, size) != size) {
printf ("could not read to next frame.\n");
close (fd);
return -1;
}
if (write (fd2, inbuf, size/2) != size/2) {
printf ("could not write frame %d.\n", frmcnt);
close (fd2);
close (fd);
return -1;
}
printf ("Frame: %-9d Timestamp:%-9d Size:%d\n", cnt++, i, size);
}
close (fd);
close (fd2);
return 0;
}
printf ("reading file :'%s'\n", argv[1]);
int checkfile(char *src) {
uint32_t i;
uint32_t size;
int fd;
int cnt = 0;
char *inbuf = NULL;
int inbufsize = 0;
printf ("reading file :'%s'\n", src);
if ((fd = open (src, O_RDONLY)) < 0) {
if ((fd = open (argv[1], O_RDONLY)) < 0) {
printf ("could not open file: %s\n", strerror(errno));
}
@ -228,22 +104,5 @@ int checkfile(char *src) {
close (fd);
return 0;
};
int main(int argc, char **argv) {
if (argc == 2) {
checkfile(argv[1]);
}
else if (argc == 3) {
fixfile(argv[1], argv[2]);
}
else {
printf ("please give a file name as parameter.\n");
printf ("checkdumpfile FILE to check file\n");
printf ("checkdumpfile SRCFILE DESTFILE to fix file\n");
printf ("\n");
}
return 0;
}

@ -2,21 +2,17 @@
#include "configuration.h"
#include "video.h"
#include "gui.h"
#include "detect.h"
#include <stdlib.h>
#include <string>
// extern VideoDev *videodev;
extern GtkBuilder *_builder_; // work around for threads
extern PosCtl posctl;
Configuration::Configuration() {
debugpath = NULL;
readdumppath = NULL;
destpath = "./";
show_debugwin = 0;
};
@ -68,9 +64,6 @@ void Configuration::SaveConfig(std::string filename) {
GtkWidget *cb;
GtkWidget *cbe;
std::string s = setlocale(LC_ALL, NULL);
setlocale (LC_ALL, "C");
//
// Add resolution, format and video device to config json element
cb = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videores"));
@ -83,37 +76,6 @@ void Configuration::SaveConfig(std::string filename) {
cbe = gtk_bin_get_child(GTK_BIN(cb));
jp.AddObject("device", (string) gtk_entry_get_text(GTK_ENTRY(cbe)));
//
// save posctl settings
double amin, amax, akp, aki, akd;
JSONParse jaxis;
posctl.LockMutex();
for (i = 0; i < 2; i++) {
posctl.GetAxisParam(i, &amin, &amax, &akp, &aki, &akd);
jaxis.Clear();
jaxis.AddObject("min", amin);
jaxis.AddObject("max", amax);
jaxis.AddObject("kp", akp);
jaxis.AddObject("ki", aki);
jaxis.AddObject("kd", akd);
printf ("%s:%d save config axis %d Out Range: %f - %f kP:%g kI:%g kD:%g\n",
__FILE__, __LINE__, i, amin, amax, akp, aki, akd);
jp.AddObject("posctl_axis" + to_string(i), jaxis);
}
jp.AddObject("posctl_filter", posctl.GetFilter());
jp.AddObject("posctl_device", posctl.GetDevice());
posctl.UnLockMutex();
//
// histogram settings and debayer mode
jp.AddObject("histogram_log", histogram_log);
jp.AddObject("debayer_mode", debayer_mode);
//
// save destination path
jp.AddObject("destination_path", destpath);
//
// save button config
for (i = 0; i < BTN_PRESET_MAX; i++) {
@ -139,57 +101,12 @@ void Configuration::SaveConfig(std::string filename) {
jp.AddObject(je);
}
//
// save windows position
printf ("%s:%d Xwayland is not able to retrieve the current position.\n", __FILE__, __LINE__);
for (i = 0; i < 6; i++) {
int x, y, w, h, show;
string name;
switch (i) {
case 0:
name = "window-main";
break;
case 1:
name = "window-input";
break;
case 2:
name = "window-output";
break;
case 3:
name = "window-detect";
break;
case 4:
name = "window-histogram";
break;
case 5:
name = "window-posctl";
break;
}
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), name.c_str()));
if (wnd) {
g_object_get (wnd, "visible", &show, NULL);
gtk_widget_show (wnd);
gtk_window_get_position (GTK_WINDOW(wnd), &x, &y);
gtk_window_get_size (GTK_WINDOW(wnd), &w, &h);
jp.AddObject(name+"_x", x);
jp.AddObject(name+"_y", y);
jp.AddObject(name+"_w", w);
jp.AddObject(name+"_h", h);
jp.AddObject(name+"_show", show);
}
}
//
// save config
if (jp.SaveToFile(filename)) {
printf ("%s:%d %s could not save to file [%s] Error: %s\n", __FILE__, __LINE__, __FUNCTION__,
filename.c_str(), strerror(errno));
}
setlocale (LC_ALL, s.c_str());
};
@ -199,9 +116,6 @@ void Configuration::LoadConfig(std::string filename) {
int i;
JSONElement je;
std::string s = setlocale(LC_ALL, NULL);
setlocale (LC_ALL, "C");
if (jp.LoadFromFile(filename)) {
printf ("%s:%d %s could not load from file [%s] Error: %s\n", __FILE__, __LINE__, __FUNCTION__,
filename.c_str(), strerror(errno));
@ -223,42 +137,6 @@ void Configuration::LoadConfig(std::string filename) {
gtk_entry_set_text(GTK_ENTRY(cbdevice), vstr.c_str());
}
//
// load posctl
double amin, amax, akp, aki, akd, f;
JSONParse jaxis;
posctl.LockMutex();
for (i = 0; i < 2; i++) {
if (jp.GetObjectJson("posctl_axis"+to_string(i), &jaxis)) {
jaxis.GetValueDouble("min", &amin);
jaxis.GetValueDouble("max", &amax);
jaxis.GetValueDouble("kp", &akp);
jaxis.GetValueDouble("ki", &aki);
jaxis.GetValueDouble("kd", &akd);
}
printf ("%s:%d load config axis %d Out Range: %f - %f kP:%f kI:%f kD:%f\n",
__FILE__, __LINE__, i, amin, amax, akp, aki, akd);
posctl.SetAxisParam(i, amin, amax, akp, aki, akd);
}
if (jp.GetValue("posctl_device", &vstr))
posctl.SetDevice(vstr);
if (jp.GetValueDouble("posctl_filter", &f))
posctl.SetFilter(f);
jp.AddObject("posctl_filter", posctl.GetFilter());
posctl.UnLockMutex();
jp.GetValueInt("histogram_log", &i);
SetHistogramLog(i);
jp.GetValueInt("debayer_mode", &i);
SetDebayerMode(i);
if (jp.GetValue("destination_path", &destpath)) {
GtkWidget *entry = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "input_entry_destpath"));
gtk_entry_set_text(GTK_ENTRY(entry), destpath.c_str());
}
//
// start streaming if a device was selected.
@ -295,79 +173,7 @@ void Configuration::LoadConfig(std::string filename) {
ctrli++;
}
}
//
// check is the windows are inside the screen
// not really needed since gnome seem to take care about the windows positions
// and placement quite well.
GdkDisplay *dsp = gdk_display_get_default();
int n_monitor = -1;
if (dsp) {
n_monitor = gdk_display_get_n_monitors (dsp);
}
if (dsp && n_monitor > 0) {
GdkMonitor *g_monitor;
GdkRectangle geometry;
for (i = 0; i < n_monitor; i++) {
g_monitor = gdk_display_get_monitor(dsp, i);
if (g_monitor) {
gdk_monitor_get_geometry(g_monitor, &geometry);
printf ("%s:%d Monitor %d Pos:%d,%d Size:%d x %d\n", __FILE__, __LINE__, i,
geometry.x, geometry.y, geometry.width, geometry.height);
}
}
}
//
// load windows position
for (i = 0; i < 6; i++) {
int x, y, w, h, show;
string name;
switch (i) {
case 0:
name = "window-main";
break;
case 1:
name = "window-input";
break;
case 2:
name = "window-output";
break;
case 3:
name = "window-detect";
break;
case 4:
name = "window-histogram";
break;
case 5:
name = "window-posctl";
break;
}
if (jp.GetValueInt(name+"_x", &x) && jp.GetValueInt(name+"_y", &y) &&
jp.GetValueInt(name+"_w", &w) && jp.GetValueInt(name+"_h", &h) &&
jp.GetValueInt(name+"_show", &show)) {
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), name.c_str()));
if (wnd) {
printf ("%s:%d window '%s' set geometry %d,%d : %d x %d\n", __FILE__, __LINE__, name.c_str(), x, y, w, h);
gtk_window_move (GTK_WINDOW(wnd), x, y);
gtk_window_resize (GTK_WINDOW(wnd), w, h);
gtk_widget_show(wnd);
// g_object_set (wnd, "visible", &show, NULL);
}
}
}
}
setlocale (LC_ALL, s.c_str());
// we need to update the gui so floating numbers will displayed with the correct
// language setting.
gdk_threads_add_idle(cb_thread_posctl, NULL);
};
@ -387,18 +193,3 @@ list<VideoDevCtrl> Configuration::GetPresetButton (int btn) {
};
void Configuration::SetHistogramLog(int trueorfalse) {
GtkWidget *cfg_logh = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "menu-settings-loghistogram"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(cfg_logh), (trueorfalse == 1));
histogram_log = trueorfalse;
};
void Configuration::SetDebayerMode(int trueorfalse) {
GtkWidget *cfg_debayer = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "menu-settings-bilinearrgb"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(cfg_debayer), (trueorfalse == 1));
debayer_mode = trueorfalse;
};

@ -3,7 +3,7 @@
#define _CONFIGURATION_H_
/*
* all configuration data will loaded and saved from here.
* all read and saved data will have to be in a
*/
#include <string>
@ -17,17 +17,12 @@
class Configuration {
private:
int histogram_log = 1; // logarithmic or linear scale
int calibration_showdata = 0; // needed for debugging calibration
std::string destpath; // destination path
JSONParse config;
std::string GetDefaultFileName();
list<VideoDevCtrl> presetbtn[BTN_PRESET_MAX];
public:
char *debugpath;
char *readdumppath;
int debayer_mode = 0; // 0..simple mode, 1..bilinear
int show_debugwin = 0;
Configuration();
~Configuration();
@ -38,17 +33,6 @@ public:
void LoadConfig(std::string filename);
void SaveConfig(std::string filename);
void SetDebayerMode(int trueorfalse);
void SetDestPath (std::string dest) { destpath = dest; };
std::string GetDestPath() { return destpath; };
void SetHistogramLog(int trueorfalse);
int GetHistogramLog() { return histogram_log; };
void SetCalibrationShowData(int enabled) { calibration_showdata = enabled; };
int GetCalibrationShowData() { return calibration_showdata; };
void SetPresetButton (int btn, list<VideoDevCtrl> *parameters);
list<VideoDevCtrl> GetPresetButton (int btn);
};

@ -4,18 +4,13 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef BUILD_WINDOWS
#include "windows.h"
#else
#include <arpa/inet.h>
#endif
#include "simpleskycam.h"
#include "convert.h"
#include "gui.h"
#include "video.h"
#include "configuration.h"
#include "debayer.h"
uint32_t convert_pixelformats [] = {
V4L2_PIX_FMT_MJPEG,
@ -25,8 +20,6 @@ uint32_t convert_pixelformats [] = {
V4L2_PIX_FMT_RGB24,
V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_UYVY,
V4L2_PIX_FMT_SGRBG16,
V4L2_PIX_FMT_SGRBG8,
0
};
@ -54,6 +47,8 @@ struct timeval convert_debug_tv;
/*
* will be called on first frame
*/
#define LEN_FILENAME 64
#define LEN_FULLFILENAME 256
int convert_debug_open(uint32_t pixelformat, int srcw, int srch) {
time_t t = time(NULL);
struct tm *tmptr;
@ -67,7 +62,7 @@ int convert_debug_open(uint32_t pixelformat, int srcw, int srch) {
//
// check to create file, if not possible try creating the directory and create the file again
tmptr = localtime(&t);
strftime(fname, LEN_FILENAME, "%Y%m%d-%H%M%S", tmptr);
strftime(fname, LEN_FILENAME, "%F-%R", tmptr);
snprintf (fullfname, LEN_FULLFILENAME, "%s/%s.videodump", config.debugpath, fname);
if ((convert_debug_fd = creat (fullfname, 0666)) == -1) {
@ -75,15 +70,11 @@ int convert_debug_open(uint32_t pixelformat, int srcw, int srch) {
printf ("%s:%d try to create folder\n", __FILE__, __LINE__);
// create folder
// FIXME: how to do thin on windows
#ifdef BUILD_WINDOWS
if ((mkdir (config.debugpath)) == -1) {
#else
if ((mkdir (config.debugpath, 0777)) == -1) {
#endif
printf ("%s:%d could not create debug folder.\n", __FILE__, __LINE__);
return -1;
}
if ((convert_debug_fd = creat (fullfname, 0666)) == -1) {
printf ("%s:%d could again not create file '%s'. Error:%s\n", __FILE__, __LINE__, fullfname, strerror(errno));
return -1;
@ -142,6 +133,9 @@ void convert_debug_dumpframe(unsigned char *ptrsrc, int srcsize, uint32_t pixelf
* close file and reset all data
*/
void convert_debug_close() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (convert_debug_fd != -1) {
close (convert_debug_fd);
convert_debug_fd = -1;
@ -181,7 +175,7 @@ inline unsigned char clamp (double x) {
inline void convert2rgb (unsigned char Y1, unsigned char Cb, unsigned char Cr,
unsigned char *ER, unsigned char *EB, unsigned char *EG) {
int y1, pb, pr;
register int y1, pb, pr;
y1 = Y1 - 16;
pb = Cb - 128;
@ -212,7 +206,6 @@ int ConvertStop(ConvertData *cdata, uint32_t pixelformat) {
return VDEV_STATUS_OK;
};
/*
* converts the video from input type to RGB24 type - 24Bit
*/
@ -233,36 +226,26 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
if (dest == NULL || ptrsrc == NULL)
return VDEV_STATUS_ERROR;
if (dest->data != NULL && dest->w != srcw && dest->h != srch) {
free (dest->data);
dest->data = NULL;
}
if (dest->data == NULL) {
dest->w = srcw;
dest->h = srch;
dest->size = srcw * srch * 3;
dest->data = (unsigned char*) malloc (dest->size);
}
ptrdst = dest->data;
switch (pixelformat) {
case (V4L2_PIX_FMT_RGB32):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
ptrsrc++;
r = *(ptrsrc++);
g = *(ptrsrc++);
b = *(ptrsrc++);
ptrsrc++;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
@ -275,21 +258,24 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
break;
case (V4L2_PIX_FMT_BGR32):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
ptrsrc++;
b = *(ptrsrc++);
g = *(ptrsrc++);
r = *(ptrsrc++);
ptrsrc++;
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
@ -301,6 +287,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
}
break;
case (V4L2_PIX_FMT_RGB24):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
@ -312,9 +301,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
@ -327,6 +316,10 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
break;
case (V4L2_PIX_FMT_BGR24):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
@ -338,9 +331,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
@ -352,21 +345,11 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
}
break;
case (V4L2_PIX_FMT_SGRBG16):
if (config.debayer_mode == 0)
debayer_grbg16_simple ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
else
debayer_grbg16_bilinear ((uint16_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
break;
case (V4L2_PIX_FMT_SGRBG8):
if (config.debayer_mode == 0)
debayer_grbg8_simple ((uint8_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
else
debayer_grbg8_bilinear ((uint8_t *)ptrsrc, srcw, srch, ptrdst, dest->w, dest->h);
break;
case (V4L2_PIX_FMT_UYVY):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
/* read the pixel */
@ -387,9 +370,9 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
/* only paint the image if the source is within the destination */
if (xd < dest->w) {
/* set the pixel */
*(ptrdst++) = r;
*(ptrdst++) = g;
*(ptrdst++) = b;
*(ptrdst++) = g;
*(ptrdst++) = r;
xd++;
}
}
@ -402,6 +385,10 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
break;
case (V4L2_PIX_FMT_YUYV):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
if (yd < dest->h) {
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
@ -438,6 +425,10 @@ int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int sr
break;
case (V4L2_PIX_FMT_MJPEG):
dest->SetSize(srcw, srch);
dest->SetPixelSize(3); // 8 bits per pixel
ptrdst = (unsigned char *)dest->GetData();
cdata->cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpg_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
@ -459,8 +450,7 @@ 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);
errorexit ((char*)"%s:%d Error no default possible, need to finish\n", __FILE__, __LINE__);
break;
}
@ -487,72 +477,3 @@ uint32_t convert_to_pixelformat(std::string s) {
};
/*
* copy part of an raw image
* destination must be pointer in case we need to align the size of the destination image.
* this function will also realloc needed memory if needed. (only if: givin size < needed size)
*
* crop image to event set of dimensions
*/
int PixCopy(unsigned char *srcdata, uint32_t srcpixfmt, int srcw, int srch,
unsigned char **dstdataptr, int *dstsize, int *dstw, int *dsth,
int regionx, int regiony, int regionw, int regionh) {
if (srcpixfmt == 0 || srcpixfmt == V4L2_PIX_FMT_MJPEG) return 0;
if (srcdata == NULL || dstdataptr == NULL) return 0;
// crop size to an even number
(*dsth) = regionw & ~1;
(*dstw) = regionh & ~1;
int bytesperpixel = 3;
int dsize = 0;
switch (srcpixfmt) {
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:
return 0;
}
//
// calculate image size and allocate memory if needed
dsize = (*dsth) * (*dstw) * bytesperpixel;
if ((*dstsize) < dsize || (*dstdataptr) == NULL) {
*dstdataptr = (unsigned char*) realloc (*dstdataptr, dsize);
if (*dstdataptr == NULL) {
errorexit((char*)"%s:%d could not realloc memory. dsize:%d error:%s\n", __FILE__, __LINE__, dsize, strerror(errno));
}
*dstsize = dsize;
printf ("%s:%d reallocate memory for destination raw image\n", __FILE__, __LINE__);
}
unsigned char *dptr, *sptr;
int y, dy, x;
// debug_drawraw(srcdata, srcpixfmt, srcw, srch);
for (y = regiony & (~1), dy = 0; dy < *dsth && y < srch; y++, dy++) {
x = regionx & (~1);
dptr = (*dstdataptr) + bytesperpixel * (dy * *dstw);
sptr = (srcdata) + bytesperpixel * ( y * srcw + x);
memcpy (dptr, sptr, *dstw * bytesperpixel);
}
if (config.show_debugwin) debug_drawraw(*dstdataptr, srcpixfmt, *dstw, *dsth);
return 1;
}

@ -21,10 +21,6 @@ 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);
int PixCopy(unsigned char *srcdata, uint32_t srcpixfmt, int srcw, int srch,
unsigned char **dstdataptr, int *dstsize, int *dstw, int *dsth,
int regionx, int regiony, int regionw, int regionh);
extern uint32_t convert_pixelformats[];
std::string convert_from_pixelformat (uint32_t fmt);
uint32_t convert_to_pixelformat(std::string s);

@ -1,38 +0,0 @@
#!/bin/bash
CROSS_DEST_DIR=/opt/W64-cross-compile/lib
CROSS_COMPILER_DIR=/usr/x86_64-w64-mingw32/lib
CROSS_GCC_DIR=/usr/lib/gcc/x86_64-w64-mingw32/10-win32
cp -v $CROSS_COMPILER_DIR/zlib1.dll ./
# copy dll dependencys
copy_dependency() {
local I
for I in `strings $1 | grep -i '\.dll$' | grep -e "^lib"`
do
if [ -e ./$I ]
then
echo "File Exist"
elif [ -e $CROSS_COMPILER_DIR/$I ]
then
cp -v $CROSS_COMPILER_DIR/$I ./
copy_dependency $CROSS_COMPILER_DIR/$I
elif [ -e $CROSS_GCC_DIR/$I ]
then
cp -v $CROSS_GCC_DIR/$I ./
copy_dependency $CROSS_GCC_DIR/$I
elif [ -e $CROSS_DEST_DIR/$I ]
then
cp -v $CROSS_DEST_DIR/$I ./
copy_dependency $CROSS_DEST_DIR/$I
fi
done
}
copy_dependency simpleskycam.exe

@ -1,10 +0,0 @@
#!/bin/bash
CROSS_PREFIX=/opt/W64-cross-compile
mkdir share
cp -rf $CROSS_PREFIX/share/glib-2.0 share/glib-2.0
cp -rf $CROSS_PREFIX/share/gtk-2.0 share/gtk-4.0
cp -rf $CROSS_PREFIX/share/gtk-3.0 share/gtk-3.0
cp -rf $CROSS_PREFIX/share/icons share/icons

@ -1,366 +0,0 @@
#include <stdio.h>
#include <stdint.h>
/*
The function converts a 16bit GRBG 2x2 CFA coded image into an 8bit
RGB image by setting the missing RGB values to zero.
*/
void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h) {
// GG RR
// BB GG
uint16_t t;
uint8_t r, g, b;
int ys, yd, xs, xd;
for (ys = 0, yd = 0; ys < src_h && yd < dst_h; ys++, yd++) {
for (xs = 0, xd = 0; xs < src_w; xs++) {
/* read the pixel but only the higher 8bit, assuming data is little endian */
t = (*(src++) >> 8) & 0xff;
if (xs & 1) {
if (ys & 1) {
// lower right green pixel
b = 0; g = t; r = 0;
} else {
// upper right red pixel
b = 0; g = 0; r = t;
}
} else {
if (ys & 1) {
// lower left blue pixel
b = t; g = 0; r = 0;
} else {
// upper left green pixel
b = 0; g = t; r = 0;
}
}
/* only paint the image if the source is within the destination */
if (xd < dst_w) {
/* set the pixel */
*(dst++) = r;
*(dst++) = g;
*(dst++) = b;
xd++;
}
}
/* if the source image is too small ignore the other places */
if (xd < dst_w)
dst += 3 * (dst_w - xd);
}
}
// macros to make code better readable
#define CE (*(src))
#define UP (*(src-src_w))
#define DN (*(src+src_w))
#define LE (*(src-1))
#define RI (*(src+1))
#define UPLE (*(src-src_w-1))
#define UPRI (*(src-src_w+1))
#define DNLE (*(src+src_w-1))
#define DNRI (*(src+src_w+1))
#define BITCONV(d) ((d>>8) & 0xff)
#define STORE *(dst++) = BITCONV(r); *(dst++) = BITCONV(g); *(dst++) = BITCONV(b); src++;
#define STORE8 *(dst++) = (r & 0xff); *(dst++) = (g & 0xff); *(dst++) = (b & 0xff); src++;
/*
The function converts a 16bit GRBG 2x2 CFA coded image into an 8bit
RGB image by bilinear interpolation.
*/
void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h) {
// GG RR GG RR
// BB GG BB GG
// GG RR GG RR
// BB GG BB GG
uint32_t r, g, b;
int xs, ys;
// start with upper left pixel (green)
r = RI;
g = CE;
b = DN;
STORE;
// upper first line, starts with RR GG RR ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + DN) / 3;
b = (DNLE + DNRI) / 2;
STORE;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = DN;
STORE;
}
// upper right pixel (red)
r = CE;
g = (DN + LE) / 2;
b = DNLE;
STORE;
// go through the "body" of the image
for (ys = 1; ys < src_h - 1; ys+=2) {
// every second line with BB GG BB GG (start at 2nd line)
// left hand pixel (blue)
r = (UPRI + DNRI) / 2;
g = (UP + DN + RI) / 3;
b = CE;
STORE;
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = (UP + DN) / 2;
g = CE;
b = (LE + RI) / 2;
STORE;
// blue pixel
r = (UPLE + UPRI + DNLE + DNRI) / 4;
g = (LE + RI + UP + DN) / 4;
b = CE;
STORE;
}
// last pixel in line (green)
r = (UP + DN) / 2;
g = CE;
b = LE;
STORE;
// every second line with GG RR GG RR ... (start at 3rd line)
// left hand pixel (green)
r = RI;
g = CE;
b = (UP + DN) / 2;
STORE;
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + UP + DN) / 4;
b = (UPLE + UPRI + DNLE + DNRI) / 4;
STORE;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = (UP + DN) / 2;
STORE;
}
// last pixel in line (red)
r = CE;
g = (UP + DN + LE) / 3;
b = (UPLE + DNLE) / 2;
STORE;
}
// bottom left pixel
r = UPRI;
g = (UP + RI) / 2;
b = CE;
STORE;
// last line starting with GG BB GG ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = UP;
g = CE;
b = (LE + RI) / 2;
STORE;
// blue pixel
r = (UPLE + UPRI) / 2;
g = (LE + UP + RI) / 2;
b = CE;
STORE;
}
// bottom right pixel (green)
r = UP;
g = CE;
b = LE;
STORE;
}
/*
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
RGB image by setting the missing RGB values to zero.
*/
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h) {
// GG RR
// BB GG
uint8_t t;
uint8_t r, g, b;
int ys, yd, xs, xd;
for (ys = 0, yd = 0; ys < src_h && yd < dst_h; ys++, yd++) {
for (xs = 0, xd = 0; xs < src_w; xs++) {
/* read the pixel but only the higher 8bit, assuming data is little endian */
t = *(src++);
if (xs & 1) {
if (ys & 1) {
// lower right green pixel
b = 0; g = t; r = 0;
} else {
// upper right red pixel
b = 0; g = 0; r = t;
}
} else {
if (ys & 1) {
// lower left blue pixel
b = t; g = 0; r = 0;
} else {
// upper left green pixel
b = 0; g = t; r = 0;
}
}
/* only paint the image if the source is within the destination */
if (xd < dst_w) {
/* set the pixel */
*(dst++) = r;
*(dst++) = g;
*(dst++) = b;
xd++;
}
}
/* if the source image is too small ignore the other places */
if (xd < dst_w)
dst += 3 * (dst_w - xd);
}
}
/*
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
RGB image by bilinear interpolation.
*/
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h) {
// GG RR GG RR
// BB GG BB GG
// GG RR GG RR
// BB GG BB GG
uint16_t r, g, b;
int xs, ys;
// start with upper left pixel (green)
r = RI;
g = CE;
b = DN;
STORE8;
// upper first line, starts with RR GG RR ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + DN) / 3;
b = (DNLE + DNRI) / 2;
STORE8;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = DN;
STORE8;
}
// upper right pixel (red)
r = CE;
g = (DN + LE) / 2;
b = DNLE;
STORE8;
// go through the "body" of the image
for (ys = 1; ys < src_h - 1; ys+=2) {
// every second line with BB GG BB GG (start at 2nd line)
// left hand pixel (blue)
r = (UPRI + DNRI) / 2;
g = (UP + DN + RI) / 3;
b = CE;
STORE8;
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = (UP + DN) / 2;
g = CE;
b = (LE + RI) / 2;
STORE8;
// blue pixel
r = (UPLE + UPRI + DNLE + DNRI) / 4;
g = (LE + RI + UP + DN) / 4;
b = CE;
STORE8;
}
// last pixel in line (green)
r = (UP + DN) / 2;
g = CE;
b = LE;
STORE8;
// every second line with GG RR GG RR ... (start at 3rd line)
// left hand pixel (green)
r = RI;
g = CE;
b = (UP + DN) / 2;
STORE8;
for (xs = 1; xs < src_w - 1; xs+=2) {
// red pixel
r = CE;
g = (LE + RI + UP + DN) / 4;
b = (UPLE + UPRI + DNLE + DNRI) / 4;
STORE8;
// green pixel
r = (LE + RI) / 2;
g = CE;
b = (UP + DN) / 2;
STORE8;
}
// last pixel in line (red)
r = CE;
g = (UP + DN + LE) / 3;
b = (UPLE + DNLE) / 2;
STORE8;
}
// bottom left pixel
r = UPRI;
g = (UP + RI) / 2;
b = CE;
STORE8;
// last line starting with GG BB GG ...
for (xs = 1; xs < src_w - 1; xs+=2) {
// green pixel
r = UP;
g = CE;
b = (LE + RI) / 2;
STORE8;
// blue pixel
r = (UPLE + UPRI) / 2;
g = (LE + UP + RI) / 2;
b = CE;
STORE8;
}
// bottom right pixel (green)
r = UP;
g = CE;
b = LE;
STORE8;
}

@ -1,16 +0,0 @@
#ifndef _DEBAYER_H_
#define _DEBAYER_H_
#include <stdint.h>
void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
uint8_t * dst, int dst_w, int dst_h);
#endif

@ -1,119 +0,0 @@
/***************************************************************************************
*
* debug-angles.cc is part of SimpleSkyCam.
*
*****************************************************************************************/
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include <math.h>
#include "debug.h"
#include "gui.h"
position_f_2d dbga_axis;
position_f_2d dbga_pos;
double dbga_angle = NAN;
double dbga_len = NAN;
#define DBGA_W 200
#define DBGA_H 200
void debug_angles_calculate() {
position_f_2d center;
center.x = DBGA_W >> 1;
center.y = DBGA_H >> 1;
dbga_len = dbga_axis.perpendicular(dbga_pos, center);
}
void debug_angles_draw(cairo_t *cr) {
int centerX = DBGA_W >> 1;
int centerY = DBGA_H >> 1;
position_f_2d v;
double d, a;
debug_angles_calculate();
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr, 0, 0);
cairo_line_to(cr, DBGA_W, 0);
cairo_line_to(cr, DBGA_W, DBGA_H);
cairo_line_to(cr, 0, DBGA_H);
cairo_stroke(cr);
if (isnan(dbga_axis.x)) return;
// len
cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
draw_printf(cr, 100, 10, 0.0, (char*)"Len: %5.2f", dbga_len);
// draw pos
cairo_set_source_rgb(cr, 0.3, 0.3, 1.0);
draw_printf(cr, 0, 10, 0.0, (char*)"Pos: %5.1f,%5.1f", dbga_pos.x, dbga_pos.y);
cairo_set_line_width(cr, 3.0);
cairo_move_to(cr, centerX, centerY);
cairo_line_to(cr, dbga_pos.x, dbga_pos.y);
cairo_stroke(cr);
cairo_set_line_width(cr, 1.0);
if (dbga_len >= 0.0) cairo_set_source_rgb(cr, 1.0, 0.5, 0.5);
else cairo_set_source_rgb(cr, 0.5, 1.0, 0.5);
d = hypot(dbga_axis.x, dbga_axis.y);
v.x = dbga_len * dbga_axis.y / d;
v.y = dbga_len * (-dbga_axis.x) / d;
cairo_move_to(cr, dbga_pos.x, dbga_pos.y);
cairo_line_to(cr, dbga_pos.x + v.x, dbga_pos.y + v.y);
cairo_stroke(cr);
// draw axis
a = 180.0 * atan2(dbga_axis.x, dbga_axis.y) / M_PI;
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
draw_printf(cr, 0, 25, 0.0, (char*)"Axis: %5.1f,%5.1f", dbga_axis.x, dbga_axis.y);
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
draw_printf(cr, 0, 40, 0.0, (char*)"Axis: %5.1f", a);
cairo_set_line_width(cr, 3.0);
cairo_move_to(cr, centerX, centerY);
cairo_line_to(cr, centerX + dbga_axis.x, centerY + dbga_axis.y);
cairo_stroke(cr);
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr, centerX, centerY);
cairo_line_to(cr, centerX + sindeg(a) * (double)centerX * 0.8, centerY + cosdeg(a) * (double)centerX * 0.8);
cairo_stroke(cr);
cairo_set_line_width(cr, 1.0);
d = hypot(dbga_axis.x, dbga_axis.y);
v.x = centerX * dbga_axis.x / d;
v.y = centerY * dbga_axis.y / d;
cairo_move_to(cr, centerX - v.x, centerY - v.y);
cairo_line_to(cr, centerX + v.x, centerY + v.y);
cairo_stroke(cr);
};
void debug_angles_motionevent(GdkEvent *event) {
if (event->motion.x < 0 || event->motion.x >= DBGA_W
|| event->motion.y < 0 || event->motion.y >= DBGA_H) return;
dbga_pos.x = event->motion.x;
dbga_pos.y = event->motion.y;
};
void debug_angles_btnpress(GdkEvent *event) {
if (event->motion.x < 0 || event->motion.x >= DBGA_W
|| event->motion.y < 0 || event->motion.y >= DBGA_H) return;
dbga_axis.x = event->motion.x - (DBGA_W >> 1);
dbga_axis.y = event->motion.y - (DBGA_H >> 1);
};

@ -1,177 +0,0 @@
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include <sys/time.h>
#include <string>
#include <time.h>
#include <fcntl.h>
#ifdef BUILD_WINDOWS
# include <backtrace.h>
#else
# include <execinfo.h>
#endif
#include "debug.h"
#include "convert.h"
#include "gui.h"
#include "video.h"
#include "configuration.h"
#include "debayer.h"
extern GtkBuilder *_builder_; // work around for threads
GtkWidget *debug_da = NULL;
GdkPixbuf *debug_pixbuf = NULL;
VideoFrame debug_frame;
int debug_uninit = 1;
GMutex debug_mutex;
time_t debug_time;
#define LEN 2048
void debug_init() {
debug_uninit = 0;
g_mutex_init (&debug_mutex);
debug_time = time(NULL);
}
void debug_tofile(char *fname, int isheader, char *fmt, ...) {
struct timeval tv;
va_list args;
char buffer[LEN];
int fd, len;
std::string fn;
if (debug_uninit) debug_init();
debug_lock_mutex();
// locale set to C, floating points decimals are .
std::string s = setlocale(LC_ALL, NULL);
setlocale (LC_ALL, "C");
// append time to filename to the start of the filename
struct tm *timetm = localtime(&debug_time);
char timestr[64] = "";
strftime(timestr, 63, "%Y%m%d-%H%M%S", timetm);
fn = "debug-" + (std::string)timestr + "-" + (std::string)fname;
gettimeofday(&tv,NULL);
#ifdef BUILD_WINDOWS
fd = open(fn.c_str(), O_WRONLY | O_APPEND | O_CREAT);
#else
fd = open(fn.c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
if (fd < 0) errorexit((char*)"%s:%d could not open debug '%s' file. Error:%s\n", __FILE__, __LINE__, fname, strerror(errno));
if (isheader) snprintf (buffer, 32, "time,");
else snprintf (buffer, 32, "%lld,", (long long int) (tv.tv_sec)*1000 + (long long int) tv.tv_usec/1000);
len = strlen (buffer);
va_start (args, fmt);
vsnprintf (buffer+len, LEN-1-len, fmt, args);
va_end (args);
buffer[LEN-1] = 0;
write (fd, buffer, strlen(buffer));
close (fd);
// reset locale to user setting
setlocale (LC_ALL, s.c_str());
debug_unlock_mutex();
}
gboolean debug_thread_cb (gpointer data) {
debug_lock_mutex();
//
// create video drawarea if needed
if (debug_da == NULL)
debug_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "debug-da"));
if (debug_pixbuf == NULL) {
debug_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, 100, 100);
memset (gdk_pixbuf_get_pixels(debug_pixbuf), 0, 3 * gdk_pixbuf_get_height(debug_pixbuf) * gdk_pixbuf_get_width(debug_pixbuf));
}
debug_frame.ToPixbuf(&debug_pixbuf); // convert Frame to pixeldata
// redraw drawarea on screen.
gdk_window_invalidate_rect(gtk_widget_get_window(debug_da), NULL, true);
debug_unlock_mutex();
return false;
}
inline void debug_lock_mutex() {
g_mutex_lock(&debug_mutex);
};
inline void debug_unlock_mutex() {
g_mutex_unlock(&debug_mutex);
};
void debug_drawraw(unsigned char *data, int pixfmt, int w, int h) {
ConvertData cd;
int size, bytesperpixel = 0;
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:
return;
}
size = bytesperpixel * w * h;
debug_lock_mutex();
ConvertStart(&cd, pixfmt);
Convert(&cd, &debug_frame, data, size, pixfmt, w, h);
ConvertStop(&cd, pixfmt);
gdk_threads_add_idle(debug_thread_cb, NULL);
debug_unlock_mutex();
};
#define BT_BUF_SIZE 100
void debug_backtrace () {
#ifndef BUILD_WINDOWS
unsigned int nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (size_t j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
#endif
};

@ -1,34 +0,0 @@
/***************************************************************************************
*
* debug.h is part of SimpleSkyCam.
*
*****************************************************************************************/
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include "config.h"
#include "simpleskycam.h"
#include "gui.h"
#include "videoframe.h"
struct Debug_ThreadData {
VideoFrameRaw raw;
};
#ifdef DEBUG_ANGLES
extern void debug_angles_draw(cairo_t *cr);
extern void debug_angles_motionevent(GdkEvent *event);
extern void debug_angles_btnpress(GdkEvent *event);
#endif
extern void debug_init();
extern void debug_tofile(char *fname, int isheader, char *fmt, ...);
extern inline void debug_lock_mutex();
extern inline void debug_unlock_mutex();
void debug_drawraw(unsigned char *data, int pixfmt, int w, int h);
void debug_backtrace ();
#endif

@ -5,15 +5,11 @@
#include <mmintrin.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include "config.h"
#include "gui.h"
#include "detect.h"
#include "convert.h"
#include "configuration.h" // needed to get V4L formats
extern Detect detect;
extern PosCtl posctl;
//
// C / C++ Wrapper for the thread function
@ -35,7 +31,7 @@ Detect::Detect() { // @suppress("Class members should be properly initialized")
inFrame.SetSize(64, 64);
oldFrame.SetSize(64, 64);
image.SetSize(64, 64);
imageRGBout.SetSize(64, 64);
imagegtk.SetSize(64, 64);
thread = NULL;
thread = g_thread_new("Detect", _DetectThread, NULL);
objectW = 300;
@ -63,87 +59,59 @@ Detect::~Detect() {
/*
* copy the framedata into the next thread. Source data must be already mutex locked.
* raw data will only be copied if the source is not an compressed stream
*/
int Detect::CopyNewFrame(VideoFrame *newframe, VideoFrameRaw *rawframe) {
int Detect::NewFrame(VideoFrame *newframe) {
if (newframe == NULL) return -1;
LockInMutex();
if (rawframe->pixfmt != V4L2_PIX_FMT_MJPEG)
inRawFrame.CopyFrom(rawframe);
else
inRawFrame.Delete();
inFrame.CopyFrom(newframe);
inFrameNew = 1;
UnLockInMutex();
return 0;
};
/*
* NewFrame: will set new frame
* Thread: newFrame |------> Find Object --- not found ---> send gui information
*/
//
// NewFrame: will set new frame
// Thread: newFrame |------> Find Object --- not found ---> send gui information
void Detect::Thread() {
DetectOutput doutput;
struct timeval timestamp;
double dt;
int oldX, oldY;
DetectOutput output;
objectX = -1;
objectY = -1;
doutput.detmatrix = (uint32_t*)malloc (sizeof(uint32_t) * DET_MAXSHIFT * DET_MAXSHIFT);
gettimeofday (&timestamp, NULL);
output.detmatrix = (uint32_t*)malloc (sizeof(uint32_t) * DET_MAXSHIFT * DET_MAXSHIFT);
while (running) {
// check for new frame
dt = get_cycletime(&timestamp);
LockInMutex();
if (inFrameNew == 1) {
inFrameNew = 0;
oldX = objectX;
oldY = objectY;
LockMutex(); // lock Config
//
// 1. check near the last known position.
//
if (objectX >= objectW/2 && objectX <= (inFrame.w-objectW/2) &&
objectY >= objectH/2 && objectY <= (inFrame.h-objectH/2))
// 1. if no position of the object is known, search brightest
// object on the inFrame image.
if (objectX < objectW/2 || objectX > (inFrame.w-objectW/2) ||
objectY < objectH/2 || objectY > (inFrame.h-objectH/2))
{
switch (autofollowtype) {
case AUTOFOLLOW_BRIGHT:
switch (autodetecttype) {
case AUTODETECT_BRIGHT:
InputDetect(&objectX, &objectY);
break;
case AUTOFOLLOW_CROSSC:
InputDetectCrossC(&objectX, &objectY);
break;
default:
break;
}
if (abs(oldX - objectX) >= DET_MAXSHIFT/5 || abs(oldY - objectY) >= DET_MAXSHIFT/5) {
objectX = -1;
objectY = -1;
}
}
//
// 2. if no position of the object is known, search brightest
// object on the inFrame image.
if (objectX < objectW/2 || objectX > (inFrame.w-objectW/2) ||
objectY < objectH/2 || objectY > (inFrame.h-objectH/2))
{
switch (autodetecttype) {
case AUTODETECT_BRIGHT:
// 2. check near the last known position.
//
else {
switch (autofollowtype) {
case AUTOFOLLOW_BRIGHT:
InputDetect(&objectX, &objectY);
break;
case AUTOFOLLOW_CROSSC:
InputDetectCrossC(&objectX, &objectY);
break;
default:
break;
}
@ -154,30 +122,25 @@ void Detect::Thread() {
// copy output image for gtk
LockImageMutex();
imageRGBout.CopyFrom(&image);
if (imageRawout.RectCopyFrom(&inRawFrame, (objectX-objectW/2), (objectY-objectH/2), objectW, objectH) == 0)
imageRawout.CopyFrom(&imageRGBout);
imagegtk.CopyFrom(&image);
UnLockImageMutex();
doutput.posx = objectX;
doutput.posy = objectY;
doutput.image = &imageRGBout;
doutput.rawimage = &imageRawout;
output.posx = objectX;
output.posy = objectY;
output.image = &imagegtk;
if (detmatrix != NULL)
memcpy (doutput.detmatrix, detmatrix, sizeof(uint32_t) * DET_MAXSHIFT * DET_MAXSHIFT);
memcpy (output.detmatrix, detmatrix, sizeof(uint32_t) * DET_MAXSHIFT * DET_MAXSHIFT);
posctl.Loop (objectX, objectY, dt);
UnLockMutex(); // unlock Config
UnLockMutex(); // unlock detect dataset
gdk_threads_add_idle(cb_thread_detect , &doutput);
gdk_threads_add_idle(cb_thread_detect , &output);
}
else
UnLockInMutex();
usleep (10000); // FIXME:: why is it here?
usleep (10000);
}
free (doutput.detmatrix);
free (output.detmatrix);
}
@ -217,8 +180,8 @@ void Detect::InputDetect(int *posx, int *posy) {
image.SetSize (objectW, objectH);
SetInputSize(inFrame.w, inFrame.h);
pxs = inFrame.data;
pxi = image.data;
pxs = (unsigned char*)inFrame.GetData();
pxi = (unsigned char*)image.GetData();
*posx = 0;
*posy = 0;
@ -250,8 +213,6 @@ void Detect::InputDetect(int *posx, int *posy) {
didx = 3* (image.w * dy + dx);
for (i = 0; i < 3; i++) pxi[didx+i] = pxs[idx+i];
}
return;
}
/* returns approx. 8-bit gray value */
@ -297,8 +258,8 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
image.SetSize (objectW, objectH);
SetInputSize(inFrame.w, inFrame.h);
pxi = inFrame.data;
pxo = oldFrame.data;
pxi = (unsigned char*)inFrame.GetData();
pxo = (unsigned char*)oldFrame.GetData();
mxx = mxy = 0;
for (shifty = 0; shifty < DET_MAXSHIFT; shifty++) {
@ -347,7 +308,6 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
*posx += (mxx-DET_MAXSHIFT/2);
*posy += (mxy-DET_MAXSHIFT/2);
CopyObjectImage (*posx, *posy);
return;
}
@ -356,8 +316,8 @@ void Detect::CopyObjectImage(int objx, int objy) {
unsigned char *pxi; // input image
unsigned char *pxd; // destination image
pxi = inFrame.data;
pxd = image.data;
pxi = (unsigned char*)inFrame.GetData();
pxd = (unsigned char*)image.GetData();
//
// copy image data to destination

@ -8,26 +8,6 @@
#ifndef _DETECT_H_
#define _DETECT_H_
#ifdef BUILD_WINDOWS
#define WIN32_LEAN_AND_MEAN
#define _NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
#define _NTDDI_VERSION_FROM_WIN32_WINNT(ver) _NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x501
#endif
#ifndef NTDDI_VERSION
# define NTDDI_VERSION _NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#endif
#include <winsock2.h>
#include <io.h>
#include <ws2tcpip.h>
#include <windows.h>
#endif
#include "pid.h"
#include "gui.h"
#include "config.h"
#include "video.h"
@ -46,149 +26,24 @@ enum {
AUTOFOLLOW_CROSSC
};
enum {
POSCTL_MODE_OFF = 0,
POSCTL_MODE_CALIB,
POSCTL_MODE_CONTROL,
POSCTL_MODE_2STEPWAIT,
POSCTL_MODE_2STEPRUN
};
enum {
POSCTL_CALIB_MODE_OFF = 0,
POSCTL_CALIB_MODE_START,
POSCTL_CALIB_MODE_STOP1,
POSCTL_CALIB_MODE_DELTAM,
POSCTL_CALIB_MODE_AXIS1START,
POSCTL_CALIB_MODE_AXIS1M,
POSCTL_CALIB_MODE_AXIS2START,
POSCTL_CALIB_MODE_AXIS2M,
POSCTL_CALIB_MODE_FINISH
};
enum {
POSCTL_DEVTYPE_TTY = 0,
POSCTL_DEVTYPE_SIM
};
struct PosCtl_2Step_Data {
int mode;
double pv[2];
double op[2];
double npv[2];
double ppv[2];
double nop[2];
double pop[2];
};
struct PosCtl_ThreadData {
position_2d c[2];
position_2d a1[2];
position_2d a2[2];
position_2d target_pos;
int calib_mode;
};
class PosCtl {
private:
GMutex mutex;
int mode;
PID pid_axis[2];
std::string device;
int device_type;
#ifdef BUILD_WINDOWS
HANDLE device_fd;
#else
int device_fd;
#endif
struct timeval calib_timestamp;
int calib_mode;
position_2d calib_pos;
position_f_2d pos;
double npv[2];
double ppv[2];
double nop[2];
double pop[2];
double posfilter;
struct PosCtl_ThreadData threaddata; // will be copied to gtk thread
void NotifyGtk();
void NotifyGtk2Step();
void CalibModeStart(int x, int y);
void CalibModeDelta(int x, int y);
void CalibModeAxis(int x, int y);
void CalibModeFinish();
void CalibModeWait(int x, int y);
int OutputClose();
int OutputOpen();
int WriteTTY(char *);
int ReadTTY(char *, int);
static double filteredvalue(double old_value, double new_value, double dt, double filter);
public:
PosCtl();
~PosCtl() {};
position_f_2d calib_rot_v;
vector_2d calib_rot;
position_f_2d calib_axis1_v;
vector_2d calib_axis1;
position_f_2d calib_axis2_v;
vector_2d calib_axis2;
position_f_2d target_pos;
position_f_2d current_pos;
double axis_pv[2];
double axis_op[2];
void LockMutex() { g_mutex_lock(&mutex); };
void UnLockMutex() { g_mutex_unlock(&mutex); };
void Stop ();
void StartCalibration ();
void StartControl ();
void Run2Step ();
void Reset2Step ();
int GetMode () { return mode; };
void SetAxisParam (int axis, double min, double max, double k, double i, double d);
void GetAxisParam (int axis, double *min, double *max, double *k, double *i, double *d);
void SetDevice(std::string d);
void SetFilter(double f) { posfilter = f; };
double GetFilter() { return posfilter; };
std::string GetDevice() { return device; };
void Loop (int posx, int posy, double dt);
int OutputWriteValue (int axis, double value);
int OutputWriteStop ();
int OutputWriteStart ();
};
struct {
VideoFrame *image; // detected image
VideoFrameRaw *rawimage; // detected rawimage
VideoFrame *image; // detected image
uint32_t *detmatrix;
int posx; // position of the detected object
int posy; // position of the detected object
int valid; // valid position detected
} typedef DetectOutput;
class Detect {
private:
int running;
VideoFrame inFrame; // input frame
VideoFrameRaw inRawFrame; // input RawFrame
VideoFrame oldFrame; // oldinput frame
int inFrameNew; // new input frame;
VideoFrame image; // output image
VideoFrame imageRGBout; // output image -- send to gtk
VideoFrameRaw imageRawout; // output raw image
VideoFrame imagegtk; // output image -- send to gtk
GMutex muteximage;
GMutex mutexin;
GMutex mutex; // general mutex for changing settings
@ -218,7 +73,7 @@ public:
Detect();
~Detect();
int CopyNewFrame(VideoFrame *newframe, VideoFrameRaw *rawframe); // set new frame data
int NewFrame(VideoFrame *newframe);
//
// Thread Releated Functions (maybe soon private?)
@ -253,6 +108,4 @@ public:
void Thread();
};
extern struct PosCtl_ThreadData posctl_threaddata;
#endif

@ -3,7 +3,6 @@
*/
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <tiffio.h>
#include "dng.h"
@ -27,25 +26,11 @@ DNG::~DNG() {
}
}
/*
Run-time detection if we are little- or big-endian.
*/
int DNG::IsBigEndian(void) {
int i = 1;
return ! *((char *)&i);
}
/*
Sets the file name of the DNG file to be written. Returns -1 on
failure, 0 on success.
*/
int DNG::setFile(char * file) {
/*
w = write
l = little endian
b = big endian
-> if neither l or b is given, data is written in native CPU format
*/
if (!(tif = TIFFOpen(file, "w"))) {
return -1;
}
@ -123,8 +108,7 @@ int DNG::writeFile(void * data) {
time_t abs_ts;
struct tm tm;
char timestamp[64];
/* get time stamp */
time (&abs_ts);
gmtime_r (&abs_ts, &tm);
sprintf(timestamp, "%04d:%02d:%02d %02d:%02d:%02d",
@ -149,15 +133,13 @@ int DNG::writeFile(void * data) {
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, SamplesPerPixel);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
if(ColorID == DNG_COLORID_RAW8 || ColorID == DNG_COLORID_RAW16) {
if(ColorID == DNG_COLORID_RAW8 || ColorID == DNG_COLORID_RAW8) {
static const short CFARepeatPattern[] = { 2,2 }; // 2x2 CFA
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, CFARepeatPattern);
TIFFSetField(tif, TIFFTAG_CFALAYOUT, 1);
TIFFSetField(tif, TIFFTAG_CFAPLANECOLOR, 3, "\000\001\002"); // RGB
// 0 = Red, 1 = Green, 2 = Blue
TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\001\000\002\001"); // GRBG
TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\001\000\002\001"); // GRGB
}
else if(ColorID == DNG_COLORID_RGB) {
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

@ -1,7 +1,6 @@
#ifndef _DNG_H_
#define _DNG_H_
/*
Example usage of the class:
---------------------------
@ -49,7 +48,6 @@ class DNG {
int BitsPerSample;
int SamplesPerPixel;
int ColorID;
int IsBigEndian(void);
public:
DNG();

@ -1,102 +0,0 @@
/***************************************************************************************
*
* error.h is part of SimpleSkyCam.
*
*****************************************************************************************/
#ifndef BUILD_WINDOWS
#include <execinfo.h>
#endif
#include <string>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "gui.h"
#include "error.h"
#include "configuration.h"
extern GtkBuilder *_builder_; // work around for threads
gboolean errormessage_thread (gpointer data) {
struct ErrorMessage *em = (struct ErrorMessage*) data;
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_),
em->window));
if (window == NULL) window = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_),
"window-main"));
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s", em->message);
gtk_window_set_title(GTK_WINDOW(dialog), em->title);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
free (em);
return false;
};
void errormessage_display (char *window, char *title, char *fmt,...) {
struct ErrorMessage *em = (struct ErrorMessage *) malloc (sizeof (struct ErrorMessage));
va_list args;
char buffer[ERRORMSG_LEN];
va_start (args, fmt);
vsnprintf (buffer, (ERRORMSG_LEN-1), fmt, args);
va_end (args);
buffer[ERRORMSG_LEN-1] = 0;
strncpy(em->title, title, ERRORMSG_LEN); em->title[ERRORMSG_LEN-1] = 0;
strncpy(em->message, buffer, ERRORMSG_LEN); em->message[ERRORMSG_LEN-1] = 0;
strncpy(em->window, window, ERRORMSG_LEN); em->window[ERRORMSG_LEN-1] = 0;
gdk_threads_add_idle(errormessage_thread, em);
};
/*
* print error message and the backtrace
*/
#define SIZE 100
void errorexit (char *fmt,...) {
//
// error message
va_list args;
char text[4096];
va_start (args, fmt);
vsnprintf (text, 4096, fmt, args);
va_end (args);
printf ("***************************\n");
printf (" ERROR\n");
printf ("***************************\n");
printf ("%s", text);
#ifndef BUILD_WINDOWS
//
// backtrace
int j, nptrs;
void *buffer[SIZE];
char **s;
nptrs = backtrace(buffer, SIZE);
if ((s = (char**) backtrace_symbols(buffer, nptrs)) == NULL) {
for (j = 0; j < nptrs; j++) printf ("%-5d %p\n", j, buffer[j]);
}
else {
for (j = 0; j < nptrs; j++) printf ("%-5d %s\n", j, s[j]);
}
#endif
exit (-1);
}

@ -1,21 +0,0 @@
/***************************************************************************************
*
* error.h is part of SimpleSkyCam.
*
*****************************************************************************************/
#ifndef _ERROR_H_
#define _ERROR_H_
#define ERRORMSG_LEN 2048
struct ErrorMessage {
char window[ERRORMSG_LEN];
char title[ERRORMSG_LEN];
char message[ERRORMSG_LEN];
};
void errorexit (char *fmt,...);
void errormessage_display (char *windowname, char *title, char *fmt,...);
#endif // _ERROR_H_

@ -0,0 +1,120 @@
#include <unistd.h>
#include "config.h"
#include "gui.h"
#include "filter.h"
extern Filter filter;
//gboolean cb_filtertemp_thread (gpointer data);
//gboolean cb_filterout_thread (gpointer data);
//
// C / C++ Wrapper for the thread function
//
gpointer _FilterThread (gpointer data) {
filter.Thread ();
return NULL;
};
Filter::Filter() { // @suppress("Class members should be properly initialized")
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
g_mutex_init (&mutexin);
g_mutex_init (&muteximage);
g_mutex_init (&mutextmp);
g_mutex_init (&mutex);
running = 1;
inFrame.SetSize(64, 64);
image.SetSize(64, 64);
imagegtk.SetSize(64, 64);
thread = NULL;
thread = g_thread_new("Filter", _FilterThread, NULL);
};
Filter::~Filter() {
running = 0;
if (thread) {
g_thread_join (thread);
thread = NULL;
}
};
int Filter::NewFrame(VideoFrame *newframe, int posx, int posy) {
if (newframe == NULL) return -1;
LockInMutex();
inFrame.CopyFrom(newframe);
inFrameNew = 1;
UnLockInMutex();
return 0;
};
void Filter::NewImage() {
newimage = 1;
}
//
// NewFrame: will set new frame
// Thread: newFrame |------> Find Object --- not found ---> send gui information
void Filter::Thread() {
while (running) {
// check for new frame
LockInMutex();
if (inFrameNew == 1) {
inFrameNew = 0;
//
// do some other stuff use if possible only the oldFrame data
ComposeOutput();
UnLockInMutex();
// copy output image for gtk
LockImageMutex();
imagegtk.CopyFrom(&image);
UnLockImageMutex();
gdk_threads_add_idle(cb_thread_filter , &imagegtk);
}
else
UnLockInMutex();
usleep (10000);
}
}
#define FACTOR 25.0
void Filter::ComposeOutput() {
int x, y, idx, i;
float *pixd = NULL; // destination
unsigned char *pixs = NULL; // source
image.SetSize(inFrame.w, inFrame.h);
pixd = image.data;
pixs = (unsigned char*)inFrame.GetData();
if (pixd == NULL || pixs == NULL) return;
if (newimage) {
inFrame.CopyTo(&image);
newimage = 0;
}
else {
for (x = 0; x < inFrame.w; x++)
for (y = 0; y < inFrame.h; y++) {
idx = 3 * (inFrame.w * y + x);
for (i = 0; i < 3; i++)
pixd[idx+i] = ((FACTOR-1.0) * (float)pixd[idx+i]/FACTOR) + (float)(pixs[idx+i] / FACTOR);
}
}
}

@ -1,48 +1,44 @@
/***************************************************************************************
*
* output.h is part of SimpleSkyCam.
* filter.h is part of SimpleSkyCam.
*
*****************************************************************************************/
#ifndef _OUTPUT_H_
#define _OUTPUT_H_
#ifndef _FILTER_H_
#define _FILTER_H_
#include "gui.h"
#include "config.h"
#include "video.h"
#include "videoframe.h"
#include "ser.h"
#define OUTPUT_MODE_SER_STARTED 0x0001
class Output {
class Filter {
private:
int running;
VideoFrameRaw inFrame; // input frame
VideoFrame inFrame; // input frame
int inFrameNew; // new input frame;
FloatImage image; // detected image
VideoFrame imagegtk; // output image -- send to gtk
GMutex muteximage;
GMutex mutexin;
GMutex mutextmp; // for access the temp image
GMutex mutex; // general mutex for changing settings
GThread *thread;
unsigned int mode; // see OUTPUT_MODE_ flags
std::string outputfilename; // current output
float *fpixels; //
int newimage;
void ComposeOutput();
void NotifyGTK ();
SER *outputser;
int outputserw; // to detect if the size
int outputserh; // changes white recording
uint32_t outputserfmt; //
public:
Output();
~Output();
int NewFrame (VideoFrameRaw *rawframe);
Filter();
~Filter();
int NewFrame (VideoFrame *newframe, int posx, int posy);
void NewImage ();
//
// Thread Releated Functions (maybe soon private?)
int TryLockInMutex() { return g_mutex_trylock(&mutexin); };
void LockInMutex() { g_mutex_lock(&mutexin);};
@ -55,17 +51,13 @@ public:
void LockMutex() { g_mutex_lock(&mutex);};
void UnLockMutex() { g_mutex_unlock(&mutex);};
//
// Object functions
void SetObjectSize (int neww, int newh);
void SetObject (VideoFrame objFrame, int newx, int newy);
void GetObjectPos (int *x, int *y);
void SERStart(std::string destpath, std::string sufix);
void SERStop();
int GetStatus() { return mode; };
void Thread();
};

222
gui.cc

@ -14,12 +14,12 @@
#include "gui.h"
#include "config.h"
#include "video.h"
#include "output.h"
#include "filter.h"
#include "detect.h"
#include "configuration.h"
extern GtkBuilder *_builder_; // work around for threads
extern Output output;
extern Filter filter;
extern Detect detect;
//
@ -33,11 +33,6 @@ GdkPixbuf *detect_pixbuf = NULL;
GtkWidget *image_da = NULL;
GdkPixbuf *image_pixbuf = NULL;
extern GtkWidget *debug_da;
extern GdkPixbuf *debug_pixbuf;
std::string filename = "";
extern Configuration config;
@ -61,12 +56,12 @@ void cb_window_show (GtkWidget *widget, gpointer data) {
GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop"));
GtkWidget *w = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-w"));
GtkWidget *h = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-h"));
GtkWidget *rbdefdetect = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cbbright"));
GtkWidget *rbdeffolow = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet2"));
GtkWidget *rboff = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cboff"));
GtkWidget *rbcrossc = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet2"));
// changing the value, will cause the 'change' event to be triggered
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rbdefdetect), true);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rbdeffolow), true);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rboff), true);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rbcrossc), true);
gtk_widget_set_sensitive(btnstart, true);
@ -77,40 +72,32 @@ void cb_window_show (GtkWidget *widget, gpointer data) {
detect.SetObjectSize(300, 300);
cb_video_btnrefreshlist (NULL, NULL);
//
// load config and setup elements
config.LoadDefault();
//
// show debug output window.
if (config.show_debugwin) {
printf ("%s:%d show debug window\n", __FILE__, __LINE__);
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-debug"));
if (wnd) gtk_widget_show (wnd);
}
GtkWidget *cfg_rgbenc = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "menu-settings-bilinearrgb"));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(cfg_rgbenc), (config.debayer_mode != 0));
//
// update the input video controls every 2 seconds.
g_timeout_add(2000, videoctrl_update, NULL);
};
void cb_menu_set_rgbenc (GtkCheckMenuItem *checkmenuitem, gpointer user_data) {
if (gtk_check_menu_item_get_active(checkmenuitem) == TRUE) config.debayer_mode = 1;
else config.debayer_mode = 0;
}
void displayerror (std::string error) {
GtkWidget *dialog;
GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (_builder_, "main-window"));
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"%s", error.c_str());
gtk_window_set_title(GTK_WINDOW(dialog), "Error");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
};
//
// callback from filter thread. Data will point to the output VideoFrame.
// Access to this data must be Locked before use.
//
/* gboolean cb_thread_filter (gpointer data) {
gboolean cb_thread_filter (gpointer data) {
VideoFrame *vf = (VideoFrame *) data;
int pix_h, pix_w;
@ -121,7 +108,7 @@ void cb_menu_set_rgbenc (GtkCheckMenuItem *checkmenuitem, gpointer user_data) {
return false;
}
output.LockImageMutex();
filter.LockImageMutex();
if (image_pixbuf) {
pix_h = gdk_pixbuf_get_height(image_pixbuf);
@ -140,14 +127,14 @@ void cb_menu_set_rgbenc (GtkCheckMenuItem *checkmenuitem, gpointer user_data) {
vf->ToPixbuf(image_pixbuf);
gdk_window_invalidate_rect(gtk_widget_get_window(image_da), NULL, true);
output.UnLockImageMutex();
filter.UnLockImageMutex();
return false;
};
*/
//
// callback from detect thread. Data will point to the temp VideoFrame.
// callback from filter thread. Data will point to the temp VideoFrame.
// this is propabely the object detection
// Access to this data must be Locked before use and pointers must be looked to
gboolean cb_thread_detect (gpointer data) {
@ -183,9 +170,9 @@ gboolean cb_thread_detect (gpointer data) {
pix_w = dout->image->w;
pix_h = dout->image->h;
}
dout->image->ToPixbuf(&detect_pixbuf);
dout->image->ToPixbuf(detect_pixbuf);
gdk_window_invalidate_rect(gtk_widget_get_window(detect_da), NULL, true);
output.NewFrame(dout->rawimage);
filter.NewFrame(dout->image, dout->posx, dout->posy);
detect.UnLockImageMutex();
@ -231,7 +218,6 @@ void cb_imagetempda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer da
if (area == image_da) src = image_pixbuf;
else if (area == detect_da) src = detect_pixbuf;
else if (area == debug_da && debug_pixbuf != NULL) src = debug_pixbuf;
else return;
clienth = gtk_widget_get_allocated_height(area);
@ -267,6 +253,61 @@ void cb_detect_btnsetsize (GtkWidget *widget, gpointer data) {
};
void cb_image_btnnew (GtkWidget *widget, gpointer data) {
filter.NewImage();
};
void cb_image_btnsave (GtkWidget *widget, gpointer data) {
GtkBuilder *builder = (GtkBuilder *) data;
GtkWindow *window = GTK_WINDOW (gtk_builder_get_object (builder, "window-main"));
GtkWidget *dialog;
GtkFileChooser *chooser;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
GtkFileFilter *filter;
gint res;
if (image_pixbuf == NULL) return;
dialog = gtk_file_chooser_dialog_new ("Save File",
window,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Save",
GTK_RESPONSE_ACCEPT,
NULL);
chooser = GTK_FILE_CHOOSER (dialog);
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.png");
gtk_file_filter_set_name(filter, "PNG File");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.*");
gtk_file_filter_set_name(filter, "All Files");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
if (filename.length () == 0)
gtk_file_chooser_set_current_name (chooser, "capture-001.png");
else
gtk_file_chooser_set_filename (chooser, filename.c_str());
res = gtk_dialog_run (GTK_DIALOG (dialog));
if (res == GTK_RESPONSE_ACCEPT) {
char *filename;
filename = gtk_file_chooser_get_filename (chooser);
gdk_pixbuf_save(image_pixbuf, filename, "png", NULL, "quality", "100", NULL);
g_free (filename);
}
gtk_widget_destroy (dialog);
};
void cb_detect_bright (GtkRange *range, gpointer data) {
double value;
@ -309,106 +350,3 @@ void cb_detect_btnsetpos (GtkWidget *widget, gpointer data) {
};
void cb_detect_show_window (GtkWidget *widget, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-detect"));
gtk_widget_show(wnd);
};
/*
* setup destination path
*/
void cb_input_btnsetdestpath (GtkWidget *widget, gpointer data) {
GtkBuilder *builder = (GtkBuilder *) data;
GtkWindow *window = GTK_WINDOW (gtk_builder_get_object (builder, "windows-input"));
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
gint res;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
dialog = gtk_file_chooser_dialog_new ("Open Folder",
window,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Open",
GTK_RESPONSE_ACCEPT,
NULL);
res = gtk_dialog_run (GTK_DIALOG (dialog));
if (res == GTK_RESPONSE_ACCEPT) {
char *filename;
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
filename = gtk_file_chooser_get_filename (chooser);
config.SetDestPath(filename);
GtkWidget *entry = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "input_entry_destpath"));
gtk_entry_set_text(GTK_ENTRY(entry), filename);
g_free (filename);
}
gtk_widget_destroy (dialog);
};
void cb_input_show_window (GtkWidget *widget, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-input"));
gtk_widget_show(wnd);
};
void draw_text (cairo_t *cr, int x, int y, float border, std::string text) {
cairo_pattern_t *t = NULL;
double r, g, b, a;
t = cairo_get_source(cr);
cairo_pattern_get_rgba(t, &r, &g, &b, &a);
for (int i = 0; i < 5; i++) {
int dx, dy;
switch (i) {
case 0:
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
dx = -1;
dy = 0;
break;
case 1:
dx = +1;
dy = 0;
break;
case 2:
dx = 0;
dy = -1;
break;
case 3:
dx = 0;
dy = +1;
break;
case 4:
cairo_set_source_rgba(cr, r, g, b, a);
dx = 0;
dy = 0;
break;
}
cairo_move_to (cr, x+dx, y+dy);
cairo_show_text(cr, text.c_str());
cairo_stroke(cr);
}
};
#define DRAW_PRINTF_LEN 512
void draw_printf(cairo_t *cr, int x, int y, float border, char *fmt,...) {
va_list args;
char buffer[DRAW_PRINTF_LEN];
va_start (args, fmt);
vsnprintf (buffer, (DRAW_PRINTF_LEN-1), fmt, args);
va_end (args);
buffer[DRAW_PRINTF_LEN-1] = 0;
draw_text (cr, x, y, border, buffer);
};

140
gui.h

@ -11,93 +11,21 @@
#include <gdk/gdk.h>
#include <glib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <list>
#define LEN_FILENAME 64
#define LEN_FULLFILENAME 256
enum {
VID_ENTERDATA_NONE = 0,
VID_ENTERDATA_POS,
VID_ENTERDATA_SETDEST
VID_ENTERDATA_POS
};
#define BUILDER_FILE "simpleskycam.ui"
class position_2d {
public:
position_2d() { x = 0; y = 0; };
~position_2d() {};
position_2d operator + (position_2d const &obj) {
position_2d res;
res.x = x + obj.x;
res.y = y + obj.y;
return res;
}
position_2d operator - (position_2d const &obj) {
position_2d res;
res.x = x - obj.x;
res.y = y - obj.y;
return res;
}
struct {
int x;
int y;
};
class position_f_2d {
public:
position_f_2d() { x = NAN; y = NAN; };
~position_f_2d() {};
position_f_2d operator + (position_f_2d const &obj) {
position_f_2d res;
res.x = x + obj.x;
res.y = y + obj.y;
return res;
}
position_f_2d operator - (position_f_2d const &obj) {
position_f_2d res;
res.x = x - obj.x;
res.y = y - obj.y;
return res;
}
double cosalpha(position_f_2d &pos) {
return (x * pos.x + y * pos.y) / (length() * pos.length());
}
double sinalpha(position_f_2d &pos) {
return (x * pos.y - y * pos.x) / (length() * pos.length());
}
double perpendicular(position_f_2d &pos, position_f_2d &base) {
position_f_2d p = pos - base;
double l = p.length();
return l == 0.0 ? 0.0 : l * sinalpha(p);
}
double length() { return hypot(x, y); }
double x;
double y;
};
class vector_2d {
public:
double a;
double l;
vector_2d () { a = NAN; l = NAN; }
~vector_2d () {};
};
} typedef position_2d;
#define DETECT_MOVEMENT_SAMPLES 50
@ -111,10 +39,7 @@ struct {
float dy;
} typedef detect_movement;
void draw_text (cairo_t *cr, int x, int y, float border, std::string text);
void draw_printf(cairo_t *cr, int x, int y, float border, char *fmt,...);
#define gtk_entry_set_text_nofocus(__w__,__t__) if (!gtk_widget_has_focus(__w__)) gtk_entry_set_text (GTK_ENTRY(__w__), __t__)
void displayerror (std::string error);
#ifdef __cplusplus
extern "C" {
@ -154,73 +79,24 @@ gboolean video_pre_long(gpointer data);
//
// thread new inframe
G_MODULE_EXPORT gboolean cb_thread_video (gpointer data);
G_MODULE_EXPORT void cb_input_show_window (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_input_btncapture (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_input_btnsnapshot (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_input_btnstop (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_input_btnscale (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_input_btnsetdestpath (GtkWidget *widget, gpointer data);
//
// filter detect or image data
G_MODULE_EXPORT void cb_imagetempda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT gboolean cb_thread_filter (gpointer data);
G_MODULE_EXPORT gboolean cb_thread_detect (gpointer data);
G_MODULE_EXPORT void cb_image_btnnew (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_image_btnsave (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_detect_bright (GtkRange *range, gpointer data);
//
// detection elements
G_MODULE_EXPORT void cb_detect_bright (GtkRange *range, gpointer data);
G_MODULE_EXPORT void cb_detect_btnsetpos (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_detect_btnsetsize (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_detect_followtype (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_detect_detecttype (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_detect_show_window (GtkWidget *widget, gpointer data);
//
// histogram elements
G_MODULE_EXPORT void cb_histogramda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_histogramda_motion (GtkWidget *widget, GdkEvent *event, gpointer data);
G_MODULE_EXPORT void cb_histogramda_btnpress (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_histogramda_btnrelease (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_histogramda_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data);
G_MODULE_EXPORT void cb_histogram_show_window (GtkWidget *widget, gpointer data);
//
// position control elements
G_MODULE_EXPORT void cb_posctl_show (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_show_window (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btncalib (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btnstop (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btnsetdest (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btncontrol (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_entryanglelen (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_change_entry (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn_axismove (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btnsimreset (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_angles_draw (GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_axis_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_track_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn2steprun (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn2stepreset (GtkWidget *widget, gpointer data);
//
// menu elements
G_MODULE_EXPORT void cb_menu_set_rgbenc (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
G_MODULE_EXPORT void cb_menu_set_histlog (GtkCheckMenuItem *checkmenuitem, gpointer user_data);
G_MODULE_EXPORT void cb_menu_set_displaycalibdata(GtkCheckMenuItem *checkmenuitem, gpointer user_data);
//
// error handling and thread handling
G_MODULE_EXPORT gboolean errormessage_thread (gpointer data);
G_MODULE_EXPORT void errormessage_cb_btnok (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT gboolean debug_thread_cb (gpointer data);
G_MODULE_EXPORT gboolean cb_thread_detect (gpointer data);
G_MODULE_EXPORT gboolean cb_thread_posctl (gpointer data);
G_MODULE_EXPORT gboolean cb_thread_output (gpointer data);
#ifdef __cplusplus
}

@ -1,252 +0,0 @@
/***************************************************************************************
*
* histogram.cc is part of SimpleSkyCam.
*
*****************************************************************************************/
#include <math.h>
#include "simpleskycam.h"
#include "histogram.h"
#include "gui.h"
#include "configuration.h"
#include "video.h"
#define HISTOGRAM_WIDTH 256
#define HISTOGRAM_MARGIN 16
GtkWidget *histogram_da = NULL;
int histogram[3][HISTOGRAM_WIDTH]; // 6* hist_width min, max, min , max.....
int histogram_max; // max vlaue
int histogram_zoom_start = 0; // first zoom value
int histogram_zoom_stop = HISTOGRAM_WIDTH-1; // second zoom value
int histogram_x; // current mouse x-coordinate
int histogram_pressed_x; // window x-coordinate when pressing a button
int histogram_released_x; // window x-coordinate when releasing a button
int histogram_pressed = 0; // indicates button pressed or not
int histogram_zoomed = 0; // indicates zoom
extern GtkBuilder *_builder_; // work around for threads
void cb_histogramda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
int clientw, clienth, px, px2, py2;
GdkRGBA color;
char txt[255];
if (histogram_da == NULL) // should only be called once
histogram_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "histogram-da"));
clienth = gtk_widget_get_allocated_height(histogram_da);
clientw = gtk_widget_get_allocated_width(histogram_da);
//
// put the drawing area on the screen
cairo_paint(cr);
cairo_fill (cr);
if (histogram_max == 0) return;
for (int chan = 0; chan < 3; chan++) {
switch (chan) {
case 0:
color.blue = 0.0;
color.red = 1.0;
color.green = 0.0;
color.alpha = 0.5;
break;
case 1:
color.blue = 0.0;
color.red = 0.0;
color.green = 1.0;
color.alpha = 0.5;
break;
case 2:
color.blue = 1.0;
color.red = 0.0;
color.green = 0.0;
color.alpha = 0.5;
break;
}
gdk_cairo_set_source_rgba(cr, &color);
int histogram_width = histogram_zoom_stop - histogram_zoom_start + 1;
int histogram_scale = histogram_width - 1 > 0 ? histogram_width - 1 : 1;
for (int i = 0; i < histogram_width; i++) {
px = HISTOGRAM_MARGIN + ((clientw-HISTOGRAM_MARGIN*2) * i) / histogram_scale;
if (config.GetHistogramLog())
py2 = (clienth-HISTOGRAM_MARGIN) - ((clienth-HISTOGRAM_MARGIN*2) * log10(histogram[chan][histogram_zoom_start+i]+1) / log10(histogram_max));
else
py2 = (clienth-HISTOGRAM_MARGIN) - ((clienth-HISTOGRAM_MARGIN*2) * histogram[chan][histogram_zoom_start+i] / histogram_max);
if (i == 0) cairo_move_to(cr, px, py2);
else cairo_line_to(cr, px, py2);
}
cairo_stroke(cr);
if (histogram_pressed) {
if (histogram_pressed_x < histogram_x) {
px = histogram_pressed_x;
px2 = histogram_x;
} else {
px2 = histogram_pressed_x;
px = histogram_x;
}
cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 0.5);
cairo_rectangle (cr, px, 0, px2-px, clienth);
cairo_fill (cr);
}
}
// draw some text
if (config.GetHistogramLog()) snprintf (txt, 255, "%d - Log", histogram_max);
else snprintf (txt, 255, "%d - Lin", histogram_max);
for (int i = 0; i < 5; i++) {
int dx, dy;
switch (i) {
case 0:
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
dx = -1;
dy = 0;
break;
case 1:
dx = +1;
dy = 0;
break;
case 2:
dx = 0;
dy = -1;
break;
case 3:
dx = 0;
dy = +1;
break;
case 4:
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
dx = 0;
dy = 0;
break;
}
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 12);
cairo_move_to (cr, 10+dx, 15+dy);
cairo_show_text(cr, txt);
cairo_stroke(cr);
}
};
/*
* test function
*/
void histogram_update(VideoFrame *vf) {
// save some time
static int to = 0;
if ((++to) % 8 == 0) return;
int chan, i, x, y;
if (vf == NULL) return;
if (vf->w <= 0 ) return;
// initialize histogram
memset (histogram, 0, sizeof(histogram));
for (i = 0, x = 0; x < vf->w; x++) {
for (y = 0; y < vf->h; y++) {
for (chan = 0; chan < 3; chan++) {
histogram[chan][vf->data[i++]]++;
}
}
}
if (histogram_da)
gdk_window_invalidate_rect(gtk_widget_get_window(histogram_da), NULL, true);
for (histogram_max = 0, chan = 0; chan < 3; chan++) for (i = 0; i < HISTOGRAM_WIDTH; i++)
if (histogram_max < histogram[chan][i]) histogram_max = histogram[chan][i];
};
void cb_histogramda_motion (GtkWidget *widget, GdkEvent *event, gpointer data) {
if(!histogram_zoomed) {
histogram_x = (int)round(event->button.x);
}
};
void cb_histogramda_btnpress (GtkWidget *widget, gpointer data) {
if (!histogram_zoomed) {
if (!histogram_pressed) {
histogram_pressed = 1;
histogram_pressed_x = histogram_x;
}
} else {
histogram_zoomed = 0;
histogram_zoom_start = 0;
histogram_zoom_stop = HISTOGRAM_WIDTH-1;
}
};
void cb_histogramda_btnrelease (GtkWidget *widget, gpointer data) {
if (!histogram_zoomed) {
if (histogram_pressed) {
histogram_pressed = 0;
histogram_released_x = histogram_x;
histogram_zoomed = 1;
// here we need to compute start/stop coordinates inside histogram
int clientw;
clientw = gtk_widget_get_allocated_width(histogram_da);
// translate first coordinate
histogram_zoom_start = (histogram_pressed_x - HISTOGRAM_MARGIN) * HISTOGRAM_WIDTH / (clientw - HISTOGRAM_MARGIN*2);
if (histogram_zoom_start < 0) histogram_zoom_start = 0;
if (histogram_zoom_start >= HISTOGRAM_WIDTH) histogram_zoom_start = HISTOGRAM_WIDTH-1;
// translate second coordinate
histogram_zoom_stop = (histogram_released_x - HISTOGRAM_MARGIN) * HISTOGRAM_WIDTH / (clientw - HISTOGRAM_MARGIN*2) + 1;
// limit the values
if (histogram_zoom_stop < 0) histogram_zoom_stop = 0;
if (histogram_zoom_stop >= HISTOGRAM_WIDTH) histogram_zoom_stop = HISTOGRAM_WIDTH-1;
// exchange the values if necessary
if (histogram_zoom_start > histogram_zoom_stop) {
int t = histogram_zoom_start;
histogram_zoom_start = histogram_zoom_stop;
histogram_zoom_stop = t;
}
}
}
};
void cb_histogramda_keypress (GtkWidget *widget, GdkEventKey *event, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (event == NULL) return;
else if (event->keyval == 'l') config.SetHistogramLog(config.GetHistogramLog() == 0);
};
void cb_histogram_show_window (GtkWidget *widget, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-histogram"));
gtk_widget_show(wnd);
};
void cb_menu_set_histlog (GtkCheckMenuItem *checkmenuitem, gpointer user_data) {
config.SetHistogramLog(gtk_check_menu_item_get_active(checkmenuitem) == TRUE);
}

@ -1,21 +0,0 @@
/***************************************************************************************
*
* histogram.h is part of SimpleSkyCam.
*
***************************************************************************************/
#ifndef _HISTOGRAM_H_
#define _HISTOGRAM_H_
#include <string>
#include <list>
#include <stdint.h>
#include "gui.h"
#include "config.h"
#include "videoframe.h"
void histogram_update(VideoFrame *vf);
#endif // _HISTOGRAM_H_

@ -210,17 +210,6 @@ int JSONParse::GetValueInt(string varname, int *dest) {
};
int JSONParse::GetValueDouble(string varname, double *dest) {
string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atof (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetValueInt64(string varname, int64_t *dest) {
string s;
int res = GetValue(varname, &s);
@ -232,7 +221,7 @@ int JSONParse::GetValueInt64(string varname, int64_t *dest) {
};
int JSONParse::GetObjectJson(string varname, JSONParse *dest) {
int JSONParse::GetObject(string varname, JSONParse *dest) {
list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
@ -532,3 +521,4 @@ string JSONElement::GetString () {
return output;
};

@ -54,9 +54,8 @@ public:
int GetValue(string varname, string *dest);
int GetValueInt(string varname, int *dest);
int GetValueDouble(string varname, double *dest);
int GetValueInt64(string varname, int64_t *dest);
int GetObjectJson(string varname, JSONParse *dest);
int GetObject(string varname, JSONParse *dest);
int GetIdx(string src, int idx, string *dest);
int GetValueIdx(string varname, int idx, string *dest);

@ -5,25 +5,26 @@
*****************************************************************************************/
#include <sys/time.h>
#include <math.h>
#include <execinfo.h>
#include "simpleskycam.h"
#include "config.h"
#include "configuration.h"
#include "gui.h"
#include "output.h"
#include "filter.h"
#include "detect.h"
#include "convert.h"
#include "ser.h"
#include "dng.h"
/**************************************************************************
* global variables
**************************************************************************/
GtkBuilder *_builder_ = NULL; // work around for the thread situation
Output output;
Filter filter;
Detect detect;
Configuration config;
PosCtl posctl;
int main (int argc, char **argv) {
GtkBuilder *builder;
@ -40,7 +41,6 @@ int main (int argc, char **argv) {
printf ("Command Line Options for testing purpose:\n");
printf (" -d <debugpath> destination for video debugging path\n");
printf (" -dd disable debugging path\n");
printf (" -dw show debug window\n");
printf ("\n");
printf (" -rd <debugpath> read video from dumpfile folder\n");
printf ("\n");
@ -52,11 +52,9 @@ int main (int argc, char **argv) {
config.debugpath = argv[i];
}
if (strcmp (argv[i], "-dd") == 0) {
i++;
config.debugpath = NULL;
}
if (strcmp (argv[i], "-dw") == 0) {
config.show_debugwin = 1;
}
if (strcmp (argv[i], "-rd") == 0) {
i++;
config.readdumppath = argv[i];
@ -93,14 +91,38 @@ float get_cycletime(struct timeval *t) {
}
void calc_vec2anglelen(position_f_2d *p, vector_2d *v) {
if (v == NULL || p == NULL) return;
v->a = atan2(p->x, p->y) * 180.0 / M_PI;
while (v->a < 0.0) v->a += 360.0;
v->l = hypot(p->x, p->y);
/*
* print error message and the backtrace
*/
#define SIZE 100
void errorexit (char *fmt,...) {
//
// error message
va_list args;
char text[4096];
va_start (args, fmt);
vsnprintf (text, 4096, fmt, args);
va_end (args);
printf ("***************************\n");
printf (" ERROR\n");
printf ("***************************\n");
printf ("%s", text);
//
// backtrace
int j, nptrs;
void *buffer[SIZE];
char **s;
nptrs = backtrace(buffer, SIZE);
if ((s = (char**) backtrace_symbols(buffer, nptrs)) == NULL) {
for (j = 0; j < nptrs; j++) printf ("%-5d %p\n", j, buffer[j]);
}
else {
for (j = 0; j < nptrs; j++) printf ("%-5d %s\n", j, s[j]);
}
exit (-1);
}

@ -1,239 +0,0 @@
#include <unistd.h>
#include "convert.h"
#include "config.h"
#include "gui.h"
#include "output.h"
#include "configuration.h"
#include "error.h"
extern GtkBuilder *_builder_; // work around for threads
extern Output output;
/*
* callback from output thread
*/
gboolean cb_thread_output (gpointer data) {
int mode = output.GetStatus();
GtkWidget *btncapture = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputcapture"));
GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputstop"));
GtkWidget *btnsnapshot = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputsnapshot"));
GtkWidget *btninputdest = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "input_btn_destpath"));
GtkWidget *inputdest = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "input_entry_destpath"));
if (mode & OUTPUT_MODE_SER_STARTED) {
gtk_widget_set_sensitive(btnstop, true);
gtk_widget_set_sensitive(btncapture, false);
gtk_widget_set_sensitive(btnsnapshot, false);
gtk_widget_set_sensitive(btninputdest, false);
gtk_widget_set_sensitive(inputdest, false);
}
else {
gtk_widget_set_sensitive(btnstop, false);
gtk_widget_set_sensitive(btncapture, true);
gtk_widget_set_sensitive(btnsnapshot, true);
gtk_widget_set_sensitive(btninputdest, true);
gtk_widget_set_sensitive(inputdest, true);
}
return false;
}
void input_getdestandsufix (std::string *sdir, std::string *ssufix) {
GtkWidget *inputdest = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "input_entry_destpath"));
GtkWidget *inputsufix = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_input_filesufix"));
if (sdir != NULL) *sdir = gtk_entry_get_text(GTK_ENTRY(inputdest));
if (ssufix != NULL) *ssufix = gtk_entry_get_text(GTK_ENTRY(inputsufix));
}
void cb_input_btncapture (GtkWidget *widget, gpointer data) {
std::string sdir, ssufix;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
input_getdestandsufix(&sdir, &ssufix);
output.SERStart(sdir, ssufix);
};
void cb_input_btnsnapshot (GtkWidget *widget, gpointer data) {
std::string sdir, ssufix;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
input_getdestandsufix(&sdir, &ssufix);
// output.Capture(sdir, ssufix);
};
void cb_input_btnstop (GtkWidget *widget, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
output.SERStop();
};
//
// C / C++ Wrapper for the thread function
//
gpointer _OutputThread (gpointer data) {
output.Thread ();
return NULL;
};
/*
*
*/
Output::Output() { // @suppress("Class members should be properly initialized")
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
outputser = NULL;
g_mutex_init (&mutexin);
g_mutex_init (&muteximage);
g_mutex_init (&mutextmp);
g_mutex_init (&mutex);
running = 1;
inFrame.Delete();
mode = 0;
thread = NULL;
thread = g_thread_new("Output", _OutputThread, NULL);
};
void Output::NotifyGTK () {
gdk_threads_add_idle(cb_thread_output, NULL);
}
/*
* open output file and set mode flag
* all the other SER stuff will be set with the first frame
*/
void Output::SERStart (std::string destpath, std::string sufix) {
time_t t = time(NULL);
struct tm *tmptr;
char fname[LEN_FILENAME];
char fullfname[LEN_FULLFILENAME];
//
// check to create file, if not possible try creating the directory and create the file again
tmptr = localtime(&t);
strftime(fname, LEN_FILENAME, "%Y%m%d-%H%M%S", tmptr);
snprintf (fullfname, LEN_FULLFILENAME, "%s/%s-%s.ser", destpath.c_str(), fname, sufix.c_str());
outputfilename = fullfname;
printf ("%s:%d SERStart Destination File: %s\n", __FILE__, __LINE__, outputfilename.c_str());
mode |= OUTPUT_MODE_SER_STARTED;
NotifyGTK();
};
/*
* clode output file
*/
void Output::SERStop () {
mode &= ~(OUTPUT_MODE_SER_STARTED);
if (outputser) {
// close SER and delete object --> deleting the object should also rewrite the write the header
delete outputser;
outputser = NULL;
}
NotifyGTK();
};
Output::~Output() {
running = 0;
if (thread) {
g_thread_join (thread);
thread = NULL;
}
};
int Output::NewFrame(VideoFrameRaw *rawframe) {
if (rawframe == NULL) return -1;
// printf ("%s:%d Output::NewFrame Frame Raw: %d x %d Type: %s\n", __FILE__, __LINE__, rawframe->w, rawframe->h, convert_from_pixelformat(rawframe->pixfmt).c_str());
if (inFrameNew) {
printf ("%s:%d Output::NewFrame truncating one frame.\n", __FILE__, __LINE__);
}
LockInMutex();
inFrame.CopyFrom(rawframe);
inFrameNew = 1;
UnLockInMutex();
return 0;
};
//
// NewFrame: will set new frame
// Thread: newFrame |------> Find Object --- not found ---> send gui information
void Output::Thread() {
while (running) {
// check for new frame
LockInMutex();
if (inFrameNew == 1) {
if (mode & OUTPUT_MODE_SER_STARTED) {
if (outputser == NULL) { // first frame of ser output
int pixsize;
int serformat;
outputserw = inFrame.w;
outputserh = inFrame.h;
outputserfmt = inFrame.pixfmt;
if (!ser_convert_type_to_ser(outputserfmt, &pixsize, &serformat)) {
errormessage_display((char*)"windows-main", (char*)"Error", (char*)"Pixelformat [%s] not supported.", convert_from_pixelformat(outputserfmt).c_str());
SERStop();
}
outputser = new SER();
if (outputser) outputser->setWidth(outputserw);
if (outputser) outputser->setHeight(outputserh);
if (outputser) outputser->setColorID(serformat);
if (outputser) outputser->setPixelDepth(pixsize);
if (outputser->setFile((char *)outputfilename.c_str()) == -1) {
errormessage_display((char*)"windows-main", (char*)"Error", (char*)"Could not set output file [%s]. Error: %s", outputfilename.c_str(), strerror(errno));
SERStop();
}
if (outputser) outputser->setObserver((char *)"FIXME:read username from OS");
if (outputser) outputser->setTelescope((char *)"FIXME:not implemented yet");
if (outputser) outputser->setInstrument((char *)"FIXME:just read device from driver");
if (outputser) outputser->setNumberOfFrames(0);
if (outputser) outputser->writeHeader();
}
else {
//
// check if the frame type or size changed
if (outputserw != inFrame.w || outputserh != inFrame.h || outputserfmt != inFrame.pixfmt) {
errormessage_display((char*)"windows-main", (char*)"Error", (char*)"Frame format or dimensions changed.\n(%s @ %d x %d) != (%s @ %d x %d)\n",
convert_from_pixelformat(outputserfmt).c_str(), outputserw, outputserh,
convert_from_pixelformat(inFrame.pixfmt).c_str(), inFrame.w, inFrame.h);
SERStop();
}
}
if (outputser) { // we need to check in case outputser got deleted.
//
// write frame
outputser->appendFrame(inFrame.data);
}
}
inFrameNew = 0;
}
UnLockInMutex();
usleep (1000); // sleep 10ms
}
}

147
pid.cc

@ -1,147 +0,0 @@
/*
The file implements a simple PID regulator. The time resolution is
1usec. The update function should be called regularily as often as
possible.
*/
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include <math.h>
#include "pid.h"
/*
This this the class constructor. The min/max values are the minimum
and maximum values output by the regulator. The three regulator
parameters must be adjusted by experiments.
*/
PID::PID(double min, double max, double kp, double kd, double ki) {
Min = min;
Max = max;
Kp = kp;
Kd = kd;
Ki = ki;
Integral = 0;
PreviousError = 0;
PreviousTime = GetTime();
}
/*
* default parameter
*/
PID::PID() {
Min = 0.0;
Max = 1.0;
Kp = 1.0;
Kd = 0.0;
Ki = 0.0;
Integral = 0;
PreviousError = 0;
PreviousTime = GetTime();
}
/*
Class destructor.
*/
PID::~PID() {
}
/*
A static function to obtain a timestamp for the integrative/derivative
parts of the regulator.
*/
int64_t PID::GetTime(void) {
struct timeval current_time;
int64_t t;
gettimeofday (&current_time, NULL);
t = current_time.tv_sec * 1000000L + current_time.tv_usec;
return t;
}
/*
The function can be used to re-start the PID regulator. Re-setting
the integral and setting the current time as starting point.
*/
void PID::Start(void) {
Integral = 0;
PreviousError = 0;
PreviousTime = GetTime();
}
/*
This is the update function of the PID regulator. Passing the
target value of the regulator, the current process value and the
timestamp when the value was obtained.
*/
double PID::Update(double target, double value, int64_t time) {
double error, out;
int64_t dt;
double P, I, D;
double Derivative;
error = target - value;
// proportional part
P = Kp * error;
// integral part
dt = time - PreviousTime;
Integral += error * dt;
I = Ki * Integral;
if (dt > 0) {
// derivative part
Derivative = (error - PreviousError) / dt;
D = Kd * Derivative;
}
else {
D = 0;
}
// calculate output of regulator
out = P + I + D;
// Min/Max limitations of the regulator output
if (out > Max) out = Max;
if (out < Min) out = Min;
// save previous error value and time
PreviousError = error;
PreviousTime = time;
return out;
}
/*
This is a shortcut function of the update function without passing
the timestamp. The timestamp will be the time when the fuction is
called.
*/
double PID::Update(double target, double value) {
return Update(target, value, GetTime());
}
void PID::SetParam (double mi, double ma, double p, double i, double d) {
Kp = p;
Ki = i/1000000.0;
Kd = d/1000000.0;
Min = mi;
Max = ma;
Start();
};
void PID::GetParam (double *mi, double *ma, double *p, double *i, double *d) {
if (p != NULL) *p = Kp;
if (i != NULL) *i = Ki*1000000.0;
if (d != NULL) *d = Kd*1000000.0;
if (mi != NULL) *mi = Min;
if (ma != NULL) *ma = Max;
};

@ -1 +0,0 @@
<mxfile host="Electron" modified="2023-02-05T21:56:36.730Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="qnZzmQGoDEGPjH1afGyG" version="20.3.0" type="device"><diagram id="1p0Bprw3xxz6Ckpdy3R8" name="Seite-1">3VnLdpswEP0aL9MDiOcytpM06enjNIsk3fQoIBs1MnKF/MrXVxhhg2Rsx6XEZQUaDSMx92oe0AODyfKGwWn8mUaI9CwjWvbAsGdZpuE54pJJVrnEte1cMGY4kkpbwT1+RcWTUjrDEUoripxSwvG0KgxpkqCQV2SQMbqoqo0oqa46hWOkCe5DSHTpA454nEt9y9vKPyI8jouVTTfIZyawUJZvksYwoouSCFz1wIBRyvO7yXKASOa8wi/5c9c1s5uNMZTwYx749Sn6encXvHp9b3jp3a5eaZBcWLmVOSQz+cJys3xVeAAl0WXmSDEKCUxTHPZAP+YTIgSmuGV0lkQoW8QQI31XcqMoqjha7vEG0QnibCUUFlv3OtJlccmzhYwhAjmeV+GBEuXxxtxmhW8Ui51YhmQkKOCQfLR9o2oipTMWIvlU2Z2KIc89YIhDNkZcMyRuSq+9Fa3RegNyoDXk8hfZsxW7mwirhkyjXYRtDeEnDWKOlrwKasoZfUEDSigTkoQmQrM/woQoIkjwOMmYIeBGQt6fI8axCHyXcmKCoyhbpr+IMUf3Uxhmay5EmD+eOplNtNxLCjlrBVVn+zJvlDjj7uAMMOrpUcHjrc53NOc/dtf5nl1zZN7L+27Twa2MQc8CkYP8yNYAEzO+9Qxc9z9IZI6Sf4B7aiJTwtxmgy2FOa+1RNY15Fw1QQXtIhdoyIUz9nNK0+5GStdQXO6+c6Qs+qQSCHCJU7PDECiVgvXuEJgaBPsimPRqBNN47RZzFypFr2lrHhSOY6vHbPDBcorxk3x4PRguy6rDVU0KhMgfhbtSoBv66Hn0Vx1BcFYB1/UVxpzaEVhqz9dywDXf1vRJptUmShGt5xsK1vLKOMCr01lSxK5zoYl7oBA6uqIyFUNHNo4CN7gqqU0zhXTPhtVICCpfgMRNbrFZDuptaWMcTIVjuF7prcXXmBQWahl3JkRylHgDVPxPLfA2XySaJpJK2KANIulNHuxu1aJxwtSrFqvVqqXxvqvBAuNcDnJTnZoNlANmtlw4+PpZE12CjnhnzhtQc6Oln7d2uwS9W/6Bs59lXUXAsWsOTwkB+x8h8BsOvjwi+5lcvZDvw9v5zOk/XLTapp36wVGJfDsweLfy+NDXpqODoXo0G/tzJobb/6m5+vavNLj6Aw==</diagram></mxfile>

30
pid.h

@ -1,30 +0,0 @@
#ifndef _PID_H_
#define _PID_H_
class PID {
private:
double Min, Max;
double Kp; // proportional factor
double Ki; // integral factor
double Kd; // derivative factor
double Integral;
double PreviousError;
int64_t PreviousTime;
public:
PID(double min, double max, double kp, double kd, double ki);
PID();
~PID();
void Start(void);
void SetParam(double mi, double ma, double p, double i, double d);
void GetParam(double *mi, double *ma, double *p, double *i, double *d);
double GetMax() { return Max; };
double GetMin() { return Min; };
double Update(double target, double value, int64_t time);
double Update(double target, double value);
static int64_t GetTime(void);
};
#endif

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
<mxfile host="Electron" modified="2024-04-04T17:50:32.413Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="RaccqhXgUPgrDxD3-wkT" version="20.3.0" type="device"><diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">7VzZdps6FP0ar3Xvg7NAeMCPsZ2hbdqkTpuhL10yCEyDkYtxbPfrrwQCoyEED8GObx+aIkVISPvsfY6m1IzeeHERwsnoM7aRXwOavagZ/RoAZkMnP2nGkmWYWpLhhp6dZOmrjFvvD2KZabGZZ6MpVzDC2I+8CZ9p4SBAVsTlwTDEc76Yg32+1Ql0kZRxa0Ffzr337GjEegHaq/xL5LmjtGW91Ul+M4ZpYdaT6QjaeJ7LMs5qRi/EOEqexose8unYpeNy/2F57189tS4+fp3+ht+7n759uasnlZ2v80rWhRAF0cZVP/R+Xz88zj74N+cw+Pop+gEQqLNReIb+jI0X62u0TAcwxLPARrQSvWZ0R9HYZ4+/UBQtGeBwFmGShcNohF0cQP8K4wkr5+AgYsV0mkaBfUqBJemhj62nJOvc82nFWpJi5U2SmkYhfsqwM2hOCgQt7MMh8rvQenLjD+1hH4fkVwEOEK3KJsbA+rL6uLNVbhctvOiB1nXSZKlH9t30ub9Iv4kmlizhkG9NG6oBw24i025kn5r7jQmGRqsVdykKl7lmaPIx6y5JrBqKU8t86gaF3hhFKGSZJc2Bmc0Uz0ILFZRjNhDB0EWsvttPfvdq0Pt9e+NcGbBev+jdzOqNpBwd0hy1mLFdIEw+MVySAiHyYeQ98/yDjMZuVi579QZ7pB9AY4oDDEDGKH6JSY5uaHwlSZfYe3mTF6pqpFrFKgINoaKkz1JF5CHXo1VWzCg1u8DA6s+vJ9bDwp/YT8PB2fXV5xSBHLus4c9oFCJo/3wmsoj/OTn5VyIcHeAratU83aDvuQF5tgjq1BS6zyiMPCJ0p+wXY8+2Y5MO0dT7A4dxfdReJrR/cY+b3Vqzn1KStWjI5lQoFaRVtFBJN2uRU0fOMNhb2gkAnRYHTDpSW5pOXe/wr2DHmaJtoVWOhi4r54DASnLuKLDk/z6MoITtdO6NfRhL0wiH3h+CA0xlT1QViEzHUqlKyzLR0FlbCCTkXkRI52nTYsn5yn9mTBrlfWdbexWxATWUwCXjkbXW4Vtryq0pG2sKjUGf0CKAEepSPzDdEnSlAmaRAE/WYgfD+89fs/EkLc98lNJpKpxrTgvyLrWhNIRCo33VJRiySyhyHbtzCRxiBfAUfXWOkj04roGWT7rQHYbkyaVPjKeD0/uXWMpDNh95EbqdwHjE5iRIfhkL0veu68PplFGaj110MXZZE7byBG7yDtSQKaWnRfKcEt3jzpCRxbKHA9qdeDZAfpjkX9ejycFF9+jx0LUKAVF3wZQQ6ZMI06II0JqBdo59nwxMmrzBUy/ycEAeCXRkGP3j8G2gLUPR7ij8jSH6m3LOTWxO4UsPxbvpugTput5tA1e20fxLcH9vPLsqZFDelyoLdmRfqh5+bV/OtOizFQJx4OKcKlt5cQYcRTtA1uaWgqJvp83ytFHwluc+hkcIBBCn6+2mDAV4Iyju+9/6D/jSvPyozz886YNx/8cPtqKWR0LlB8UA8/iQaRoCMqoA5q1IolbL5tbOajdTsdR/pc+PnC9T+y+aEN3Opj5s06mgwn0Vrfq96r72NhVUz9RlDX08u1WaTBVLbYX4FNr39sttde1Eaxj8BIS5uE2X23a6vFZkdTn47ggodn4iYpxLcPLyCHhQiVJOaLnxwqUbXScOmd5YIxhGJzayvGlcpVKbt2TYGlMT0f8pRNZQiGzrzUQWbC2ymyjqLqN5ETyF6O9aMcvup+wv4C/67Bzl0iWAY4tmxDizyohfbQnGoQQzGfU44q14uKcgJKUKtyBdELAfCKWy9fa943rkQarKPgrn1gdiIEDesnhnYerOdoXrdFs4DVMPNzDV5SWB/2Fkqnf2Hpo2DkxatSOVVsX8v2i9+FCEFUg0/XL9nnQ1nQDv4LSN3m6bHHu3PW1TwekaefdBAu/IzyXmj2htvE9W2TlF2azLHkksDNNeVZ3KziQKJ6J0wa+VPZEoLqS3Kz6RKMeb2fbFavciyfDSjPjMIj2yaMcbgMmZxaQM+QZPfI/kDV/cCalAccs6wFRidqKwZoeD9ZDWV5W9B3IYS4SOjj1pPaDR7PUsmszkTcZ3cshDPMGoiFezg4aF5y52t6srL2mnQ6x5DvkRIETd2YGvtmWGUxqLNuCgSJlSxZ6uOrQypTHe92JbJRF/dnj1NedbNuLXd+58tyKYzK9U0Y6cUaptordilDKokEf+b7BeRbC+66C7omDaaPHOudlpbhZMgwZPhA6oNphuKuy+dDDtxOL0/oLpQgU4wFg6uxrU5l/ZSWytvvUlnz2RoVvJl0U9imfxGK70UsvLyRprjJuLg7pToKQ45LyQKsBO87bVEPFA2qZXBLMP2tcVQXmh0o2e6KCRaZjvBa5kOoRhEW8skocYms1GU+FTHNNClrWWRKjCI9441zO08lGOofHIZHsQ+ThHU5iY6AV2FufoqtWTd0/ssl6/GmI3BD62xAl5WWKLCiFV9NbElqPiv8ROkGkLyCjuxFRMbFUk9+6J3TooYhsCsU3xsnBpjy2YT/YHSaoidusvsV8gtiC5puIqt5LYYvC2CbHbd99njvfp1P36ZYo+G5ozub1U3N8I0WxKr+cNZ45D14bEuxsWniyTaUvcb7vGbqSyVfGCS8MlUM5m7i/N9VOUfeREu8BYMSErB3vpqEx1EwSoVp82wJgkV39dJ6Hv6k8UGWf/AQ==</diagram></mxfile>

@ -12,39 +12,6 @@
#include <time.h>
#include <sys/time.h>
#include "ser.h"
#include "videodev.h"
/*
* Convert v4l2 pixelformat to the corresponding ser format.
* Also return depth per channel.
*/
int ser_convert_type_to_ser (int v4l2_fmt, int *pixeldepth, int *serformat) {
if (pixeldepth == NULL || serformat == NULL) return 0;
switch (v4l2_fmt) {
case (V4L2_PIX_FMT_RGB24):
*serformat = SER_COLORID_RGB;
*pixeldepth = 8;
break;
case (V4L2_PIX_FMT_BGR24):
*serformat = SER_COLORID_BGR;
*pixeldepth = 8;
break;
case (V4L2_PIX_FMT_SGRBG8):
*serformat = SER_COLORID_BAYER_GRBG;
*pixeldepth = 8;
break;
case (V4L2_PIX_FMT_SGRBG16):
*serformat = SER_COLORID_BAYER_GRBG;
*pixeldepth = 16;
break;
default: return 0;
}
return 1;
}
SER::SER() {
/* clear header */
@ -54,7 +21,7 @@ SER::SER() {
memcpy(header.FileID, "LUCAM-RECORDER", strlen("LUCAM-RECORDER"));
header.LuID = 0;
header.ColorID = SER_COLORID_RGB;
header.LittleEndian = 0; // opposite meaning of the specification
header.LittleEndian = 1;
header.ImageWidth = 0;
header.ImageHeight = 0;
header.PixelDepthPerPlane = 8;
@ -84,7 +51,7 @@ SER::~SER() {
if(!Reading) {
int err;
int64_t offset = (int64_t)&header.FrameCount - (int64_t)&header;
long offset = (long)&header.FrameCount - (long)&header;
header.FrameCount = FramePointer;
/* goto file beginning */
@ -220,8 +187,8 @@ int SER::writeHeader(void) {
}
/* allocate some memory for the upcoming timestamps */
if((TimeStamps = (int64_t *)malloc(sizeof(header.DateTime) * NumberOfTimeStamps)) == NULL) {
fprintf(stderr, "Error: failed to allocate %llu bytes for timestamps\n",
(long long unsigned int) sizeof(header.DateTime) * (long)NumberOfTimeStamps);
fprintf(stderr, "Error: failed to allocate %lu bytes for timestamps\n",
sizeof(header.DateTime) * (long)NumberOfTimeStamps);
return -1;
}
@ -267,7 +234,7 @@ int SER::appendFrame(void *data) {
fprintf(stderr, "Error: appending frame, SER file not yet specified\n");
return -1;
}
/* write frame data */
if(fwrite(data, FrameSize, 1, FileDesc) != 1) {
fprintf(stderr, "Error: failed write SER frame (%s)\n", strerror(errno));
@ -276,11 +243,10 @@ int SER::appendFrame(void *data) {
/* ensure we have enough memory allocated for timestamps */
if(FramePointer >= NumberOfTimeStamps) {
while(FramePointer >= NumberOfTimeStamps)
NumberOfTimeStamps *= 2;
NumberOfTimeStamps *= 2;
if((TimeStamps = (int64_t *)realloc(TimeStamps, sizeof(header.DateTime) * NumberOfTimeStamps)) == NULL) {
fprintf(stderr, "Error: failed to re-allocate %llu bytes for timestamps\n",
(long long unsigned int) sizeof(header.DateTime) * (long)NumberOfTimeStamps);
fprintf(stderr, "Error: failed to re-allocate %lu bytes for timestamps\n",
sizeof(header.DateTime) * (long)NumberOfTimeStamps);
return -1;
}
}
@ -517,7 +483,7 @@ int64_t SER::differenceLocalUTC(void) {
/* Unfortunately, GMT still has summer time. Get rid of it:*/
if (gmt_time_info.tm_isdst == 1) gmt_ts -= 3600;
fprintf(stdout, "Debug: difference between local time and UTC is %lld hours\n",
(long long int)(loc_ts - gmt_ts) / 3600);
fprintf(stdout, "Debug: difference between local time and UTC is %ld hours\n",
(loc_ts - gmt_ts) / 3600);
return ((int64_t)loc_ts - (int64_t)gmt_ts) * 10000000L;
}

@ -38,9 +38,6 @@
*/
int ser_convert_type_to_ser (int v4l2_fmt, int *pixeldepth, int *serformat);
enum {
SER_COLORID_MONO = 0,
SER_COLORID_BAYER_RGGB = 8,
@ -90,7 +87,7 @@ class SER {
void updateHeaderData(void);
int64_t differenceLocalUTC(void);
public:
SER();
~SER();

@ -2,16 +2,7 @@
#ifndef _SIMPLESKYCAM_H_
#define _SIMPLESKYCAM_H_
#include "config.h"
#include "gui.h"
#include "debug.h"
extern void errorexit(char *fmt, ...);
extern void calc_vec2anglelen(position_f_2d *p, vector_2d *v);
#define sindeg(_angle_) sin((M_PI * (_angle_) / 180.0))
#define cosdeg(_angle_) cos((M_PI * (_angle_) / 180.0))
#endif

File diff suppressed because it is too large Load Diff

@ -9,16 +9,13 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "gui.h"
#include "output.h"
#include "filter.h"
#include "detect.h"
#include "configuration.h"
#include "video.h"
#include "videodev.h"
#include "histogram.h"
#include "simpleskycam.h"
VideoDev *videodev = NULL;
GThread *videodev_thread = NULL;
@ -31,9 +28,11 @@ extern position_2d video_enterdata_pos;
extern detect_movement detectedpos_data;
extern Configuration config;
void videoctrl_grid_delete ();
void videoctrl_grid_build ();
/*
* stop video recording
*/
@ -122,13 +121,10 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
char txt2[255];
GdkRGBA color;
static GtkWidget *e_x = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posx"));
static GtkWidget *e_y = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posy"));
static GtkWidget *e_w = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-w"));
static GtkWidget *e_h = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-h"));
static GtkWidget *lbX = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "lb_input_xdelta"));
static GtkWidget *lbY = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "lb_input_ydelta"));
GtkWidget *e_x = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posx"));
GtkWidget *e_y = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posy"));
GtkWidget *e_w = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-w"));
GtkWidget *e_h = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-h"));
int x, y, w1, h1;
if (video_da == NULL) return;
@ -155,38 +151,6 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
g_object_unref (pixbuf);
//
// need to draw the new destination?
if (video_enterdata == VID_ENTERDATA_SETDEST) {
color.blue = 1.0;
color.red = 0.0;
color.green = 1.0;
color.alpha = 1.0;
gdk_cairo_set_source_rgba(cr, &color);
cairo_move_to(cr, S_X(video_enterdata_pos.x)-10, S_Y(video_enterdata_pos.y)-10);
cairo_line_to(cr, S_X(video_enterdata_pos.x)+10, S_Y(video_enterdata_pos.y)+10);
cairo_move_to(cr, S_X(video_enterdata_pos.x)+10, S_Y(video_enterdata_pos.y)-10);
cairo_line_to(cr, S_X(video_enterdata_pos.x)-10, S_Y(video_enterdata_pos.y)+10);
cairo_stroke(cr);
}
else if (posctl_threaddata.target_pos.x != -1 and posctl_threaddata.target_pos.y != -1) {
color.blue = 0.0;
color.red = 0.0;
color.green = 0.5;
color.alpha = 1.0;
gdk_cairo_set_source_rgba(cr, &color);
cairo_move_to(cr, S_X(posctl_threaddata.target_pos.x), S_Y(posctl_threaddata.target_pos.y)-5);
cairo_line_to(cr, S_X(posctl_threaddata.target_pos.x), S_Y(posctl_threaddata.target_pos.y)+5);
cairo_move_to(cr, S_X(posctl_threaddata.target_pos.x)-5, S_Y(posctl_threaddata.target_pos.y));
cairo_line_to(cr, S_X(posctl_threaddata.target_pos.x)+5, S_Y(posctl_threaddata.target_pos.y));
cairo_stroke(cr);
}
//
// need to draw the select new position cross
if (video_enterdata == VID_ENTERDATA_POS) {
@ -265,50 +229,45 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
}
// draw movement vector to screen
snprintf (txt1, 255, "X: %f", detectedpos_data.dx);
snprintf (txt2, 255, "Y: %f", detectedpos_data.dy);
gtk_label_set_text(GTK_LABEL(lbX), txt1);
gtk_label_set_text(GTK_LABEL(lbY), txt2);
if (config.GetCalibrationShowData()) {
// printf ("%s:%d posctl_threaddata.c : %d \t %d -> \t %d \t %d\n", __FILE__, __LINE__,
// posctl_threaddata.c[0].x, posctl_threaddata.c[0].y,
// posctl_threaddata.c[1].x, posctl_threaddata.c[1].y);
// printf ("%s:%d posctl_threaddata.a1: %d \t %d -> \t %d \t %d\n", __FILE__, __LINE__,
// posctl_threaddata.a1[0].x, posctl_threaddata.a1[0].y,
// posctl_threaddata.a1[1].x, posctl_threaddata.a1[1].y);
// printf ("%s:%d posctl_threaddata.a2: %d \t %d -> \t %d \t %d\n", __FILE__, __LINE__,
// posctl_threaddata.a2[0].x, posctl_threaddata.a2[0].y,
// posctl_threaddata.a2[1].x, posctl_threaddata.a2[1].y);
if (posctl_threaddata.c[0].x != -1 && posctl_threaddata.c[0].y != -1 &&
posctl_threaddata.c[1].x != -1 && posctl_threaddata.c[1].y != -1) {
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr, S_X(posctl_threaddata.c[0].x), S_Y(posctl_threaddata.c[0].y));
cairo_line_to(cr, S_X(posctl_threaddata.c[1].x), S_Y(posctl_threaddata.c[1].y));
cairo_stroke(cr);
}
if (posctl_threaddata.a1[0].x != -1 && posctl_threaddata.a1[0].y != -1 &&
posctl_threaddata.a1[1].x != -1 && posctl_threaddata.a1[1].y != -1) {
cairo_set_source_rgb(cr, 1.0, 0.5, 1.0);
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr, S_X(posctl_threaddata.a1[0].x), S_Y(posctl_threaddata.a1[0].y));
cairo_line_to(cr, S_X(posctl_threaddata.a1[1].x), S_Y(posctl_threaddata.a1[1].y));
cairo_stroke(cr);
snprintf (txt1, 255, "%f", detectedpos_data.dx);
snprintf (txt2, 255, "%f", detectedpos_data.dy);
for (int i = 0; i < 5; i++) {
int dx, dy;
switch (i) {
case 0:
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
dx = -1;
dy = 0;
break;
case 1:
dx = +1;
dy = 0;
break;
case 2:
dx = 0;
dy = -1;
break;
case 3:
dx = 0;
dy = +1;
break;
case 4:
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
dx = 0;
dy = 0;
break;
}
if (posctl_threaddata.a2[0].x != -1 && posctl_threaddata.a2[0].y != -1 &&
posctl_threaddata.a2[1].x != -1 && posctl_threaddata.a2[1].y != -1) {
cairo_set_source_rgb(cr, 1.0, 0.5, 1.0);
cairo_set_line_width(cr, 1.0);
cairo_move_to(cr, S_X(posctl_threaddata.a2[0].x), S_Y(posctl_threaddata.a2[0].y));
cairo_line_to(cr, S_X(posctl_threaddata.a2[1].x), S_Y(posctl_threaddata.a2[1].y));
cairo_stroke(cr);
}
}
#ifdef DEBUG_ANGLES
debug_angles_draw(cr);
#endif
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 12);
cairo_move_to (cr, 10+dx, 15+dy);
cairo_show_text(cr, txt1);
cairo_stroke(cr);
cairo_move_to (cr, 10+dx, 30+dy);
cairo_show_text(cr, txt2);
cairo_stroke(cr);
}
};
@ -336,16 +295,10 @@ void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data) {
devlist.clear();
VideoDev_Dumpfile vdef1; vdef1.GetDeviceList(&devlist);
#ifdef USE_V4L2
VideoDev_V4L2 vdef2; vdef2.GetDeviceList(&devlist);
#endif
#ifdef USE_SVBONY
VideoDev_SVBCam vdef3; vdef3.GetDeviceList(&devlist);
#endif
#ifdef USE_VFW
VideoDev_VFW vdef4; vdef4.GetDeviceList(&devlist);
#endif
VideoDev_Simulation vdef5; vdef5.GetDeviceList(&devlist);
for (iter = devlist.begin(); iter != devlist.end(); iter++) {
gtk_list_store_insert_with_values(GTK_LIST_STORE(model), NULL, -1,
@ -387,17 +340,11 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) {
//
// load the selected driver
if (driver.compare("VIDEODUMP") == 0) videodev = new VideoDev_Dumpfile;
#ifdef USE_V4L2
else if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2;
#endif
if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2;
#ifdef USE_SVBONY
else if (driver.compare("SVBCAM") == 0) videodev = new VideoDev_SVBCam;
#endif
#ifdef USE_VFW
else if (driver.compare("VFW") == 0) videodev = new VideoDev_VFW;
#endif
else if (driver.compare("SIMULATION") == 0) videodev = new VideoDev_Simulation;
else if (driver.compare("VIDEODUMP") == 0) videodev = new VideoDev_Dumpfile;
else videodev = new VideoDev;
std::string format = gtk_entry_get_text(GTK_ENTRY(cbfmtentry));
@ -411,7 +358,7 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) {
videodev->SetConfig(device, w, h, format, parameter, cb_thread_video);
videodev_thread = g_thread_new(driver.c_str(), videodev_threadprocess_wrapper, NULL);
// FIXME: workaround, solution should be: create a timer and request all controls
// FIXME: workaround, soltuion should be: create a timer and request all controls
};
@ -474,7 +421,7 @@ void videoctrl_grid_build () {
gtk_range_set_value(GTK_RANGE(scale),value);
gtk_widget_set_hexpand (scale,true);
gtk_scale_set_draw_value(GTK_SCALE(scale), false);
g_signal_connect (GTK_RANGE(scale), "value-changed", G_CALLBACK(cb_vidctrl_scale_change), (void*)(size_t)i);
g_signal_connect (GTK_RANGE(scale), "value-changed", G_CALLBACK(cb_vidctrl_scale_change), (void*)(long int)i);
}
else {
printf ("%s:%d control %s check not valid min[%d] < max[%d]\n", __FILE__, __LINE__, iter->c_str(), min, max);
@ -484,7 +431,7 @@ void videoctrl_grid_build () {
// entry field
GtkWidget *entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), std::to_string(value).c_str());
g_signal_connect (entry, "activate", G_CALLBACK(cb_vidctrl_entry_change), (void*)(size_t)i);
g_signal_connect (entry, "activate", G_CALLBACK(cb_vidctrl_entry_change), (void*)(long int)i);
gtk_grid_insert_row(GTK_GRID(grid), i);
if (i == 0) {
@ -524,30 +471,26 @@ void cb_video_btnstop (GtkWidget *widget, gpointer data) {
* Access to this data must be Locked before use.
*/
gboolean cb_thread_video (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"));
GtkWidget *btnstart;
GtkWidget *btnstop;
VideoDevThreadData *cbdata = (VideoDevThreadData*) data;
VideoFrame *vf = NULL;
VideoFrameRaw *vfr = NULL;
if (videodev == NULL) return false;
// printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
//
// after video starts, on the first frame
// read out all controls
if (cbdata != NULL) {
vf = &cbdata->vf;
vfr = &cbdata->vfr;
if (cbdata->running == 1) {
videoctrl_grid_build();
cbdata->running = 2;
}
if (vf->w <= 0 || vf->h <= 0 || vf->data == NULL) vf = NULL;
if (vfr->w <= 0 || vfr->h <= 0 || vfr->data == NULL) vfr = NULL;
if (vf->w <= 0 || vf->h <= 0) vf = NULL;
}
if (videodev == NULL) return false;
btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop"));
btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec"));
//
// create video drawarea if needed
if (video_da == NULL)
video_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "video-da"));
@ -556,9 +499,6 @@ gboolean cb_thread_video (gpointer data) {
memset (gdk_pixbuf_get_pixels(video_pixbuf), 0, 3 * gdk_pixbuf_get_height(video_pixbuf) * gdk_pixbuf_get_width(video_pixbuf));
}
//
// if cbdata not set, we have a error on the video stream
// stop recording. Else push framedata into the detect thread.
if (cbdata == NULL) {
printf ("%s:%d %s something went wrong CBData == NULL\n", __FILE__, __LINE__, __FUNCTION__);
videodev->Stop();
@ -572,9 +512,6 @@ gboolean cb_thread_video (gpointer data) {
int pix_h, pix_w;
videodev->LockMutex();
//
// check and resize video_drawarea if needed
if (video_pixbuf) {
pix_h = gdk_pixbuf_get_height(video_pixbuf);
pix_w = gdk_pixbuf_get_width(video_pixbuf);
@ -589,14 +526,9 @@ gboolean cb_thread_video (gpointer data) {
pix_w = vf->w;
pix_h = vf->h;
}
vf->ToPixbuf(&video_pixbuf); // convert Frame to pixeldata
histogram_update(vf); // update histogram
detect.CopyNewFrame(vf, vfr); // push new data to detect object
vf->ToPixbuf(video_pixbuf);
detect.NewFrame(vf);
videodev->UnLockMutex();
// redraw drawarea on screen.
gdk_window_invalidate_rect(gtk_widget_get_window(video_da), NULL, true);
}
@ -620,7 +552,7 @@ void cb_vidctrl_scale_change (GtkRange *range, gpointer data) {
GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid"));
GtkWidget *scale = NULL;
GtkWidget *label = NULL;
int64_t idx = (int64_t)data;
int idx = (long int)data;
double value;
label = gtk_grid_get_child_at(GTK_GRID(grid), 0, idx);
@ -639,7 +571,7 @@ void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data) {
GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid"));
GtkWidget *label = NULL;
GtkWidget *entry = NULL;
int64_t idx = (int64_t)data;
int idx = (long int)data;
int value;
label = gtk_grid_get_child_at(GTK_GRID(grid), 0, idx);
@ -651,9 +583,6 @@ void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data) {
};
/*
*
*/
void cb_videoda_motionevent (GtkWidget *widget, GdkEvent *event, gpointer data) {
int dw, dh, sw, sh;
float sar, dar;
@ -680,10 +609,6 @@ void cb_videoda_motionevent (GtkWidget *widget, GdkEvent *event, gpointer data)
gdk_window_invalidate_rect(gtk_widget_get_window(video_da), NULL, true);
}
#ifdef DEBUG_ANGLES
debug_angles_motionevent(event);
#endif
};
@ -691,10 +616,6 @@ void cb_videoda_btnpress (GtkWidget *widget, GdkEvent *event, gpointer data) {
int x = event->motion.x;
int y = event->motion.y;
#ifdef DEBUG_ANGLES
debug_angles_btnpress(event);
#endif
printf ("%s:%d %s %d, %d\n", __FILE__, __LINE__, __FUNCTION__, x, y);
};
@ -831,16 +752,11 @@ void cb_video_cbox_videodev (GtkWidget *widget, gpointer data) {
//
// load the selected driver
if (driver.compare("DUMMY") == 0) videodev = new VideoDev;
#ifdef USE_V4L2
else if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2;
#endif
if (driver.compare("V4L2") == 0) videodev = new VideoDev_V4L2;
#ifdef USE_SVBONY
else if (driver.compare("SVBCAM") == 0) videodev = new VideoDev_SVBCam;
#endif
#ifdef USE_VFW
else if (driver.compare("VFW") == 0) videodev = new VideoDev_VFW;
#endif
else if (driver.compare("DUMMY") == 0) videodev = new VideoDev;
else videodev = new VideoDev;
videodev->GetDeviceFormats(device, &lst_format);
@ -855,46 +771,17 @@ void cb_video_cbox_videodev (GtkWidget *widget, gpointer data) {
videodev->GetDeviceResolutions(device, &lst_format);
delete videodev;
videodev = NULL;
};
/*
* resize windows depending on the button which was pressed
*/
void cb_input_btnscale (GtkWidget *widget, gpointer data) {
int dw, dh, ww, wh;
float scale = 1.0;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (videodev == NULL || video_da == NULL) return;
//
// what scale button was pressed
GtkWidget *btn11 = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputscale11"));
GtkWidget *btn12 = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputscale12"));
GtkWidget *btn14 = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn_inputscale14"));
if (widget == btn11) scale = 1.0;
if (widget == btn12) scale = 0.5;
if (widget == btn14) scale = 0.25;
// get resolution
//
// read our video size from gui and calculate size of gui elements
GtkWidget *win = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "window-input"));
gtk_window_get_size(GTK_WINDOW(win), &ww, &wh);
dh = gtk_widget_get_allocated_height(video_da);
dw = gtk_widget_get_allocated_width(video_da);
dw = ww-dw;
dh = wh-dh;
// get controls
videodev->GetVideoInfo(&ww, &wh, NULL);
ww = dw + (scale * ww) + 1;
wh = dh + (scale * wh);
//
// close device
gtk_window_resize(GTK_WINDOW(win), ww, wh);
delete videodev;
videodev = NULL;
};

@ -11,6 +11,7 @@
#include <list>
#include <stdint.h>
#include <jpeglib.h>
#include <linux/videodev2.h>
#include <setjmp.h>
#include "json.h"

@ -16,9 +16,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#ifndef BUILD_WINDOWS
#include <linux/videodev2.h>
#endif
#include <list>
#include <string>
@ -32,7 +30,7 @@ class VideoDev_Dummy: public VideoDev {
private:
ConvertData cdata;
int Grab(VideoFrameRaw *vf);
int Grab(VideoFrame *vf);
int Open();
int Close();
int CaptureStart();

@ -7,31 +7,20 @@
* This is needed only for debugging.
************************************************************************************/
/* enable files > 2GB on 32 bit systems */
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <fcntl.h>
#ifdef BUILD_WINDOWS
#include <winsock2.h>
#include <io.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif
#include <sys/stat.h>
#include "convert.h"
#include "configuration.h"
#include "videodev-dumpfile.h"
VideoDev_Dumpfile::VideoDev_Dumpfile() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
filesize = 0;
filepos = 0;
fd = -1;
w = 0;
h = 0;
@ -40,7 +29,6 @@ VideoDev_Dumpfile::VideoDev_Dumpfile() {
inframe_size = 0;
inframe_maxsize = 0;
inframe_nexttime = 0;
fixedframesize = 0;
};
@ -72,19 +60,16 @@ int VideoDev_Dumpfile::GetDeviceList(std::list<std::string> *list) {
}
while ((de = readdir (dir))) {
#ifndef BUILD_WINDOWS
if (de->d_type & DT_REG) {
#endif
for (i = 0; i < 255 && de->d_name[i] != 0; i++) fname[i] = toupper(de->d_name[i]);
fname[i] = 0;
if (strstr (fname, ".VIDEODUMP") != NULL) {
device = (std::string) "VIDEODUMP " + (std::string) de->d_name;
list->push_back(device);
}
#ifndef BUILD_WINDOWS
}
#endif
}
closedir(dir);
return 1;
@ -97,37 +82,17 @@ int VideoDev_Dumpfile::GetDeviceList(std::list<std::string> *list) {
* prepare the buffer, InitMMAP and read all controls
*/
int VideoDev_Dumpfile::Open() {
if (config.readdumppath == NULL) return VDEV_STATUS_ERROR;
std::string fname = config.readdumppath;
fname = fname + "/" + conf_device;
VideoDevCtrl vctl;
uint32_t inbuf[3];
int i;
struct stat s;
std::string fname = config.readdumppath;
fname = fname + "/" + conf_device;
printf ("%s:%d %s file %s\n", __FILE__, __LINE__, __FUNCTION__, fname.c_str());
if (fd >= 0) close (fd);
fd = -1;
//
// read filesize
if (stat (fname.c_str(), &s) != 0) {
printf ("%s:%d %s could not read stat of file '%s'. Error:%s\n", __FILE__, __LINE__, __FUNCTION__,
fname.c_str(), strerror(errno));
Close();
return VDEV_STATUS_ERROR;
}
filesize = s.st_size;
#ifdef BUILD_WINDOWS
if ((fd = open(fname.c_str(), O_RDONLY | O_BINARY)) == -1) {
#else
if ((fd = open(fname.c_str(), O_RDONLY)) == -1) {
#endif
printf ("%s:%d could not open file '%s' error:%s\n", __FILE__, __LINE__, fname.c_str(), strerror(errno));
return VDEV_STATUS_ERROR;
}
@ -141,19 +106,9 @@ int VideoDev_Dumpfile::Open() {
return VDEV_STATUS_ERROR;
}
i = 0;
filepos = 12;
conf_width = w = ntohl(inbuf[i++]);
conf_height = h = ntohl(inbuf[i++]);
w = ntohl(inbuf[i++]);
h = ntohl(inbuf[i++]);
pixformat = ntohl(inbuf[i++]);
conf_format = convert_from_pixelformat (pixformat);
vidctrls.clear();
vctl.name = "FilePosition";
vctl.id = 1;
vctl.min = 0;
vctl.max = 255;
vctl.value = 0;
vidctrls.push_back(vctl);
return VDEV_STATUS_OK;
};
@ -169,8 +124,6 @@ int VideoDev_Dumpfile::Close() {
if (fd >= 0) {
close(fd);
fd = -1;
filesize = 0;
filepos = 0;
}
return VDEV_STATUS_OK;
@ -194,7 +147,8 @@ int VideoDev_Dumpfile::CaptureStart() {
// read timestamp and first header and frame
gettimeofday(&starttv, NULL);
pixelformat = pixformat;
ConvertStart(&cdata, pixformat);
ReadFrame();
return VDEV_STATUS_OK;
@ -214,6 +168,9 @@ int VideoDev_Dumpfile::CaptureStop() {
inframe_size = 0;
inframe = NULL;
}
ConvertStop(&cdata, pixformat);
return VDEV_STATUS_OK;
};
@ -223,12 +180,9 @@ int VideoDev_Dumpfile::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.
*/
#define SIZE_FRAMEHEADER 8
#define SIZE_DUMPHEADER 12
int VideoDev_Dumpfile::Grab(VideoFrameRaw *vf) {
int VideoDev_Dumpfile::Grab(VideoFrame *vf) {
struct timeval curtv;
unsigned int diff = 0;
std::list<VideoDevCtrl>::iterator ctrl;
if (fd == -1) return VDEV_STATUS_ERROR;
@ -243,49 +197,17 @@ int VideoDev_Dumpfile::Grab(VideoFrameRaw *vf) {
usleep ((inframe_nexttime-diff)*1000);
} while (diff < inframe_nexttime);
// if (diff - inframe_nexttime > 1000)
// printf ("%s:%d time difference to big. (%dms) Maybe to slow hard drive?\n",
// __FILE__, __LINE__, (diff - inframe_nexttime));
if (diff - inframe_nexttime > 1000)
printf ("%s:%d time difference to bit. (%dms) Maybe to slow hard drive?\n",
__FILE__, __LINE__, (diff - inframe_nexttime));
LockMutex();
vf->CopyFrom(pixformat, w, h, inframe_size, inframe);
Convert(&cdata, vf, inframe, inframe_size, pixformat, w, h);
UnLockMutex();
ctrl = vidctrls.begin();
if (ctrl->value == 0) {
// fixed framesize -> calculate frames
switch (pixformat) {
case(V4L2_PIX_FMT_RGB24):
case(V4L2_PIX_FMT_BGR24):
fixedframesize = 3 * w * h;
break;
case(V4L2_PIX_FMT_RGB32):
case(V4L2_PIX_FMT_BGR32):
fixedframesize = 4 * w * h;
break;
case(V4L2_PIX_FMT_SGRBG8):
fixedframesize = 1 * w * h;
break;
case(V4L2_PIX_FMT_SGRBG16):
fixedframesize = 2 * w * h;
break;
default:
ctrl->max = 0;
ctrl->value = -1;
fixedframesize = 0;
break;
}
if (fixedframesize > 0)
ctrl->max = (filesize-SIZE_DUMPHEADER) / (fixedframesize + SIZE_FRAMEHEADER);
}
if (ctrl->value != -1) ctrl->value++;
//
// read next frame
LockMutex();
ReadFrame();
UnLockMutex();
return VDEV_STATUS_OK;
}
@ -299,30 +221,11 @@ int VideoDev_Dumpfile::ReadFrame() {
if (fd < 0) return VDEV_STATUS_ERROR;
//
// check position, if end of file restart from beginning
if (filepos == filesize) {
printf ("%s:%d end of file start with first frame\n", __FILE__, __LINE__);
std::list<VideoDevCtrl>::iterator ctrl;
ctrl = vidctrls.begin();
ctrl->value = 0;
if (lseek(fd, 12, SEEK_SET) != 12) {
printf ("%s:%d %s lseek returned: %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno));
Close();
}
else { // reset filepos and starttime
filepos = 12;
gettimeofday(&starttv, NULL);
}
}
//
// read frame
// read header
if (read (fd, inbuf, 4*2) != 4*2) {
printf ("%s:%d could not read frame header: %s\n", __FILE__, __LINE__, strerror(errno));
printf ("%s:%d could not read frame header\n", __FILE__, __LINE__);
Close();
}
filepos += (4*2);
inframe_size = ntohl(inbuf[0]);
inframe_nexttime = ntohl(inbuf[1]);
@ -339,14 +242,14 @@ int VideoDev_Dumpfile::ReadFrame() {
// allocate memory and read frame
if (inframe == NULL) {
Close();
printf ("%s:%d could not allocate enough memory\n", __FILE__, __LINE__);
printf ("%s:%d cloud not allocate enought memory\n", __FILE__, __LINE__);
return VDEV_CBSTATUS_ERROR;
}
if (read (fd, inframe, inframe_size) != inframe_size) {
printf ("%s:%d could not read frame: %s\n", __FILE__, __LINE__, strerror(errno));
Close();
printf ("%s:%d could not read frame\n", __FILE__, __LINE__);
Close();
}
filepos += inframe_size;
return VDEV_STATUS_OK;
}
@ -361,41 +264,6 @@ int VideoDev_Dumpfile::ReadFrame() {
* set video control identified by id
*/
int VideoDev_Dumpfile::SetDevCtrl(unsigned int id, int value) {
std::list<VideoDevCtrl>::iterator ctrl;
int framerest;
off_t newfilepos = 0;
printf ("%s:%d VideoDev_Dumpfile::SetDevCtrl Set Offset to %d id:%d fixedframesize:%d\n", __FILE__, __LINE__, value, id, fixedframesize);
struct timeval curtv;
if (id == 1) {
ctrl = vidctrls.begin();
if (value != ctrl->value && value < ctrl->max) {
filepos = SIZE_DUMPHEADER + ((off_t)value * (SIZE_FRAMEHEADER + (off_t)fixedframesize));
printf ("%s:%d filepos:%ld\n", __FILE__, __LINE__, filepos);
if ((newfilepos = lseek (fd, filepos, SEEK_SET)) < 0) {
printf ("%s:%d ******* lseek error:%s\n", __FILE__, __LINE__, strerror(errno));
}
else {
framerest = (newfilepos - SIZE_DUMPHEADER)%(SIZE_FRAMEHEADER + fixedframesize);
ctrl->value = (newfilepos - SIZE_DUMPHEADER)/(SIZE_FRAMEHEADER + fixedframesize);
if (ctrl->value != value || framerest != 0) {
printf ("%s:%d could not set file to correct position. ctrl->value:%d value:%d Framerest:%d\n", __FILE__, __LINE__, ctrl->value, value, framerest);
}
else {
//
// read first frame
ReadFrame();
gettimeofday(&curtv, NULL);
starttv.tv_sec = curtv.tv_sec - (inframe_nexttime/1000);
}
}
}
// else printf ("%s:%d could not set video position (ctrl->value:%d value:%d max:%d)\n",
// __FILE__, __LINE__, ctrl->value, value, ctrl->max);
}
return VDEV_STATUS_OK;
};

@ -10,17 +10,19 @@
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
// #include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
// #include <sys/mman.h>
// #include <linux/videodev2.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <list>
#include <string>
#include "convert.h"
#include "gui.h"
#include "videodev.h"
@ -32,16 +34,13 @@ private:
uint32_t w;
uint32_t h;
uint32_t pixformat;
off_t filesize;
off_t filepos;
struct timeval starttv;
unsigned char *inframe;
uint32_t inframe_nexttime;
int inframe_maxsize;
int inframe_size;
int fixedframesize;
int Grab(VideoFrameRaw *vf);
int Grab(VideoFrame *vf);
int Open();
int Close();
int CaptureStart();

@ -1,372 +0,0 @@
/************************************************************************************
* videodev-simulation:
* creates an black screen with an small white circle at a simulated movement
* needed for testing the PID functionality
*
* This is needed only for debugging.
************************************************************************************/
#include <ctype.h>
#ifdef BUILD_WINDOWS
#include "windows.h"
#else
#include <arpa/inet.h>
#endif
#include <sys/stat.h>
#include <math.h>
#include "debug.h"
#include "convert.h"
#include "configuration.h"
#include "videodev-simulation.h"
#define SIMULATION_MOTORSPEEDUP 1.0
Simulation simulation;
gpointer simulation_threadprocess_wrapper (gpointer data);
void cb_posctl_btnsimreset (GtkWidget *widget, gpointer data) {
simulation.Reset();
}
VideoDev_Simulation::VideoDev_Simulation() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
conf_width = 1920;
conf_height = 1080;
inframe = NULL;
simulation_thread = NULL;
};
VideoDev_Simulation::~VideoDev_Simulation() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (inframe != NULL) Close();
inframe = NULL;
}
/*
* searchs in the given path for any videodump files and present them as
* video device.
*/
int VideoDev_Simulation::GetDeviceList(std::list<std::string> *list) {
list->push_back("SIMULATION");
return 1;
}
/*
* Open Device
* prepare the buffer, InitMMAP and read all controls
*/
int VideoDev_Simulation::Open() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (inframe != NULL) Close();
conf_format = convert_from_pixelformat (V4L2_PIX_FMT_RGB24);
simulation.SetResolution(conf_width, conf_height);
simulation_thread = g_thread_new("Simulation", simulation_threadprocess_wrapper, NULL);
inframe = (unsigned char *) malloc (conf_width * conf_height * 3);
return VDEV_STATUS_OK;
};
/*
* Close Device
* Free videobuffer
*/
int VideoDev_Simulation::Close() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (inframe != NULL) {
free (inframe);
inframe = NULL;
}
simulation.Stop();
return VDEV_STATUS_OK;
};
/*****************************************************************************************************
* VideoGrabbing
*/
/*
* send the start capture signal to the cam
*/
int VideoDev_Simulation::CaptureStart() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (inframe != NULL) Close();
if (Open() != VDEV_STATUS_OK) return VDEV_STATUS_ERROR;
pixelformat = V4L2_PIX_FMT_RGB24;
get_cycletime(&lastframetv);
return VDEV_STATUS_OK;
};
int VideoDev_Simulation::CaptureStop() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (inframe != NULL) Close();
return VDEV_STATUS_OK;
};
/*
* try to grab one frame and convert it into RGB32.
* 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.
*/
#define SIMULATION_SIZE 16
#define SIMULATION_NOISE 15
int VideoDev_Simulation::Grab(VideoFrameRaw *vf) {
int posx, posy, x ,y, r, radius;
double a, dsec;
// try to match a speed of 20Hz
dsec = get_cycletime(&lastframetv);
if (dsec < 0.040) usleep (50000 - dsec*1000.0);
memset (inframe, 0x0, conf_width*conf_height*3);
simulation.GetPos(&posx, &posy);
radius = conf_width * SIMULATION_SIZE / 1920;
for (r = 1; r < radius; r++) for (a = 0; a < M_PI * 2.0; a += 0.1) {
x = posx + (sin(a) * r) + (SIMULATION_NOISE/2 - SIMULATION_NOISE *(float) rand()/ (float)RAND_MAX);
y = posy + (cos(a) * r) + (SIMULATION_NOISE/2 - SIMULATION_NOISE *(float) rand()/ (float)RAND_MAX);
if (x >= 0 && x < conf_width && y >= 0 && y < conf_height) {
inframe[3*(x+y*conf_width)+0] = 200;
inframe[3*(x+y*conf_width)+1] = 200;
inframe[3*(x+y*conf_width)+2] = 200;
}
}
LockMutex();
vf->CopyFrom(V4L2_PIX_FMT_RGB24, conf_width, conf_height, (conf_width*conf_height*3), inframe);
UnLockMutex();
return VDEV_STATUS_OK;
}
/*****************************************************************************************************
* Controls
*/
/*
* set video control identified by id
*/
int VideoDev_Simulation::SetDevCtrl(unsigned int id, int value) {
return VDEV_STATUS_OK;
};
/*
* get video control identified by id
*/
int VideoDev_Simulation::GetDevCtrl(unsigned int id, int *value) {
return VDEV_STATUS_OK;
};
/*********************************************************************************************************
* Simulation
*/
gpointer simulation_threadprocess_wrapper (gpointer data) {
simulation.ThreadProcess();
return NULL;
}
Simulation::Simulation() {
w = 1920;
h = 1080;
posX = w/2;
posY = h/2;
running = 0;
#ifdef DEBUG_POSCTL
debug_tofile((char*)"simulation.log", 1, (char*)"dAngle,dLen,x,y,dx,dy,timedelay,a1.defAngle,a1.defLen,a1.v,a1.dx,a1.dy,a2.defAngle,a2.defLen,a2.v,a2.dx,a2.dy,finalX,finalY\n");
#endif
Reset();
};
void Simulation::Reset() {
int i;
static int first = 1;
LockMutex();
if(first) {
time_t t = time(NULL);
srand (t);
first = 0;
}
//
// object movement
dAngle = 360.0 * (double)rand() / (double) RAND_MAX;
dLen = 1.0 + 5.0 * (double)rand() / (double) RAND_MAX;
printf ("%s:%d %s dAngle:%f dLen:%f\n", __FILE__, __LINE__, __FUNCTION__, dAngle, dLen);
//
// axis movement
i = 0;
axis[i % 2].defAngle = 180.0 + dAngle + (10.0 * (double)rand() / ((double) RAND_MAX)) - 5.0;
axis[i % 2].defLen = dLen + ((dLen/2.0) * (double)rand() / ((double) RAND_MAX) - (dLen/4.0));
axis[i % 2].v = 1.0;
axis[i % 2].vdest = 1.0;
axis[i % 2].active = 1;
i++;
axis[i % 2].defAngle = 180.0 + dAngle + (10.0 * (double)rand() / ((double) RAND_MAX)) + 85.0;
axis[i % 2].defLen = dLen + ((dLen/2.0) * (double)rand() / ((double) RAND_MAX) - (dLen/4.0));
axis[i % 2].v = 1.0;
axis[i % 2].vdest = 1.0;
axis[i % 2].active = 1;
// normalize angle between 0..360°
for (i = 0; i < 2; i++) {
while (axis[i].defAngle < 0.0) axis[i].defAngle += 360.0;
while (axis[i].defAngle > 360.0) axis[i].defAngle -= 360.0;
}
printf ("%s:%d %s Axis1: %f° Len:%f Axis2: %f° Len:%f\n", __FILE__, __LINE__, __FUNCTION__,
axis[0].defAngle,axis[0].defLen, axis[1].defAngle,axis[1].defLen);
UnLockMutex();
}
Simulation::~Simulation() {
LockMutex ();
running = 0;
UnLockMutex ();
};
void Simulation::GetPos (int *nx, int *ny) {
LockMutex();
if (nx != NULL) *nx = (int)posX;
if (ny != NULL) *ny = (int)posY;
UnLockMutex();
}
void Simulation::ThreadProcess() {
int r = 1;
struct timeval tv;
double ms;
double dx[3], dy[3];
#ifdef DEBUG_POSCTL
double x, y;
#endif
get_cycletime (&tv);
if (running) return;
running = 1;
do {
usleep (20000);
ms = get_cycletime(&tv);
LockMutex();
//
// simulate rotation movement
// calculate movement
dx[0] = sindeg(dAngle) * dLen * ms;
dy[0] = cosdeg(dAngle) * dLen * ms;
//
// simulate motor axis movement
for (int i = 0; i < 2; i++)
if (axis[i].active) {
dx[i+1] = sindeg(axis[i].defAngle) * axis[i].defLen * (1.0 + axis[i].v) * ms;
dy[i+1] = cosdeg(axis[i].defAngle) * axis[i].defLen * (1.0 + axis[i].v) * ms;
}
else {
dx[i+1] = 0.0;
dy[i+1] = 0.0;
}
// this is needed for debugging
#ifdef DEBUG_POSCTL
x = posX; y = posY;
#endif
posX = posX + dx[0] + dx[1] + dx[2];
posY = posY + dy[0] + dy[1] + dy[2];
if (posX < 0) posX = w - 1.0;
if (posY < 0) posY = h - 1.0;
if (posX > w) posX = 0.0;
if (posY > h) posY = 0.0;
for (int i = 0; i < 2; i++) {
axis[i].v = axis[i].v * (1.0-SIMULATION_MOTORSPEEDUP) + axis[i].vdest * SIMULATION_MOTORSPEEDUP;
}
// printf ("%s:%d axis %f (%f) %f (%f)\n", __FILE__, __LINE__, axis[0].v, axis[0].vdest, axis[1].v, axis[1].vdest);
#ifdef DEBUG_POSCTL
debug_tofile((char*)"simulation.log", 0, (char*)"%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g\n",
dAngle, dLen, x, y, dx[0], dy[0], ms,
axis[0].defAngle,axis[0].defLen,axis[0].v,dx[1],dy[1],
axis[1].defAngle,axis[1].defLen,axis[1].v,dx[2],dy[2],
posX, posY
);
#endif
r = running;
UnLockMutex();
} while (r);
running = 0;
}
void Simulation::Start() {
}
void Simulation::Stop() {
running = 0;
}
void Simulation::SetResolution (int w, int h) {
LockMutex();
this->w = w;
this->h = h;
posX = w / 2;
posY = h / 2;
UnLockMutex();
}
void Simulation::AxisSetValue (int a, double v) {
// printf ("%s:%d %s Axis:%d Value:%f\n", __FILE__, __LINE__, __FUNCTION__, a, v);
if (a < 0 || a > 1) return;
axis[a].vdest = v;
axis[a].active = 1;
}
void Simulation::AxisStop() {
// printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
axis[0].vdest = axis[0].v = 0.0;
axis[1].vdest = axis[1].v = 0.0;
axis[0].active = 0;
axis[1].active = 0;
}

@ -1,90 +0,0 @@
#ifndef _H_VIDEODEV_SIMULATION_H_
#define _H_VIDEODEV_SIMULATION_H_
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
//#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
//#include <sys/mman.h>
//#include <linux/videodev2.h>
#include <list>
#include <string>
#include "convert.h"
#include "gui.h"
#include "videodev.h"
struct SimAxisCtl {
int active;
double vdest;
double v;
double defLen;
double defAngle;
};
class Simulation {
private:
int w;
int h;
double posX;
double posY;
double dAngle;
double dLen;
int running;
struct SimAxisCtl axis[2];
GMutex mutex;
public:
Simulation();
~Simulation();
void GetPos (int *nx, int *ny);
void ThreadProcess();
void Start();
void Stop();
void Reset();
void AxisSetValue(int a, double v);
void AxisStop();
void SetResolution (int w, int h);
void LockMutex() { g_mutex_lock(&mutex); };
void UnLockMutex() { g_mutex_unlock(&mutex); };
};
class VideoDev_Simulation: public VideoDev {
private:
struct timeval lastframetv;
unsigned char *inframe;
ConvertData cdata;
GThread *simulation_thread;
int Grab(VideoFrameRaw *vf);
int Open();
int Close();
int CaptureStart();
int CaptureStop();
int SetDevCtrl(unsigned int id, int value);
int GetDevCtrl(unsigned int id, int *value);
public:
VideoDev_Simulation();
~VideoDev_Simulation();
int GetDeviceList(std::list<std::string> *list);
int GetDeviceFormats(string device, std::list<string> *formats) { return VDEV_STATUS_OK; };
int GetDeviceResolutions(string device, std::list<string> *formats) { return VDEV_STATUS_OK; };
};
#endif

@ -117,7 +117,7 @@ int VideoDev_SVBCam::Open() {
Close();
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s MaxHeight: %ld MaxWidth: %ld\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight, camprop.MaxWidth);
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);
@ -162,7 +162,7 @@ int VideoDev_SVBCam::Open() {
printf("\t\tSVB_IMG_END\n");
break;
default:
printf ("\t\tunknown\n");
printf ("\t\tunbekannt\n");
break;
}
}
@ -178,12 +178,10 @@ int VideoDev_SVBCam::Open() {
print_error(err);
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s Control-%02d name:%s desc:%s [%ld:%ld-%ld] auto:%ld write:%ld type:%d\n", __FILE__, __LINE__, __FUNCTION__,
i, camcontrols[i].Name, camcontrols[i].Description,
(long)camcontrols[i].DefaultValue, (long)camcontrols[i].MinValue, (long)camcontrols[i].MaxValue,
(long)camcontrols[i].IsAutoSupported, (long)camcontrols[i].IsWritable, (unsigned int)camcontrols[i].ControlType);
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 = camcontrols[i].ControlType;
vctl.id = i;
vctl.min = camcontrols[i].MinValue;
vctl.max = camcontrols[i].MaxValue;
GetDevCtrl(i, &vctl.value);
@ -205,38 +203,26 @@ int VideoDev_SVBCam::Open() {
inframe_pixfmt = convert_to_pixelformat(conf_format);
switch (inframe_pixfmt) {
case (V4L2_PIX_FMT_SGRBG16):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RAW16)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_SGRBG8):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RAW8)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_BGR32):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB32)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
case (V4L2_PIX_FMT_BGR24):
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
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_BGR24);
inframe_pixfmt = V4L2_PIX_FMT_BGR24;
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
conf_format = convert_from_pixelformat(V4L2_PIX_FMT_RGB24);
inframe_pixfmt = V4L2_PIX_FMT_RGB24;
if ((err = SVBSetOutputImageType(camid, SVB_IMG_RGB24)) != SVB_SUCCESS) {
print_error(err);
return VDEV_STATUS_ERROR;
}
break;
}
@ -272,8 +258,8 @@ int VideoDev_SVBCam::Close() {
/*
* prepare inframe for raw picture data, will hold a video frame with 16bit per channel or BGR32/BGR24
* inframe size = 4*W*H
* prepare inframe for raw picture data, will hold a video frame with 16bit per channel
* inframe size = 2*3*W*H
* send the start capture signal to the cam
*/
int VideoDev_SVBCam::CaptureStart() {
@ -289,12 +275,10 @@ int VideoDev_SVBCam::CaptureStart() {
//
// allocate memory for frame data
if (inframe != NULL) free (inframe);
inframe_size = get_bytesperpixel(inframe_pixfmt) * inframe_w * inframe_h;
inframe_size = 6 * inframe_w * inframe_h;
inframe = (unsigned char*) malloc(inframe_size);
if (inframe == NULL) {
errorexit ((char*)"%s:%d could not allocate memory for framebuffer. Error:%s\n", __FILE__, __LINE__, strerror(errno));
}
pixelformat = inframe_pixfmt;
ConvertStart(&cdata, inframe_pixfmt);
return VDEV_STATUS_OK;
};
@ -319,6 +303,8 @@ int VideoDev_SVBCam::CaptureStop() {
inframe_size = 0;
}
ConvertStop(&cdata, inframe_pixfmt);
return VDEV_STATUS_OK;
};
@ -329,23 +315,19 @@ int VideoDev_SVBCam::CaptureStop() {
* 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(VideoFrameRaw *vfr) {
int VideoDev_SVBCam::Grab(VideoFrame *vf) {
int err;
if (inframe == NULL) return VDEV_STATUS_ERROR;
if ((err = SVBGetVideoData(camid, inframe, (long)inframe_size, 50)) != SVB_SUCCESS) {
if (err != SVB_ERROR_TIMEOUT) {
print_error(err);
// UnLockMutex(); <-- Warum?
UnLockMutex();
return VDEV_STATUS_ERROR;
}
else {
return VDEV_STATUS_AGAIN;
}
}
LockMutex();
vfr->CopyFrom(inframe_pixfmt, inframe_w, inframe_h, inframe_size, inframe);
Convert(&cdata, vf, inframe, inframe_size, inframe_pixfmt, inframe_w, inframe_h);
UnLockMutex();
return VDEV_STATUS_OK;
@ -380,53 +362,13 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
Close();
return VDEV_STATUS_ERROR;
}
printf ("%s:%d %s MaxHeight:%ld MaxWidth:%ld MaxDepth:%d\n", __FILE__, __LINE__, __FUNCTION__, camprop.MaxHeight,
camprop.MaxWidth, camprop.MaxBitDepth);
char pattern[5];
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
strcpy(pattern, "RGGB");
break;
case SVB_BAYER_BG:
strcpy(pattern, "BGGR");
break;
case SVB_BAYER_GR:
strcpy(pattern, "GRBG");
break;
case SVB_BAYER_GB:
strcpy(pattern, "GBRG");
break;
default:
strcpy(pattern, "NONE");
break;
}
printf ("%s:%d %s BayerPattern:%s Color:%d Binning: \n", __FILE__, __LINE__, __FUNCTION__, pattern, camprop.IsColorCam);
for(int i=0; i < 16 && camprop.SupportedBins[i] != 0; i++) {
printf ("%s:%d %s Binning Index:%d ", __FILE__, __LINE__, __FUNCTION__, i);
printf ("\t\t%dx%d\n", camprop.SupportedBins[i], camprop.SupportedBins[i]);
}
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");
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SRGGB8));
break;
case SVB_BAYER_BG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SBGGR8));
break;
case SVB_BAYER_GR:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGRBG8));
break;
case SVB_BAYER_GB:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGBRG8));
break;
default:
break;
}
break;
case SVB_IMG_RAW10:
printf("\t\tSVB_IMG_RAW10\n");
@ -439,22 +381,6 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
break;
case SVB_IMG_RAW16:
printf("\t\tSVB_IMG_RAW16\n");
switch(camprop.BayerPattern) {
case SVB_BAYER_RG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SRGGB16));
break;
case SVB_BAYER_BG:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SBGGR16));
break;
case SVB_BAYER_GR:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGRBG16));
break;
case SVB_BAYER_GB:
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_SGBRG16));
break;
default:
break;
}
break;
case SVB_IMG_Y8:
printf("\t\tSVB_IMG_Y8\n");
@ -473,17 +399,17 @@ int VideoDev_SVBCam::GetDeviceFormats(string device, std::list<string> *formats)
break;
case SVB_IMG_RGB24:
printf("\t\tSVB_IMG_RGB24\n");
formats->push_back(convert_from_pixelformat(V4L2_PIX_FMT_BGR24));
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_BGR32));
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\tunknown\n");
printf ("\t\tunbekannt\n");
break;
}
}

@ -10,24 +10,17 @@
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#ifndef BUILD_WINDOWS
#include <sys/ioctl.h>
#endif
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#ifndef BUILD_WINDOWS
#include <sys/mman.h>
#include <linux/videodev2.h>
#endif
#include <list>
#include <string>
#ifdef BUILD_WINDOWS
#include "windows.h"
#endif
#include "convert.h"
#include "gui.h"
@ -44,7 +37,7 @@ private:
ConvertData cdata;
int camid;
int Grab(VideoFrameRaw *vfr);
int Grab(VideoFrame *vf);
int Open();
int Close();
int CaptureStart();

@ -1,8 +1,6 @@
#include "simpleskycam.h"
#include "convert.h"
#ifdef USE_V4L2
#include "videodev-v4l2.h"
VideoDev_V4L2::VideoDev_V4L2() {
@ -207,8 +205,6 @@ int VideoDev_V4L2::Open() {
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));
close (fd);
fd = -1;
return VDEV_STATUS_ERROR;
}
@ -263,7 +259,8 @@ int VideoDev_V4L2::InitMMap() {
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &bufreq)) {
if (EINVAL == errno) {
printf("%s does not support memory mapping", conf_device.c_str());
printf("%s does not support "
"memory mappingn", conf_device.c_str());
return VDEV_STATUS_ERROR;
} else {
printf ("%s:%d %s Error %s\n", __FILE__, __LINE__, __FUNCTION__, strerror(errno));
@ -284,15 +281,14 @@ int VideoDev_V4L2::InitMMap() {
if(ioctl(fd, VIDIOC_QUERYBUF, &bufinfo) < 0){
perror("VIDIOC_QUERYBUF");
exit(1);
errorexit((char*)"%s:%d\n", __FILE__, __LINE__);
}
inbuffer[i].size = bufinfo.length;
inbuffer[i].data = (unsigned char*)mmap(NULL, bufinfo.length, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, bufinfo.m.offset);
if (inbuffer[i].data == MAP_FAILED) {
printf ( "%s:%d error on mmap %s\n", __FILE__, __LINE__, strerror(errno));
exit (1);
errorexit ((char*)"%s:%d error on mmap %s\n", __FILE__, __LINE__, strerror(errno));
}
}
return VDEV_STATUS_OK;
@ -331,8 +327,7 @@ int VideoDev_V4L2::UnInit() {
for (inbuffer_idx = 0; inbuffer_idx < VDEV_INBUFFERS; inbuffer_idx++)
if (inbuffer[inbuffer_idx].data) {
if (-1 == munmap(inbuffer[inbuffer_idx].data, inbuffer[inbuffer_idx].size)){
fprintf(stderr, "Fatal Error @ %s:%d munmap Error:%s\n", __FILE__, __LINE__, strerror(errno));
exit(1);
errorexit((char*)"Fatal Error @ %s:%d munmap Error:%s\n", __FILE__, __LINE__, strerror(errno));
}
inbuffer[inbuffer_idx].data = NULL;
inbuffer[inbuffer_idx].size = 0;
@ -394,7 +389,7 @@ int VideoDev_V4L2::CaptureStart() {
return VDEV_STATUS_ERROR;
}
pixelformat = fmt.fmt.pix.pixelformat;
ConvertStart(&cdata, fmt.fmt.pix.pixelformat);
return VDEV_STATUS_OK;
};
@ -404,6 +399,8 @@ int VideoDev_V4L2::CaptureStop() {
enum v4l2_buf_type type;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
ConvertStop(&cdata, fmt.fmt.pix.pixelformat);
switch (io) {
case IOMODE_READ:
/* Nothing to do. */
@ -424,11 +421,11 @@ int VideoDev_V4L2::CaptureStop() {
/*
* try to grab one frame and convert it into RGB32.
* 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.
* To reduce the time of malloc/free reuse the destination buffer.
*/
int VideoDev_V4L2::Grab(VideoFrameRaw *vf) {
int VideoDev_V4L2::Grab(VideoFrame *vf) {
struct v4l2_buffer buf;
int len;
@ -448,7 +445,7 @@ int VideoDev_V4L2::Grab(VideoFrameRaw *vf) {
}
else {
LockMutex();
Convert(&cdata, vf, inbuffer[0].data, len, fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height);
UnLockMutex();
}
break;
@ -466,8 +463,6 @@ int VideoDev_V4L2::Grab(VideoFrameRaw *vf) {
case EIO:
printf ( "%s:%d error on VIDIOC_DQBUF EIO %s\n", __FILE__, __LINE__, strerror(errno));
return VDEV_STATUS_ERROR;
default:
printf ( "%s:%d error on VIDIOC_DQBUF %s\n", __FILE__, __LINE__, strerror(errno));
return VDEV_STATUS_ERROR;
@ -476,7 +471,7 @@ int VideoDev_V4L2::Grab(VideoFrameRaw *vf) {
if (buf.index >= 0 && buf.index < VDEV_INBUFFERS) {
LockMutex();
vf->CopyFrom(fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, buf.bytesused, inbuffer[buf.index].data);
Convert(&cdata, vf, inbuffer[buf.index].data, buf.bytesused, fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height);
UnLockMutex();
}
@ -578,4 +573,3 @@ int VideoDev_V4L2::GetDevCtrl(unsigned int id, int *value) {
};
#endif

@ -46,7 +46,9 @@ private:
struct v4l2_crop crop;
struct v4l2_format fmt;
int Grab(VideoFrameRaw *vf);
ConvertData cdata;
int Grab(VideoFrame *vf);
int Open();
int Close();
int CaptureStart();

@ -1,477 +0,0 @@
/*
* Module to grab video data from VfW interface. The interface is
* poorly documented for which some odd comments maybe found here.
*/
#include "config.h"
#include <windows.h>
#include <windowsx.h>
#include <vfw.h>
#include <aviriff.h>
#include <list>
#include <string>
#include "convert.h"
#include "videodev-vfw.h"
static char classNameVfW[] = "VFW-Class";
/*
* Constructor
*/
VideoDev_VFW::VideoDev_VFW() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
hwnd = cap = NULL;
camid = -1;
inframe_pixfmt = 0x0;
inframe_w = -1;
inframe_h = -1;
inframe = NULL;
inframe_size = 0;
vfw_size = 0;
hclass = NULL;
hinst = NULL;
};
/*
* Destructor
*/
VideoDev_VFW::~VideoDev_VFW() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (running > 0)
CaptureStop();
}
/*
* Check for connected devices and returns the result in a list.
*/
int VideoDev_VFW::GetDeviceList(std::list<std::string> *list) {
char name[256];
char desc[256];
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (list == NULL) return VDEV_STATUS_ERROR;
// go through a list of 10 (maximum number defined by VfW)
for(int i=0; i < 10; i++)
if(capGetDriverDescription(i, name, sizeof(name), desc, sizeof(desc))) {
// create a driver for the return list
std::string device;
device = "VFW " + to_string(i) + " " + (string)name + " [" + (string)desc + "]";
printf ("%s:%d %s Found device '%s'\n", __FILE__, __LINE__, __FUNCTION__, device.c_str());
list->push_back(device);
}
return VDEV_STATUS_OK;
}
/*
* Destroy and unregister window class.
*/
int VideoDev_VFW::DestroyClass() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (hclass) {
if(!UnregisterClass(classNameVfW, hinst)) {
printf ("%s:%d %s Could not unregister VFW class\n", __FILE__, __LINE__, __FUNCTION__);
return 0;
}
free (hclass);
hclass = NULL;
}
return 1;
}
/*
* Create and register window class.
*/
int VideoDev_VFW::CreateClass() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (hclass) return 1;
hclass = (WNDCLASSEX *)malloc(sizeof(WNDCLASSEX));
hclass->hInstance = hinst;
hclass->lpszClassName = classNameVfW;
hclass->lpfnWndProc = DefWindowProc;
hclass->style = CS_DBLCLKS;
hclass->cbSize = sizeof(WNDCLASSEX);
hclass->hIcon = LoadIcon(NULL,IDI_APPLICATION);
hclass->hIconSm = LoadIcon(NULL,IDI_APPLICATION);
hclass->hCursor = LoadCursor(NULL,IDC_ARROW);
hclass->lpszMenuName = NULL;
hclass->cbClsExtra = 0;
hclass->cbWndExtra = 0;
hclass->hbrBackground = (HBRUSH)COLOR_BACKGROUND;
if(!RegisterClassEx (hclass)) {
printf ("%s:%d %s Could not register VFW class\n", __FILE__, __LINE__, __FUNCTION__);
return 0;
}
return 1;
}
/*
* Print driver capabilities.
*/
void VideoDev_VFW::GetCapabilities() {
CAPDRIVERCAPS caps;
if(!capDriverGetCaps(cap, &caps, sizeof(caps))) {
printf ("%s:%d %s Unable to get driver capabilities\n", __FILE__, __LINE__, __FUNCTION__);
}
else {
printf ("%s:%d %s Id: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.wDeviceIndex);
printf ("%s:%d %s Overlay: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasOverlay);
printf ("%s:%d %s VideoSource Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoSource);
printf ("%s:%d %s VideoFormat Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoFormat);
printf ("%s:%d %s VideoDisplay Dialog: %d\n", __FILE__, __LINE__, __FUNCTION__, caps.fHasDlgVideoDisplay);
}
}
/*
* The callback is run when an error in the capture driver occurred.
*/
LRESULT VFW_error_callback (HWND h, int nID, LPCSTR lpsz) {
printf("%s:%d %s id=%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, nID, lpsz);
return TRUE;
}
/*
* The callback is run when a status update in the capture driver occurred.
*/
LRESULT VFW_status_callback (HWND h, int nID, LPCSTR lpsz) {
printf("%s:%d %s id=%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, nID, lpsz);
return TRUE;
}
#define USE_PREVIEW 0
/*
* Opens the device.
*/
int VideoDev_VFW::Open() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
// extract camera id from device name
camid = atoi (conf_device.c_str());
printf ("%s:%d %s Opening VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid);
// find application instance handle for later use
hinst = GetModuleHandle(NULL);
// create and register window class
if (!CreateClass())
return VDEV_STATUS_ERROR;
// now create the parent window for capture devicey
// some notes:
// - the minimum possible size of 3x3
// - the WS_POPUPWINDOW removes window decorations
// - it does not need a parent window
// - the window MUST be visible, otherwise video grabbing does not work (no callbacks run)
#if USE_PREVIEW
hwnd = CreateWindowEx(0, classNameVfW, "CameraPreview", WS_POPUPWINDOW|WS_VISIBLE, 0, 0, 3, 3, NULL, NULL, hinst, NULL);
#else
hwnd = CreateWindowEx(0, classNameVfW, "CameraPreview", WS_POPUPWINDOW|WS_VISIBLE, 0, 0, 0, 0, NULL, NULL, hinst, NULL);
#endif
if (!hwnd) {
printf ("%s:%d %s Could not create window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError());
return VDEV_STATUS_ERROR;
}
#if USE_PREVIEW
if(!ShowWindow(hwnd, SW_SHOW)) {
printf ("%s:%d %s Could not show window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError());
return VDEV_STATUS_ERROR;
}
#else
if(!ShowWindow(hwnd, SW_HIDE)) {
printf ("%s:%d %s Could not hide window (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError());
return VDEV_STATUS_ERROR;
}
#endif
// create capture driver window handle, also here minim size is 1x1
#if USE_PREVIEW
cap = capCreateCaptureWindow("VFW", WS_CHILD|WS_VISIBLE, 0, 0, 1, 1, hwnd, camid);
#else
cap = capCreateCaptureWindow("VFW", WS_CHILD, 0, 0, 0, 0, hwnd, camid);
#endif
if(!cap) {
printf ("%s:%d %s Could not open VFW id %d window\n", __FILE__, __LINE__, __FUNCTION__, camid);
return VDEV_STATUS_ERROR;
}
if(!capSetCallbackOnStatus(cap, VFW_status_callback)) {
printf ("%s:%d %s Could not set status callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError());
return VDEV_STATUS_ERROR;
}
if(!capSetCallbackOnError(cap, VFW_error_callback)) {
printf ("%s:%d %s Could not set error callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError());
return VDEV_STATUS_ERROR;
}
// connect to driver
if(!capDriverConnect(cap, camid)) {
printf ("%s:%d %s Could not connect to VFW id %d\n", __FILE__, __LINE__, __FUNCTION__, camid);
return VDEV_STATUS_ERROR;
}
// check capabilities
GetCapabilities();
// let the callbacks know this class pointer
capSetUserData(cap, this);
// set video source, capture format and size
//capDlgVideoSource(cap);
//capDlgVideoFormat(cap);
CAPTUREPARMS cp;
if(!capCaptureGetSetup(cap, &cp, sizeof(cp))) {
printf ("%s:%d %s Could not get VFW capture setup\n", __FILE__, __LINE__, __FUNCTION__);
return VDEV_STATUS_ERROR;
}
cp.dwRequestMicroSecPerFrame = 10000; // rate in us
cp.fMakeUserHitOKToCapture = 0;
cp.wPercentDropForError = 10;
cp.fYield = TRUE;
cp.wNumVideoRequested = 1;
cp.fCaptureAudio = 0;
cp.vKeyAbort = 0;
cp.fAbortLeftMouse = 0;
cp.fAbortRightMouse = 0;
cp.fLimitEnabled = 0;
if(!capCaptureSetSetup(cap, &cp, sizeof(cp))) {
printf ("%s:%d %s Could not set VFW capture setup\n", __FILE__, __LINE__, __FUNCTION__);
return VDEV_STATUS_ERROR;
}
// get current valid width/height
BITMAPINFO bi;
int i = 0;
capGetVideoFormat(cap, &bi, sizeof(BITMAPINFO));
inframe_w = bi.bmiHeader.biWidth;
inframe_h = bi.bmiHeader.biHeight;
printf ("%s:%d %s Current capture size is %dx%d\n", __FILE__, __LINE__, __FUNCTION__, inframe_w, inframe_h);
conf_format = convert_from_pixelformat(bi.bmiHeader.biCompression);
inframe_pixfmt = bi.bmiHeader.biCompression;
printf ("%s:%d %s Current capture format is %s\n", __FILE__, __LINE__, __FUNCTION__, conf_format.c_str());
// try to set the configured width/height
if(conf_width != -1) {
inframe_w = bi.bmiHeader.biWidth = conf_width;
inframe_h = bi.bmiHeader.biHeight = conf_height;
bi.bmiHeader.biCompression = inframe_pixfmt;
if(!capSetVideoFormat(cap, &bi, sizeof(BITMAPINFO))) {
printf ("%s:%d %s Could not set capture size %dx%d (%s)\n", __FILE__, __LINE__, __FUNCTION__, conf_width, conf_height, conf_format.c_str());
return VDEV_STATUS_ERROR;
}
}
// find out maximum resolution
else {
int sizes[][2] = {{320, 240}, {640, 480}, {800, 600}, {1024, 768}, {1280, 720}, {1280, 1024}, {1920, 1080}, {-1, -1}};
while(sizes[i][0] != -1) {
inframe_w = bi.bmiHeader.biWidth = sizes[i][0];
inframe_h = bi.bmiHeader.biHeight = sizes[i][1];
bi.bmiHeader.biCompression = inframe_pixfmt;
if(capSetVideoFormat(cap, &bi, sizeof(BITMAPINFO))) {
printf ("%s:%d %s Resolution %dx%d (%s) works\n", __FILE__, __LINE__, __FUNCTION__, inframe_w, inframe_h, conf_format.c_str());
if (inframe_w >= conf_width && inframe_h >= conf_height) {
conf_width = inframe_w;
conf_height = inframe_h;
}
}
i++;
}
}
// translate this special format to what our convert functions can work with
if (inframe_pixfmt == V4L2_PIX_FMT_YUY2) {
inframe_pixfmt = V4L2_PIX_FMT_YUYV;
}
return VDEV_STATUS_OK;
};
/*
* Close the device.
*/
int VideoDev_VFW::Close() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if(cap) {
capDriverDisconnect(cap);
DestroyWindow(cap);
DestroyWindow(hwnd);
hwnd = cap = NULL;
}
DestroyClass();
return VDEV_STATUS_OK;
};
/*****************************************************************************************************
* VideoGrabbing
*/
/*
* The callback is run when a new frame is available. It copies the
* available data into the framebuffer of the class instance.
*/
LRESULT CALLBACK VFW_frame_callback (HWND h, LPVIDEOHDR v) {
VideoDev_VFW * obj = (VideoDev_VFW *)capGetUserData(h);
obj->SetFrameBufferSize(v->dwBytesUsed);
if (obj->GetFrameBuffer()) {
memcpy(obj->GetFrameBuffer(), v->lpData, obj->GetFrameBufferSize());
}
return TRUE;
}
/*
* Prepare inframe for raw picture data, will hold a video frame with
* maximum size of inframe size = 4*W*H. Setup capture
* callbacks. Then send the start capture signal to the camera.
*/
int VideoDev_VFW::CaptureStart() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
// allocate memory for frame data
if (inframe != NULL) free (inframe);
inframe_size = 4 * inframe_w * inframe_h;
inframe = (unsigned char *) malloc(inframe_size);
pixelformat = inframe_pixfmt;
#if USE_PREVIEW
if(!capSetCallbackOnFrame(cap, VFW_frame_callback)) {
printf ("%s:%d %s Could not set frame callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError());
return VDEV_STATUS_ERROR;
}
#else
if(!capSetCallbackOnVideoStream(cap, VFW_frame_callback)) {
printf ("%s:%d %s Could not set videostream callback to VFW id %d (%ld)\n", __FILE__, __LINE__, __FUNCTION__, camid, GetLastError());
return VDEV_STATUS_ERROR;
}
#endif
// disable overlay
capOverlay(cap, FALSE);
#if USE_PREVIEW
// use preview window for grabbing
capPreviewRate (cap, 10); // rate in ms
capPreviewScale (cap, FALSE);
capPreview (cap, TRUE);
#else
// otherwise use other capture
capPreview (cap, FALSE);
if(!capCaptureSequenceNoFile (cap)) {
printf ("%s:%d %s Could not start capture (%ld)\n", __FILE__, __LINE__, __FUNCTION__, GetLastError());
}
#endif
return VDEV_STATUS_OK;
};
/*
* Stop capture and free framebuffer.
*/
int VideoDev_VFW::CaptureStop() {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
capCaptureAbort(cap);
capSetCallbackOnFrame(cap, NULL);
capSetCallbackOnVideoStream(cap, NULL);
capSetCallbackOnStatus(cap, NULL);
capSetCallbackOnError(cap, NULL);
// free inframe memory
if (inframe) {
free (inframe);
inframe_size = 0;
inframe = NULL;
}
return VDEV_STATUS_OK;
};
/*
* This function needed to continue running the capture window.
*/
void VideoDev_VFW::HandleMessages() {
MSG msg;
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/*
* Try to grab one frame and copy it into raw video buffer. 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.
*/
int VideoDev_VFW::Grab(VideoFrameRaw *vf) {
// Do not know exactly why, but needed to translate/dispatch window message
HandleMessages();
if (inframe == NULL) return VDEV_STATUS_ERROR;
if (GetFrameBufferSize() > 0) {
LockMutex();
vf->CopyFrom(inframe_pixfmt, inframe_w, inframe_h, GetFrameBufferSize(), inframe);
SetFrameBufferSize(0);
UnLockMutex();
}
else {
return VDEV_STATUS_AGAIN;
}
return VDEV_STATUS_OK;
}
/*
* For VfW this seems difficult / impossible to obtain the supported
* video formats, but they must be selected via capDlgVideoFormat().
*/
int VideoDev_VFW::GetDeviceFormats(string device, std::list<string> *formats) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
return VDEV_STATUS_OK;
}
/*****************************************************************************************************
* Controls
*/
/*
* set video control identified by id
*/
int VideoDev_VFW::SetDevCtrl(unsigned int id, int value) {
return VDEV_STATUS_OK;
};
/*
* get video control identified by id
*/
int VideoDev_VFW::GetDevCtrl(unsigned int id, int *value) {
return VDEV_STATUS_OK;
};

@ -1,45 +0,0 @@
#ifndef _H_VIDEODEV_VFW_H_
#define _H_VIDEODEV_VFW_H_
#include "videodev.h"
class VideoDev_VFW: public VideoDev {
private:
unsigned char *inframe;
int inframe_size;
int inframe_w, inframe_h;
int inframe_pixfmt;
int vfw_size;
ConvertData cdata;
int camid;
HWND cap, hwnd;
WNDCLASSEX * hclass;
HINSTANCE hinst;
int Grab(VideoFrameRaw *vf);
int Open();
int Close();
int CaptureStart();
int CaptureStop();
int SetDevCtrl(unsigned int id, int value);
int GetDevCtrl(unsigned int id, int *value);
int CreateClass();
int DestroyClass();
void HandleMessages();
void GetCapabilities();
void print_error(int err);
public:
VideoDev_VFW();
~VideoDev_VFW();
int GetDeviceList(std::list<std::string> *list);
int GetDeviceFormats(string device, std::list<string> *formats);
int GetDeviceResolutions(string device, std::list<string> *formats) { return VDEV_STATUS_OK; };
unsigned char * GetFrameBuffer(void) { return inframe; };
void SetFrameBufferSize(int s) { vfw_size = s; };
int GetFrameBufferSize(void) { return vfw_size; };
};
#endif

@ -9,25 +9,24 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <errno.h>
#include <getopt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.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() {
@ -40,7 +39,6 @@ VideoDev::VideoDev() {
conf_width = 600;
running = 0;
callback = NULL;
pixelformat = 0x0;
g_mutex_init (&mutex);
};
@ -141,7 +139,6 @@ void VideoDev::SetConfig(std::string dev, int w, int h, std::string format, std:
#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;
@ -166,21 +163,16 @@ void VideoDev::ThreadProcess() {
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);
i = Grab(&threaddata.vf);
switch (i) {
case VDEV_STATUS_OK:
numframes++;
if (callback) gdk_threads_add_idle(callback, &threaddata);
break;
@ -191,15 +183,13 @@ void VideoDev::ThreadProcess() {
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);
printf ("%s:%d %s cycle_time:%f Freq:%f Hz \r", __FILE__, __LINE__, __FUNCTION__, cycle_time, (1.0/cycle_time));
lastsec = cycle_timestamp.tv_sec;
numframes = 0;
}
if (cycle_wait > 0.0 && cycle_wait < 1.0 ) usleep ((int)(cycle_wait * 1000000.0));
}
@ -207,7 +197,6 @@ void VideoDev::ThreadProcess() {
//
// stop capturing
if (callback) gdk_threads_add_idle(callback, NULL);
ConvertStop(&cdata, pixelformat);
CaptureStop();
Close();
@ -225,9 +214,9 @@ void VideoDev::Stop() {
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;
*format = conf_format;
*w = conf_width;
*h = conf_height;
}
@ -236,29 +225,3 @@ list<VideoDevCtrl> VideoDev::GetCtrlsMinMaxValue() {
};
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;
}

@ -10,7 +10,6 @@
#include <string>
#include <list>
#include "simpleskycam.h"
#include "json.h"
#include "gui.h"
#include "config.h"
@ -66,7 +65,6 @@ struct {
struct {
int running;
VideoFrame vf;
VideoFrameRaw vfr;
} typedef VideoDevThreadData;
#ifndef CLEAR
@ -86,14 +84,13 @@ private:
std::string conf_devicename; // human friendly name of the device
std::string conf_format; // video or image format (should every device have)
std::string conf_parameter; // can hold additional parameters
uint32_t pixelformat; // pixelformat
int conf_height;
int conf_width;
int running; // 0 ... not running
// 1 ... initialized (init, first frame)
// 2 ... running
ConvertData cdata;
GMutex mutex;
gboolean (*callback)(gpointer data);
@ -103,7 +100,7 @@ private:
std::list<VideoDevCtrl> vidctrls;
/* grabs a single frame, writes the RGB24 converted frame to the VideoFrame pointer */
virtual int Grab(VideoFrameRaw *vf) { return VDEV_STATUS_AGAIN; };
virtual int Grab(VideoFrame *vf) { return VDEV_STATUS_AGAIN; };
/* opens the device, will need to fill the controls as well */
virtual int Open() { return VDEV_STATUS_OK; };
@ -124,20 +121,14 @@ private:
virtual int GetDevCtrl(unsigned int id, int *value) { return VDEV_STATUS_OK; };
friend class VideoDev_Dumpfile;
friend class VideoDev_Simulation;
friend class VideoDev_V4L2;
#ifdef USE_SVBONY
friend class VideoDev_SVBCam;
#endif
#ifdef USE_VFW
friend class VideoDev_VFW;
#endif
public:
VideoDev();
virtual ~VideoDev();
static int get_bytesperpixel (uint32_t pixfmt);
void SetConfig(std::string dev, int w, int h, std::string format, std::string parameter, gboolean (*callback_func)(gpointer data));
void ThreadProcess();
void Stop();
@ -163,17 +154,10 @@ public:
};
#include "videodev-dumpfile.h"
#include "videodev-simulation.h"
#ifdef USE_V4L2
#include "videodev-v4l2.h"
#endif
#include "videodev-dumpfile.h"
#ifdef USE_SVBONY
#include "videodev-svbcam.h"
#endif
#ifdef USE_VFW
#include "videodev-vfw.h"
#endif
#endif

@ -1,106 +1,16 @@
#include <errno.h>
#include <string.h>
#include "video.h"
#include "config.h"
#include "gui.h"
#include "error.h"
#include "convert.h"
#include "videodev.h"
#include "simpleskycam.h"
VideoFrameRaw::VideoFrameRaw() {
size = 0;
data = NULL;
w = 0;
h = 0;
pixfmt = 0x0;
}
VideoFrameRaw::~VideoFrameRaw() {
if (data != NULL) {
free (data);
data = NULL;
}
}
int VideoFrameRaw::CopyFrom(int spixfmt, int sw, int sh, int ssize, unsigned char *sdata) {
if (size != ssize) {
if (ReAlloc(ssize) != 0) {
errorexit((char*) "%s:%d %s could not reallocate memory. Error:%s\n",
__FILE__, __LINE__, __FUNCTION__, strerror(errno));
}
}
if (data == NULL) {
errorexit((char*) "%s:%d %s invalid pointer of data. Error:%s\n",
__FILE__, __LINE__, __FUNCTION__, strerror(errno));
}
w = sw;
h = sh;
pixfmt = spixfmt;
memcpy (data, sdata, ssize);
return 1;
}
int VideoFrameRaw::CopyFrom(VideoFrameRaw *src) {
if (src == NULL) return 0;
return CopyFrom(src->pixfmt, src->w, src->h, src->size, src->data);
}
int VideoFrameRaw::CopyFrom(VideoFrame *src) {
if (src == NULL) return 0;
return CopyFrom(V4L2_PIX_FMT_RGB24, src->w, src->h, src->size, src->data);
}
int VideoFrameRaw::ReAlloc(int newsize) {
unsigned char *newdata = NULL;
if (newsize == 0) {
free (data);
data = NULL;
size = newsize;
return 0;
}
if (data == NULL) {
if ((data = (unsigned char*) malloc (newsize)) == NULL) return -1;
}
else if (size < newsize || size > newsize) {
if ((newdata = (unsigned char*) realloc (data, newsize)) == NULL) {
free (data);
data = NULL;
size = 0;
return -1;
}
data = newdata;
}
size = newsize;
return 0;
}
int VideoFrameRaw::RectCopyFrom(VideoFrameRaw *src, int rectx, int recty, int rectw, int recth) {
int res = 0;
pixfmt = src->pixfmt;
res = PixCopy (src->data, src->pixfmt, src->w, src->h,
&data, &size, &w, &h,
rectx, recty, rectw, recth);
return res;
}
#define VIDEOFRAME_DEPTH_BYTES 3
VideoFrame::VideoFrame() {
data = NULL;
w = 0;
h = 0;
size = 0;
pixelsize = 3;
};
@ -118,8 +28,8 @@ VideoFrame::~VideoFrame() {
//
// we will only allocate a new image if the needed size increases
void VideoFrame::SetSize(int nw, int nh) {
uint32_t newsize = VIDEOFRAME_DEPTH_BYTES * nh * nw;
void VideoFrame::SetMemorySize(int nw, int nh, int nps) {
uint32_t newsize = nps * nh * nw;
if (newsize > size || data == NULL) {
unsigned char *newdata = (unsigned char *) malloc (newsize);
@ -129,12 +39,14 @@ void VideoFrame::SetSize(int nw, int nh) {
}
w = nw;
h = nh;
pixelsize = nps;
};
VideoFrame VideoFrame::operator=(VideoFrame rightside) {
w = rightside.w;
h = rightside.h;
pixelsize = rightside.pixelsize;
size = rightside.size;
if (size > 0) data = (unsigned char *) malloc (rightside.size);
if (rightside.data != NULL && size > 0) {
@ -145,16 +57,20 @@ VideoFrame VideoFrame::operator=(VideoFrame rightside) {
void VideoFrame::CopyFrom(VideoFrame *source) {
SetPixelSize(source->pixelsize);
SetSize (source->w, source->h);
memcpy(data, source->data, VIDEOFRAME_DEPTH_BYTES * w * h);
memcpy(data, source->data, pixelsize * w * h);
}
/*
* will copy the FloatImage to VideoFrame
* with respect of the bits per pixel (3 or 6).
*/
void VideoFrame::CopyFrom(FloatImage *source) {
float min, max, f;
int x, y, i, idx;
unsigned char v;
SetSize (source->w, source->h);
@ -168,59 +84,105 @@ void VideoFrame::CopyFrom(FloatImage *source) {
if (max < source->data[idx+i]) max = source->data[idx+i];
}
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
f = (float)(255.0 * (source->data[idx+i]-min) / (max-min));
if (f < 0.0) v = 0;
else if (f > 255.0) v = 255;
else v = f;
data[idx+i] = v;
}
//
// 3 bytes per pixel (each channel ^ 1 byte)
if (pixelsize == 3) {
unsigned char v;
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = pixelsize * (y * w + x);
f = (float)(255.0 * (source->data[idx+i]-min) / (max-min));
if (f < 0.0) v = 0;
else if (f > 255.0) v = 255;
else v = f;
data[idx+i] = v;
}
}
//
// 6 bytes per pixel (each channel ^ 2 byte)
else if (pixelsize == 6) {
uint16_t v;
int max = (2^16)-1;
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = pixelsize * (y * w + x);
f = (float)(double(max) * (source->data[idx+i]-min) / (max-min));
if (f < 0.0) v = 0;
else if (f > double(max)) v = max;
else v = f;
memcpy(data+(idx+2*i), &v, 2);
}
}
else {
errorexit((char*)"Pixelsize not known or implemented. pixelsize should be 3 or 6, current value is:%d\n", pixelsize);
}
}
void VideoFrame::CopyTo(FloatImage *dest) {
int x, y, i, idx;
if (dest == NULL) return;
dest->SetSize (w, h);
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
dest->data[idx+i] = data[idx+i];
}
if (pixelsize == 3) {
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
dest->data[idx+i] = data[idx+i];
}
}
else if (pixelsize == 6) {
uint16_t *sdata = (uint16_t*)data;
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
dest->data[idx+i] = sdata[idx+i];
}
}
else {
errorexit ((char*) "pixelsize not supported.\n");
}
}
void VideoFrame::ToPixbuf(GdkPixbuf** dest) {
int destw, desth, bytelen;
void VideoFrame::ToPixbuf(GdkPixbuf* dest) {
int destw, desth;
unsigned char *destpixel;
if (dest == NULL) return;
desth = gdk_pixbuf_get_height(*dest);
destw = gdk_pixbuf_get_width(*dest);
if (pixelsize == 3) {
desth = gdk_pixbuf_get_height(dest);
destw = gdk_pixbuf_get_width(dest);
destpixel = gdk_pixbuf_get_pixels(dest);
// check if the memory allocation way ok.
if (destw != w || desth != h) {
g_object_unref (*dest);
*dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, w, h);
}
if (destw * desth < h * w) {
destw = w;
desth = h;
}
// copy data
destpixel = gdk_pixbuf_get_pixels(*dest);
bytelen = gdk_pixbuf_get_byte_length(*dest);
if (bytelen < h * w * 3) {
printf ("******* Error: %s:%d bytelen (set to:%d) is not %d\n", __FILE__, __LINE__, bytelen, (h * w * 3));
printf ("******* please inform the maintainer of this project.\n");
printf ("******* this should not have happened at all.\n");
exit (-1);
memcpy (destpixel, data, 3*destw*desth);
}
else if (pixelsize == 6) {
desth = gdk_pixbuf_get_height(dest);
destw = gdk_pixbuf_get_width(dest);
destpixel = gdk_pixbuf_get_pixels(dest);
uint16_t *sdata = (uint16_t*)data;
int x, y, idx, i;
for (y = 0; y < desth; y++) for (x = 0; x < destw; x++)
for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x);
destpixel[idx+i] = sdata[idx+i];
}
}
else {
errorexit ((char*) "pixelsize (%d) not supported.\n", pixelsize);
}
memcpy (destpixel, data, 3*w*h);
}

@ -21,53 +21,34 @@ public:
void SetW(int nw) { SetSize(nw, h); };
void SetH(int nh) { SetSize(w, nh); };
void CopyFrom(FloatImage *source);
void Delete() { w = 0; h = 0; };
};
/*
* contains RGB data
*/
class VideoFrame {
private:
void SetMemorySize (int nw, int nh, int nps);
unsigned char *data;
public:
int w;
int h;
uint32_t pixelsize;
uint32_t size;
unsigned char *data;
VideoFrame();
~VideoFrame();
VideoFrame operator=(VideoFrame rightside);
void SetSize(int nw, int nh);
void SetW(int nw) { SetSize(nw, h); };
void SetH(int nh) { SetSize(w, nh); };
void SetSize(int nw, int nh) { SetMemorySize (nw, nh, pixelsize); };
void* GetData() { return data; };
void SetPixelSize(uint32_t nps) { SetMemorySize (w, h, nps); };
void SetW(int nw) { SetMemorySize(nw, h, pixelsize); };
void SetH(int nh) { SetMemorySize(w, nh, pixelsize); };
void CopyFrom(VideoFrame *source);
void CopyFrom(FloatImage *source);
void CopyTo(FloatImage *dest);
void ToPixbuf(GdkPixbuf** dest);
void Delete() { w = 0; h = 0; };
};
class VideoFrameRaw {
private:
public:
unsigned char *data;
int size;
int w;
int h;
uint32_t pixfmt;
VideoFrameRaw();
~VideoFrameRaw();
int ReAlloc(int newsize);
int CopyFrom(VideoFrame *src);
int CopyFrom(VideoFrameRaw *src);
int CopyFrom(int spixfmt, int sw, int sh, int ssize, unsigned char *sdata);
int RectCopyFrom(VideoFrameRaw *src, int rectx, int recty, int rectw, int recth);
void Delete() { w = 0; h = 0; pixfmt = 0;};
void ToPixbuf(GdkPixbuf* dest);
};

@ -1,14 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include "windows.h"
void strfromd (char* dest, int len, char *fmt,...) {
va_list args;
va_start (args, fmt);
vsnprintf (dest, len-1, fmt, args);
va_end (args);
dest[len-1] = 0;
}

@ -1,76 +0,0 @@
#ifndef _WINDOWS_H_
#define _WINDOWS_H_
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#define WIN32_LEAN_AND_MEAN
#define _NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
#define _NTDDI_VERSION_FROM_WIN32_WINNT(ver) _NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x501
#endif
#ifndef NTDDI_VERSION
# define NTDDI_VERSION _NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#endif
// #include <winsock.h>
#include <winsock2.h>
#include <io.h>
#include <ws2tcpip.h>
#include <string.h>
#define socklen_t size_t
#ifndef bzero
#define bzero(__z__, __x__) memset (__z__, 0x0, __x__)
#endif
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
#endif
#endif
extern void strfromd (char* dest, int len, char *fmt,...);
#define __u32 uint32_t
/*
* since this application is ported from linux and uses some linux based definitions
* we needed to copy some of the definitions and information.
*
* the following part comes from the Video 4 Linux 2 source more details can be found
* at https://linuxtv.org.
*/
#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */
#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */
#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG */
#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */
#define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16 GRGR.. BGBG.. */
#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */
#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
#define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16 RGRG.. GBGB.. */
#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */
#define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16 GBGB.. RGRG.. */
#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
#define V4L2_PIX_FMT_YUY2 v4l2_fourcc('Y', 'U', 'Y', '2') /* ??? */
#define v4l2_fourcc(a, b, c, d)\
((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
#define v4l2_fourcc_be(a, b, c, d) (v4l2_fourcc(a, b, c, d) | (1U << 31))
#endif
Loading…
Cancel
Save