You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SimpleSkyCam/video.cc

201 lines
5.5 KiB

/***************************************************************************************
*
* video.cc is part of SimpleSkyCam.
*
*****************************************************************************************/
#include <list>
#include <string>
#include "gui.h"
#include "video.h"
VideoDev videodev;
GtkWidget *video_da = NULL;
GdkPixbuf *video_pixbuf;
void videoframe_to_pixbuf(GdkPixbuf* dest, VideoFrame *src) {
int destw, desth;
unsigned char *destpixel;
if (dest == NULL || src == NULL) return;
destw = gdk_pixbuf_get_height(dest);
desth = gdk_pixbuf_get_width(dest);
destpixel = gdk_pixbuf_get_pixels(dest);
if (destw > src->w) destw = src->w;
if (desth > src->h) destw = src->h;
memcpy (destpixel, src->data, 3*destw*desth);
}
void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
if (video_da == NULL) return;
//cairo_move_to(cr, 30, 30);
//cairo_set_font_size(cr,15);
//cairo_show_text(cr, "hello world");
gdk_cairo_set_source_pixbuf(cr, video_pixbuf, 0, 0);
cairo_paint(cr);
cairo_fill (cr);
};
void video_draw_image (VideoFrame *vf) {
int pix_w;
int pix_h;
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;
int x, y;
// 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 new pixbuf\n", __FILE__, __LINE__);
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
void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data) {
GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev"));
GtkListStore *model = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(cbox)));
std::list<std::string> devlist;
std::list<std::string>::iterator iter;
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
if (model == NULL) {
model = gtk_list_store_new(1, G_TYPE_STRING);
gtk_combo_box_set_model(GTK_COMBO_BOX(cbox),GTK_TREE_MODEL(model));
}
gtk_list_store_clear(GTK_LIST_STORE(model));
if (videodev.GetDeviceList(&devlist)) {
for (iter = devlist.begin(); iter != devlist.end(); iter++) {
gtk_list_store_insert_with_values(GTK_LIST_STORE(model), NULL, -1,
0, iter->c_str(),
-1);
}
}
};
//
// start recording from the videodev (will start a new thread)
void cb_video_btnrec (GtkWidget *widget, gpointer data) {
GtkWidget *cbox = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "cb-videodev"));
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 *cbdevice = gtk_bin_get_child(GTK_BIN(cbox));
std::string device = gtk_entry_get_text(GTK_ENTRY(cbdevice));
device = device.substr (0, device.find(' '));
printf ("%s:%d %s open device: '%s'\n", __FILE__, __LINE__, __FUNCTION__, device.c_str());
gtk_widget_set_sensitive(btnstart, false);
gtk_widget_set_sensitive(btnstop, true);
videodev.Start(device, cb_thread_video);
};
//
// stop recording from the videodev (will stop the running thread)
void cb_video_btnstop (GtkWidget *widget, gpointer data) {
GtkWidget *btnstart = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-rec"));
GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop"));
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
videodev.Stop();
gtk_widget_set_sensitive(btnstart, true);
gtk_widget_set_sensitive(btnstop, false);
};
gboolean cb_thread_video (gpointer data) {
struct timeval tv;
float f;
GtkWidget *btnstart;
GtkWidget *btnstop;
VideoFrame *vf = (VideoFrame *) data;
// get_cycletime(&tv);
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"));
if (vf == NULL) {
printf ("%s:%d %s something went wrong\n", __FILE__, __LINE__, __FUNCTION__);
videodev.Stop();
video_draw_image(NULL);
gtk_widget_set_sensitive(btnstart, true);
gtk_widget_set_sensitive(btnstop, false);
}
video_draw_image(vf);
// printf ("%s:%d Time for %s ... %f ms\n", __FILE__, __LINE__, __FUNCTION__, get_cycletime(&tv));
return false;
};