Few improvements to move to good.
authorEdgard Lima <edgard.lima@indt.org.br>
Mon, 1 May 2006 21:37:51 +0000 (21:37 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Mon, 1 May 2006 21:37:51 +0000 (21:37 +0000)
Original commit message from CVS:
Few improvements to move to good.

ChangeLog
sys/v4l2/Makefile.am
sys/v4l2/gstv4l2colorbalance.c
sys/v4l2/gstv4l2xoverlay.c
sys/v4l2/v4l2_calls.c
tests/icles/Makefile.am
tests/icles/v4l2src-test.c [new file with mode: 0644]

index 3fa25322e76290c2440b6b7e0b500c58a4a057f0..ec78ace77619cdc3bba04a7a740d92b7b2f239a7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2006-05-01  Edgard Lima <edgard.lima@indt.org.br>
+
+       * sys/v4l2/Makefile.am:
+       * sys/v4l2/gstv4l2colorbalance.c:
+       * sys/v4l2/gstv4l2xoverlay.c:
+       * sys/v4l2/v4l2_calls.c:
+       * tests/icles/Makefile.am:
+       * tests/icles/v4l2src-test.c:
+       Few improvements to move to good.
+
 2006-05-01  Thomas Vander Stichele  <thomas at apestaart dot org>
 
        * configure.ac:
index 165657a0c4ec1a4b9e776a9c9d5f284888d8aa98..547e06878e27ba85ec8569b8afcd37aca38aed66 100644 (file)
@@ -8,23 +8,29 @@ xv_source =
 xv_libs =
 endif
 
-libgstvideo4linux2_la_SOURCES = \
-       gstv4l2.c \
-       gstv4l2colorbalance.c \
-       gstv4l2element.c \
-       gstv4l2src.c \
-       gstv4l2tuner.c \
-       v4l2_calls.c \
-       v4l2src_calls.c $(xv_source)
+libgstvideo4linux2_la_SOURCES = gstv4l2.c \
+                               gstv4l2colorbalance.c \
+                               gstv4l2element.c \
+                               gstv4l2src.c \
+                               gstv4l2tuner.c \
+                               v4l2_calls.c \
+                               v4l2src_calls.c \
+                               $(xv_source)
 
-libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_CFLAGS) \
-                              $(GST_PLUGINS_BASE_CFLAGS) 
+libgstvideo4linux2_la_CFLAGS =   $(GST_PLUGINS_BASE_CFLAGS) \
+                                $(GST_BASE_CFLAGS) \
+                                $(GST_CFLAGS) \
+                                $(X_CFLAGS)
+                               
 libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstvideo4linux2_la_LIBADD = \
-       -lgstinterfaces-$(GST_MAJORMINOR) \
-       $(GST_BASE_LIBS) $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(xv_libs)
+
+libgstvideo4linux2_la_LIBADD =   $(GST_PLUGINS_BASE_LIBS) \
+                                $(GST_BASE_LIBS) \
+                                $(GST_LIBS) \
+                                $(xv_libs) \
+                                -lgstinterfaces-$(GST_MAJORMINOR) 
 
 noinst_HEADERS = gstv4l2element.h v4l2_calls.h \
-               gstv4l2src.h v4l2src_calls.h \
-               gstv4l2tuner.h gstv4l2xoverlay.h \
-               gstv4l2colorbalance.h
+                gstv4l2src.h v4l2src_calls.h \
+                gstv4l2tuner.h gstv4l2xoverlay.h \
+                gstv4l2colorbalance.h
index cfb3d578eb0cdfaaea27defbf65f9165f484a29f..7a0378f741bf2385dd6b2886797253098a10a3ed 100644 (file)
 #include "gstv4l2colorbalance.h"
 #include "gstv4l2element.h"
 
-static void
-gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
-    klass);
-static void gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel *
-    channel);
-
 static const GList *gst_v4l2_color_balance_list_channels (GstColorBalance *
     balance);
 static void gst_v4l2_color_balance_set_value (GstColorBalance * balance,
@@ -40,44 +34,27 @@ static void gst_v4l2_color_balance_set_value (GstColorBalance * balance,
 static gint gst_v4l2_color_balance_get_value (GstColorBalance * balance,
     GstColorBalanceChannel * channel);
 
-static GstColorBalanceChannelClass *parent_class = NULL;
 
-GType
-gst_v4l2_color_balance_channel_get_type (void)
+GST_BOILERPLATE (GstV4l2ColorBalanceChannel,
+    gst_v4l2_color_balance_channel,
+    GstColorBalanceChannel, GST_TYPE_COLOR_BALANCE_CHANNEL);
+
+
+static void
+gst_v4l2_color_balance_channel_base_init (gpointer g_class)
 {
-  static GType gst_v4l2_color_balance_channel_type = 0;
-
-  if (!gst_v4l2_color_balance_channel_type) {
-    static const GTypeInfo v4l2_tuner_channel_info = {
-      sizeof (GstV4l2ColorBalanceChannelClass),
-      NULL,
-      NULL,
-      (GClassInitFunc) gst_v4l2_color_balance_channel_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4l2ColorBalanceChannel),
-      0,
-      (GInstanceInitFunc) gst_v4l2_color_balance_channel_init,
-      NULL
-    };
-
-    gst_v4l2_color_balance_channel_type =
-        g_type_register_static (GST_TYPE_COLOR_BALANCE_CHANNEL,
-        "GstV4l2ColorBalanceChannel", &v4l2_tuner_channel_info, 0);
-  }
-
-  return gst_v4l2_color_balance_channel_type;
 }
 
+
 static void
 gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *
     klass)
 {
-  parent_class = g_type_class_peek_parent (klass);
 }
 
 static void
-gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel)
+gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel * channel,
+    GstV4l2ColorBalanceChannelClass * klass)
 {
   channel->id = (guint32) - 1;
 }
index 66ea505c3a6f4900da4e35a12f5e96611f639e78..8d597a45b9067cdfd1b39002d1b460a08655282c 100644 (file)
@@ -71,30 +71,33 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
 
   /* we need a display, obviously */
   if (!name || !(dpy = XOpenDisplay (name))) {
-    GST_WARNING ("No $DISPLAY set or failed to open - no overlay");
+    GST_WARNING_OBJECT (v4l2element,
+        "No $DISPLAY set or failed to open - no overlay");
     return;
   }
 
   /* First let's check that XVideo extension is available */
   if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) {
-    GST_WARNING ("Xv extension not available - no overlay");
+    GST_WARNING_OBJECT (v4l2element, "Xv extension not available - no overlay");
     XCloseDisplay (dpy);
     return;
   }
 
   /* find port that belongs to this device */
   if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
-    GST_WARNING ("Xv extension not supported - no overlay");
+    GST_WARNING_OBJECT (v4l2element, "Xv extension not supported - no overlay");
     XCloseDisplay (dpy);
     return;
   }
   if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) {
-    GST_WARNING ("Failed to query Xv adaptors");
+    GST_WARNING_OBJECT (v4l2element, "Failed to query Xv adaptors");
     XCloseDisplay (dpy);
     return;
   }
   if (fstat (v4l2element->video_fd, &s) < 0) {
-    GST_ERROR ("Failed to stat() file descriptor: %s", g_strerror (errno));
+    GST_ELEMENT_ERROR (v4l2element, RESOURCE, GST_RESOURCE_ERROR_NOT_FOUND,
+        (_("Cannot identify '%s': %d, %s\n"),
+            v4l2element->videodev, errno, strerror (errno)), GST_ERROR_SYSTEM);
     XCloseDisplay (dpy);
     return;
   }
@@ -112,7 +115,7 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
   XvFreeAdaptorInfo (ai);
 
   if (id == 0) {
-    GST_WARNING ("Did not find XvPortID for device - no overlay");
+    GST_WARNING (v4l2element, "Did not find XvPortID for device - no overlay");
     XCloseDisplay (dpy);
     return;
   }
index 81516b41bee9c410d664de6376aa1760f16bc30e..a43811fd2e0c1dd1018d13a0a7aa3fd847dac26f 100644 (file)
@@ -48,13 +48,14 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 gboolean
 gst_v4l2_get_capabilities (GstV4l2Element * v4l2element)
 {
-  GST_DEBUG ("getting capabilities");
+  GST_DEBUG_OBJECT (v4l2element, "getting capabilities");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
-    GST_ERROR_OBJECT (v4l2element, "Error getting %s capabilities: %s",
-        v4l2element->videodev, g_strerror (errno));
+    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS,
+        (_("Error getting capabilities '%s': %d, %s\n"),
+            v4l2element->videodev, errno, strerror (errno)), GST_ERROR_SYSTEM);
     return FALSE;
   }
 
@@ -74,7 +75,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
   gint n;
   GstPadDirection dir = GST_PAD_UNKNOWN;
 
-  GST_DEBUG ("getting enumerations");
+  GST_DEBUG_OBJECT (v4l2element, "getting enumerations");
   GST_V4L2_CHECK_OPEN (v4l2element);
 
   if (dir != GST_PAD_SINK) {
@@ -242,7 +243,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         /* we only handle these for now */
         break;
       default:
-        GST_DEBUG ("ControlID %s (%d) unhandled, FIXME", control.name, n);
+        GST_DEBUG_OBJECT (v4l2element, "ControlID %s (%d) unhandled, FIXME",
+            control.name, n);
         control.id++;
         break;
     }
@@ -305,7 +307,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
 static void
 gst_v4l2_empty_lists (GstV4l2Element * v4l2element)
 {
-  GST_DEBUG ("deleting enumerations");
+  GST_DEBUG_OBJECT (v4l2element, "deleting enumerations");
 
   g_list_foreach (v4l2element->inputs, (GFunc) g_object_unref, NULL);
   g_list_free (v4l2element->inputs);
@@ -381,7 +383,8 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
 {
   struct stat st;
 
-  GST_DEBUG ("Trying to open device %s", v4l2element->videodev);
+  GST_DEBUG_OBJECT (v4l2element, "Trying to open device %s",
+      v4l2element->videodev);
   GST_V4L2_CHECK_NOT_OPEN (v4l2element);
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
 
@@ -391,12 +394,15 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
 
   /* check if it is a device */
   if (-1 == stat (v4l2element->videodev, &st)) {
-    GST_ERROR ("Cannot identify '%s': %d, %s\n",
-        v4l2element->videodev, errno, strerror (errno));
+    GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND,
+        (_("Cannot identify '%s': %d, %s\n"),
+            v4l2element->videodev, errno, strerror (errno)), GST_ERROR_SYSTEM);
     goto error;
   }
   if (!S_ISCHR (st.st_mode)) {
-    GST_ERROR ("%s is no device\n", v4l2element->videodev);
+    GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND,
+        (_("It isn't a device '%s': %d, %s\n"),
+            v4l2element->videodev, errno, strerror (errno)), GST_ERROR_SYSTEM);
     goto error;
   }
 
@@ -460,7 +466,7 @@ error:
 gboolean
 gst_v4l2_close (GstV4l2Element * v4l2element)
 {
-  GST_DEBUG ("Trying to close %s", v4l2element->videodev);
+  GST_DEBUG_OBJECT (v4l2element, "Trying to close %s", v4l2element->videodev);
   GST_V4L2_CHECK_OPEN (v4l2element);
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
 
@@ -484,7 +490,7 @@ gst_v4l2_close (GstV4l2Element * v4l2element)
 gboolean
 gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
 {
-  GST_DEBUG ("getting norm");
+  GST_DEBUG_OBJECT (v4l2element, "getting norm");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
@@ -508,7 +514,7 @@ gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
 gboolean
 gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
 {
-  GST_DEBUG ("trying to set norm to %llx", norm);
+  GST_DEBUG_OBJECT (v4l2element, "trying to set norm to %llx", norm);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
   if (!GST_V4L2_IS_ACTIVE (v4l2element))
@@ -536,7 +542,7 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
 {
   gint n;
 
-  GST_DEBUG ("trying to get input");
+  GST_DEBUG_OBJECT (v4l2element, "trying to get input");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
@@ -562,7 +568,7 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
 gboolean
 gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
 {
-  GST_DEBUG ("trying to set input to %d", input);
+  GST_DEBUG_OBJECT (v4l2element, "trying to set input to %d", input);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
   if (!GST_V4L2_IS_ACTIVE (v4l2element))
@@ -589,7 +595,7 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
 {
   gint n;
 
-  GST_DEBUG ("trying to get output");
+  GST_DEBUG_OBJECT (v4l2element, "trying to get output");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
@@ -615,7 +621,7 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
 gboolean
 gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
 {
-  GST_DEBUG ("trying to set output to %d", output);
+  GST_DEBUG_OBJECT (v4l2element, "trying to set output to %d", output);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
   if (!GST_V4L2_IS_ACTIVE (v4l2element))
@@ -645,7 +651,7 @@ gst_v4l2_get_frequency (GstV4l2Element * v4l2element,
   struct v4l2_frequency freq;
   GstTunerChannel *channel;
 
-  GST_DEBUG ("getting current tuner frequency");
+  GST_DEBUG_OBJECT (v4l2element, "getting current tuner frequency");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
@@ -678,7 +684,8 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
   struct v4l2_frequency freq;
   GstTunerChannel *channel;
 
-  GST_DEBUG ("setting current tuner frequency to %lu", frequency);
+  GST_DEBUG_OBJECT (v4l2element, "setting current tuner frequency to %lu",
+      frequency);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
   if (!GST_V4L2_IS_ACTIVE (v4l2element))
@@ -714,7 +721,7 @@ gst_v4l2_signal_strength (GstV4l2Element * v4l2element,
 {
   struct v4l2_tuner tuner;
 
-  GST_DEBUG ("trying to get signal strength");
+  GST_DEBUG_OBJECT (v4l2element, "trying to get signal strength");
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
@@ -747,7 +754,8 @@ gst_v4l2_get_attribute (GstV4l2Element * v4l2element,
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
-  GST_DEBUG ("getting value of attribute %d", attribute_num);
+  GST_DEBUG_OBJECT (v4l2element, "getting value of attribute %d",
+      attribute_num);
 
   control.id = attribute_num;
 
@@ -779,7 +787,8 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element,
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
 
-  GST_DEBUG ("setting value of attribute %d to %d", attribute_num, value);
+  GST_DEBUG_OBJECT (v4l2element, "setting value of attribute %d to %d",
+      attribute_num, value);
 
   control.id = attribute_num;
   control.value = value;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2c9080d1da082b17eea2c4dd9b30998bb34e7ac7 100644 (file)
@@ -0,0 +1,15 @@
+if USE_GST_V4L2 
+
+GST_V4L2_TESTS = v4l2src-test
+
+v4l2src_test_SOURCES = v4l2src-test.c
+v4l2src_test_CFLAGS =   $(GST_PLUGINS_BASE_CFLAGS)
+
+v4l2src_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -lgstinterfaces-$(GST_MAJORMINOR)
+
+else
+GST_V4L2_TESTS =
+endif
+
+noinst_PROGRAMS = $(GST_V4L2_TESTS)
+
diff --git a/tests/icles/v4l2src-test.c b/tests/icles/v4l2src-test.c
new file mode 100644 (file)
index 0000000..b8f85e1
--- /dev/null
@@ -0,0 +1,241 @@
+
+#include <gst/gst.h>
+#include <gst/interfaces/tuner.h>
+#include <gst/interfaces/colorbalance.h>
+
+GstElement *pipeline, *source, *sink;
+GMainLoop *loop;
+volatile int exit_read = 0;
+
+void
+print_options ()
+{
+  printf
+      ("\nLaunch \"./v4l2src-test.c devname\" to choose the device (default: /dev/video0)\n");
+  printf ("\nf - to change the fequency\n");
+  printf ("i - to change the input\n");
+  printf ("c - list color balance\n");
+  printf ("e - to exit\n");
+}
+
+void
+run_options (char opt)
+{
+  switch (opt) {
+    case 'f':
+    {
+      GstTuner *tuner = GST_TUNER (source);
+      GstTunerChannel *channel = gst_tuner_get_channel (tuner);
+      guint freq;
+
+      printf ("type the new frequency (current = %lu) (-1 to cancel): ",
+          gst_tuner_get_frequency (tuner, channel));
+      scanf ("%u", &freq);
+      if (freq != -1)
+        gst_tuner_set_frequency (tuner, channel, freq);
+    }
+      break;
+    case 'i':
+    {
+      GstTuner *tuner = GST_TUNER (source);
+      const GList *item, *list;
+      const GstTunerChannel *current_channel;
+      GstTunerChannel *channel = NULL;
+      gint index, next_channel;
+
+      list = gst_tuner_list_channels (tuner);
+      current_channel = gst_tuner_get_channel (tuner);
+
+      printf ("\nlist of inputs:\n");
+      for (item = list, index = 0; item != NULL; item = item->next, ++index) {
+        channel = item->data;
+        if (current_channel == channel) {
+          printf (" * %u - %s\n", index, channel->label);
+        } else {
+          printf ("   %u - %s\n", index, channel->label);
+        }
+      }
+      printf ("\ntype the number of input you want (-1 to cancel): ");
+      scanf ("%d", &next_channel);
+      if (next_channel < 0 || index <= next_channel) {
+        break;
+      }
+      for (item = list, index = 0; item != NULL && index <= next_channel;
+          item = item->next, ++index) {
+        channel = item->data;
+      }
+      if (channel)
+        gst_tuner_set_channel (tuner, channel);
+    }
+      break;
+    case 'e':
+      gst_element_set_state (pipeline, GST_STATE_NULL);
+      g_main_loop_quit (loop);
+      printf ("Bye\n");
+      g_thread_exit (0);
+      break;
+    case 'c':
+    {
+      GstColorBalance *balance = GST_COLOR_BALANCE (source);
+      const GList *controls = gst_color_balance_list_channels (balance);
+      GstColorBalanceChannel *channel;
+      const GList *item;
+      gint index, new_value;
+
+      if (controls) {
+        printf ("\nlist of controls:\n");
+        for (item = controls, index = 0; item != NULL;
+            item = item->next, ++index) {
+          channel = item->data;
+          printf ("   %u - %s (%d - %d) = %d\n", index, channel->label,
+              channel->min_value, channel->max_value,
+              gst_color_balance_get_value (balance, channel));
+        }
+        printf ("\ntype the number of color control you want (-1 to cancel): ");
+        scanf ("%d", &new_value);
+        if (new_value == -1)
+          break;
+        for (item = controls, index = 0; item != NULL && index <= new_value;
+            item = item->next, ++index) {
+          channel = item->data;
+        }
+        printf ("   %u - %s (%d - %d) = %d, type the new value: ", index,
+            channel->label, channel->min_value, channel->max_value,
+            gst_color_balance_get_value (balance, channel));
+        scanf ("%d", &new_value);
+        if (new_value == -1)
+          break;
+        gst_color_balance_set_value (balance, channel, new_value);
+      }
+    }
+      break;
+    default:
+      if (opt != 10)
+        printf ("error: invalid option %c", opt);
+      break;
+  }
+
+}
+
+gpointer
+read_user (gpointer data)
+{
+
+  char opt;
+
+  while (!exit_read) {
+
+    print_options ();
+
+    opt = getchar ();
+    if (exit_read) {
+      break;
+    }
+
+    run_options (opt);
+
+  }
+
+  return NULL;
+
+}
+
+static gboolean
+my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
+{
+
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_ERROR:{
+      GError *err;
+      gchar *debug;
+
+      gst_message_parse_error (message, &err, &debug);
+      g_print ("Error: %s - element %s\n", err->message,
+          gst_element_get_name (message->src));
+      g_error_free (err);
+      g_free (debug);
+
+      printf ("presse any key to exit\n");
+      exit_read = 1;
+      g_main_loop_quit (loop);
+      break;
+    case GST_MESSAGE_EOS:
+      /* end-of-stream */
+      printf ("presse any key to exit\n");
+      exit_read = 1;
+      g_main_loop_quit (loop);
+      break;
+    default:
+      break;
+    }
+  }
+  return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+
+  GThread *input_thread;
+
+  /* init */
+  gst_init (&argc, &argv);
+
+  /* create elements */
+  if (!(pipeline = gst_pipeline_new ("my_pipeline"))) {
+    fprintf (stderr, "error: gst_pipeline_new return NULL");
+    return -1;
+  }
+
+  if (!(source = gst_element_factory_make ("v4l2src", NULL))) {
+    fprintf (stderr,
+        "error: gst_element_factory_make (\"v4l2src\", NULL) return NULL");
+    return -1;
+  }
+
+  if (!(sink = gst_element_factory_make ("xvimagesink", NULL))) {
+    fprintf (stderr,
+        "error: gst_element_factory_make (\"xvimagesink\", NULL) return NULL");
+    return -1;
+  }
+
+  if (argv < 2) {
+    g_object_set (source, "device", "/dev/video0", NULL);
+  } else {
+    g_object_set (source, "device", argv[1], NULL);
+  }
+
+  /* you would normally check that the elements were created properly */
+  gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
+      my_bus_callback, NULL);
+
+  /* put together a pipeline */
+  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
+  gst_element_link_pads (source, "src", sink, "sink");
+
+  /* start the pipeline */
+  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+  loop = g_main_loop_new (NULL, FALSE);
+
+  if (!(input_thread = g_thread_create (read_user, source, TRUE, NULL))) {
+    fprintf (stderr, "error: g_thread_create return NULL");
+    return -1;
+  }
+
+  if (argv < 2)
+    printf
+        ("\nOpening /dev/video0. Launch ./v4l2src-test.c devname to try another one\n");
+
+
+  g_main_loop_run (loop);
+  g_thread_join (input_thread);
+
+  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+
+  gst_object_unref (pipeline);
+
+  gst_deinit ();
+
+  return 0;
+
+}