started to work on detection and filter

test16bit
Steffen Pohle 4 years ago
parent 605e81389e
commit 874796b87f

@ -4,7 +4,7 @@ APP = simpleskycam
-include Makefile.rules -include Makefile.rules
OBJECTS = gui.oo main.oo video.oo videodev.oo OBJECTS = gui.oo main.oo video.oo videoframe.oo videodev.oo filter.oo
DISTNAME=simpleskycam-$(VERSION) DISTNAME=simpleskycam-$(VERSION)
ifeq ($(TARGET),) ifeq ($(TARGET),)

@ -7,8 +7,8 @@
#include "filter.h" #include "filter.h"
extern Filter filter; extern Filter filter;
gboolean cb_filtertemp_thread (gpointer data); //gboolean cb_filtertemp_thread (gpointer data);
gboolean cb_filterout_thread (gpointer data); //gboolean cb_filterout_thread (gpointer data);
// //
// C / C++ Wrapper for the thread function // C / C++ Wrapper for the thread function
@ -21,8 +21,10 @@ gpointer _FilterThread (gpointer data) {
Filter::Filter() { // @suppress("Class members should be properly initialized") Filter::Filter() { // @suppress("Class members should be properly initialized")
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
g_mutex_init (&mutexin); g_mutex_init (&mutexin);
g_mutex_init (&mutexout); g_mutex_init (&muteximage);
g_mutex_init (&mutextmp); g_mutex_init (&mutextmp);
g_mutex_init (&mutex); g_mutex_init (&mutex);
running = 1; running = 1;
@ -49,11 +51,12 @@ Filter::~Filter() {
int Filter::NewFrame(VideoFrame *newframe) { int Filter::NewFrame(VideoFrame *newframe) {
if (newframe == NULL) return -1;
LockInMutex(); LockInMutex();
inFrame.CopyFrom(newframe); inFrame.CopyFrom(newframe);
inFrameNew = 1; inFrameNew = 1;
UnLockInMutex(); UnLockInMutex();
return -1; return 0;
}; };
@ -61,16 +64,18 @@ int Filter::NewFrame(VideoFrame *newframe) {
// NewFrame: will set new frame // NewFrame: will set new frame
// Thread: newFrame |------> Find Object --- not found ---> send gui information // Thread: newFrame |------> Find Object --- not found ---> send gui information
void Filter::Thread() { void Filter::Thread() {
int _run_once = 1;
while (running) { while (running) {
// check for new frame // check for new frame
LockInMutex(); LockInMutex();
if (inFrameNew == 1) { if (inFrameNew == 1) {
inFrameNew = 0; inFrameNew = 0;
// //
// do some input detection improvement // do some input detection improvement
InputDetect(); InputDetect();
oldFrame.CopyFrom(&inFrame); oldFrame.CopyFrom(&inFrame);
UnLockInMutex(); UnLockInMutex();
@ -78,17 +83,17 @@ void Filter::Thread() {
LockTempMutex(); LockTempMutex();
tempgtk.CopyFrom(&temp); tempgtk.CopyFrom(&temp);
UnLockTempMutex(); UnLockTempMutex();
gdk_threads_add_idle(cb_filtertemp_thread , &tempgtk); gdk_threads_add_idle(cb_thread_filtertemp , &tempgtk);
// //
// do some other stuff use if possible only the oldFrame data // do some other stuff use if possible only the oldFrame data
ComposeOutput(); ComposeOutput();
// copy output image for gtk // copy output image for gtk
LockOutMutex(); LockImageMutex();
imagegtk.CopyFrom(&image); imagegtk.CopyFrom(&image);
UnLockOutMutex(); UnLockImageMutex();
gdk_threads_add_idle(cb_filterout_thread , &imagegtk); gdk_threads_add_idle(cb_thread_filterimage , &imagegtk);
} }
else else
UnLockInMutex(); UnLockInMutex();
@ -104,7 +109,6 @@ void Filter::InputDetect() {
unsigned char *pxs, *pxso, *pxstemp; unsigned char *pxs, *pxso, *pxstemp;
unsigned char pixel; unsigned char pixel;
int idx; int idx;
FloatImage fi;;
float fmin, fmax; float fmin, fmax;
temp.SetSize (inFrame.w, inFrame.h); temp.SetSize (inFrame.w, inFrame.h);
@ -136,22 +140,24 @@ void Filter::InputDetect() {
#define FACTOR 100.0 #define FACTOR 25.0
void Filter::ComposeOutput() { void Filter::ComposeOutput() {
int x, y, idx, i; int x, y, idx, i;
float *pixd; // destination float *pixd = NULL; // destination
unsigned char *pixs; // source unsigned char *pixs = NULL; // source
image.SetSize(oldFrame.w, oldFrame.h); image.SetSize(oldFrame.w, oldFrame.h);
pixd = image.data; pixd = image.data;
pixs = oldFrame.data; pixs = oldFrame.data;
if (pixd == NULL || pixs == NULL) return;
for (x = 0; x < temp.w && x < inFrame.w && x < oldFrame.w; x++) for (x = 0; x < temp.w && x < inFrame.w && x < oldFrame.w; x++)
for (y = 0; y < temp.h && y < inFrame.h && y < oldFrame.h; y++) { for (y = 0; y < temp.h && y < inFrame.h && y < oldFrame.h; y++) {
idx = 3 * (oldFrame.w * y + x); idx = 3 * (oldFrame.w * y + x);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
pixd[idx+i] = (FACTOR * pixd[idx+i]/FACTOR) + (pixs[idx+i] / FACTOR); pixd[idx+i] = ((FACTOR-1) * pixd[idx+i]/FACTOR) + (pixs[idx+i] / FACTOR);
} }
} }

@ -24,11 +24,12 @@ private:
VideoFrame tempgtk; // temp image for gtk VideoFrame tempgtk; // temp image for gtk
FloatImage image; // output image FloatImage image; // output image
VideoFrame imagegtk; // output image -- send to gtk VideoFrame imagegtk; // output image -- send to gtk
GMutex mutexout; GMutex muteximage;
GMutex mutexin; GMutex mutexin;
GMutex mutextmp; // for access the temp image GMutex mutextmp; // for access the temp image
GMutex mutex; // general mutex for changing settings GMutex mutex; // general mutex for changing settings
GThread *thread; GThread *thread;
FloatImage fi;
int objectW; // object Image Size Width int objectW; // object Image Size Width
int objectH; // object Image Size Height int objectH; // object Image Size Height
@ -54,9 +55,9 @@ public:
void LockTempMutex() { g_mutex_lock(&mutextmp);}; void LockTempMutex() { g_mutex_lock(&mutextmp);};
void UnLockTempMutex() { g_mutex_unlock(&mutextmp);}; void UnLockTempMutex() { g_mutex_unlock(&mutextmp);};
int TryLockOutMutex() { return g_mutex_trylock(&mutexout); }; int TryLockImageMutex() { return g_mutex_trylock(&muteximage); };
void LockOutMutex() { g_mutex_lock(&mutexout);}; void LockImageMutex() { g_mutex_lock(&muteximage);};
void UnLockOutMutex() { g_mutex_unlock(&mutexout);}; void UnLockImageMutex() { g_mutex_unlock(&muteximage);};
void LockMutex() { g_mutex_lock(&mutex);}; void LockMutex() { g_mutex_lock(&mutex);};
void UnLockMutex() { g_mutex_unlock(&mutex);}; void UnLockMutex() { g_mutex_unlock(&mutex);};

123
gui.cc

@ -12,8 +12,18 @@
#include <list> #include <list>
#include "gui.h" #include "gui.h"
#include "config.h" #include "config.h"
#include "video.h"
#include "filter.h"
extern GtkBuilder *_builder_; // work around for threads extern GtkBuilder *_builder_; // work around for threads
extern Filter filter;
GtkWidget *temp_da = NULL;
GdkPixbuf *temp_pixbuf = NULL;
GtkWidget *image_da = NULL;
GdkPixbuf *image_pixbuf = NULL;
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
// //
@ -55,3 +65,116 @@ void displayerror (std::string error) {
//
// callback from filter thread. Data will point to the output VideoFrame.
// Access to this data must be Locked before use.
gboolean cb_thread_filterimage (gpointer data) {
VideoFrame *vf = (VideoFrame *) data;
int pix_h, pix_w;
if (image_da == NULL)
image_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "image-da"));
if (vf == NULL) {
return false;
}
filter.LockImageMutex();
if (image_pixbuf) {
pix_h = gdk_pixbuf_get_height(image_pixbuf);
pix_w = gdk_pixbuf_get_width(image_pixbuf);
}
else pix_h = 0;
if (image_pixbuf == NULL || pix_h != vf->h || pix_w != vf->w) {
if (image_pixbuf != NULL) g_object_unref (image_pixbuf);
printf ("%s:%d %s New Pixbuf: %d x %d\n", __FILE__, __LINE__, __FUNCTION__, vf->w, vf->h);
image_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, vf->w, vf->h);
pix_w = vf->w;
pix_h = vf->h;
}
videoframe_to_pixbuf(image_pixbuf, vf);
gdk_window_invalidate_rect(gtk_widget_get_window(image_da), NULL, true);
filter.UnLockImageMutex();
return false;
};
//
// 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_filtertemp (gpointer data) {
VideoFrame *vf = (VideoFrame *) data;
int pix_h, pix_w;
if (temp_da == NULL)
temp_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "temp-da"));
if (vf == NULL) {
return false;
}
filter.LockTempMutex();
if (temp_pixbuf) {
pix_h = gdk_pixbuf_get_height(temp_pixbuf);
pix_w = gdk_pixbuf_get_width(temp_pixbuf);
}
else pix_h = 0;
if (temp_pixbuf == NULL || pix_h != vf->h || pix_w != vf->w) {
if (temp_pixbuf != NULL) g_object_unref (temp_pixbuf);
printf ("%s:%d %s New Pixbuf: %d x %d\n", __FILE__, __LINE__, __FUNCTION__, vf->w, vf->h);
temp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, vf->w, vf->h);
pix_w = vf->w;
pix_h = vf->h;
}
videoframe_to_pixbuf(temp_pixbuf, vf);
gdk_window_invalidate_rect(gtk_widget_get_window(temp_da), NULL, true);
filter.UnLockTempMutex();
return false;
};
void cb_imagetempda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
int clientw, clienth, pixbufw, pixbufh;
float clientar, pixbufar;
GdkPixbuf *pixbuf = NULL;
GdkPixbuf *src = NULL;
if (area == temp_da) src = temp_pixbuf;
else if (area == image_da) src = image_pixbuf;
else return;
clienth = gtk_widget_get_allocated_height(area);
clientw = gtk_widget_get_allocated_width(area);
clientar = (float)clientw/(float)clienth;
pixbufh = gdk_pixbuf_get_height(src);
pixbufw = gdk_pixbuf_get_width(src);
pixbufar = (float)pixbufw/(float)pixbufh;
if (pixbufar < clientar) {
clientw = (pixbufar * (float) clienth);
}
else {
clienth = ((float) clientw / pixbufar);
}
pixbuf = gdk_pixbuf_scale_simple (src, clientw, clienth, GDK_INTERP_NEAREST);
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
cairo_fill (cr);
g_object_unref (pixbuf);
};

11
gui.h

@ -16,7 +16,6 @@
#include <list> #include <list>
#define BUILDER_FILE "simpleskycam.ui" #define BUILDER_FILE "simpleskycam.ui"
extern GtkBuilder *_builder_;
void displayerror (std::string error); void displayerror (std::string error);
@ -48,14 +47,20 @@ gboolean videoctrl_update(gpointer data);
// //
// thread handles // thread new inframe
G_MODULE_EXPORT gboolean cb_thread_video (gpointer data); G_MODULE_EXPORT gboolean cb_thread_video (gpointer data);
//
// filter new temp 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_filterimage (gpointer data);
G_MODULE_EXPORT gboolean cb_thread_filtertemp (gpointer data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
extern float get_cycletime(struct timeval *t); extern float get_cycletime(struct timeval *t);
#endif // _GUI_H_ #endif // _GUI_H_

@ -8,6 +8,7 @@
#include "config.h" #include "config.h"
#include "gui.h" #include "gui.h"
#include "filter.h"
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
// //
@ -15,6 +16,7 @@
// //
GtkBuilder *_builder_ = NULL; // work around for the thread situation GtkBuilder *_builder_ = NULL; // work around for the thread situation
Filter filter;
int main (int argc, char **argv) { int main (int argc, char **argv) {
GtkBuilder *builder; GtkBuilder *builder;

@ -213,11 +213,231 @@
<property name="tab-fill">False</property> <property name="tab-fill">False</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<!-- n-columns=7 n-rows=2 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">8</property>
<property name="margin-right">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="label" translatable="yes">Position</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Size:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">8</property>
<property name="margin-right">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="label" translatable="yes">X:</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="label" translatable="yes">W:</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-left">4</property>
<property name="margin-right">4</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="max-length">5</property>
<property name="width-chars">5</property>
<property name="max-width-chars">5</property>
<property name="input-purpose">digits</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-left">4</property>
<property name="margin-right">4</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="width-chars">5</property>
<property name="max-width-chars">5</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="label" translatable="yes">Y:</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">0</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">nix da - page 2</property> <property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="label" translatable="yes">H:</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-left">4</property>
<property name="margin-right">4</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="width-chars">5</property>
<property name="max-width-chars">5</property>
</object>
<packing>
<property name="left-attach">4</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-left">4</property>
<property name="margin-right">4</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="width-chars">5</property>
<property name="max-width-chars">5</property>
</object>
<packing>
<property name="left-attach">4</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="detect_cbauto">
<property name="label" translatable="yes">Auto</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="margin-left">10</property>
<property name="margin-right">8</property>
<property name="margin-start">10</property>
<property name="margin-end">8</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">5</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btnSet">
<property name="label" translatable="yes">Set Object</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-left">8</property>
<property name="margin-right">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
</object>
<packing>
<property name="left-attach">5</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object> </object>
<packing> <packing>
<property name="position">1</property> <property name="position">1</property>
@ -281,10 +501,10 @@
<property name="position-set">True</property> <property name="position-set">True</property>
<property name="wide-handle">True</property> <property name="wide-handle">True</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkDrawingArea" id="temp-da">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">Video Object</property> <signal name="draw" handler="cb_imagetempda_draw" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="resize">False</property> <property name="resize">False</property>
@ -292,10 +512,10 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkDrawingArea" id="image-da">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">Image Filtered</property> <signal name="draw" handler="cb_imagetempda_draw" swapped="no"/>
</object> </object>
<packing> <packing>
<property name="resize">True</property> <property name="resize">True</property>

@ -9,12 +9,13 @@
#include <stdlib.h> #include <stdlib.h>
#include "gui.h" #include "gui.h"
#include "video.h" #include "video.h"
#include "filter.h"
VideoDev videodev; VideoDev videodev;
GtkWidget *video_da = NULL; GtkWidget *video_da = NULL;
GdkPixbuf *video_pixbuf = NULL; GdkPixbuf *video_pixbuf = NULL;
extern GtkBuilder *_builder_; // work around for threads
extern Filter filter;
gboolean videoctrl_update(gpointer data) { gboolean videoctrl_update(gpointer data) {
GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid"));
@ -48,12 +49,15 @@ void videoframe_to_pixbuf(GdkPixbuf* dest, VideoFrame *src) {
if (dest == NULL || src == NULL) return; if (dest == NULL || src == NULL) return;
destw = gdk_pixbuf_get_height(dest); desth = gdk_pixbuf_get_height(dest);
desth = gdk_pixbuf_get_width(dest); destw = gdk_pixbuf_get_width(dest);
destpixel = gdk_pixbuf_get_pixels(dest); destpixel = gdk_pixbuf_get_pixels(dest);
if (destw > src->w) destw = src->w; if (destw * desth < src->h * src->w) {
if (desth > src->h) destw = src->h; destw = src->w;
desth = src->h;
}
memcpy (destpixel, src->data, 3*destw*desth); memcpy (destpixel, src->data, 3*destw*desth);
} }
@ -93,69 +97,6 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
}; };
void video_draw_image (VideoFrame *vf) {
int pix_w;
int pix_h;
int x, y;
if (video_da == NULL) {
video_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "video-da"));
if (video_da == NULL) {
printf ("%s:%d could not find drawingarea.\n", __FILE__, __LINE__);
return;
}
}
// check if the pixbuf is already allocated?
if (video_pixbuf) {
pix_h = gdk_pixbuf_get_height(video_pixbuf);
pix_w = gdk_pixbuf_get_width(video_pixbuf);
}
else pix_h = 0;
// display error screen?
if (vf == NULL) {
unsigned char *pixels;
// need to allocate?
if (video_pixbuf == NULL) {
printf ("%s:%d new pixbuf\n", __FILE__, __LINE__);
video_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, 640, 480);
pix_w = 640;
pix_h = 480;
}
pixels = gdk_pixbuf_get_pixels(video_pixbuf);
for (y = 0; y < pix_h; y++) for (x = 0; x < pix_w; x++) {
if ((x & 1) && (y & 1)) {
*(++pixels) = 0xFF;
*(++pixels) = 0xFF;
*(++pixels) = 0xFF;
}
else {
*(++pixels) = 0x0;
*(++pixels) = 0x0;
*(++pixels) = 0x0;
}
}
}
else {
//
// changes in resolution?
if (video_pixbuf == NULL || pix_h != vf->h || pix_w != vf->w) {
if (video_pixbuf != NULL) g_object_unref (video_pixbuf);
printf ("%s:%d %s New Pixbuf: %d x %d\n", __FILE__, __LINE__, __FUNCTION__, vf->w, vf->h);
video_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, vf->w, vf->h);
pix_w = vf->w;
pix_h = vf->h;
}
videoframe_to_pixbuf(video_pixbuf, vf);
}
gdk_window_invalidate_rect(gtk_widget_get_window(video_da), NULL, true);
};
// //
// refresh the possible devices // refresh the possible devices
@ -273,7 +214,6 @@ void cb_video_btnstop (GtkWidget *widget, gpointer data) {
}; };
// //
// callback from videodev thread. data will point to the latest VideoFrame. // callback from videodev thread. data will point to the latest VideoFrame.
// Access to this data must be Locked before use. // Access to this data must be Locked before use.
@ -285,16 +225,43 @@ gboolean cb_thread_video (gpointer data) {
btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); 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")); btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec"));
if (video_da == NULL)
video_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "video-da"));
if (vf == NULL) { if (vf == NULL) {
printf ("%s:%d %s something went wrong\n", __FILE__, __LINE__, __FUNCTION__); printf ("%s:%d %s something went wrong\n", __FILE__, __LINE__, __FUNCTION__);
videodev.Stop(); videodev.Stop();
video_draw_image(NULL); if (video_pixbuf == NULL) {
video_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, 100, 100);
}
memset (gdk_pixbuf_get_pixels(video_pixbuf), 0, 3 * gdk_pixbuf_get_height(video_pixbuf) * gdk_pixbuf_get_width(video_pixbuf));
gtk_widget_set_sensitive(btnstart, true); gtk_widget_set_sensitive(btnstart, true);
gtk_widget_set_sensitive(btnstop, false); gtk_widget_set_sensitive(btnstop, false);
} }
else {
int pix_h, pix_w;
videodev.LockMutex(); videodev.LockMutex();
video_draw_image(vf); if (video_pixbuf) {
pix_h = gdk_pixbuf_get_height(video_pixbuf);
pix_w = gdk_pixbuf_get_width(video_pixbuf);
}
else pix_h = 0;
if (video_pixbuf == NULL || pix_h != vf->h || pix_w != vf->w) {
if (video_pixbuf != NULL) g_object_unref (video_pixbuf);
printf ("%s:%d %s New Pixbuf: %d x %d\n", __FILE__, __LINE__, __FUNCTION__, vf->w, vf->h);
video_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, false, 8, vf->w, vf->h);
pix_w = vf->w;
pix_h = vf->h;
}
videoframe_to_pixbuf(video_pixbuf, vf);
filter.NewFrame(vf);
videodev.UnLockMutex(); videodev.UnLockMutex();
}
gdk_window_invalidate_rect(gtk_widget_get_window(video_da), NULL, true);
return false; return false;
}; };

@ -16,6 +16,7 @@
#include "gui.h" #include "gui.h"
#include "config.h" #include "config.h"
#include "videoframe.h"
enum { enum {
@ -65,14 +66,7 @@ struct {
} typedef VideoInBuffer; } typedef VideoInBuffer;
struct { #define VDEV_INBUFFERS 3
int w;
int h;
uint32_t size;
unsigned char *data;
} typedef VideoFrame;
#define VDEV_INBUFFERS 2
class VideoDev { class VideoDev {
private: private:
std::string conf_device; std::string conf_device;
@ -130,13 +124,14 @@ public:
void PrintCaps (uint32_t caps); void PrintCaps (uint32_t caps);
void PrintFmt(struct v4l2_format *f); void PrintFmt(struct v4l2_format *f);
void LockMutex(); void LockMutex() { g_mutex_lock(&mutex); };
void UnLockMutex(); void UnLockMutex() { g_mutex_unlock(&mutex); };
}; };
extern VideoDev videodev; extern VideoDev videodev;
extern void videoframe_to_pixbuf(GdkPixbuf* dest, VideoFrame *src);
#endif // _VIDEO_H_ #endif // _VIDEO_H_

@ -465,8 +465,8 @@ int VideoDev::OpenInit() {
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920; fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080; fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; // fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_NONE; fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) { if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) {
@ -918,14 +918,3 @@ int VideoDev::Convert (VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uin
}; };
void VideoDev::LockMutex() {
g_mutex_lock(&mutex);
};
void VideoDev::UnLockMutex() {
g_mutex_unlock(&mutex);
};

@ -28,7 +28,7 @@ VideoFrame::~VideoFrame() {
// //
// we will only allocate a new image if the needed size increases // we will only allocate a new image if the needed size increases
void VideoFrame::SetSize(int nw, int nh) { void VideoFrame::SetSize(int nw, int nh) {
uint32_t newsize = VIDEOFRAME_DEPTH_BYTES * h * w; uint32_t newsize = VIDEOFRAME_DEPTH_BYTES * nh * nw;
if (newsize > size || data == NULL) { if (newsize > size || data == NULL) {
unsigned char *newdata = (unsigned char *) malloc (newsize); unsigned char *newdata = (unsigned char *) malloc (newsize);
@ -81,6 +81,7 @@ void VideoFrame::CopyFrom(FloatImage *source) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
idx = 3 * (y * w + x); idx = 3 * (y * w + x);
v = (float)(256.0 * (source->data[idx+i]-min) / (max-min)); v = (float)(256.0 * (source->data[idx+i]-min) / (max-min));
data[idx+i] = v;
} }
} }
@ -110,7 +111,7 @@ FloatImage::~FloatImage() {
// //
// we will only allocate a new image if the needed size increases // we will only allocate a new image if the needed size increases
void FloatImage::SetSize(int nw, int nh) { void FloatImage::SetSize(int nw, int nh) {
uint32_t newsize = 3 * h * w * sizeof(float); uint32_t newsize = 3 * nh * nw * sizeof(float);
if (newsize > size || data == NULL) { if (newsize > size || data == NULL) {
float *newdata = (float *) malloc (newsize); float *newdata = (float *) malloc (newsize);

@ -4,9 +4,6 @@
#include "gui.h" #include "gui.h"
#include "config.h" #include "config.h"
class FloatImage { class FloatImage {
public: public:
int w; int w;

Loading…
Cancel
Save