diff --git a/data/camorama.glade b/data/camorama.glade
index 9a39cd51b9e4..196d5d705405 100644
--- a/data/camorama.glade
+++ b/data/camorama.glade
@@ -2239,7 +2239,7 @@
<property name="column_spacing">6</property>
<child>
- <widget class="GtkHScale" id="slider2">
+ <widget class="GtkHScale" id="contrast_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">True</property>
@@ -2260,7 +2260,7 @@
</child>
<child>
- <widget class="GtkHScale" id="slider3">
+ <widget class="GtkHScale" id="brightness_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">True</property>
@@ -2282,7 +2282,7 @@
</child>
<child>
- <widget class="GtkHScale" id="slider4">
+ <widget class="GtkHScale" id="color_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">True</property>
@@ -2304,7 +2304,7 @@
</child>
<child>
- <widget class="GtkHScale" id="slider5">
+ <widget class="GtkHScale" id="hue_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">True</property>
@@ -2326,7 +2326,7 @@
</child>
<child>
- <widget class="GtkHScale" id="slider6">
+ <widget class="GtkHScale" id="balance_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">True</property>
@@ -2348,7 +2348,7 @@
</child>
<child>
- <widget class="GtkLabel" id="label64">
+ <widget class="GtkLabel" id="contrast_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Contrast:</property>
<property name="use_underline">False</property>
@@ -2376,7 +2376,7 @@
</child>
<child>
- <widget class="GtkLabel" id="label65">
+ <widget class="GtkLabel" id="brightness_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Brightness:</property>
<property name="use_underline">False</property>
@@ -2404,7 +2404,7 @@
</child>
<child>
- <widget class="GtkLabel" id="label66">
+ <widget class="GtkLabel" id="color_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Color:</property>
<property name="use_underline">False</property>
@@ -2432,7 +2432,7 @@
</child>
<child>
- <widget class="GtkLabel" id="label67">
+ <widget class="GtkLabel" id="hue_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Hue:</property>
<property name="use_underline">False</property>
@@ -2460,7 +2460,7 @@
</child>
<child>
- <widget class="GtkLabel" id="label68">
+ <widget class="GtkLabel" id="balance_label">
<property name="visible">True</property>
<property name="label" translatable="yes">White Balance:</property>
<property name="use_underline">False</property>
diff --git a/src/Makefile.am b/src/Makefile.am
index 1531700662be..19f8fc738f27 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,7 +36,7 @@ camorama_SOURCES = \
filter.h \
$(BUILT_SOURCES)\
$(NULL)
-camorama_LDADD = $(PACKAGE_LIBS) -lv4l1
+camorama_LDADD = $(PACKAGE_LIBS) -lv4l2 -lm
DISTCLEANFILES=$(BUILT_SOURCES)
diff --git a/src/Makefile.in b/src/Makefile.in
index 7d3580cab462..8380179f47d8 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -248,7 +248,7 @@ camorama_SOURCES = \
$(BUILT_SOURCES)\
$(NULL)
-camorama_LDADD = $(PACKAGE_LIBS) -lv4l1
+camorama_LDADD = $(PACKAGE_LIBS) -lv4l2 -lm
DISTCLEANFILES = $(BUILT_SOURCES)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
diff --git a/src/callbacks.c b/src/callbacks.c
index 8f86c7d29009..0b193c804266 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -9,7 +9,7 @@
#include <libgnomeui/gnome-propertybox.h>
#include <libgnomeui/gnome-window-icon.h>
#include <pthread.h>
-#include <libv4l1.h>
+#include <libv4l2.h>
extern GtkWidget *main_window, *prefswindow;
//extern state func_state;
@@ -20,7 +20,6 @@ extern int seconds;
extern GtkWidget *dentry, *entry2, *string_entry;
extern GtkWidget *host_entry,
*directory_entry, *filename_entry, *login_entry, *pw_entry;
-int frame;
/*
* pref callbacks
@@ -369,88 +368,41 @@ void on_change_size_activate (GtkWidget * widget, cam * cam)
name = gtk_widget_get_name (widget);
printf("name = %s\n",name);
if (strcmp (name, "small") == 0) {
- cam->x = cam->vid_cap.minwidth;
- cam->y = cam->vid_cap.minheight;
+ cam->width = cam->min_width;
+ cam->height = cam->min_height;
if (cam->debug) {
printf ("\nsmall\n");
}
} else if (strcmp (name, "medium") == 0) {
- cam->x = cam->vid_cap.maxwidth / 2;
- cam->y = cam->vid_cap.maxheight / 2;
+ cam->width = cam->max_width / 2;
+ cam->height = cam->max_height / 2;
if (cam->debug) {
printf ("\nmed\n");
}
} else {
- cam->x = cam->vid_cap.maxwidth;
- cam->y = cam->vid_cap.maxheight;
+ cam->width = cam->max_width;
+ cam->height = cam->max_height;
if (cam->debug) {
printf ("\nlarge\n");
}
}
-
- /*
- * if(cam->read == FALSE) {
- * cam->pic = v4l1_mmap(0, cam->vid_buf.size, PROT_READ | PROT_WRITE, MAP_SHARED, cam->dev, 0);
- *
- * if((unsigned char *) -1 == (unsigned char *) cam->pic) {
- * if(cam->debug == TRUE) {
- * fprintf(stderr, "Unable to capture image (mmap).\n");
- * }
- * error_dialog(_("Unable to capture image."));
- * exit(-1);
- * }
- * }else{
- * cam->pic_buf = malloc(cam->x * cam->y * cam->depth);
- * v4l1_read(cam->dev,cam->pic,(cam->x * cam->y * 3));
- * }
- */
-
- cam->vid_win.x = 0;
- cam->vid_win.y = 0;
- cam->vid_win.width = cam->x;
- cam->vid_win.height = cam->y;
- cam->vid_win.chromakey = 0;
- cam->vid_win.flags = 0;
-
+ if (cam->read == FALSE)
+ stop_streaming(cam);
set_win_info (cam);
- // get_win_info(cam);
- cam->vid_map.height = cam->y;
- cam->vid_map.width = cam->x;
- /*
- * cam->vid_win.height = cam->y;
- * * cam->vid_win.width = cam->x;
- * * get_win_info(cam);
- */
- cam->vid_map.format = cam->vid_pic.palette;
- // get_win_info(cam);
- /*
- * if(cam->read == FALSE) {
- * * for(frame = 0; frame < cam->vid_buf.frames; frame++) {
- * * cam->vid_map.frame = frame;
- * * if(v4l1_ioctl(cam->dev, VIDIOCMCAPTURE, &cam->vid_map) < 0) {
- * * if(cam->debug == TRUE) {
- * * fprintf(stderr, "Unable to capture image (VIDIOCMCAPTURE) during resize.\n");
- * * }
- * * //error_dialog(_("Unable to capture image."));
- * * //exit(-1);
- * * }
- * * }
- * * }
- */
- get_win_info (cam);
+ if (cam->read == FALSE)
+ start_streaming(cam);
- cam->pixmap = gdk_pixmap_new (NULL, cam->x, cam->y, cam->desk_depth);
+ cam->pixmap = gdk_pixmap_new (NULL, cam->width, cam->height, cam->desk_depth);
gtk_widget_set_size_request (glade_xml_get_widget (cam->xml, "da"),
- cam->x, cam->y);
+ cam->width, cam->height);
- frame = 0;
gtk_window_resize (GTK_WINDOW
(glade_xml_get_widget (cam->xml, "main_window")), 320,
240);
- title = g_strdup_printf ("Camorama - %s - %dx%d", cam->vid_cap.name,
- cam->x, cam->y);
+ title = g_strdup_printf ("Camorama - %s - %dx%d", cam->name,
+ cam->width, cam->height);
gtk_window_set_title (GTK_WINDOW
(glade_xml_get_widget (cam->xml, "main_window")),
title);
@@ -530,14 +482,14 @@ static void
apply_filters(cam* cam) {
/* v4l has reverse rgb order from what camora expect so call the color
filter to fix things up before running the user selected filters */
- camorama_filter_color_filter(NULL, cam->pic_buf, cam->x, cam->y, cam->depth);
- camorama_filter_chain_apply(cam->filter_chain, cam->pic_buf, cam->x, cam->y, cam->depth);
+ camorama_filter_color_filter(NULL, cam->pic_buf, cam->width, cam->height, cam->depth);
+ camorama_filter_chain_apply(cam->filter_chain, cam->pic_buf, cam->width, cam->height, cam->depth);
#warning "FIXME: enable the threshold channel filter"
// if((effect_mask & CAMORAMA_FILTER_THRESHOLD_CHANNEL) != 0)
-// threshold_channel (cam->pic_buf, cam->x, cam->y, cam->dither);
+// threshold_channel (cam->pic_buf, cam->width, cam->height, cam->dither);
#warning "FIXME: enable the threshold filter"
// if((effect_mask & CAMORAMA_FILTER_THRESHOLD) != 0)
-// threshold (cam->pic_buf, cam->x, cam->y, cam->dither);
+// threshold (cam->pic_buf, cam->width, cam->height, cam->dither);
}
/*
@@ -547,24 +499,24 @@ gint
read_timeout_func(cam* cam) {
int i, count = 0;
GdkGC *gc;
+ unsigned char *pic_buf = cam->pic_buf;
- v4l1_read (cam->dev, cam->pic, (cam->x * cam->y * 3));
+ v4l2_read (cam->dev, cam->pic_buf, (cam->width * cam->height * cam->depth / 8));
frames2++;
/*
* update_rec.x = 0;
* update_rec.y = 0;
- * update_rec.width = cam->x;
- * update_rec.height = cam->y;
+ * update_rec.width = cam->width;
+ * update_rec.height = cam->height;
*/
count++;
/*
* refer the frame
*/
- cam->pic_buf = cam->pic; // + cam->vid_buf.offsets[frame];
- if (cam->vid_pic.palette == VIDEO_PALETTE_YUV420P) {
- yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->x, cam->y, cam->depth);
- cam->pic_buf = cam->tmp;
+ if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
+ yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->width, cam->height, cam->depth);
+ pic_buf = cam->tmp;
}
apply_filters(cam);
@@ -572,12 +524,12 @@ read_timeout_func(cam* cam) {
gc = gdk_gc_new (cam->pixmap);
gdk_draw_rgb_image (cam->pixmap,
gc, 0, 0,
- cam->vid_win.width, cam->vid_win.height,
- GDK_RGB_DITHER_NORMAL, cam->pic_buf,
- cam->vid_win.width * cam->depth);
+ cam->width, cam->height,
+ GDK_RGB_DITHER_NORMAL, pic_buf,
+ cam->width * cam->depth / 8);
gtk_widget_queue_draw_area (glade_xml_get_widget (cam->xml, "da"), 0,
- 0, cam->x, cam->y);
+ 0, cam->width, cam->height);
return 1;
}
@@ -586,34 +538,17 @@ gint timeout_func (cam * cam)
{
int i, count = 0;
GdkGC *gc;
+ unsigned char *pic_buf = cam->pic_buf;
- i = -1;
- while (i < 0) {
- i = v4l1_ioctl (cam->dev, VIDIOCSYNC, &frame);
+ capture_buffers(cam, cam->pic_buf, cam->width * cam->height * cam->bytesperline);
- if (i < 0 && errno == EINTR) {
- if (cam->debug == TRUE) {
- printf ("i = %d\n", i);
- }
- continue;
- }
- if (i < 0) {
- if (cam->debug == TRUE) {
- fprintf (stderr, "Unable to capture image (VIDIOCSYNC)\n");
- }
- error_dialog (_("Unable to capture image."));
- exit (-1);
- }
- break;
- }
count++;
/*
* refer the frame
*/
- cam->pic_buf = cam->pic + cam->vid_buf.offsets[frame];
- if (cam->vid_pic.palette == VIDEO_PALETTE_YUV420P) {
- yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->x, cam->y, cam->depth);
- cam->pic_buf = cam->tmp;
+ if (cam->pixformat == V4L2_PIX_FMT_YUV420) {
+ yuv420p_to_rgb (cam->pic_buf, cam->tmp, cam->width, cam->height, cam->depth);
+ pic_buf = cam->tmp;
}
apply_filters(cam);
@@ -623,33 +558,12 @@ gint timeout_func (cam * cam)
gdk_draw_rgb_image (cam->pixmap,
gc, 0, 0,
- cam->vid_win.width, cam->vid_win.height,
- GDK_RGB_DITHER_NORMAL, cam->pic_buf,
- cam->vid_win.width * cam->depth);
+ cam->width, cam->height,
+ GDK_RGB_DITHER_NORMAL, pic_buf,
+ cam->width * cam->depth / 8);
gtk_widget_queue_draw_area (glade_xml_get_widget (cam->xml, "da"), 0,
- 0, cam->x, cam->y);
-
- cam->vid_map.frame = frame;
- if (v4l1_ioctl (cam->dev, VIDIOCMCAPTURE, &cam->vid_map) < 0) {
- if (cam->debug == TRUE) {
- fprintf (stderr, "Unable to capture image (VIDIOCMCAPTURE)\n");
- }
- error_dialog (_("Unable to capture image."));
- exit (-1);
- }
-
- /*
- * next frame
- */
- frame++;
-
- /*
- * reset to the 1st frame
- */
- if (frame >= cam->vid_buf.frames) {
- frame = 0;
- }
+ 0, cam->width, cam->height);
frames2++;
g_object_unref ((gpointer) gc);
@@ -675,45 +589,15 @@ void on_status_show (GtkWidget * sb, cam * cam)
cam->status = sb;
}
-void init_cam (GtkWidget * capture, cam * cam)
-{
- cam->pic =
- v4l1_mmap (0, cam->vid_buf.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, cam->dev, 0);
-
- if ((unsigned char *) -1 == (unsigned char *) cam->pic) {
- if (cam->debug == TRUE) {
- fprintf (stderr, "Unable to capture image (mmap).\n");
- }
- error_dialog (_("Unable to capture image."));
- exit (-1);
- }
- cam->vid_map.height = cam->y;
- cam->vid_map.width = cam->x;
- cam->vid_map.format = cam->vid_pic.palette;
- for (frame = 0; frame < cam->vid_buf.frames; frame++) {
- cam->vid_map.frame = frame;
- if (v4l1_ioctl (cam->dev, VIDIOCMCAPTURE, &cam->vid_map) < 0) {
- if (cam->debug == TRUE) {
- fprintf (stderr,
- "Unable to capture image (VIDIOCMCAPTURE).\n");
- }
- error_dialog (_("Unable to capture image."));
- exit (-1);
- }
- }
- frame = 0;
-}
-
void capture_func (GtkWidget * widget, cam * cam)
{
if (cam->debug == TRUE) {
printf
("capture_func\nx = %d, y = %d, depth = %d, realloc size = %d\n",
- cam->x, cam->y, cam->depth, (cam->x * cam->y * cam->depth));
+ cam->width, cam->height, cam->depth, (cam->width * cam->height * cam->depth / 8));
}
- memcpy (cam->tmp, cam->pic_buf, cam->x * cam->y * cam->depth);
+ memcpy (cam->tmp, cam->pic_buf, cam->width * cam->height * cam->depth / 8);
if (cam->rcap == TRUE) {
remote_save (cam);
@@ -728,7 +612,7 @@ gint timeout_capture_func (cam * cam)
{
/* GdkRectangle rect;
* rect->x = 0; rect->y = 0;
- * rect->width = cam->x; rect->height = cam->y; */
+ * rect->width = cam->width; rect->height = cam->height; */
/* need to return true, or the timeout will be destroyed - don't forget! :) */
if (cam->hidden == TRUE) {
@@ -742,7 +626,7 @@ gint timeout_capture_func (cam * cam)
pt2Function (cam);
}
- memcpy (cam->tmp, cam->pic_buf, cam->x * cam->y * cam->depth);
+ memcpy (cam->tmp, cam->pic_buf, cam->width * cam->height * cam->depth / 8);
if (cam->cap == TRUE) {
local_save (cam);
@@ -756,39 +640,36 @@ gint timeout_capture_func (cam * cam)
void contrast_change (GtkHScale * sc1, cam * cam)
{
- cam->vid_pic.contrast =
- 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
- set_pic_info (cam);
+ cam->contrast = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
+ v4l2_set_control(cam->dev, V4L2_CID_CONTRAST, cam->contrast);
}
void brightness_change (GtkHScale * sc1, cam * cam)
{
- cam->vid_pic.brightness =
- 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
- set_pic_info (cam);
+ cam->brightness = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
+ v4l2_set_control(cam->dev, V4L2_CID_BRIGHTNESS, cam->brightness);
}
void colour_change (GtkHScale * sc1, cam * cam)
{
- cam->vid_pic.colour = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
- set_pic_info (cam);
+ cam->colour = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
+ v4l2_set_control(cam->dev, V4L2_CID_SATURATION, cam->colour);
}
void hue_change (GtkHScale * sc1, cam * cam)
{
- cam->vid_pic.hue = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
- set_pic_info (cam);
+ cam->hue = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
+ v4l2_set_control(cam->dev, V4L2_CID_HUE, cam->hue);
}
void wb_change (GtkHScale * sc1, cam * cam)
{
- cam->vid_pic.whiteness =
- 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
- set_pic_info (cam);
+ cam->whiteness = 256 * (int) gtk_range_get_value ((GtkRange *) sc1);
+ v4l2_set_control(cam->dev, V4L2_CID_WHITENESS, cam->whiteness);
}
void help_cb (GtkWidget * widget, gpointer data)
diff --git a/src/callbacks.h b/src/callbacks.h
index a4294f9161b8..6cebc103866a 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -43,7 +43,6 @@ void prefs_func (GtkWidget *, cam *);
gint io_func (cam *, gint, GdkInputCondition);
void capture_func2 (GtkWidget *, cam *);
void capture_func (GtkWidget *, cam *);
-void init_cam (GtkWidget * capture, cam * cam);
gint timeout_capture_func (cam *);
gint fps (GtkWidget *);
gint timeout_func (cam *);
diff --git a/src/camorama-window.c b/src/camorama-window.c
index c420b388895f..62beec38b003 100644
--- a/src/camorama-window.c
+++ b/src/camorama-window.c
@@ -243,8 +243,8 @@ load_interface(cam* cam) {
* glade_xml_signal_autoconnect(xml);
* this won't work, can't pass data to callbacks. have to do it individually :(*/
- title = g_strdup_printf ("Camorama - %s - %dx%d", cam->vid_cap.name,
- cam->x, cam->y);
+ title = g_strdup_printf ("Camorama - %s - %dx%d", cam->name,
+ cam->width, cam->height);
gtk_window_set_title (GTK_WINDOW
(glade_xml_get_widget (cam->xml, "main_window")),
title);
@@ -283,31 +283,61 @@ load_interface(cam* cam) {
G_CALLBACK (delete_event), NULL);
/* sliders */
- glade_xml_signal_connect_data (cam->xml, "contrast_change",
- G_CALLBACK (contrast_change), cam);
- gtk_range_set_value ((GtkRange *)
- glade_xml_get_widget (cam->xml, "slider2"),
- (int) (cam->contrast / 256));
- glade_xml_signal_connect_data (cam->xml, "brightness_change",
- G_CALLBACK (brightness_change), cam);
- gtk_range_set_value ((GtkRange *)
- glade_xml_get_widget (cam->xml, "slider3"),
- (int) (cam->brightness / 256));
- glade_xml_signal_connect_data (cam->xml, "colour_change",
- G_CALLBACK (colour_change), cam);
- gtk_range_set_value ((GtkRange *)
- glade_xml_get_widget (cam->xml, "slider4"),
- (int) (cam->colour / 256));
- glade_xml_signal_connect_data (cam->xml, "hue_change",
- G_CALLBACK (hue_change), cam);
- gtk_range_set_value ((GtkRange *)
- glade_xml_get_widget (cam->xml, "slider5"),
- (int) (cam->hue / 256));
- glade_xml_signal_connect_data (cam->xml, "wb_change",
- G_CALLBACK (wb_change), cam);
- gtk_range_set_value ((GtkRange *)
- glade_xml_get_widget (cam->xml, "slider6"),
- (int) (cam->wb / 256));
+ if (cam->contrast < 0) {
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "contrast_icon"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "contrast_label"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "contrast_slider"));
+ } else {
+ glade_xml_signal_connect_data (cam->xml, "contrast_change",
+ G_CALLBACK (contrast_change), cam);
+ gtk_range_set_value ((GtkRange *)
+ glade_xml_get_widget (cam->xml, "contrast_slider"),
+ (int) (cam->contrast / 256));
+ }
+ if (cam->brightness < 0) {
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "brightness_icon"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "brightness_label"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "brightness_slider"));
+ } else {
+ glade_xml_signal_connect_data (cam->xml, "brightness_change",
+ G_CALLBACK (brightness_change), cam);
+ gtk_range_set_value ((GtkRange *)
+ glade_xml_get_widget (cam->xml, "brightness_slider"),
+ (int) (cam->brightness / 256));
+ }
+ if (cam->colour < 1) {
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "color_icon"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "color_label"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "color_slider"));
+ } else {
+ glade_xml_signal_connect_data (cam->xml, "colour_change",
+ G_CALLBACK (colour_change), cam);
+ gtk_range_set_value ((GtkRange *)
+ glade_xml_get_widget (cam->xml, "color_slider"),
+ (int) (cam->colour / 256));
+ }
+ if (cam->hue < 0) {
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "hue_icon"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "hue_label"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "hue_slider"));
+ } else {
+ glade_xml_signal_connect_data (cam->xml, "hue_change",
+ G_CALLBACK (hue_change), cam);
+ gtk_range_set_value ((GtkRange *)
+ glade_xml_get_widget (cam->xml, "hue_slider"),
+ (int) (cam->hue / 256));
+ }
+ if (cam->whiteness < 0) {
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "balance_icon"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "balance_label"));
+ gtk_widget_hide(glade_xml_get_widget (cam->xml, "balance_slider"));
+ } else {
+ glade_xml_signal_connect_data (cam->xml, "wb_change",
+ G_CALLBACK (wb_change), cam);
+ gtk_range_set_value ((GtkRange *)
+ glade_xml_get_widget (cam->xml, "balance_slider"),
+ (int) (cam->whiteness / 256));
+ }
/* buttons */
glade_xml_signal_connect_data (cam->xml, "on_status_show",
@@ -459,7 +489,7 @@ load_interface(cam* cam) {
(cam->xml, "string_entry"), cam->usestring);
gtk_widget_set_size_request (glade_xml_get_widget (cam->xml, "da"),
- cam->x, cam->y);
+ cam->width, cam->height);
prefswindow = glade_xml_get_widget (cam->xml, "prefswindow");
}
diff --git a/src/fileio.c b/src/fileio.c
index 43ee0b2744aa..ff6897f62208 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -112,7 +112,7 @@ void remote_save (cam * cam)
//cam->tmp = NULL;
if (cam->rtimestamp == TRUE) {
- add_rgb_text (cam->tmp, cam->x, cam->y, cam->ts_string,
+ add_rgb_text (cam->tmp, cam->width, cam->height, cam->ts_string,
cam->date_format, cam->usestring, cam->usedate);
}
@@ -129,8 +129,8 @@ void remote_save (cam * cam)
filename = g_strdup_printf ("camorama.%s", ext);
//g_free(ext);
pb = gdk_pixbuf_new_from_data (cam->tmp, GDK_COLORSPACE_RGB, FALSE, 8,
- cam->x, cam->y,
- cam->x * cam->vid_pic.depth / 8, NULL,
+ cam->width, cam->height,
+ cam->width * cam->depth / 8, NULL,
NULL);
if (pb == NULL) {
@@ -174,10 +174,10 @@ void remote_save (cam * cam)
* exit (0);
* }
*
- * tmp = malloc (sizeof (char) * cam->x * cam->y * cam->depth * 2);
+ * tmp = malloc (sizeof (char) * cam->width * cam->height * cam->depth * 2);
* while (!feof (fp))
* {
- * bytes += fread (tmp, 1, cam->x * cam->y * cam->depth, fp);
+ * bytes += fread (tmp, 1, cam->width * cam->height * cam->depth, fp);
* }
* fclose (fp);
*
@@ -280,9 +280,9 @@ void save_thread (cam * cam)
//exit (0);
}
- tmp = malloc (sizeof (char) * cam->x * cam->y * cam->depth * 2);
+ tmp = malloc (sizeof (char) * cam->width * cam->height * cam->depth * 2);
while (!feof (fp)) {
- bytes += fread (tmp, 1, cam->x * cam->y * cam->depth, fp);
+ bytes += fread (tmp, 1, cam->width * cam->height * cam->depth, fp);
}
fclose (fp);
@@ -367,10 +367,10 @@ int local_save (cam * cam)
ext = g_strdup ((gchar *) "jpeg");
}
//cam->tmp = NULL;
- //memcpy (cam->tmp, cam->pic_buf, cam->x * cam->y * cam->depth);
+ //memcpy (cam->tmp, cam->pic_buf, cam->width * cam->height * cam->depth);
if (cam->timestamp == TRUE) {
- add_rgb_text (cam->tmp, cam->x, cam->y, cam->ts_string,
+ add_rgb_text (cam->tmp, cam->width, cam->height, cam->ts_string,
cam->date_format, cam->usestring, cam->usedate);
}
@@ -421,8 +421,8 @@ int local_save (cam * cam)
}
pb = gdk_pixbuf_new_from_data (cam->tmp, GDK_COLORSPACE_RGB, FALSE, 8,
- cam->x, cam->y,
- (cam->x * cam->vid_pic.depth / 8), NULL,
+ cam->width, cam->height,
+ (cam->width * cam->depth / 8), NULL,
NULL);
pbs = gdk_pixbuf_save (pb, filename, ext, NULL, NULL);
if (pbs == FALSE) {
diff --git a/src/main.c b/src/main.c
index 8fb289aeea9f..8cda62e08ee2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,8 @@
#include "interface.h"
#include "callbacks.h"
+#include "filter.h"
+#include "camorama-window.h"
#include "support.h"
#include <config.h>
@@ -9,7 +11,7 @@
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlibrgb.h>
#include <locale.h>
-#include <libv4l1.h>
+#include <libv4l2.h>
#include "camorama-display.h"
#include "camorama-stock-items.h"
@@ -71,6 +73,7 @@ main(int argc, char *argv[]) {
gboolean buggery = FALSE;
GtkWidget *button;
GConfClient *gc;
+ unsigned int bufsize;
const struct poptOption popt_options[] = {
{"version", 'V', POPT_ARG_NONE, &ver, 0,
@@ -97,11 +100,12 @@ main(int argc, char *argv[]) {
cam = &cam_object;
/* set some default values */
cam->frame_number = 0;
- cam->pic = NULL;
cam->pixmap = NULL;
cam->size = PICHALF;
cam->video_dev = NULL;
cam->read = FALSE;
+ cam->width = 0;
+ cam->height = 0;
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -120,8 +124,8 @@ main(int argc, char *argv[]) {
cam->debug = buggery;
- cam->x = x;
- cam->y = y;
+ cam->width = x;
+ cam->height = y;
glade_gnome_init ();
glade_set_custom_handler (camorama_glade_handler,
cam);
@@ -141,7 +145,7 @@ main(int argc, char *argv[]) {
cam->size = PICHALF;
}
if (use_read) {
- printf ("gah!\n");
+ printf ("Forcing read mode\n");
cam->read = TRUE;
}
gc = gconf_client_get_default ();
@@ -198,7 +202,7 @@ main(int argc, char *argv[]) {
cam->acap = gconf_client_get_bool (cam->gc, KEY20, NULL);
cam->timeout_interval = gconf_client_get_int (cam->gc, KEY21, NULL);
cam->show_adjustments = gconf_client_get_bool (cam->gc, KEY22, NULL);
- cam->show_effects = gconf_client_get_bool (cam->gc, KEY23, NULL);
+ cam->show_effects = gconf_client_get_bool (cam->gc, KEY23, NULL);
/* get desktop depth */
@@ -207,53 +211,37 @@ main(int argc, char *argv[]) {
gdk_pixbuf_xlib_init (display, 0);
cam->desk_depth = xlib_rgb_get_depth ();
- cam->dev = v4l1_open (cam->video_dev, O_RDWR);
+ cam->dev = v4l2_open (cam->video_dev, O_RDWR | O_NONBLOCK);
camera_cap (cam);
get_win_info (cam);
- /* query/set window attributes */
- cam->vid_win.x = 0;
- cam->vid_win.y = 0;
- cam->vid_win.width = cam->x;
- cam->vid_win.height = cam->y;
- cam->vid_win.chromakey = 0;
- cam->vid_win.flags = 0;
-
set_win_info (cam);
get_win_info (cam);
/* get picture attributes */
get_pic_info (cam);
- set_pic_info (cam);
- cam->contrast = cam->vid_pic.contrast;
- cam->brightness = cam->vid_pic.brightness;
- cam->colour = cam->vid_pic.colour;
- cam->hue = cam->vid_pic.hue;
- cam->wb = cam->vid_pic.whiteness;
- cam->depth = cam->vid_pic.depth / 8;
- cam->pic_buf = malloc (cam->x * cam->y * cam->depth);
- cam->tmp =
- malloc (cam->vid_cap.maxwidth * cam->vid_cap.maxheight * cam->depth);
- //cam->tmp = NULL;
- /* set the buffer size */
- if (cam->read == FALSE) {
- set_buffer (cam);
+
+ bufsize = cam->max_width * cam->max_height * cam->depth / 8;
+ cam->pic_buf = malloc (bufsize);
+ cam->tmp = malloc (bufsize);
+
+ if (!cam->pic_buf || !cam->tmp) {
+ printf("Failed to allocate memory for buffers\n");
+ exit(0);
}
+
//cam->read = FALSE;
/* initialize cam and create the window */
if (cam->read == FALSE) {
pt2Function = timeout_func;
- init_cam (NULL, cam);
+ start_streaming (cam);
} else {
printf ("using read()\n");
- cam->pic =
- realloc (cam->pic,
- (cam->vid_cap.maxwidth * cam->vid_cap.maxheight * 3));
pt2Function = read_timeout_func;
}
- cam->pixmap = gdk_pixmap_new (NULL, cam->x, cam->y, cam->desk_depth);
+ cam->pixmap = gdk_pixmap_new (NULL, cam->width, cam->height, cam->desk_depth);
filename =
gnome_program_locate_file (NULL,
@@ -285,8 +273,10 @@ main(int argc, char *argv[]) {
gtk_timeout_add (2000, (GSourceFunc) fps, cam->status);
gtk_main ();
- v4l1_munmap(cam->pic, cam->vid_buf.size);
- v4l1_close(cam->dev);
-
+ if (cam->read == FALSE) {
+ stop_streaming (cam);
+ }
+ v4l2_close(cam->dev);
+
return 0;
}
diff --git a/src/v4l.c b/src/v4l.c
index f848ce7f944a..47c0fe60bb7d 100644
--- a/src/v4l.c
+++ b/src/v4l.c
@@ -2,260 +2,496 @@
#include<time.h>
#include<errno.h>
#include<gnome.h>
-#include <libv4l1.h>
+#include <sys/select.h>
#include "support.h"
extern int frame_number;
extern int errno;
void print_cam(cam *cam){
- printf("\nCamera Info\n");
- printf("-------------\n");
- printf("device = %s, x = %d, y = %d\n",cam->video_dev, cam->x,cam->y);
- printf("depth = %d, desk_depth = %d, size = %d\n",cam->depth,cam->desk_depth,cam->size);
- printf("capture directory = %s, capture file = %s\n",cam->pixdir, cam->capturefile);
- printf("remote capture directory = %s, remote capture file = %s\n",cam->rpixdir, cam->rcapturefile);
- printf("remote host = %s, remote login = %s\n",cam->rhost,cam->rlogin);
- printf("timestamp = %s\n\n",cam->ts_string);
-
-}
-void print_palette(int p)
-{
-
- switch (p) {
- case VIDEO_PALETTE_HI240:
- printf("High 240 cube (BT848)\n");
- break;
-
- case VIDEO_PALETTE_RGB565:
- printf("565 16 bit RGB\n");
- break;
-
- case VIDEO_PALETTE_RGB24:
- printf("24bit RGB\n");
- break;
+ printf("\nCamera Info\n");
+ printf("-------------\n");
+ printf("device = %s, x = %d, y = %d\n",cam->video_dev, cam->width,cam->height);
+ printf("depth = %d, desk_depth = %d, size = %d\n",cam->depth,cam->desk_depth,cam->size);
+ printf("capture directory = %s, capture file = %s\n",cam->pixdir, cam->capturefile);
+ printf("remote capture directory = %s, remote capture file = %s\n",cam->rpixdir, cam->rcapturefile);
+ printf("remote host = %s, remote login = %s\n",cam->rhost,cam->rlogin);
+ printf("timestamp = %s\n\n",cam->ts_string);
- case VIDEO_PALETTE_RGB32:
- printf("32bit RGB\n");
- break;
-
- case VIDEO_PALETTE_RGB555:
- printf("555 15bit RGB\n");
- break;
+}
- case VIDEO_PALETTE_YUV422:
- printf("YUV422 capture");
- break;
+void camera_cap(cam * cam)
+{
+ char *msg;
+ int i;
+ struct v4l2_capability vid_cap = { 0 };
+ struct v4l2_fmtdesc fmtdesc = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
+ struct v4l2_format fmt;
- case VIDEO_PALETTE_YUYV:
- printf("YUYV\n");
- break;
+ /* Query device capabilities */
+ if(v4l2_ioctl(cam->dev, VIDIOC_QUERYCAP, &vid_cap) == -1) {
+ if(cam->debug == TRUE) {
+ fprintf(stderr, "VIDIOC_QUERYCAP -- could not get camera capabilities, exiting.....\n");
+ }
+ msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
- case VIDEO_PALETTE_UYVY:
- printf("UYVY\n");
- break;
+ /* Query supported resolutions */
- case VIDEO_PALETTE_YUV420:
- printf("YUV420\n");
- break;
+ cam->min_width = -1;
+ cam->min_height = -1;
+ cam->max_width = 0;
+ cam->max_height = 0;
+ for (i = 0; ; i++) {
+ fmtdesc.index = i;
- case VIDEO_PALETTE_YUV411:
- printf("YUV411 capture\n");
- break;
+ if (v4l2_ioctl(cam->dev, VIDIOC_ENUM_FMT, &fmtdesc))
+ break;
- case VIDEO_PALETTE_RAW:
- printf("RAW capture (BT848)\n");
- break;
+ if(cam->debug == TRUE)
+ printf("format index %d: FOURCC: '%c%c%c%c' (%08x)%s\n", i,
+ fmtdesc.pixelformat & 0xff,
+ (fmtdesc.pixelformat >> 8) & 0xff,
+ (fmtdesc.pixelformat >> 16) & 0xff,
+ fmtdesc.pixelformat >> 24,
+ fmtdesc.pixelformat,
+ fmtdesc.flags & V4L2_FMT_FLAG_EMULATED ? " (emulated)" : ""
+ );
- case VIDEO_PALETTE_YUV422P:
- printf("YUV 4:2:2 Planar");
- break;
+ /* FIXME: add a check for emulated formats */
- case VIDEO_PALETTE_YUV411P:
- printf("YUV 4:1:1 Planar\n");
- break;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.pixelformat = fmtdesc.pixelformat;
+ fmt.fmt.pix.width = 48;
+ fmt.fmt.pix.height = 32;
- case VIDEO_PALETTE_YUV420P:
- printf("YUV 4:2:0 Planar\n");
- break;
+ if (!v4l2_ioctl(cam->dev, VIDIOC_TRY_FMT, &fmt)) {
+ if (fmt.fmt.pix.width < cam->min_width)
+ cam->min_width = fmt.fmt.pix.width;
+ if (fmt.fmt.pix.height < cam->min_height)
+ cam->min_height = fmt.fmt.pix.height;
+ if (cam->debug == TRUE)
+ printf(" MIN: %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
+ }
- case VIDEO_PALETTE_YUV410P:
- printf("YUV 4:1:0 Planar\n");
- break;
- }
-}
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.pixelformat = fmtdesc.pixelformat;
+ fmt.fmt.pix.width = 100000;
+ fmt.fmt.pix.height = 100000;
-void camera_cap(cam * cam)
-{
- char *msg;
- if(v4l1_ioctl(cam->dev, VIDIOCGCAP, &cam->vid_cap) == -1) {
- if(cam->debug == TRUE) {
- fprintf(stderr, "VIDIOCGCAP -- could not get camera capabilities, exiting.....\n");
+ if (!v4l2_ioctl(cam->dev, VIDIOC_TRY_FMT, &fmt)) {
+ if (fmt.fmt.pix.width > cam->max_width)
+ cam->max_width = fmt.fmt.pix.width;
+ if (fmt.fmt.pix.height > cam->max_height)
+ cam->max_height = fmt.fmt.pix.height;
+ if(cam->debug == TRUE)
+ printf(" MAX: %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
}
- msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
- error_dialog(msg);
- g_free(msg);
- exit(0);
}
- if(cam->x > 0 && cam->y > 0) {
- if(cam->vid_cap.maxwidth < cam->x) {
- cam->x = cam->vid_cap.maxwidth;
+
+ /* Adjust camera resolution */
+
+ if(cam->width > 0 && cam->height > 0) {
+ if(cam->max_width < cam->width) {
+ cam->width = cam->max_width;
}
- if(cam->vid_cap.minwidth > cam->x) {
- cam->x = cam->vid_cap.minwidth;
+ if(cam->min_width > cam->width) {
+ cam->width = cam->min_width;
}
- if(cam->vid_cap.maxheight < cam->y) {
- cam->y = cam->vid_cap.maxheight;
+ if(cam->max_height < cam->height) {
+ cam->height = cam->max_height;
}
- if(cam->vid_cap.minheight > cam->y) {
- cam->y = cam->vid_cap.minheight;
+ if(cam->min_height > cam->height) {
+ cam->height = cam->min_height;
}
} else {
switch (cam->size) {
case PICMAX:
- cam->x = cam->vid_cap.maxwidth;
- cam->y = cam->vid_cap.maxheight;
+ cam->width = cam->max_width;
+ cam->height = cam->max_height;
break;
case PICMIN:
- cam->x = cam->vid_cap.minwidth;
- cam->y = cam->vid_cap.minheight;
+ cam->width = cam->min_width;
+ cam->height = cam->min_height;
break;
case PICHALF:
- cam->x = cam->vid_cap.maxwidth / 2;
- cam->y = cam->vid_cap.maxheight / 2;
+ cam->width = cam->max_width / 2;
+ cam->height = cam->max_height / 2;
break;
default:
- cam->x = cam->vid_cap.maxwidth / 2;
- cam->y = cam->vid_cap.maxheight / 2;
+ cam->width = cam->max_width / 2;
+ cam->height = cam->max_height / 2;
break;
}
}
- if((cam->vid_cap.type & VID_TYPE_CAPTURE) != 1) {
+
+ if(!(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ if(cam->debug == TRUE) {
+ fprintf(stderr, "VIDIOC_QUERYCAP -- it is not a capture device, exiting.....\n");
+ }
+ msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+
+ if(!(vid_cap.capabilities & V4L2_CAP_STREAMING)) {
cam->read = TRUE;
}
+ strncpy(cam->name, vid_cap.card, sizeof(cam->name));
+ cam->name[sizeof(cam->name) - 1] = '\0';
+
if(cam->debug == TRUE) {
- printf("\nVIDIOCGCAP\n");
- printf("device name = %s\n", cam->vid_cap.name);
- printf("device type = %d\n", cam->vid_cap.type);
- if(cam->read == FALSE){
- printf("can use mmap()\n");
- }
- printf("# of channels = %d\n", cam->vid_cap.channels);
- printf("# of audio devices = %d\n", cam->vid_cap.audios);
- printf("max width = %d\n", cam->vid_cap.maxwidth);
- printf("max height = %d\n", cam->vid_cap.maxheight);
- printf("min width = %d\n", cam->vid_cap.minwidth);
- printf("min height = %d\n", cam->vid_cap.minheight);
+ printf("\nVIDIOC_QUERYCAP\n");
+ printf("device name = %s\n", vid_cap.card);
+ printf("device caps = 0x%08x\n", vid_cap.capabilities);
+ printf("max width = %d\n", cam->max_width);
+ printf("max height = %d\n", cam->max_height);
+ printf("min width = %d\n", cam->min_width);
+ printf("min height = %d\n", cam->min_height);
}
}
-void
-set_pic_info(cam* cam) {
- char *msg;
- if(cam->debug) {
- g_message("SET PIC");
- }
- cam->vid_pic.palette = VIDEO_PALETTE_RGB24;
- cam->vid_pic.depth = 24;
- //cam->vid_pic.palette = VIDEO_PALETTE_YUV420P;
- if(v4l1_ioctl(cam->dev, VIDIOCSPICT, &cam->vid_pic) == -1) {
- if(cam->debug) {
- g_message("VIDIOCSPICT -- could not set picture info, exiting....");
- }
- msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
- error_dialog(msg);
- g_free(msg);
- exit(0);
- }
-}
-
void get_pic_info(cam * cam){
-//set_pic_info(cam);
char *msg;
-
- if(v4l1_ioctl(cam->dev, VIDIOCGPICT, &cam->vid_pic) == -1) {
- msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
- error_dialog(msg);
- if(cam->debug == TRUE) {
- fprintf(stderr, "VIDIOCGPICT -- could not get picture info, exiting....\n");
- }
- g_free(msg);
- exit(0);
+ int i;
+
+ if(cam->debug == TRUE)
+ printf("\nVideo control settings:\n");
+
+ i = v4l2_get_control(cam->dev, V4L2_CID_HUE);
+ if (i >= 0) {
+ cam->hue = i;
+ if(cam->debug == TRUE)
+ printf("hue = %d\n", cam->hue);
+ } else {
+ cam->hue = -1;
}
-
- if(cam->debug == TRUE) {
- printf("\nVIDIOCGPICT:\n");
- printf("bright = %d\n", cam->vid_pic.brightness);
- printf("hue = %d\n", cam->vid_pic.hue);
- printf("colour = %d\n", cam->vid_pic.colour);
- printf("contrast = %d\n", cam->vid_pic.contrast);
- printf("whiteness = %d\n", cam->vid_pic.whiteness);
- printf("colour depth = %d\n", cam->vid_pic.depth);
- print_palette(cam->vid_pic.palette);
+ i = v4l2_get_control(cam->dev, V4L2_CID_SATURATION);
+ if (i >= 0) {
+ cam->colour = i;
+ if(cam->debug == TRUE)
+ printf("colour = %d\n", cam->colour);
+ } else {
+ cam->colour = -1;
+ }
+ i = v4l2_get_control(cam->dev, V4L2_CID_CONTRAST);
+ if (i >= 0) {
+ cam->contrast = i;
+ if(cam->debug == TRUE)
+ printf("contrast = %d\n", cam->contrast);
+ } else {
+ cam->contrast = -1;
+ }
+ i = v4l2_get_control(cam->dev, V4L2_CID_WHITENESS);
+ if (i >= 0) {
+ cam->whiteness = i;
+ if(cam->debug == TRUE)
+ printf("whiteness = %d\n", cam->whiteness);
+ } else {
+ cam->whiteness = -1;
+ }
+ i = v4l2_get_control(cam->dev, V4L2_CID_BRIGHTNESS);
+ if (i >= 0) {
+ cam->brightness = i;
+ if(cam->debug == TRUE)
+ printf("brightness = %d\n", cam->brightness);
+ } else {
+ cam->brightness = -1;
}
}
void get_win_info(cam * cam)
{
gchar *msg;
- if(v4l1_ioctl(cam->dev, VIDIOCGWIN, &cam->vid_win) == -1) {
+ struct v4l2_format fmt = { 0 };
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (v4l2_ioctl(cam->dev, VIDIOC_G_FMT, &fmt)) {
msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
error_dialog(msg);
if(cam->debug == TRUE) {
- fprintf(stderr, "VIDIOCGWIN -- could not get window info, exiting....\n");
+ g_message("VIDIOC_G_FMT -- could not get picture info");
}
- exit(0);
+ return;
}
+
if(cam->debug == TRUE) {
- printf("\nVIDIOCGWIN\n");
- printf("x = %d\n", cam->vid_win.x);
- printf("y = %d\n", cam->vid_win.y);
- printf("width = %d\n", cam->vid_win.width);
- printf("height = %d\n", cam->vid_win.height);
- printf("chromakey = %d\n", cam->vid_win.chromakey);
- printf("flags = %d\n", cam->vid_win.flags);
+ printf("\nVIDIOC_G_FMT\n");
+ printf("format FOURCC: '%c%c%c%c' (%08x)\n",
+ fmt.fmt.pix.pixelformat & 0xff,
+ (fmt.fmt.pix.pixelformat >> 8) & 0xff,
+ (fmt.fmt.pix.pixelformat >> 16) & 0xff,
+ fmt.fmt.pix.pixelformat >> 24,
+ fmt.fmt.pix.pixelformat);
+ printf("x = %d\n", fmt.fmt.pix.width);
+ printf("y = %d\n", fmt.fmt.pix.height);
+ if (fmt.fmt.pix.bytesperline)
+ printf("bytes/line = %d\n", fmt.fmt.pix.bytesperline);
+ }
+
+ if (!fmt.fmt.pix.bytesperline) {
+ if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+ fmt.fmt.pix.bytesperline = fmt.fmt.pix.width * 2;
+ else
+ fmt.fmt.pix.bytesperline = fmt.fmt.pix.width * 3;
+ }
+
+ if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24 ||
+ fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
+
+ cam->pixformat = fmt.fmt.pix.pixelformat;
+ cam->depth = ((fmt.fmt.pix.bytesperline << 3) + (fmt.fmt.pix.width - 1)) / fmt.fmt.pix.width;
+ cam->width = fmt.fmt.pix.width;
+ cam->height = fmt.fmt.pix.height;
+ cam->bytesperline = fmt.fmt.pix.bytesperline;
}
}
+
void set_win_info(cam * cam)
{
gchar *msg;
- if(v4l1_ioctl(cam->dev, VIDIOCSWIN, &cam->vid_win) == -1) {
+ struct v4l2_format fmt;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* Get current settings, apply our changes and try the new setting */
+ if (v4l2_ioctl(cam->dev, VIDIOC_G_FMT, &fmt)) {
+ if(cam->debug) {
+ g_message("VIDIOC_G_FMT -- could not get window info, exiting....");
+ }
msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
error_dialog(msg);
- if(cam->debug == TRUE) {
- fprintf(stderr, "VIDIOCSWIN -- could not set window info, exiting....\nerrno = %d", errno);
+ g_free(msg);
+ exit(0);
+ }
+
+ if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24 &&
+ fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_YUV420)
+ cam->pixformat = V4L2_PIX_FMT_BGR24;
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.pixelformat = cam->pixformat;
+ fmt.fmt.pix.width = cam->width;
+ fmt.fmt.pix.height = cam->height;
+ if (v4l2_ioctl(cam->dev, VIDIOC_S_FMT, &fmt)) {
+ if(cam->debug) {
+ g_message("VIDIOC_S_FMT -- could not set window info, exiting....");
+ }
+ msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+
+ /* Check if returned format is valid */
+ if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24 &&
+ fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_YUV420) {
+ if(cam->debug) {
+ g_message("VIDIOC_S_FMT -- could not set format to %c%c%c%c (was set to %c%c%c%c instead), exiting....",
+ cam->pixformat & 0xff,
+ (cam->pixformat >> 8) & 0xff,
+ (cam->pixformat >> 16) & 0xff,
+ cam->pixformat >> 24,
+ fmt.fmt.pix.pixelformat & 0xff,
+ (fmt.fmt.pix.pixelformat >> 8) & 0xff,
+ (fmt.fmt.pix.pixelformat >> 16) & 0xff,
+ fmt.fmt.pix.pixelformat >> 24);
}
+ msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
+ error_dialog(msg);
g_free(msg);
exit(0);
}
- cam->x = cam->vid_win.width;
- cam->y = cam->vid_win.height;
+ /* Resolution may have changed. Store the retrieved one */
+ cam->pixformat = fmt.fmt.pix.pixelformat;
+ cam->bytesperline = fmt.fmt.pix.bytesperline;
+
+ cam->depth = ((fmt.fmt.pix.bytesperline << 3) + (fmt.fmt.pix.width - 1)) / fmt.fmt.pix.width;
+
+ cam->width = fmt.fmt.pix.width;
+ cam->height = fmt.fmt.pix.height;
}
-void set_buffer(cam * cam)
+void start_streaming(cam * cam)
{
char *msg;
- if(v4l1_ioctl(cam->dev, VIDIOCGMBUF, &cam->vid_buf) == -1) {
- msg = g_strdup_printf(_("Could not connect to video device (%s).\nPlease check connection."), cam->video_dev);
+ unsigned int i;
+ enum v4l2_buf_type type;
+ struct v4l2_buffer buf;
+
+ memset(&cam->req, 0, sizeof(cam->req));
+ cam->req.count = 2;
+ cam->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cam->req.memory = V4L2_MEMORY_MMAP;
+ if (v4l2_ioctl(cam->dev, VIDIOC_REQBUFS, &cam->req)) {
+ msg = g_strdup_printf(_("VIDIOC_REQBUFS -- could not request buffers (%s), exiting...."), cam->video_dev);
error_dialog(msg);
- if(cam->debug == TRUE) {
- fprintf(stderr, "VIDIOCGMBF -- could not set buffer info, exiting...\n");
+ g_free(msg);
+ exit(0);
+ }
+
+ cam->buffers = calloc(cam->req.count, sizeof(*cam->buffers));
+ for (cam->n_buffers = 0; cam->n_buffers < cam->req.count; ++cam->n_buffers) {
+ memset(&buf, 0, sizeof(buf));
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = cam->n_buffers;
+
+ if (v4l2_ioctl(cam->dev, VIDIOC_QUERYBUF, &buf)) {
+ msg = g_strdup_printf(_("VIDIOC_QUERYBUF -- could not query buffers (%s), exiting...."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+
+ cam->buffers[cam->n_buffers].length = buf.length;
+ cam->buffers[cam->n_buffers].start = v4l2_mmap(NULL, buf.length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ cam->dev, buf.m.offset);
+
+ if (MAP_FAILED == cam->buffers[cam->n_buffers].start) {
+ msg = g_strdup_printf(_("failed to memory map buffers (%s), exiting...."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
}
+ }
+
+ for (i = 0; i < cam->n_buffers; ++i) {
+ memset(&buf, 0, sizeof(buf));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+ if (v4l2_ioctl(cam->dev, VIDIOC_QBUF, &buf)) {
+ msg = g_strdup_printf(_("VIDIOC_QBUF -- could not enqueu buffers (%s), exiting...."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+ }
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (v4l2_ioctl(cam->dev, VIDIOC_STREAMON, &type)) {
+ msg = g_strdup_printf(_("failed to start streaming (%s), exiting...."), cam->video_dev);
+ error_dialog(msg);
g_free(msg);
exit(0);
+ }
+}
+
+void capture_buffers(cam * cam, unsigned char *outbuf, int len)
+{
+ char *msg;
+ unsigned char *inbuf;
+ int r, y;
+ fd_set fds;
+ struct v4l2_buffer buf;
+ struct timeval tv;
+
+ do {
+ FD_ZERO(&fds);
+ FD_SET(cam->dev, &fds);
+
+ /* Timeout. */
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+ r = select(cam->dev + 1, &fds, NULL, NULL, &tv);
+ } while ((r == -1 && (errno == EINTR)));
+
+ if (r == -1) {
+ msg = g_strdup_printf(_("Timeout while waiting for frames (%s)"), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
}
-
- if(cam->debug == TRUE) {
- printf("\nVIDIOCGMBUF\n");
- printf("mb.size = %d\n", cam->vid_buf.size);
- printf("mb.frames = %d\n", cam->vid_buf.frames);
- printf("mb.offset = %d\n", cam->vid_buf.offsets[1]);
+
+ memset(&buf, 0, sizeof(buf));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_ioctl(cam->dev, VIDIOC_DQBUF, &buf);
+
+ if (len > buf.bytesused)
+ len = buf.bytesused;
+
+ inbuf = cam->buffers[buf.index].start;
+ for (y = 0; y < cam->height; y++) {
+ memcpy(outbuf, inbuf, cam->width * cam->depth / 8);
+ outbuf += cam->width * cam->depth / 8;
+ inbuf += cam->bytesperline;
}
+ v4l2_ioctl(cam->dev, VIDIOC_QBUF, &buf);
+}
+
+
+void stop_streaming(cam * cam)
+{
+ char *msg;
+ unsigned int i;
+ int r;
+ enum v4l2_buf_type type;
+ fd_set fds;
+ struct v4l2_buffer buf;
+ struct timeval tv;
+
+ /* Dequeue all pending buffers */
+ for (i = 0; i < cam->n_buffers; ++i) {
+ FD_ZERO(&fds);
+ FD_SET(cam->dev, &fds);
+
+ /* Timeout. */
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ r = select(cam->dev + 1, &fds, NULL, &fds, &tv);
+ if (r == -1 && errno == EINTR)
+ continue;
+
+ if (r != -1) {
+ memset(&buf, 0, sizeof(buf));
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ if (v4l2_ioctl(cam->dev, VIDIOC_DQBUF, &buf))
+ break;
+ }
+ };
+
+ /* Streams off */
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (v4l2_ioctl(cam->dev, VIDIOC_STREAMOFF, &type)) {
+ msg = g_strdup_printf(_("failed to stop streaming (%s), exiting...."), cam->video_dev);
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+
+ /* Unmap buffers */
+ for (i = 0; i < cam->n_buffers; ++i)
+ v4l2_munmap(cam->buffers[i].start, cam->buffers[i].length);
+
+ /* Free existing buffers */
+ memset(&cam->req, 0, sizeof(cam->req));
+ cam->req.count = 0;
+ cam->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cam->req.memory = V4L2_MEMORY_MMAP;
+ v4l2_ioctl(cam->dev, VIDIOC_REQBUFS, &cam->req);
+
+ free(cam->buffers);
+ cam->buffers = NULL;
}
diff --git a/src/v4l.h b/src/v4l.h
index 24479f5dad50..1c076410c779 100644
--- a/src/v4l.h
+++ b/src/v4l.h
@@ -12,7 +12,9 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <gtk/gtk.h>
-#include <libv4l1.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <libv4l2.h>
#include <signal.h>
#include <png.h>
#include <glade/glade.h>
@@ -21,62 +23,75 @@
#include "camorama-filter-chain.h"
typedef enum {
- PICMAX = 0,
- PICMIN = 1,
- PICHALF = 2
+ PICMAX = 0,
+ PICMIN = 1,
+ PICHALF = 2
} CamoImageSize;
enum {
- JPEG = 0,
- PNG = 1,
- PPM = 2
+ JPEG = 0,
+ PNG = 1,
+ PPM = 2
+};
+
+struct buffer_start_len {
+ void *start;
+ size_t length;
};
typedef struct camera {
- int dev;
- int x;
- int y;
- int depth;
- int desk_depth;
- CamoImageSize size;
- int contrast, brightness, colour, hue, wb;
- int frame_number;
- struct video_capability vid_cap;
- struct video_picture vid_pic;
- struct video_window vid_win;
- struct video_mbuf vid_buf;
- struct video_mmap vid_map;
- char *video_dev;
- unsigned char *pic;
- unsigned char *image;
- gchar *capturefile, *rcapturefile;
- gchar *pixdir, *rpixdir;
- int savetype, rsavetype;
- gchar *rhost, *rlogin, *rpw;
- gchar *ts_string;
- gchar *date_format;
- gboolean debug, read, hidden;
- gboolean cap, rcap, acap, show_adjustments, show_effects;
- gboolean timestamp, rtimestamp, usedate, usestring;
- gboolean rtimefn, timefn;
- GdkPixmap *pixmap;
- GtkWidget *da, *tray_tooltip, *status;
- unsigned char *pic_buf, *tmp;
- guint timeout_id, idle_id;
- guint32 timeout_interval;
- GConfClient *gc;
- GladeXML *xml;
- GtkStatusIcon *tray_icon;
+ int dev;
+ int width;
+ int height;
+ int depth;
+ int desk_depth;
+ CamoImageSize size;
+ char name[32];
+ int contrast, brightness, whiteness, colour, hue, bytesperline;
+ unsigned int pixformat;
+ int frame_number;
+
+ int min_width, min_height, max_width, max_height;
+
+ char *video_dev;
+ unsigned char *image;
+ gchar *capturefile, *rcapturefile;
+ gchar *pixdir, *rpixdir;
+ int savetype, rsavetype;
+ gchar *rhost, *rlogin, *rpw;
+ gchar *ts_string;
+ gchar *date_format;
+ gboolean debug, read, hidden;
+ gboolean cap, rcap, acap, show_adjustments, show_effects;
+ gboolean timestamp, rtimestamp, usedate, usestring;
+ gboolean rtimefn, timefn;
+ GdkPixmap *pixmap;
+ GtkWidget *da, *tray_tooltip, *status;
+ unsigned char *pic_buf, *tmp;
+ guint timeout_id, idle_id;
+ guint32 timeout_interval;
+ GConfClient *gc;
+ GladeXML *xml;
+ GtkStatusIcon *tray_icon;
+
+ CamoramaFilterChain* filter_chain;
- CamoramaFilterChain* filter_chain;
+ /* Buffer handling - should be used only inside v4l.c */
+ struct v4l2_requestbuffers req;
+ unsigned int n_buffers;
+ struct {
+ void *start;
+ size_t length;
+ } *buffers;
} cam;
void camera_cap (cam *);
void set_win_info (cam * cam);
void get_pic_info (cam *);
-void set_pic_info (cam *);
void get_win_info (cam *);
-void set_buffer (cam *);
+void start_streaming(cam * cam);
+void capture_buffers(cam * cam, unsigned char *outbuf, int len);
+void stop_streaming(cam * cam);
#endif /* !CAMORAMA_V4L_H */