V4L2 ported to 0.10.
authorEdgard Lima <edgard.lima@indt.org.br>
Sat, 11 Mar 2006 22:50:03 +0000 (22:50 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Sat, 11 Mar 2006 22:50:03 +0000 (22:50 +0000)
Original commit message from CVS:
V4L2 ported to 0.10.

15 files changed:
sys/v4l2/Makefile.am
sys/v4l2/gstv4l2.c
sys/v4l2/gstv4l2colorbalance.h
sys/v4l2/gstv4l2element.c
sys/v4l2/gstv4l2element.h
sys/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/gstv4l2tuner.c
sys/v4l2/gstv4l2tuner.h
sys/v4l2/gstv4l2xoverlay.c
sys/v4l2/gstv4l2xoverlay.h
sys/v4l2/v4l2_calls.c
sys/v4l2/v4l2_calls.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index 89e6b85..223e807 100644 (file)
@@ -1,5 +1,4 @@
-plugin_LTLIBRARIES = \
-       libgstvideo4linux2.la
+plugin_LTLIBRARIES = libgstvideo4linux2.la
 
 if USE_XVIDEO
 xv_source = gstv4l2xoverlay.c
@@ -10,18 +9,19 @@ xv_libs =
 endif
 
 libgstvideo4linux2_la_SOURCES = \
-       gstv4l2element.c v4l2_calls.c \
-       gstv4l2src.c v4l2src_calls.c \
        gstv4l2.c \
+       gstv4l2colorbalance.c \
+       gstv4l2element.c \
+       gstv4l2src.c \
        gstv4l2tuner.c \
-       $(xv_source) \
-       gstv4l2colorbalance.c
-libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS)
+       v4l2_calls.c \
+       v4l2src_calls.c $(xv_source)
+
+libgstvideo4linux2_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_LIBS_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) 
+libgstvideo4linux2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstvideo4linux2_la_LIBADD = \
-       $(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la
-libgstvideo4linux2_la_LDFLAGS = \
-       $(GST_PLUGIN_LDFLAGS) \
-       $(xv_libs)
+       -lgstinterfaces-$(GST_MAJORMINOR) \
+       $(GST_BASE_LIBS) $(GST_LIBS) $(xv_libs)
 
 noinst_HEADERS = gstv4l2element.h v4l2_calls.h \
                gstv4l2src.h v4l2src_calls.h \
index b81080b..23da8da 100644 (file)
@@ -1,5 +1,8 @@
-/* G-Streamer Video4linux2 video-capture plugin
- * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+/* GStreamer
+ *
+ * gstv4l2.c: plugin for v4l2 elements
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "config.h"
 #endif
 
-#include <gst/gst.h>
-
 #include "gst/gst-i18n-plugin.h"
 
+#include <gst/gst.h>
+
 #include "gstv4l2element.h"
 #include "gstv4l2src.h"
+/* #include "gstv4l2jpegsrc.h" */
+/* #include "gstv4l2mjpegsrc.h" */
+/* #include "gstv4l2mjpegsink.h" */
+
+GST_DEBUG_CATEGORY (v4l2_debug);        /* used in v4l2_calls.c and v4l2src_calls.c */
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  if (!gst_element_register (plugin, "v4l2element",
-          GST_RANK_NONE, GST_TYPE_V4L2ELEMENT) ||
-      !gst_element_register (plugin, "v4l2src",
-          GST_RANK_NONE, GST_TYPE_V4L2SRC))
+  GST_DEBUG_CATEGORY_INIT (v4l2_debug, "v4l2", 0, "V4L2 API calls");
+
+  if (!gst_element_register (plugin, "v4l2src", GST_RANK_NONE,
+          GST_TYPE_V4L2SRC))
+    /*       !gst_element_register (plugin, "v4l2jpegsrc", */
+    /*           GST_RANK_NONE, GST_TYPE_V4L2JPEGSRC) || */
+    /*       !gst_element_register (plugin, "v4l2mjpegsrc", */
+    /*           GST_RANK_NONE, GST_TYPE_V4L2MJPEGSRC) || */
+    /*       !gst_element_register (plugin, "v4l2mjpegsink", */
+    /*           GST_RANK_NONE, GST_TYPE_V4L2MJPEGSINK)) */
     return FALSE;
 
 #ifdef ENABLE_NLS
@@ -48,5 +62,5 @@ plugin_init (GstPlugin * plugin)
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "video4linux2",
-    "elements for Video 4 Linux 2",
+    "elements for Video 4 Linux",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
index b573cb2..487b348 100644 (file)
@@ -23,7 +23,7 @@
 #define __GST_V4L2_COLOR_BALANCE_H__
 
 #include <gst/gst.h>
-#include <gst/colorbalance/colorbalance.h>
+#include <gst/interfaces/colorbalance.h>
 #include "v4l2_calls.h"
 
 G_BEGIN_DECLS
@@ -32,10 +32,10 @@ G_BEGIN_DECLS
   (gst_v4l2_color_balance_channel_get_type ())
 #define GST_V4L2_COLOR_BALANCE_CHANNEL(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
-                               GstV4l2ColorBalanceChannel))
+                              GstV4l2ColorBalanceChannel))
 #define GST_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \
-                            GstV4l2ColorBalanceChannelClass))
+                           GstV4l2ColorBalanceChannelClass))
 #define GST_IS_V4L2_COLOR_BALANCE_CHANNEL(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL))
 #define GST_IS_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \
@@ -51,8 +51,8 @@ typedef struct _GstV4l2ColorBalanceChannelClass {
   GstColorBalanceChannelClass parent;
 } GstV4l2ColorBalanceChannelClass;
 
-GType   gst_v4l2_color_balance_channel_get_type (void);
+GType  gst_v4l2_color_balance_channel_get_type (void);
 
-void    gst_v4l2_color_balance_interface_init   (GstColorBalanceClass *klass);
+void   gst_v4l2_color_balance_interface_init   (GstColorBalanceClass *klass);
 
 #endif /* __GST_V4L2_COLOR_BALANCE_H__ */
index 139378b..e5acbf8 100644 (file)
@@ -1,5 +1,8 @@
-/* G-Streamer generic V4L2 element
- * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+/* GStreamer
+ *
+ * gstv4l2element.c: base class for V4L2 elements
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -25,6 +28,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
+#include <string.h>
+
+#include <gst/interfaces/propertyprobe.h>
 
 #include "v4l2_calls.h"
 #include "gstv4l2tuner.h"
 #endif
 #include "gstv4l2colorbalance.h"
 
-#include <gst/propertyprobe/propertyprobe.h>
-
-/* elementfactory details */
-static GstElementDetails gst_v4l2element_details = {
-  "Generic video4linux2 Element",
-  "Generic/Video",
-  "Generic plugin for handling common video4linux2 calls",
-  "Ronald Bultje <rbultje@ronald.bitfreak.net>"
-};
 
-/* V4l2Element signals and args */
 enum
 {
-  /* FILL ME */
-  SIGNAL_OPEN,
-  SIGNAL_CLOSE,
-  LAST_SIGNAL
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME,
+  PROP_FLAGS,
+  PROP_STD,
+  PROP_INPUT,
+  PROP_FREQUENCY
 };
 
-enum
-{
-  ARG_0,
-  ARG_DEVICE,
-  ARG_DEVICE_NAME,
-  ARG_NORM,
-  ARG_CHANNEL,
-  ARG_FREQUENCY,
-  ARG_FLAGS
-};
 
+static void gst_v4l2element_init_interfaces (GType type);
 
-static void gst_v4l2element_class_init (GstV4l2ElementClass * klass);
-static void gst_v4l2element_base_init (GstV4l2ElementClass * klass);
-static void gst_v4l2element_init (GstV4l2Element * v4lelement);
-static void gst_v4l2element_dispose (GObject * object);
-static void gst_v4l2element_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4l2element_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-static GstStateChangeReturn
-gst_v4l2element_change_state (GstElement * element, GstStateChange transition);
+GST_BOILERPLATE_FULL (GstV4l2Element, gst_v4l2element, GstPushSrc,
+    GST_TYPE_PUSH_SRC, gst_v4l2element_init_interfaces)
 
 
-static GstElementClass *parent_class = NULL;
-static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 };
+     static void gst_v4l2element_dispose (GObject * object);
+     static void gst_v4l2element_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+     static void gst_v4l2element_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+     static gboolean gst_v4l2element_start (GstBaseSrc * src);
+     static gboolean gst_v4l2element_stop (GstBaseSrc * src);
 
 
-static gboolean
-gst_v4l2_iface_supported (GstImplementsInterface * iface, GType iface_type)
+     static gboolean
+         gst_v4l2_iface_supported (GstImplementsInterface * iface,
+    GType iface_type)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (iface);
 
@@ -104,7 +92,6 @@ gst_v4l2_iface_supported (GstImplementsInterface * iface, GType iface_type)
   return TRUE;
 }
 
-
 static void
 gst_v4l2_interface_init (GstImplementsInterfaceClass * klass)
 {
@@ -112,7 +99,6 @@ gst_v4l2_interface_init (GstImplementsInterfaceClass * klass)
   klass->supported = gst_v4l2_iface_supported;
 }
 
-
 static const GList *
 gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
 {
@@ -133,7 +119,7 @@ gst_v4l2_class_probe_devices (GstV4l2ElementClass * klass, gboolean check)
   static GList *devices = NULL;
 
   if (!init && !check) {
-    gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
+    gchar *dev_base[] = { "/dev/video", "/dev/v4l2/video", NULL };
     gint base, n, fd;
 
     while (devices) {
@@ -148,8 +134,7 @@ gst_v4l2_class_probe_devices (GstV4l2ElementClass * klass, gboolean check)
     for (n = 0; n < 64; n++) {
       for (base = 0; dev_base[base] != NULL; base++) {
         struct stat s;
-        gchar *device = g_strdup_printf ("%s%d",
-            dev_base[base], n);
+        gchar *device = g_strdup_printf ("%s%d", dev_base[base], n);
 
         /* does the /dev/ entry exist at all? */
         if (stat (device, &s) == 0) {
@@ -181,7 +166,7 @@ gst_v4l2_probe_probe_property (GstPropertyProbe * probe,
   GstV4l2ElementClass *klass = GST_V4L2ELEMENT_GET_CLASS (probe);
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       gst_v4l2_class_probe_devices (klass, FALSE);
       break;
     default:
@@ -198,7 +183,7 @@ gst_v4l2_probe_needs_probe (GstPropertyProbe * probe,
   gboolean ret = FALSE;
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       ret = !gst_v4l2_class_probe_devices (klass, TRUE);
       break;
     default:
@@ -243,7 +228,7 @@ gst_v4l2_probe_get_values (GstPropertyProbe * probe,
   GValueArray *array = NULL;
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       array = gst_v4l2_class_list_devices (klass);
       break;
     default:
@@ -254,7 +239,6 @@ gst_v4l2_probe_get_values (GstPropertyProbe * probe,
   return array;
 }
 
-
 static void
 gst_v4l2_property_probe_interface_init (GstPropertyProbeInterface * iface)
 {
@@ -264,75 +248,6 @@ gst_v4l2_property_probe_interface_init (GstPropertyProbeInterface * iface)
   iface->get_values = gst_v4l2_probe_get_values;
 }
 
-
-GType
-gst_v4l2element_get_type (void)
-{
-  static GType v4l2element_type = 0;
-
-  if (!v4l2element_type) {
-    static const GTypeInfo v4l2element_info = {
-      sizeof (GstV4l2ElementClass),
-      (GBaseInitFunc) gst_v4l2element_base_init,
-      NULL,
-      (GClassInitFunc) gst_v4l2element_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4l2Element),
-      0,
-      (GInstanceInitFunc) gst_v4l2element_init,
-      NULL
-    };
-    static const GInterfaceInfo v4l2iface_info = {
-      (GInterfaceInitFunc) gst_v4l2_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo v4l2_tuner_info = {
-      (GInterfaceInitFunc) gst_v4l2_tuner_interface_init,
-      NULL,
-      NULL,
-    };
-#ifdef HAVE_XVIDEO
-    static const GInterfaceInfo v4l2_xoverlay_info = {
-      (GInterfaceInitFunc) gst_v4l2_xoverlay_interface_init,
-      NULL,
-      NULL,
-    };
-#endif
-    static const GInterfaceInfo v4l2_colorbalance_info = {
-      (GInterfaceInitFunc) gst_v4l2_color_balance_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo v4l2_propertyprobe_info = {
-      (GInterfaceInitFunc) gst_v4l2_property_probe_interface_init,
-      NULL,
-      NULL,
-    };
-
-    v4l2element_type =
-        g_type_register_static (GST_TYPE_ELEMENT,
-        "GstV4l2Element", &v4l2element_info, 0);
-
-    g_type_add_interface_static (v4l2element_type,
-        GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
-    g_type_add_interface_static (v4l2element_type,
-        GST_TYPE_TUNER, &v4l2_tuner_info);
-#ifdef HAVE_XVIDEO
-    g_type_add_interface_static (v4l2element_type,
-        GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
-#endif
-    g_type_add_interface_static (v4l2element_type,
-        GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
-    g_type_add_interface_static (v4l2element_type,
-        GST_TYPE_PROPERTY_PROBE, &v4l2_propertyprobe_info);
-  }
-
-  return v4l2element_type;
-}
-
-
 #define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ())
 GType
 gst_v4l2_device_get_type (void)
@@ -341,16 +256,13 @@ gst_v4l2_device_get_type (void)
 
   if (v4l2_device_type == 0) {
     static const GFlagsValue values[] = {
-      {V4L2_CAP_VIDEO_CAPTURE, "CAPTURE",
-          "Device can capture"},
-      {V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK",
-          "Device can playback"},
-      {V4L2_CAP_VIDEO_OVERLAY, "OVERLAY",
-          "Device can do overlay"},
-      {V4L2_CAP_TUNER, "TUNER",
-          "Device has a tuner"},
-      {V4L2_CAP_AUDIO, "AUDIO",
-          "Device handles audio"},
+      {V4L2_CAP_VIDEO_CAPTURE, "CAPTURE", "Device can capture"},
+      {V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK", "Device can playback"},
+      {V4L2_CAP_VIDEO_OVERLAY, "OVERLAY", "Device can do overlay"},
+
+      {V4L2_CAP_TUNER, "TUNER", "Device has a tuner"},
+      {V4L2_CAP_AUDIO, "AUDIO", "Device handles audio"},
+
       {0, NULL, NULL}
     };
 
@@ -362,73 +274,108 @@ gst_v4l2_device_get_type (void)
 }
 
 static void
-gst_v4l2element_base_init (GstV4l2ElementClass * klass)
+gst_v4l2element_init_interfaces (GType type)
+{
+  static const GInterfaceInfo v4l2iface_info = {
+    (GInterfaceInitFunc) gst_v4l2_interface_init,
+    NULL,
+    NULL,
+  };
+  static const GInterfaceInfo v4l2_tuner_info = {
+    (GInterfaceInitFunc) gst_v4l2_tuner_interface_init,
+    NULL,
+    NULL,
+  };
+#ifdef HAVE_XVIDEO
+  static const GInterfaceInfo v4l2_xoverlay_info = {
+    (GInterfaceInitFunc) gst_v4l2_xoverlay_interface_init,
+    NULL,
+    NULL,
+  };
+#endif
+  static const GInterfaceInfo v4l2_colorbalance_info = {
+    (GInterfaceInitFunc) gst_v4l2_color_balance_interface_init,
+    NULL,
+    NULL,
+  };
+  static const GInterfaceInfo v4l2_propertyprobe_info = {
+    (GInterfaceInitFunc) gst_v4l2_property_probe_interface_init,
+    NULL,
+    NULL,
+  };
+
+  g_type_add_interface_static (type,
+      GST_TYPE_IMPLEMENTS_INTERFACE, &v4l2iface_info);
+  g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l2_tuner_info);
+#ifdef HAVE_XVIDEO
+  g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l2_xoverlay_info);
+#endif
+  g_type_add_interface_static (type,
+      GST_TYPE_COLOR_BALANCE, &v4l2_colorbalance_info);
+  g_type_add_interface_static (type,
+      GST_TYPE_PROPERTY_PROBE, &v4l2_propertyprobe_info);
+}
+
+
+static void
+gst_v4l2element_base_init (gpointer g_class)
 {
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GstV4l2ElementClass *klass = GST_V4L2ELEMENT_CLASS (g_class);
 
   klass->devices = NULL;
-
-  gst_element_class_set_details (gstelement_class, &gst_v4l2element_details);
 }
 
 static void
 gst_v4l2element_class_init (GstV4l2ElementClass * klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GObjectClass *gobject_class;
+  GstBaseSrcClass *basesrc_class;
 
-  parent_class = g_type_class_peek_parent (klass);
+  gobject_class = (GObjectClass *) klass;
+  basesrc_class = (GstBaseSrcClass *) klass;
+
+  gobject_class->set_property = gst_v4l2element_set_property;
+  gobject_class->get_property = gst_v4l2element_get_property;
 
-  g_object_class_install_property (gobject_class, ARG_DEVICE,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE,
       g_param_spec_string ("device", "Device", "Device location",
           NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_DEVICE_NAME,
-      g_param_spec_string ("device_name", "Device name",
-          "Name of the device", NULL, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class, ARG_FLAGS,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME,
+      g_param_spec_string ("device_name", "Device name", "Name of the device",
+          NULL, G_PARAM_READABLE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
       g_param_spec_flags ("flags", "Flags", "Device type flags",
           GST_TYPE_V4L2_DEVICE_FLAGS, 0, G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class, ARG_NORM,
-      g_param_spec_string ("norm", "norm",
-          "Norm to use", NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_CHANNEL,
-      g_param_spec_string ("channel", "channel",
-          "input/output to switch to", NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_FREQUENCY,
+  g_object_class_install_property (gobject_class, PROP_STD,
+      g_param_spec_string ("std", "std",
+          "standard (norm) to use", NULL, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_INPUT,
+      g_param_spec_string ("input", "input",
+          "input/output (channel) to switch to", NULL, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_FREQUENCY,
       g_param_spec_ulong ("frequency", "frequency",
           "frequency to tune to (in Hz)", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
 
-  /* signals */
-  gst_v4l2element_signals[SIGNAL_OPEN] =
-      g_signal_new ("open", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstV4l2ElementClass, open),
-      NULL, NULL, g_cclosure_marshal_VOID__STRING,
-      G_TYPE_NONE, 1, G_TYPE_STRING);
-  gst_v4l2element_signals[SIGNAL_CLOSE] =
-      g_signal_new ("close", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstV4l2ElementClass, close),
-      NULL, NULL, g_cclosure_marshal_VOID__STRING,
-      G_TYPE_NONE, 1, G_TYPE_STRING);
+  basesrc_class->start = gst_v4l2element_start;
+  basesrc_class->stop = gst_v4l2element_stop;
 
-  gobject_class->set_property = gst_v4l2element_set_property;
-  gobject_class->get_property = gst_v4l2element_get_property;
   gobject_class->dispose = gst_v4l2element_dispose;
-
-  gstelement_class->change_state = gst_v4l2element_change_state;
 }
 
 
 static void
-gst_v4l2element_init (GstV4l2Element * v4l2element)
+gst_v4l2element_init (GstV4l2Element * v4l2element, GstV4l2ElementClass * klass)
 {
   /* some default values */
   v4l2element->video_fd = -1;
   v4l2element->buffer = NULL;
-  v4l2element->device = g_strdup ("/dev/video0");
+  v4l2element->videodev = g_strdup ("/dev/video0");
 
-  v4l2element->channels = NULL;
-  v4l2element->norms = NULL;
+  v4l2element->stds = NULL;
+  v4l2element->inputs = NULL;
   v4l2element->colors = NULL;
+
+  v4l2element->xwindow_id = 0;
 }
 
 
@@ -437,35 +384,29 @@ gst_v4l2element_dispose (GObject * object)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
 
-  g_free (v4l2element->device);
-  v4l2element->device = NULL;
-  g_free (v4l2element->norm);
-  v4l2element->norm = NULL;
-  g_free (v4l2element->channel);
-  v4l2element->channel = NULL;
+  if (v4l2element->videodev) {
+    g_free (v4l2element->videodev);
+    v4l2element->videodev = NULL;
+  }
 
   if (((GObjectClass *) parent_class)->dispose)
     ((GObjectClass *) parent_class)->dispose (object);
 }
 
+
 static void
 gst_v4l2element_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  GstV4l2Element *v4l2element;
-
-  g_return_if_fail (GST_IS_V4L2ELEMENT (object));
-  v4l2element = GST_V4L2ELEMENT (object);
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
 
   switch (prop_id) {
-    case ARG_DEVICE:
-      if (!GST_V4L2_IS_OPEN (v4l2element)) {
-        if (v4l2element->device)
-          g_free (v4l2element->device);
-        v4l2element->device = g_value_dup_string (value);
-      }
+    case PROP_DEVICE:
+      if (v4l2element->videodev)
+        g_free (v4l2element->videodev);
+      v4l2element->videodev = g_strdup (g_value_get_string (value));
       break;
-    case ARG_NORM:
+    case PROP_STD:
       if (GST_V4L2_IS_OPEN (v4l2element)) {
         GstTuner *tuner = GST_TUNER (v4l2element);
         GstTunerNorm *norm = gst_tuner_find_norm_by_name (tuner,
@@ -475,12 +416,12 @@ gst_v4l2element_set_property (GObject * object,
           gst_tuner_set_norm (tuner, norm);
         }
       } else {
-        g_free (v4l2element->norm);
-        v4l2element->norm = g_value_dup_string (value);
-        g_object_notify (object, "norm");
+        g_free (v4l2element->std);
+        v4l2element->std = g_value_dup_string (value);
+        g_object_notify (object, "std");
       }
       break;
-    case ARG_CHANNEL:
+    case PROP_INPUT:
       if (GST_V4L2_IS_OPEN (v4l2element)) {
         GstTuner *tuner = GST_TUNER (v4l2element);
         GstTunerChannel *channel = gst_tuner_find_channel_by_name (tuner,
@@ -490,12 +431,12 @@ gst_v4l2element_set_property (GObject * object,
           gst_tuner_set_channel (tuner, channel);
         }
       } else {
-        g_free (v4l2element->channel);
-        v4l2element->channel = g_value_dup_string (value);
-        g_object_notify (object, "channel");
+        g_free (v4l2element->input);
+        v4l2element->input = g_value_dup_string (value);
+        g_object_notify (object, "input");
       }
       break;
-    case ARG_FREQUENCY:
+    case PROP_FREQUENCY:
       if (GST_V4L2_IS_OPEN (v4l2element)) {
         GstTuner *tuner = GST_TUNER (v4l2element);
         GstTunerChannel *channel = gst_tuner_get_channel (tuner);
@@ -520,39 +461,40 @@ static void
 gst_v4l2element_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec)
 {
-  GstV4l2Element *v4l2element;
-
-  g_return_if_fail (GST_IS_V4L2ELEMENT (object));
-  v4l2element = GST_V4L2ELEMENT (object);
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (object);
 
   switch (prop_id) {
-    case ARG_DEVICE:
-      g_value_set_string (value, v4l2element->device);
+    case PROP_DEVICE:
+      g_value_set_string (value, v4l2element->videodev);
       break;
-    case ARG_DEVICE_NAME:{
+    case PROP_DEVICE_NAME:{
       gchar *new = NULL;
 
       if (GST_V4L2_IS_OPEN (v4l2element))
-        new = v4l2element->vcap.card;
+        new = (gchar *) v4l2element->vcap.card;
       g_value_set_string (value, new);
       break;
     }
-    case ARG_FLAGS:{
+    case PROP_FLAGS:{
       guint flags = 0;
 
       if (GST_V4L2_IS_OPEN (v4l2element)) {
-        flags |= v4l2element->vcap.capabilities & 0x30007;
+        flags |= v4l2element->vcap.capabilities &
+            (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+            V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_TUNER | V4L2_CAP_AUDIO);
+        if (v4l2element->vcap.capabilities & V4L2_CAP_AUDIO)
+          flags |= V4L2_FBUF_CAP_CHROMAKEY;
       }
       g_value_set_flags (value, flags);
       break;
     }
-    case ARG_NORM:
-      g_value_set_string (value, v4l2element->norm);
+    case PROP_STD:
+      g_value_set_string (value, v4l2element->std);
       break;
-    case ARG_CHANNEL:
-      g_value_set_string (value, v4l2element->channel);
+    case PROP_INPUT:
+      g_value_set_string (value, v4l2element->input);
       break;
-    case ARG_FREQUENCY:
+    case PROP_FREQUENCY:
       g_value_set_ulong (value, v4l2element->frequency);
       break;
     default:
@@ -561,48 +503,32 @@ gst_v4l2element_get_property (GObject * object,
   }
 }
 
-
-static GstStateChangeReturn
-gst_v4l2element_change_state (GstElement * element, GstStateChange transition)
+static gboolean
+gst_v4l2element_start (GstBaseSrc * src)
 {
-  GstV4l2Element *v4l2element;
-
-  g_return_val_if_fail (GST_IS_V4L2ELEMENT (element), GST_STATE_CHANGE_FAILURE);
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (src);
 
-  v4l2element = GST_V4L2ELEMENT (element);
-
-  /* if going down into NULL state, close the device if it's open
-   * if going to READY, open the device (and set some options)
-   */
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      if (!gst_v4l2_open (v4l2element))
-        return GST_STATE_CHANGE_FAILURE;
+  if (!gst_v4l2_open (v4l2element))
+    return FALSE;
 
 #ifdef HAVE_XVIDEO
-      gst_v4l2_xoverlay_open (v4l2element);
+  gst_v4l2_xoverlay_start (v4l2element);
 #endif
 
-      /* emit a signal! whoopie! */
-      g_signal_emit (G_OBJECT (v4l2element),
-          gst_v4l2element_signals[SIGNAL_OPEN], 0, v4l2element->device);
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-#ifdef HAVE_XVIDEO
-      gst_v4l2_xoverlay_close (v4l2element);
-#endif
+  return TRUE;
+}
 
-      if (!gst_v4l2_close (v4l2element))
-        return GST_STATE_CHANGE_FAILURE;
+static gboolean
+gst_v4l2element_stop (GstBaseSrc * src)
+{
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (src);
 
-      /* emit yet another signal! wheehee! */
-      g_signal_emit (G_OBJECT (v4l2element),
-          gst_v4l2element_signals[SIGNAL_CLOSE], 0, v4l2element->device);
-      break;
-  }
+#ifdef HAVE_XVIDEO
+  gst_v4l2_xoverlay_stop (v4l2element);
+#endif
 
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (!gst_v4l2_close (v4l2element))
+    return FALSE;
 
-  return GST_STATE_CHANGE_SUCCESS;
+  return TRUE;
 }
index 62663a2..06e50bf 100644 (file)
@@ -1,5 +1,8 @@
-/* G-Streamer generic V4L2 element
- * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+/* GStreamer
+ *
+ * gstv4l2element.h: base class for V4L2 elements
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -20,9 +23,6 @@
 #ifndef __GST_V4L2ELEMENT_H__
 #define __GST_V4L2ELEMENT_H__
 
-#include <gst/gst.h>
-#include <gst/xwindowlistener/xwindowlistener.h>
-
 /* Because of some really cool feature in video4linux1, also known as
  * 'not including sys/types.h and sys/time.h', we had to include it
  * ourselves. In all their intelligence, these people decided to fix
  * errors here, check your linux/time.h && sys/time.h header setup.
  */
 #include <sys/types.h>
-#include <linux/types.h>
 #define _LINUX_TIME_H
-#define __user
 #include <linux/videodev2.h>
 
-/*
- * See bug #135919, the Suse9 (and Mandrake10) videodev2 headers
- * contain a bug where (for userspace applications) the v4l2_buffer
- * struct is not declared, so applications have to declare it.
- * Declaration straightly ripped out from <linux/videodev2.h>.
- */
-#ifdef GST_V4L2_MISSING_BUFDECL
-struct v4l2_buffer
-{
-        __u32                   index;
-        enum v4l2_buf_type      type;
-        __u32                   bytesused;
-        __u32                   flags;
-        enum v4l2_field         field;
-        struct timeval          timestamp;
-        struct v4l2_timecode    timecode;
-        __u32                   sequence;
-
-        /* memory location */
-        enum v4l2_memory        memory;
-        union {
-                __u32           offset;
-                unsigned long   userptr;
-        } m;
-        __u32                   length;
-
-        __u32                   reserved[2];
-};
-#endif /* GST_V4L2_MISSING_BUFDECL */
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
 
 
-#define GST_TYPE_V4L2ELEMENT \
-                (gst_v4l2element_get_type())
-#define GST_V4L2ELEMENT(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_V4L2ELEMENT, GstV4l2Element))
-#define GST_V4L2ELEMENT_CLASS(klass) \
-                (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
-#define GST_IS_V4L2ELEMENT(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_V4L2ELEMENT))
-#define GST_IS_V4L2ELEMENT_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_V4L2ELEMENT))
-#define GST_V4L2ELEMENT_GET_CLASS(obj) \
-                (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
+G_BEGIN_DECLS
 
+#define GST_TYPE_V4L2ELEMENT                   \
+  (gst_v4l2element_get_type())
+#define GST_V4L2ELEMENT(obj)                                           \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2ELEMENT,GstV4l2Element))
+#define GST_V4L2ELEMENT_CLASS(klass)                                   \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2ELEMENT,GstV4l2ElementClass))
+#define GST_IS_V4L2ELEMENT(obj)                                        \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2ELEMENT))
+#define GST_IS_V4L2ELEMENT_CLASS(obj)                          \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2ELEMENT))
+#define GST_V4L2ELEMENT_GET_CLASS(obj)                                 \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_V4L2ELEMENT, GstV4l2ElementClass))
 
-typedef struct _GstV4l2Element          GstV4l2Element;
-typedef struct _GstV4l2ElementClass     GstV4l2ElementClass;
-typedef struct _GstV4l2Xv               GstV4l2Xv;
+typedef struct _GstV4l2Element GstV4l2Element;
+typedef struct _GstV4l2ElementClass GstV4l2ElementClass;
+typedef struct _GstV4l2Xv GstV4l2Xv;
 
 struct _GstV4l2Element {
-        GstElement element;
+  GstPushSrc element;
 
-        /* the video device */
-        char *device;
+  /* the video device */
+  char *videodev;
 
-        /* the video-device's file descriptor */
-        gint video_fd;
+  /* the video-device's file descriptor */
+  gint video_fd;
 
-        /* the video buffer (mmap()'ed) */
-        guint8 **buffer;
+  /* the video buffer (mmap()'ed) */
+  guint8 **buffer;
 
-        /* the video-device's capabilities */
-        struct v4l2_capability vcap;
+  /* the video device's capabilities */
+  struct v4l2_capability vcap;
 
-        /* the toys available to us */
-        GList *channels;
-        GList *norms;
-        GList *colors;
+  /* the video device's window properties */
+  struct v4l2_window vwin;
 
-        /* X-overlay */
-        GstV4l2Xv *xv;
-        XID xwindow_id;
+  /* some more info about the current input's capabilities */
+  struct v4l2_input vinput;
 
-        /* properties */
-        gchar *norm;
-        gchar *channel;
-        gulong frequency;
-};
+  /* lists... */
+  GList *colors;
+  GList *stds;
+  GList *inputs;
+
+  /* properties */
+  gchar *std;
+  gchar *input;
+  gulong frequency;
 
-struct _GstV4l2ElementClass {
-        GstElementClass parent_class;
 
-        /* probed devices */
-        GList *devices;
+  /* X-overlay */
+  GstV4l2Xv *xv;
+  gulong xwindow_id;
+};
 
-        /* signals */
-        void     (*open)            (GstElement  *element,
-                                     const gchar *device);
-        void     (*close)           (GstElement  *element,
-                                     const gchar *device);
+struct _GstV4l2ElementClass {
+  GstPushSrcClass parent_class;
+
+  /* probed devices */
+  GList *devices;
+
+  /* actions */
+  gboolean (*get_attribute)   (GstElement  *element,
+                               const gchar *attr_name,
+                               int         *value);
+  gboolean (*set_attribute)   (GstElement  *element,
+                               const gchar *attr_name,
+                               const int    value);
 };
 
+GType gst_v4l2element_get_type(void);
+
 
-GType gst_v4l2element_get_type (void);
+G_END_DECLS
 
 #endif /* __GST_V4L2ELEMENT_H__ */
index 02fc41b..180ab94 100644 (file)
@@ -1,5 +1,8 @@
-/* G-Streamer Video4linux2 video-capture plugin
- * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+/* GStreamer
+ *
+ * gstv4l2src.c: BT8x8/V4L2 source element
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include <string.h>
 #include <sys/time.h>
 #include "v4l2src_calls.h"
-#include "gstv4l2tuner.h"
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+
+static GstElementDetails gst_v4l2src_details =
+GST_ELEMENT_DETAILS ("Video (video4linux2/raw) Source",
+    "Source/Video",
+    "Reads raw frames from a video4linux2 (BT8x8) device",
+    "Ronald Bultje <rbultje@ronald.bitfreak.net>,"
+    " Edgard Lima <edgard.lima@indt.org.br>");
+
 
 GST_DEBUG_CATEGORY (v4l2src_debug);
 #define GST_CAT_DEFAULT v4l2src_debug
 
-/* elementfactory details */
-static GstElementDetails gst_v4l2src_details = {
-  "Video (video4linux2) Source",
-  "Source/Video",
-  "Reads frames (compressed or uncompressed) from a video4linux2 device",
-  "Ronald Bultje <rbultje@ronald.bitfreak.net>"
-};
 
-/* V4l2Src signals and args */
 enum
 {
-  SIGNAL_FRAME_CAPTURE,
-  SIGNAL_FRAME_DROP,
-  SIGNAL_FRAME_INSERT,
-  SIGNAL_FRAME_LOST,
-  LAST_SIGNAL
+  PROP_0,
+  PROP_USE_FIXED_FPS
 };
 
-/* arguments */
-enum
-{
-  ARG_0,
-  ARG_NUMBUFS,
-  ARG_BUFSIZE,
-  ARG_USE_FIXED_FPS
-};
 
-guint32 gst_v4l2_formats[] = {
-  /* from Linux 2.6.0 videodev2.h */
-  V4L2_PIX_FMT_RGB332,          /*  8  RGB-3-3-2     */
-  V4L2_PIX_FMT_RGB555,          /* 16  RGB-5-5-5     */
-  V4L2_PIX_FMT_RGB565,          /* 16  RGB-5-6-5     */
-  V4L2_PIX_FMT_RGB555X,         /* 16  RGB-5-5-5 BE  */
-  V4L2_PIX_FMT_RGB565X,         /* 16  RGB-5-6-5 BE  */
-  V4L2_PIX_FMT_BGR24,           /* 24  BGR-8-8-8     */
-  V4L2_PIX_FMT_RGB24,           /* 24  RGB-8-8-8     */
-  V4L2_PIX_FMT_BGR32,           /* 32  BGR-8-8-8-8   */
-  V4L2_PIX_FMT_RGB32,           /* 32  RGB-8-8-8-8   */
-  V4L2_PIX_FMT_GREY,            /*  8  Greyscale     */
-  V4L2_PIX_FMT_YVU410,          /*  9  YVU 4:1:0     */
-  V4L2_PIX_FMT_YVU420,          /* 12  YVU 4:2:0     */
-  V4L2_PIX_FMT_YUYV,            /* 16  YUV 4:2:2     */
-  V4L2_PIX_FMT_UYVY,            /* 16  YUV 4:2:2     */
-  V4L2_PIX_FMT_YUV422P,         /* 16  YVU422 planar */
-  V4L2_PIX_FMT_YUV411P,         /* 16  YVU411 planar */
-  V4L2_PIX_FMT_Y41P,            /* 12  YUV 4:1:1     */
-  V4L2_PIX_FMT_NV12,            /* 12  Y/CbCr 4:2:0  */
-  V4L2_PIX_FMT_NV21,            /* 12  Y/CrCb 4:2:0  */
-  V4L2_PIX_FMT_YUV410,          /*  9  YUV 4:1:0     */
-  V4L2_PIX_FMT_YUV420,          /* 12  YUV 4:2:0     */
-  V4L2_PIX_FMT_YYUV,            /* 16  YUV 4:2:2     */
-  V4L2_PIX_FMT_HI240,           /*  8  8-bit color   */
-  V4L2_PIX_FMT_MJPEG,           /* Motion-JPEG       */
-  V4L2_PIX_FMT_JPEG,            /* JFIF JPEG         */
-  V4L2_PIX_FMT_DV,              /* 1394              */
-  V4L2_PIX_FMT_MPEG,            /* MPEG              */
-  V4L2_PIX_FMT_WNVA             /* Winnov hw compres */
+static guint32 gst_v4l2_formats[] = {
+  /* from Linux 2.6.15 videodev2.h */
+  V4L2_PIX_FMT_RGB332,
+  V4L2_PIX_FMT_RGB555,
+  V4L2_PIX_FMT_RGB565,
+  V4L2_PIX_FMT_RGB555X,
+  V4L2_PIX_FMT_RGB565X,
+  V4L2_PIX_FMT_BGR24,
+  V4L2_PIX_FMT_RGB24,
+  V4L2_PIX_FMT_BGR32,
+  V4L2_PIX_FMT_RGB32,
+  V4L2_PIX_FMT_GREY,
+  V4L2_PIX_FMT_YVU410,
+  V4L2_PIX_FMT_YVU420,
+  V4L2_PIX_FMT_YUYV,
+  V4L2_PIX_FMT_UYVY,
+  V4L2_PIX_FMT_YUV422P,
+  V4L2_PIX_FMT_YUV411P,
+  V4L2_PIX_FMT_Y41P,
+
+  /* two planes -- one Y, one Cr + Cb interleaved  */
+  V4L2_PIX_FMT_NV12,
+  V4L2_PIX_FMT_NV21,
+
+  /*  The following formats are not defined in the V4L2 specification */
+  V4L2_PIX_FMT_YUV410,
+  V4L2_PIX_FMT_YUV420,
+  V4L2_PIX_FMT_YYUV,
+  V4L2_PIX_FMT_HI240,
+
+  /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+  V4L2_PIX_FMT_SBGGR8,
+
+  /* compressed formats */
+  V4L2_PIX_FMT_MJPEG,
+  V4L2_PIX_FMT_JPEG,
+  V4L2_PIX_FMT_DV,
+  V4L2_PIX_FMT_MPEG,
+
+  /*  Vendor-specific formats   */
+  V4L2_PIX_FMT_WNVA,
+  V4L2_PIX_FMT_SN9C10X
+      /* V4L2_PIX_FMT_PWC1 FIX */
+      /* V4L2_PIX_FMT_PWC2 FIX */
 };
 
+
 #define GST_V4L2_FORMAT_COUNT (G_N_ELEMENTS (gst_v4l2_formats))
 
-GST_FORMATS_FUNCTION (GstPad *, gst_v4l2src_get_formats,
-    GST_FORMAT_TIME, GST_FORMAT_DEFAULT);
-GST_QUERY_TYPE_FUNCTION (GstPad *, gst_v4l2src_get_query_types,
-    GST_QUERY_POSITION);
-
-/* init functions */
-static void gst_v4l2src_class_init (gpointer g_class, gpointer class_data);
-static void gst_v4l2src_base_init (gpointer g_class);
-static void gst_v4l2src_init (GTypeInstance * instance, gpointer g_class);
-
-/* signal functions */
-static void gst_v4l2src_open (GstElement * element, const gchar * device);
-static void gst_v4l2src_close (GstElement * element, const gchar * device);
-
-/* pad/buffer functions */
-static const GstCaps *gst_v4l2src_get_all_caps (void);
-static GstPadLinkReturn gst_v4l2src_link (GstPad * pad, const GstCaps * caps);
-static GstCaps *gst_v4l2src_getcaps (GstPad * pad);
-static GstCaps *gst_v4l2src_fixate (GstPad * pad, const GstCaps * caps);
-static GstData *gst_v4l2src_get (GstPad * pad);
-static gboolean gst_v4l2src_src_convert (GstPad * pad,
-    GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-static gboolean gst_v4l2src_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * format, gint64 * value);
-
-/* get/set params */
-static void gst_v4l2src_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4l2src_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
 
-/* state handling */
-static GstStateChangeReturn gst_v4l2src_change_state (GstElement * element,
-    GstStateChange transition);
+GST_BOILERPLATE (GstV4l2Src, gst_v4l2src, GstV4l2Element, GST_TYPE_V4L2ELEMENT);
 
-/* set_clock function for A/V sync */
-static void gst_v4l2src_set_clock (GstElement * element, GstClock * clock);
 
-static GstElementClass *parent_class = NULL;
-static guint gst_v4l2src_signals[LAST_SIGNAL] = { 0 };
+/* basesrc methods */
+static gboolean gst_v4l2src_start (GstBaseSrc * src);
+static gboolean gst_v4l2src_stop (GstBaseSrc * src);
+static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
+static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
+static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
 
+static void gst_v4l2src_fixate (GstPad * pad, GstCaps * caps);
 
-GType
-gst_v4l2src_get_type (void)
-{
-  static GType v4l2src_type = 0;
-
-  if (!v4l2src_type) {
-    static const GTypeInfo v4l2src_info = {
-      sizeof (GstV4l2SrcClass),
-      gst_v4l2src_base_init,
-      NULL,
-      gst_v4l2src_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4l2Src),
-      0,
-      gst_v4l2src_init,
-      NULL
-    };
-
-    v4l2src_type = g_type_register_static (GST_TYPE_V4L2ELEMENT,
-        "GstV4l2Src", &v4l2src_info, 0);
-    GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "v4l2src element");
-  }
-  return v4l2src_type;
-}
+static void
+gst_v4l2src_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void
+gst_v4l2src_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_v4l2src_get_all_caps (void);
 
 static void
 gst_v4l2src_base_init (gpointer g_class)
 {
-  GstPadTemplate *template;
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
   gst_element_class_set_details (gstelement_class, &gst_v4l2src_details);
 
-  template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
-      gst_caps_copy (gst_v4l2src_get_all_caps ()));
-
-  gst_element_class_add_pad_template (gstelement_class, template);
+  gst_element_class_add_pad_template
+      (gstelement_class,
+      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+          gst_v4l2src_get_all_caps ()));
 }
 
 static void
-gst_v4l2src_class_init (gpointer g_class, gpointer class_data)
+gst_v4l2src_class_init (GstV4l2SrcClass * klass)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-  GstV4l2ElementClass *v4l2_class = GST_V4L2ELEMENT_CLASS (g_class);
+  GObjectClass *gobject_class;
+  GstBaseSrcClass *basesrc_class;
+  GstPushSrcClass *pushsrc_class;
 
-  parent_class = g_type_class_peek_parent (g_class);
+  gobject_class = G_OBJECT_CLASS (klass);
+  basesrc_class = GST_BASE_SRC_CLASS (klass);
+  pushsrc_class = GST_PUSH_SRC_CLASS (klass);
 
   gobject_class->set_property = gst_v4l2src_set_property;
   gobject_class->get_property = gst_v4l2src_get_property;
 
-  g_object_class_install_property (gobject_class, ARG_NUMBUFS,
-      g_param_spec_int ("num_buffers", "num_buffers", "num_buffers",
-          G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_BUFSIZE,
-      g_param_spec_int ("buffer_size", "buffer_size", "buffer_size",
-          G_MININT, G_MAXINT, 0, G_PARAM_READABLE));
-
-  g_object_class_install_property (gobject_class, ARG_USE_FIXED_FPS,
+  g_object_class_install_property
+      (gobject_class, PROP_USE_FIXED_FPS,
       g_param_spec_boolean ("use_fixed_fps", "Use Fixed FPS",
           "Drop/Insert frames to reach a certain FPS (TRUE) "
           "or adapt FPS to suit the number of frabbed frames",
           TRUE, G_PARAM_READWRITE));
 
-  /* signals */
-  gst_v4l2src_signals[SIGNAL_FRAME_CAPTURE] =
-      g_signal_new ("frame-capture", G_TYPE_FROM_CLASS (g_class),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4l2SrcClass, frame_capture), NULL,
-      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-  gst_v4l2src_signals[SIGNAL_FRAME_DROP] =
-      g_signal_new ("frame-drop", G_TYPE_FROM_CLASS (g_class),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4l2SrcClass, frame_drop), NULL,
-      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-  gst_v4l2src_signals[SIGNAL_FRAME_INSERT] =
-      g_signal_new ("frame_insert", G_TYPE_FROM_CLASS (g_class),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4l2SrcClass, frame_insert), NULL,
-      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-  gst_v4l2src_signals[SIGNAL_FRAME_LOST] =
-      g_signal_new ("frame-lost", G_TYPE_FROM_CLASS (g_class),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4l2SrcClass, frame_lost), NULL,
-      NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
-
-  gstelement_class->change_state = gst_v4l2src_change_state;
-
-  v4l2_class->open = gst_v4l2src_open;
-  v4l2_class->close = gst_v4l2src_close;
-
-  gstelement_class->set_clock = gst_v4l2src_set_clock;
-}
+  GST_DEBUG_CATEGORY_INIT (v4l2src_debug, "v4l2src", 0, "V4L2 source element");
+
+  basesrc_class->get_caps = gst_v4l2src_get_caps;
+  basesrc_class->set_caps = gst_v4l2src_set_caps;
+  basesrc_class->start = gst_v4l2src_start;
+  basesrc_class->stop = gst_v4l2src_stop;
 
+  pushsrc_class->create = gst_v4l2src_create;
+}
 
 static void
-gst_v4l2src_init (GTypeInstance * instance, gpointer g_class)
+gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
 {
-  GstV4l2Src *v4l2src = GST_V4L2SRC (instance);
-
-  GST_OBJECT_FLAG_SET (GST_ELEMENT (v4l2src), GST_ELEMENT_THREAD_SUGGESTED);
-
-  v4l2src->srcpad =
-      gst_pad_new_from_template (gst_element_class_get_pad_template
-      (GST_ELEMENT_GET_CLASS (v4l2src), "src"), "src");
-  gst_element_add_pad (GST_ELEMENT (v4l2src), v4l2src->srcpad);
-
-  gst_pad_set_get_function (v4l2src->srcpad, gst_v4l2src_get);
-  gst_pad_set_link_function (v4l2src->srcpad, gst_v4l2src_link);
-  gst_pad_set_getcaps_function (v4l2src->srcpad, gst_v4l2src_getcaps);
-  gst_pad_set_fixate_function (v4l2src->srcpad, gst_v4l2src_fixate);
-  gst_pad_set_convert_function (v4l2src->srcpad, gst_v4l2src_src_convert);
-  gst_pad_set_formats_function (v4l2src->srcpad, gst_v4l2src_get_formats);
-  gst_pad_set_query_function (v4l2src->srcpad, gst_v4l2src_src_query);
-  gst_pad_set_query_type_function (v4l2src->srcpad,
-      gst_v4l2src_get_query_types);
 
   v4l2src->breq.count = 0;
 
   v4l2src->formats = NULL;
 
-  /* no clock */
-  v4l2src->clock = NULL;
-
   /* fps */
   v4l2src->use_fixed_fps = TRUE;
 
   v4l2src->is_capturing = FALSE;
-}
 
+  gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (v4l2src),
+      gst_v4l2src_fixate);
 
-static void
-gst_v4l2src_open (GstElement * element, const gchar * device)
-{
-  gst_v4l2src_fill_format_list (GST_V4L2SRC (element));
+  gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
 }
 
-
 static void
-gst_v4l2src_close (GstElement * element, const gchar * device)
+gst_v4l2src_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  gst_v4l2src_clear_format_list (GST_V4L2SRC (element));
-}
+  GstV4l2Src *v4l2src;
 
+  g_return_if_fail (GST_IS_V4L2SRC (object));
+  v4l2src = GST_V4L2SRC (object);
 
-static gfloat
-gst_v4l2src_get_fps (GstV4l2Src * v4l2src)
-{
-  v4l2_std_id norm;
-  const GList *item;
-
-  if (!v4l2src->use_fixed_fps && v4l2src->clock != NULL && v4l2src->handled > 0) {
-    /* try to get time from clock master and calculate fps */
-    GstClockTime time = gst_clock_get_time (v4l2src->clock) -
-        v4l2src->substract_time;
-    return v4l2src->handled * GST_SECOND / time;
+  switch (prop_id) {
+    case PROP_USE_FIXED_FPS:
+      if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
+        v4l2src->use_fixed_fps = g_value_get_boolean (value);
+      }
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
+}
 
-  /* if that failed ... */
 
-  if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src)))
-    return 0.;
+static void
+gst_v4l2src_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstV4l2Src *v4l2src;
+
+  g_return_if_fail (GST_IS_V4L2SRC (object));
+  v4l2src = GST_V4L2SRC (object);
 
-  if (!gst_v4l2_get_norm (GST_V4L2ELEMENT (v4l2src), &norm))
-    return 0.;
-  for (item = GST_V4L2ELEMENT (v4l2src)->norms; item != NULL; item = item->next) {
-    GstV4l2TunerNorm *v4l2norm = item->data;
+  switch (prop_id) {
+    case PROP_USE_FIXED_FPS:
+      g_value_set_boolean (value, v4l2src->use_fixed_fps);
+      break;
 
-    if (v4l2norm->index == norm)
-      return GST_TUNER_NORM (v4l2norm)->fps;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
-
-  return 0.;
 }
 
-static gboolean
-gst_v4l2src_src_convert (GstPad * pad,
-    GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
+
+gboolean
+get_fmt_width_height (GstV4l2Src * v4l2src, int *width, int *height)
 {
-  GstV4l2Src *v4l2src;
-  gdouble fps;
+  int ret;
 
-  v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad));
+  struct v4l2_format format;
 
-  if ((fps = gst_v4l2src_get_fps (v4l2src)) == 0)
-    return FALSE;
+  memset (&format, 0x00, sizeof (format));
 
-  switch (src_format) {
-    case GST_FORMAT_TIME:
-      switch (*dest_format) {
-        case GST_FORMAT_DEFAULT:
-          *dest_value = src_value * fps / GST_SECOND;
-          break;
-        default:
-          return FALSE;
-      }
-      break;
+  format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = src_value * GST_SECOND / fps;
-          break;
-        default:
-          return FALSE;
-      }
-      break;
+  ret = ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_G_FMT, &format);
+
+  if (ret == 0) {
+
+    *width = format.fmt.pix.width;
+    *height = format.fmt.pix.height;
 
-    default:
-      return FALSE;
   }
 
-  return TRUE;
+  return (ret == 0);
+
 }
 
-static gboolean
-gst_v4l2src_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * format, gint64 * value)
+/* this function is a bit of a last resort */
+static void
+gst_v4l2src_fixate (GstPad * pad, GstCaps * caps)
 {
-  GstV4l2Src *v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad));
-  gboolean res = TRUE;
-  gdouble fps;
+  GstStructure *structure;
+  gint i;
+  G_GNUC_UNUSED gchar *caps_str;
 
-  if ((fps = gst_v4l2src_get_fps (v4l2src)) == 0)
-    return FALSE;
+  caps_str = gst_caps_to_string (caps);
+  GST_DEBUG_OBJECT (GST_PAD_PARENT (pad), "fixating caps %s", caps_str);
+  g_free (caps_str);
 
-  switch (type) {
-    case GST_QUERY_POSITION:
-      switch (*format) {
-        case GST_FORMAT_TIME:
-          *value = v4l2src->handled * GST_SECOND / fps;
-          break;
-        case GST_FORMAT_DEFAULT:
-          *value = v4l2src->handled;
-          break;
-        default:
-          res = FALSE;
-          break;
-      }
-      break;
-    default:
-      res = FALSE;
-      break;
-  }
+  for (i = 0; i < gst_caps_get_size (caps); ++i) {
+    structure = gst_caps_get_structure (caps, i);
+    const GValue *v;
+
+    gst_structure_fixate_field_nearest_int (structure, "width", G_MAXINT);
+    gst_structure_fixate_field_nearest_int (structure, "height", G_MAXINT);
 
-  return res;
+    v = gst_structure_get_value (structure, "format");
+    if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
+      guint32 fourcc;
+
+      g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
+
+      fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
+      gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
+    }
+  }
 }
 
 static GstStructure *
@@ -535,42 +439,12 @@ gst_v4l2src_v4l2fourcc_to_caps (guint32 fourcc)
     case V4L2_PIX_FMT_WNVA:    /* Winnov hw compres */
       break;
     default:
-      GST_DEBUG ("Unknown fourcc 0x%08x %" GST_FOURCC_FORMAT,
+      GST_DEBUG ("Unknown fourcc 0x%08x " GST_FOURCC_FORMAT,
           fourcc, GST_FOURCC_ARGS (fourcc));
       break;
   }
-#if 0
-  gst_caps_set_simple (caps,
-      "width", G_TYPE_INT, width,
-      "height", G_TYPE_INT, height, "framerate", G_TYPE_DOUBLE, fps, NULL);
-#endif
-  return structure;
-}
-
-static struct v4l2_fmtdesc *
-gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
-{
-  struct v4l2_fmtdesc *fmt;
-  GSList *walk;
-
-  if (fourcc == 0)
-    return NULL;
-
-  walk = v4l2src->formats;
-  while (walk) {
-    fmt = (struct v4l2_fmtdesc *) walk->data;
-    if (fmt->pixelformat == fourcc)
-      return fmt;
-    /* special case for jpeg */
-    if ((fmt->pixelformat == V4L2_PIX_FMT_MJPEG && fourcc == V4L2_PIX_FMT_JPEG)
-        || (fmt->pixelformat == V4L2_PIX_FMT_JPEG
-            && fourcc == V4L2_PIX_FMT_MJPEG)) {
-      return fmt;
-    }
-    walk = g_slist_next (walk);
-  }
 
-  return NULL;
+  return structure;
 }
 
 static guint32
@@ -642,13 +516,39 @@ gst_v4l2_fourcc_from_structure (GstStructure * structure)
 }
 
 static struct v4l2_fmtdesc *
+gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
+{
+  struct v4l2_fmtdesc *fmt;
+  GSList *walk;
+
+  if (fourcc == 0)
+    return NULL;
+
+  walk = v4l2src->formats;
+  while (walk) {
+    fmt = (struct v4l2_fmtdesc *) walk->data;
+    if (fmt->pixelformat == fourcc)
+      return fmt;
+    /* special case for jpeg */
+    if ((fmt->pixelformat == V4L2_PIX_FMT_MJPEG && fourcc == V4L2_PIX_FMT_JPEG)
+        || (fmt->pixelformat == V4L2_PIX_FMT_JPEG
+            && fourcc == V4L2_PIX_FMT_MJPEG)) {
+      return fmt;
+    }
+    walk = g_slist_next (walk);
+  }
+
+  return NULL;
+}
+
+static struct v4l2_fmtdesc *
 gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src * v4l2src, GstStructure * structure)
 {
   return gst_v4l2src_get_format_from_fourcc (v4l2src,
       gst_v4l2_fourcc_from_structure (structure));
 }
 
-static const GstCaps *
+static GstCaps *
 gst_v4l2src_get_all_caps (void)
 {
   static GstCaps *caps = NULL;
@@ -664,8 +564,7 @@ gst_v4l2src_get_all_caps (void)
         gst_structure_set (structure,
             "width", GST_TYPE_INT_RANGE, 1, 4096,
             "height", GST_TYPE_INT_RANGE, 1, 4096,
-            "framerate", GST_TYPE_DOUBLE_RANGE, (double) 0, G_MAXDOUBLE, NULL);
-
+            "framerate", GST_TYPE_FRACTION_RANGE, 1, 1, 100, 1, NULL);
         gst_caps_append_structure (caps, structure);
       }
     }
@@ -675,108 +574,30 @@ gst_v4l2src_get_all_caps (void)
 }
 
 static GstCaps *
-gst_v4l2src_fixate (GstPad * pad, const GstCaps * const_caps)
-{
-  gint i;
-  GstStructure *structure;
-  G_GNUC_UNUSED gchar *caps_str;
-  gboolean changed = FALSE;
-  GstCaps *caps = gst_caps_copy (const_caps);
-
-  caps_str = gst_caps_to_string (caps);
-  GST_DEBUG_OBJECT (gst_pad_get_parent (pad), "fixating caps %s", caps_str);
-  g_free (caps_str);
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    structure = gst_caps_get_structure (caps, i);
-    changed |=
-        gst_structure_fixate_field_nearest_int (structure, "width", G_MAXINT);
-  }
-  if (changed)
-    return caps;
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    structure = gst_caps_get_structure (caps, i);
-    changed |=
-        gst_structure_fixate_field_nearest_int (structure, "height", G_MAXINT);
-  }
-  if (changed)
-    return caps;
-
-  gst_caps_free (caps);
-  return NULL;
-}
-
-static GstPadLinkReturn
-gst_v4l2src_link (GstPad * pad, const GstCaps * caps)
-{
-  GstV4l2Src *v4l2src;
-  GstV4l2Element *v4l2element;
-  struct v4l2_fmtdesc *format;
-  int w, h;
-  GstStructure *structure;
-  gboolean was_capturing;
-
-  v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad));
-  v4l2element = GST_V4L2ELEMENT (v4l2src);
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  /* clean up if we still haven't cleaned up our previous
-   * capture session */
-  if ((was_capturing = v4l2src->is_capturing)) {
-    if (!gst_v4l2src_capture_stop (v4l2src))
-      return GST_PAD_LINK_REFUSED;
-  }
-  if (GST_V4L2_IS_ACTIVE (v4l2element)) {
-    if (!gst_v4l2src_capture_deinit (v4l2src))
-      return GST_PAD_LINK_REFUSED;
-  } else if (!GST_V4L2_IS_OPEN (v4l2element)) {
-    return GST_PAD_LINK_DELAYED;
-  }
-
-  /* we want our own v4l2 type of fourcc codes */
-  if (!(format = gst_v4l2_caps_to_v4l2fourcc (v4l2src, structure))) {
-    return GST_PAD_LINK_REFUSED;
-  }
-
-  gst_structure_get_int (structure, "width", &w);
-  gst_structure_get_int (structure, "height", &h);
-
-  /* we found the pixelformat! - try it out */
-  if (gst_v4l2src_set_capture (v4l2src, format, w, h)) {
-    if (gst_v4l2src_capture_init (v4l2src)) {
-      if (was_capturing || GST_STATE (v4l2src) == GST_STATE_PLAYING)
-        if (!gst_v4l2src_capture_start (v4l2src))
-          return GST_PAD_LINK_REFUSED;
-
-      return GST_PAD_LINK_OK;
-    }
-  }
-
-  return GST_PAD_LINK_REFUSED;
-}
-
-
-static GstCaps *
-gst_v4l2src_getcaps (GstPad * pad)
+gst_v4l2src_get_caps (GstBaseSrc * src)
 {
-  GstV4l2Src *v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad));
+  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
   GstCaps *caps;
   struct v4l2_fmtdesc *format;
   int min_w, max_w, min_h, max_h;
   GSList *walk;
   GstStructure *structure;
-  gdouble fps;
+  gint fps_n, fps_d;
+
 
   if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src))) {
-    return gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+    return
+        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
+            (v4l2src)));
   }
 
+  if (!v4l2src->formats)
+    gst_v4l2src_fill_format_list (v4l2src);
+
   /* build our own capslist */
   caps = gst_caps_new_empty ();
   walk = v4l2src->formats;
-  fps = gst_v4l2src_get_fps (v4l2src);
+  gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d);
   while (walk) {
     format = (struct v4l2_fmtdesc *) walk->data;
     walk = g_slist_next (walk);
@@ -787,14 +608,10 @@ gst_v4l2src_getcaps (GstPad * pad)
       continue;
     }
     /* template */
-    if (min_w < 1)
-      min_w = 1;
-    if (min_h < 1)
-      min_h = 1;
-    if (max_w > 4096)
-      max_w = 4096;
-    if (max_h > 4096)
-      max_h = 4096;
+    min_w = CLAMP (min_w, 1, 4096);
+    min_h = CLAMP (min_h, 1, 4096);
+    max_w = CLAMP (max_w, min_w, 4096);
+    max_h = CLAMP (max_h, min_h, 4096);
 
     /* add to list */
     structure = gst_v4l2src_v4l2fourcc_to_caps (format->pixelformat);
@@ -803,7 +620,7 @@ gst_v4l2src_getcaps (GstPad * pad)
       gst_structure_set (structure,
           "width", GST_TYPE_INT_RANGE, min_w, max_w,
           "height", GST_TYPE_INT_RANGE, min_h, max_h,
-          "framerate", G_TYPE_DOUBLE, fps, NULL);
+          "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
 
       gst_caps_append_structure (caps, structure);
     }
@@ -812,269 +629,190 @@ gst_v4l2src_getcaps (GstPad * pad)
   return caps;
 }
 
-static GstData *
-gst_v4l2src_get (GstPad * pad)
+static gboolean
+gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
 {
   GstV4l2Src *v4l2src;
-  GstBuffer *buf;
-  gint i, num = -1;
-  gdouble fps = 0;
+  gint w, h;
+  GstStructure *structure;
+  struct v4l2_fmtdesc *format;
 
-  v4l2src = GST_V4L2SRC (gst_pad_get_parent (pad));
+  v4l2src = GST_V4L2SRC (src);
 
-  if (v4l2src->use_fixed_fps && (fps = gst_v4l2src_get_fps (v4l2src)) == 0) {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
-        ("could not get frame rate for element"));
-    return NULL;
+  /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
+  if (!GST_V4L2_IS_OPEN (v4l2src))
+    return FALSE;
+
+  /* make sure we stop capturing and dealloc buffers */
+  if (GST_V4L2_IS_ACTIVE (v4l2src)) {
+    if (!gst_v4l2src_capture_stop (v4l2src))
+      return FALSE;
+    if (!gst_v4l2src_capture_deinit (v4l2src))
+      return FALSE;
   }
 
-  if (v4l2src->need_writes > 0) {
-    /* use last frame */
-    buf = v4l2src->cached_buffer;
-    v4l2src->need_writes--;
-  } else {
-    GstClockTime time;
-
-    /* grab a frame from the device */
-    num = gst_v4l2src_grab_frame (v4l2src);
-    if (num == -1)
-      return NULL;
-
-    /* to check if v4l2 sets the correct time */
-    time = GST_TIMEVAL_TO_TIME (v4l2src->pool->buffers[num].buffer.timestamp);
-    if (v4l2src->clock && v4l2src->use_fixed_fps && time != 0) {
-      gboolean have_frame = FALSE;
-
-      do {
-        /* FIXME: isn't this v4l2 timestamp its own clock?! */
-        /* by default, we use the frame once */
-        v4l2src->need_writes = 1;
-
-        g_assert (time >= v4l2src->substract_time);
-        time -= v4l2src->substract_time;
-
-        /* first check whether we lost any frames according to the device */
-        if (v4l2src->last_seq != 0) {
-          if (v4l2src->pool->buffers[num].buffer.sequence - v4l2src->last_seq >
-              1) {
-            v4l2src->need_writes =
-                v4l2src->pool->buffers[num].buffer.sequence - v4l2src->last_seq;
-            g_signal_emit (G_OBJECT (v4l2src),
-                gst_v4l2src_signals[SIGNAL_FRAME_LOST], 0,
-                v4l2src->need_writes - 1);
-          }
-        }
-        v4l2src->last_seq = v4l2src->pool->buffers[num].buffer.sequence;
-
-        /* decide how often we're going to write the frame - set
-         * v4lmjpegsrc->need_writes to (that-1) and have_frame to TRUE
-         * if we're going to write it - else, just continue.
-         * 
-         * time is generally the system or audio clock. Let's
-         * say that we've written one second of audio, then we want
-         * to have written one second of video too, within the same
-         * timeframe. This means that if time - begin_time = X sec,
-         * we want to have written X*fps frames. If we've written
-         * more - drop, if we've written less - dup... */
-        if (v4l2src->handled * (GST_SECOND / fps) - time >
-            1.5 * (GST_SECOND / fps)) {
-          /* yo dude, we've got too many frames here! Drop! DROP! */
-          v4l2src->need_writes--;       /* -= (v4l2src->handled - (time / fps)); */
-          g_signal_emit (G_OBJECT (v4l2src),
-              gst_v4l2src_signals[SIGNAL_FRAME_DROP], 0);
-        } else if (v4l2src->handled * (GST_SECOND / fps) - time <
-            -1.5 * (GST_SECOND / fps)) {
-          /* this means we're lagging far behind */
-          v4l2src->need_writes++;       /* += ((time / fps) - v4l2src->handled); */
-          g_signal_emit (G_OBJECT (v4l2src),
-              gst_v4l2src_signals[SIGNAL_FRAME_INSERT], 0);
-        }
-
-        if (v4l2src->need_writes > 0) {
-          have_frame = TRUE;
-          v4l2src->need_writes--;
-        } else {
-          if (!gst_v4l2src_queue_frame (v4l2src, num))
-            return NULL;
-          num = gst_v4l2src_grab_frame (v4l2src);
-          if (num == -1)
-            return NULL;
-        }
-      } while (!have_frame);
-    }
+  /* it's fixed, one struct */
+  structure = gst_caps_get_structure (caps, 0);
 
-    g_assert (num != -1);
-    GST_LOG_OBJECT (v4l2src, "buffer %d needs %d writes", num,
-        v4l2src->need_writes + 1);
-    i = v4l2src->pool->buffers[num].buffer.bytesused >
-        0 ? v4l2src->pool->buffers[num].buffer.bytesused : v4l2src->pool->
-        buffers[num].length;
-    /* check if this is the last buffer in the queue. If so do a memcpy to put it back asap
-       to avoid framedrops and deadlocks because of stupid elements */
-    if (gst_atomic_int_read (&v4l2src->pool->refcount) == v4l2src->breq.count) {
-      GST_LOG_OBJECT (v4l2src, "using memcpy'd buffer");
-      buf = gst_buffer_new_and_alloc (i);
-      memcpy (GST_BUFFER_DATA (buf), v4l2src->pool->buffers[num].start, i);
-      if (!gst_v4l2src_queue_frame (v4l2src, num)) {
-        gst_data_unref (GST_DATA (buf));
-        return NULL;
-      }
-    } else {
-      GST_LOG_OBJECT (v4l2src, "using mmap'd buffer");
-      buf = gst_buffer_new ();
-      GST_BUFFER_DATA (buf) = v4l2src->pool->buffers[num].start;
-      GST_BUFFER_SIZE (buf) = i;
-      GST_BUFFER_FREE_DATA_FUNC (buf) = gst_v4l2src_free_buffer;
-      GST_BUFFER_PRIVATE (buf) = &v4l2src->pool->buffers[num];
-      /* no need to be careful here, both are > 0, because the element uses them */
-      gst_atomic_int_inc (&v4l2src->pool->buffers[num].refcount);
-      gst_atomic_int_inc (&v4l2src->pool->refcount);
-    }
-    GST_BUFFER_MAXSIZE (buf) = v4l2src->pool->buffers[num].length;
-    if (v4l2src->use_fixed_fps) {
-      GST_BUFFER_TIMESTAMP (buf) = v4l2src->handled * GST_SECOND / fps;
-      GST_BUFFER_DURATION (buf) = GST_SECOND / fps;
-    } else {
-      /* calculate time based on our own clock */
-      GST_BUFFER_TIMESTAMP (buf) =
-          GST_TIMEVAL_TO_TIME (v4l2src->pool->buffers[num].buffer.timestamp) -
-          v4l2src->substract_time;
-    }
-    if (v4l2src->need_writes > 0) {
-      v4l2src->cached_buffer = buf;
-      for (i = 0; i < v4l2src->need_writes; i++) {
-        gst_data_ref (GST_DATA (buf));
-      }
-    }
+  /* we want our own v4l2 type of fourcc codes */
+  if (!(format = gst_v4l2_caps_to_v4l2fourcc (v4l2src, structure))) {
+    return FALSE;
+  }
+
+  gst_structure_get_int (structure, "width", &w);
+  gst_structure_get_int (structure, "height", &h);
+
+  GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d, format %s",
+      w, h, format->description);
+  /* this only fills in v4l2src->mmap values */
+  if (!gst_v4l2src_set_capture (v4l2src, format, w, h)) {
+    GST_WARNING_OBJECT (v4l2src, "could not set_capture %dx%d, format %s",
+        w, h, format->description);
+    return FALSE;
   }
 
-  v4l2src->handled++;
-  g_signal_emit (G_OBJECT (v4l2src), gst_v4l2src_signals[SIGNAL_FRAME_CAPTURE],
-      0);
+  if (!gst_v4l2src_capture_init (v4l2src))
+    return FALSE;
+
+  if (!gst_v4l2src_capture_start (v4l2src))
+    return FALSE;
 
-  return GST_DATA (buf);
+  return TRUE;
 }
 
-static void
-gst_v4l2src_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
+/* start and stop are not symmetric -- start will open the device, but not start
+   capture. it's setcaps that will start capture, which is called via basesrc's
+   negotiate method. stop will both stop capture and close the device.
+*/
+static gboolean
+gst_v4l2src_start (GstBaseSrc * src)
 {
-  GstV4l2Src *v4l2src;
+  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
 
-  g_return_if_fail (GST_IS_V4L2SRC (object));
-  v4l2src = GST_V4L2SRC (object);
+  if (!GST_BASE_SRC_CLASS (parent_class)->start (src))
+    return FALSE;
 
-  switch (prop_id) {
-    case ARG_NUMBUFS:
-      if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
-        v4l2src->breq.count = g_value_get_int (value);
-      }
-      break;
+  v4l2src->offset = 0;
 
-    case ARG_USE_FIXED_FPS:
-      if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
-        v4l2src->use_fixed_fps = g_value_get_boolean (value);
-      }
-      break;
+  return TRUE;
+}
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+static gboolean
+gst_v4l2src_stop (GstBaseSrc * src)
+{
+  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+
+  if (GST_V4L2_IS_ACTIVE (v4l2src) && !gst_v4l2src_capture_stop (v4l2src))
+    return FALSE;
+
+  if (GST_V4L2ELEMENT (v4l2src)->buffer != NULL) {
+    if (!gst_v4l2src_capture_deinit (v4l2src))
+      return FALSE;
   }
-}
 
+  if (!GST_BASE_SRC_CLASS (parent_class)->stop (src))
+    return FALSE;
 
-static void
-gst_v4l2src_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
+  return TRUE;
+}
+
+static GstFlowReturn
+gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
 {
-  GstV4l2Src *v4l2src;
+  gint amount;
+  gint buffersize;
 
-  g_return_if_fail (GST_IS_V4L2SRC (object));
-  v4l2src = GST_V4L2SRC (object);
+  buffersize = v4l2src->format.fmt.pix.sizeimage;
 
-  switch (prop_id) {
-    case ARG_NUMBUFS:
-      g_value_set_int (value, v4l2src->breq.count);
-      break;
+  do {
+    *buf = gst_v4l2src_buffer_new (v4l2src, buffersize, NULL, NULL);
+    GST_BUFFER_OFFSET (*buf) = GST_BUFFER_OFFSET_NONE;
+    gst_buffer_set_caps (*buf, GST_PAD_CAPS (v4l2src->srcpad));
 
-    case ARG_BUFSIZE:
-      g_value_set_int (value, v4l2src->format.fmt.pix.sizeimage);
+    amount =
+        read (GST_V4L2ELEMENT (v4l2src)->video_fd, GST_BUFFER_DATA (*buf),
+        buffersize);
+    if (amount == buffersize) {
       break;
+    } else if (amount == -1) {
+      if (errno == EAGAIN || errno == EINTR) {
+        continue;
+      } else {
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("error read()ing a buffer on device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        gst_buffer_unref (*buf);
+        return GST_FLOW_ERROR;
+      }
+    } else {
+      GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+          ("error read()ing a buffer on device %s: got only %d bytes instead of expected %d",
+              GST_V4L2ELEMENT (v4l2src)->videodev, amount, buffersize));
+      gst_buffer_unref (*buf);
+      return GST_FLOW_ERROR;
+    }
+  } while (TRUE);
 
-    case ARG_USE_FIXED_FPS:
-      g_value_set_boolean (value, v4l2src->use_fixed_fps);
-      break;
+  return GST_FLOW_OK;
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
 }
 
 
-static GstStateChangeReturn
-gst_v4l2src_change_state (GstElement * element, GstStateChange transition)
+static GstFlowReturn
+gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
 {
-  GstV4l2Src *v4l2src;
-  GstStateChangeReturn parent_return;
-  GTimeVal time;
+  gint i, num = -1;
 
-  g_return_val_if_fail (GST_IS_V4L2SRC (element), GST_STATE_CHANGE_FAILURE);
-  v4l2src = GST_V4L2SRC (element);
 
-  if (GST_ELEMENT_CLASS (parent_class)->change_state) {
-    parent_return =
-        GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-    if (parent_return != GST_STATE_CHANGE_SUCCESS)
-      return parent_return;
-  }
+  /* grab a frame from the device */
+  num = gst_v4l2src_grab_frame (v4l2src);
+  if (num == -1)
+    return GST_FLOW_ERROR;
 
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      if (!gst_v4l2src_get_capture (v4l2src))
-        return GST_STATE_CHANGE_FAILURE;
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      v4l2src->handled = 0;
-      v4l2src->need_writes = 0;
-      v4l2src->substract_time = 0;
-      /* buffer setup moved to capsnego */
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      /* queue all buffer, start streaming capture */
-      if (GST_V4L2ELEMENT (v4l2src)->buffer &&
-          !gst_v4l2src_capture_start (v4l2src))
-        return GST_STATE_CHANGE_FAILURE;
-      g_get_current_time (&time);
-      v4l2src->substract_time = GST_TIMEVAL_TO_TIME (time) -
-          v4l2src->substract_time;
-      v4l2src->last_seq = 0;
-      break;
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      g_get_current_time (&time);
-      v4l2src->substract_time = GST_TIMEVAL_TO_TIME (time) -
-          v4l2src->substract_time;
-      /* de-queue all queued buffers */
-      if (v4l2src->is_capturing && !gst_v4l2src_capture_stop (v4l2src))
-        return GST_STATE_CHANGE_FAILURE;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      /* stop capturing, unmap all buffers */
-      if (GST_V4L2ELEMENT (v4l2src)->buffer &&
-          !gst_v4l2src_capture_deinit (v4l2src))
-        return GST_STATE_CHANGE_FAILURE;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
+  i = v4l2src->format.fmt.pix.sizeimage;
+
+  /* check if this is the last buffer in the queue. If so do a memcpy to put it back asap
+     to avoid framedrops and deadlocks because of stupid elements */
+  if (g_atomic_int_get (&v4l2src->pool->refcount) == v4l2src->breq.count) {
+    GST_LOG_OBJECT (v4l2src, "using memcpy'd buffer");
+    *buf = gst_v4l2src_buffer_new (v4l2src, i, NULL, NULL);
+    memcpy (GST_BUFFER_DATA (*buf), v4l2src->pool->buffers[num].start, i);
+    if (!gst_v4l2src_queue_frame (v4l2src, num)) {
+      gst_buffer_unref (*buf);
+      return GST_FLOW_ERROR;
+    }
+  } else {
+    GST_LOG_OBJECT (v4l2src, "using mmap'd buffer");
+    *buf =
+        gst_v4l2src_buffer_new (v4l2src, i, v4l2src->pool->buffers[num].start,
+        &v4l2src->pool->buffers[num]);
+    /* no need to be careful here, both are > 0, because the element uses them */
+    g_atomic_int_inc (&v4l2src->pool->buffers[num].refcount);
+    g_atomic_int_inc (&v4l2src->pool->refcount);
   }
 
-  return GST_STATE_CHANGE_SUCCESS;
+  return GST_FLOW_OK;
 }
 
-
-static void
-gst_v4l2src_set_clock (GstElement * element, GstClock * clock)
+static GstFlowReturn
+gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
 {
-  GST_V4L2SRC (element)->clock = clock;
+  GstV4l2Src *v4l2src = GST_V4L2SRC (src);
+  GstFlowReturn ret;
+  gint fps_n, fps_d;
+
+  if (v4l2src->use_fixed_fps
+      && gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d) == 0) {
+    GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
+        ("could not get frame rate for element"));
+    return GST_FLOW_ERROR;
+  }
+
+  if (v4l2src->breq.memory == V4L2_MEMORY_MMAP) {
+    ret = gst_v4l2src_get_mmap (v4l2src, buf);
+  } else {
+    ret = gst_v4l2src_get_read (v4l2src, buf);
+  }
+
+  return ret;
 }
index c5aac38..12c3cd4 100644 (file)
@@ -1,5 +1,8 @@
-/* G-Streamer Video4linux2 video-capture plugin
- * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+/* GStreamer
+ *
+ * gstv4l2src.h: BT8x8/V4L2 video source element
+ *
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -20,6 +23,7 @@
 #ifndef __GST_V4L2SRC_H__
 #define __GST_V4L2SRC_H__
 
+
 #include <gstv4l2element.h>
 
 GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
@@ -27,83 +31,86 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
 #define GST_V4L2_MAX_BUFFERS 16
 #define GST_V4L2_MIN_BUFFERS 2
 
-#define GST_TYPE_V4L2SRC \
-                (gst_v4l2src_get_type())
-#define GST_V4L2SRC(obj) \
-                (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2SRC,GstV4l2Src))
-#define GST_V4L2SRC_CLASS(klass) \
-                (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2SRC,GstV4l2SrcClass))
-#define GST_IS_V4L2SRC(obj) \
-                (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC))
-#define GST_IS_V4L2SRC_CLASS(obj) \
-                (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC))
-
-typedef struct _GstV4l2BufferPool       GstV4l2BufferPool;
-typedef struct _GstV4l2Buffer           GstV4l2Buffer;
-typedef struct _GstV4l2Src              GstV4l2Src;
-typedef struct _GstV4l2SrcClass         GstV4l2SrcClass;
+G_BEGIN_DECLS
+
+#define GST_TYPE_V4L2SRC                       \
+  (gst_v4l2src_get_type())
+#define GST_V4L2SRC(obj)                                               \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2SRC,GstV4l2Src))
+#define GST_V4L2SRC_CLASS(klass)                                       \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2SRC,GstV4l2SrcClass))
+#define GST_IS_V4L2SRC(obj)                            \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2SRC))
+#define GST_IS_V4L2SRC_CLASS(obj)                      \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2SRC))
+
+
+typedef struct _GstV4l2BufferPool      GstV4l2BufferPool;
+typedef struct _GstV4l2Buffer          GstV4l2Buffer;
+typedef struct _GstV4l2Src GstV4l2Src;
+typedef struct _GstV4l2SrcClass GstV4l2SrcClass;
+
 
 /* global info */
 struct _GstV4l2BufferPool {
-  GstAtomicInt          refcount; /* number of users: 1 for every buffer, 1 for element */
-  gint                  video_fd;
-  guint                 buffer_count;
-  GstV4l2Buffer *       buffers;
+  gint                 refcount; /* number of users: 1 for every buffer, 1 for element */
+  gint                 video_fd;
+  guint                        buffer_count;
+  GstV4l2Buffer *      buffers;
 };
 
 struct _GstV4l2Buffer {
-  struct v4l2_buffer    buffer;
-  guint8 *              start;
-  guint                 length;
-  GstAtomicInt          refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */
-  GstV4l2BufferPool *   pool;
+  struct v4l2_buffer   buffer;
+  guint8 *             start;
+  guint                        length;
+  gint                 refcount; /* add 1 if in use by element, add 1 if in use by GstBuffer */
+  GstV4l2BufferPool *  pool;
 };
 
-struct _GstV4l2Src {
-        GstV4l2Element v4l2element;
+enum
+  {
+    QUEUE_STATE_ERROR = -1,
+    QUEUE_STATE_READY_FOR_QUEUE,  /* the frame is ready to be queued for capture */
+    QUEUE_STATE_QUEUED,           /* the frame is queued for capture */
+    QUEUE_STATE_SYNCED            /* the frame is captured */
+  };
 
-        /* pads */
-        GstPad *srcpad;
 
-        /* internal lists */
-        GSList *formats; /* list of available capture formats */
+struct _GstV4l2Src
+{
+  GstV4l2Element v4l2element;
 
-        /* buffers */
-        GstV4l2BufferPool *pool;
+  /* pads */
+  GstPad *srcpad;
 
-        struct v4l2_requestbuffers breq;
-        struct v4l2_format format;
+  /* internal lists */
+  GSList *formats; /* list of available capture formats */
 
-        /* True if we want to stop */
-        gboolean quit, is_capturing;
+  /* buffers */
+  GstV4l2BufferPool *pool;
 
-        /* A/V sync... frame counter and internal cache */
-        gulong handled;
-        gint need_writes;
-        GstBuffer *cached_buffer;
-        gulong last_seq;
+  struct v4l2_requestbuffers breq;
+  struct v4l2_format format;
 
-        /* clock */
-        GstClock *clock;
-        
-        /* time to substract from clock time to get back to timestamp */
-        GstClockTime substract_time;
+  /* True if we want to stop */
+  gboolean quit, is_capturing;
 
-        /* how are we going to push buffers? */
-        gboolean use_fixed_fps;
-};
+  gint offset;
 
-struct _GstV4l2SrcClass {
-        GstV4l2ElementClass parent_class;
+  /* how are we going to push buffers? */
+  gboolean use_fixed_fps;
+};
 
-        void (*frame_capture) (GObject *object);
-        void (*frame_drop)    (GObject *object);
-        void (*frame_insert)  (GObject *object);
-        void (*frame_lost)    (GObject *object,
-                               gint     num_lost);
+struct _GstV4l2SrcClass
+{
+  GstV4l2ElementClass parent_class;
 };
 
 
-GType gst_v4l2src_get_type(void);
+GType gst_v4l2src_get_type (void);
+
+
+G_END_DECLS
+
 
 #endif /* __GST_V4L2SRC_H__ */
index 353cbb1..9fb4e3c 100644 (file)
@@ -24,7 +24,6 @@
 #endif
 
 #include <gst/gst.h>
-#include <gst/tuner/tuner.h>
 
 #include "gstv4l2tuner.h"
 #include "gstv4l2element.h"
@@ -156,13 +155,8 @@ gst_v4l2_tuner_interface_init (GstTunerClass * klass)
 static gboolean
 gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
 {
-  const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element));
   GstPadDirection dir = GST_PAD_UNKNOWN;
 
-  /* get direction */
-  if (pads && g_list_length ((GList *) pads) == 1)
-    dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
-
   return (dir == GST_PAD_SINK);
 }
 
@@ -172,7 +166,7 @@ gst_v4l2_tuner_contains_channel (GstV4l2Element * v4l2element,
 {
   const GList *item;
 
-  for (item = v4l2element->channels; item != NULL; item = item->next)
+  for (item = v4l2element->inputs; item != NULL; item = item->next)
     if (item->data == v4l2channel)
       return TRUE;
 
@@ -183,7 +177,7 @@ static const GList *
 gst_v4l2_tuner_list_channels (GstTuner * mixer)
 {
   /* ... or output, if we're a sink... */
-  return GST_V4L2ELEMENT (mixer)->channels;
+  return GST_V4L2ELEMENT (mixer)->inputs;
 }
 
 static void
@@ -201,7 +195,7 @@ gst_v4l2_tuner_set_channel (GstTuner * mixer, GstTunerChannel * channel)
       gst_v4l2_set_output (v4l2element, v4l2channel->index) :
       gst_v4l2_set_input (v4l2element, v4l2channel->index)) {
     gst_tuner_channel_changed (mixer, channel);
-    g_object_notify (G_OBJECT (v4l2element), "channel");
+    g_object_notify (G_OBJECT (v4l2element), "input");
   }
 }
 
@@ -221,7 +215,7 @@ gst_v4l2_tuner_get_channel (GstTuner * mixer)
   else
     gst_v4l2_get_input (v4l2element, &channel);
 
-  for (item = v4l2element->channels; item != NULL; item = item->next) {
+  for (item = v4l2element->inputs; item != NULL; item = item->next) {
     if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index)
       return (GstTunerChannel *) item->data;
   }
@@ -235,7 +229,7 @@ gst_v4l2_tuner_contains_norm (GstV4l2Element * v4l2element,
 {
   const GList *item;
 
-  for (item = v4l2element->norms; item != NULL; item = item->next)
+  for (item = v4l2element->stds; item != NULL; item = item->next)
     if (item->data == v4l2norm)
       return TRUE;
 
@@ -245,7 +239,7 @@ gst_v4l2_tuner_contains_norm (GstV4l2Element * v4l2element,
 static const GList *
 gst_v4l2_tuner_list_norms (GstTuner * mixer)
 {
-  return GST_V4L2ELEMENT (mixer)->norms;
+  return GST_V4L2ELEMENT (mixer)->stds;
 }
 
 static void
@@ -260,7 +254,7 @@ gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm)
 
   if (gst_v4l2_set_norm (v4l2element, v4l2norm->index)) {
     gst_tuner_norm_changed (mixer, norm);
-    g_object_notify (G_OBJECT (v4l2element), "norm");
+    g_object_notify (G_OBJECT (v4l2element), "std");
   }
 }
 
@@ -276,7 +270,7 @@ gst_v4l2_tuner_get_norm (GstTuner * mixer)
 
   gst_v4l2_get_norm (v4l2element, &norm);
 
-  for (item = v4l2element->norms; item != NULL; item = item->next) {
+  for (item = v4l2element->stds; item != NULL; item = item->next) {
     if (norm == GST_V4L2_TUNER_NORM (item->data)->index)
       return (GstTunerNorm *) item->data;
   }
index c51bf19..a7a5f43 100644 (file)
@@ -23,7 +23,7 @@
 #define __GST_V4L2_TUNER_H__
 
 #include <gst/gst.h>
-#include <gst/tuner/tuner.h>
+#include <gst/interfaces/tuner.h>
 
 #include "gstv4l2element.h"
 
@@ -33,10 +33,10 @@ G_BEGIN_DECLS
   (gst_v4l2_tuner_channel_get_type ())
 #define GST_V4L2_TUNER_CHANNEL(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_CHANNEL, \
-                               GstV4l2TunerChannel))
+                              GstV4l2TunerChannel))
 #define GST_V4L2_TUNER_CHANNEL_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_CHANNEL, \
-                            GstV4l2TunerChannelClass))
+                           GstV4l2TunerChannelClass))
 #define GST_IS_V4L2_TUNER_CHANNEL(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_CHANNEL))
 #define GST_IS_V4L2_TUNER_CHANNEL_CLASS(klass) \
@@ -58,10 +58,10 @@ typedef struct _GstV4l2TunerChannelClass {
   (gst_v4l2_tuner_norm_get_type ())
 #define GST_V4L2_TUNER_NORM(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_NORM, \
-                               GstV4l2TunerNorm))
+                              GstV4l2TunerNorm))
 #define GST_V4L2_TUNER_NORM_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_NORM, \
-                            GstV4l2TunerNormClass))
+                           GstV4l2TunerNormClass))
 #define GST_IS_V4L2_TUNER_NORM(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_NORM))
 #define GST_IS_V4L2_TUNER_NORM_CLASS(klass) \
@@ -77,9 +77,9 @@ typedef struct _GstV4l2TunerNormClass {
   GstTunerNormClass parent;
 } GstV4l2TunerNormClass;
 
-GType   gst_v4l2_tuner_channel_get_type (void);
-GType   gst_v4l2_tuner_norm_get_type    (void);
+GType  gst_v4l2_tuner_channel_get_type (void);
+GType  gst_v4l2_tuner_norm_get_type    (void);
 
-void    gst_v4l2_tuner_interface_init   (GstTunerClass *klass);
+void   gst_v4l2_tuner_interface_init   (GstTunerClass *klass);
 
 #endif /* __GST_V4L2_TUNER_H__ */
index 2e416b3..66ea505 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <string.h>
 #include <gst/gst.h>
-#include <gst/xoverlay/xoverlay.h>
 #include <X11/X.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/Xv.h>
@@ -59,13 +58,14 @@ gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass)
       "V4L2 XOverlay interface debugging");
 }
 
-void
+static void
 gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
 {
   struct stat s;
   GstV4l2Xv *v4l2xv;
   const gchar *name = g_getenv ("DISPLAY");
-  int ver, rel, req, ev, err, anum, i, id = 0, first_id = 0, min;
+  unsigned int ver, rel, req, ev, err, anum;
+  int i, id = 0, first_id = 0, min;
   XvAdaptorInfo *ai;
   Display *dpy;
 
@@ -75,6 +75,13 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
     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");
+    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");
@@ -93,7 +100,7 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
   }
   min = s.st_rdev & 0xff;
   for (i = 0; i < anum; i++) {
-    if (!strcmp (ai[i].name, "video4linux")) {
+    if (!strcmp (ai[i].name, "video4linux2")) {
       if (first_id == 0)
         first_id = ai[i].base_id;
 
@@ -123,7 +130,7 @@ gst_v4l2_xoverlay_open (GstV4l2Element * v4l2element)
   }
 }
 
-void
+static void
 gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element)
 {
   GstV4l2Xv *v4l2xv = v4l2element->xv;
@@ -143,6 +150,20 @@ gst_v4l2_xoverlay_close (GstV4l2Element * v4l2element)
   v4l2element->xv = NULL;
 }
 
+void
+gst_v4l2_xoverlay_start (GstV4l2Element * v4l2element)
+{
+  if (v4l2element->xwindow_id) {
+    gst_v4l2_xoverlay_open (v4l2element);
+  }
+}
+
+void
+gst_v4l2_xoverlay_stop (GstV4l2Element * v4l2element)
+{
+  gst_v4l2_xoverlay_close (v4l2element);
+}
+
 static gboolean
 idle_refresh (gpointer data)
 {
@@ -170,12 +191,17 @@ static void
 gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (overlay);
-  GstV4l2Xv *v4l2xv = v4l2element->xv;
+  GstV4l2Xv *v4l2xv;
   XWindowAttributes attr;
   gboolean change = (v4l2element->xwindow_id != xwindow_id);
 
   GST_LOG_OBJECT (v4l2element, "Setting XID to %lx", (gulong) xwindow_id);
 
+  if (!v4l2element->xv && GST_V4L2_IS_OPEN (v4l2element))
+    gst_v4l2_xoverlay_open (v4l2element);
+
+  v4l2xv = v4l2element->xv;
+
   if (v4l2xv)
     g_mutex_lock (v4l2xv->mutex);
 
index a1bf5d7..a0c25ab 100644 (file)
 #define __GST_V4L2_X_OVERLAY_H__
 
 #include <gst/gst.h>
-#include <gst/xoverlay/xoverlay.h>
+#include <gst/interfaces/xoverlay.h>
 
 #include "gstv4l2element.h"
 
 G_BEGIN_DECLS
 
-void    gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass);
+void   gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass);
 
-void    gst_v4l2_xoverlay_open          (GstV4l2Element  *v4l2element);
-void    gst_v4l2_xoverlay_close         (GstV4l2Element  *v4l2element);
+void   gst_v4l2_xoverlay_start         (GstV4l2Element  *v4l2element);
+void   gst_v4l2_xoverlay_stop          (GstV4l2Element  *v4l2element);
 
 #endif /* __GST_V4L2_X_OVERLAY_H__ */
index b4b16d9..a89122f 100644 (file)
 
 #include "gstv4l2src.h"
 
-#define DEBUG(format, args...) \
-        GST_DEBUG_OBJECT (\
-                GST_ELEMENT(v4l2element), \
-                "V4L2: " format, ##args)
-
+GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
+#define GST_CAT_DEFAULT v4l2_debug
 
 /******************************************************
  * gst_v4l2_get_capabilities():
  * return value: TRUE on success, FALSE on error
  ******************************************************/
 
-static gboolean
+gboolean
 gst_v4l2_get_capabilities (GstV4l2Element * v4l2element)
 {
-  DEBUG ("getting capabilities");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("getting capabilities");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Error getting %s capabilities: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_ERROR_OBJECT (v4l2element, "Error getting %s capabilities: %s",
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -75,16 +72,11 @@ static gboolean
 gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
 {
   gint n;
-  const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element));
   GstPadDirection dir = GST_PAD_UNKNOWN;
 
-  DEBUG ("getting enumerations");
+  GST_DEBUG ("getting enumerations");
   GST_V4L2_CHECK_OPEN (v4l2element);
 
-  /* sinks have outputs, all others have inputs */
-  if (pads && g_list_length ((GList *) pads) == 1)
-    dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
-
   if (dir != GST_PAD_SINK) {
     /* and now, the inputs */
     for (n = 0;; n++) {
@@ -99,14 +91,14 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         else {
           GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
               ("Failed to get %d in input enumeration for %s: %s",
-                  n, v4l2element->device, g_strerror (errno)));
+                  n, v4l2element->videodev, g_strerror (errno)));
           return FALSE;
         }
       }
 
       v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
       channel = GST_TUNER_CHANNEL (v4l2channel);
-      channel->label = g_strdup (input.name);
+      channel->label = g_strdup ((const gchar *) input.name);
       channel->flags = GST_TUNER_CHANNEL_INPUT;
       v4l2channel->index = n;
       if (input.type == V4L2_INPUT_TYPE_TUNER) {
@@ -119,7 +111,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
           GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
               ("Failed to get tuner %d settings on %s: %s",
-                  input.tuner, v4l2element->device, g_strerror (errno)));
+                  input.tuner, v4l2element->videodev, g_strerror (errno)));
           g_object_unref (G_OBJECT (channel));
           return FALSE;
         }
@@ -138,8 +130,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         channel->flags |= GST_TUNER_CHANNEL_AUDIO;
       }
 
-      v4l2element->channels =
-          g_list_append (v4l2element->channels, (gpointer) channel);
+      v4l2element->inputs =
+          g_list_append (v4l2element->inputs, (gpointer) channel);
     }
   } else {
     /* outputs */
@@ -155,14 +147,14 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         else {
           GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
               ("Failed to get %d in output enumeration for %s: %s",
-                  n, v4l2element->device, g_strerror (errno)));
+                  n, v4l2element->videodev, g_strerror (errno)));
           return FALSE;
         }
       }
 
       v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
       channel = GST_TUNER_CHANNEL (v4l2channel);
-      channel->label = g_strdup (output.name);
+      channel->label = g_strdup ((const gchar *) output.name);
       channel->flags = GST_TUNER_CHANNEL_OUTPUT;
       v4l2channel->index = n;
       if (output.audioset) {
@@ -173,8 +165,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         channel->flags |= GST_TUNER_CHANNEL_AUDIO;
       }
 
-      v4l2element->channels =
-          g_list_append (v4l2element->channels, (gpointer) channel);
+      v4l2element->inputs =
+          g_list_append (v4l2element->inputs, (gpointer) channel);
     }
   }
 
@@ -191,19 +183,19 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
       else {
         GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
             ("Failed to get %d in norm enumeration for %s: %s",
-                n, v4l2element->device, g_strerror (errno)));
+                n, v4l2element->videodev, g_strerror (errno)));
         return FALSE;
       }
     }
 
     v4l2norm = g_object_new (GST_TYPE_V4L2_TUNER_NORM, NULL);
     norm = GST_TUNER_NORM (v4l2norm);
-    norm->label = g_strdup (standard.name);
-    norm->fps = (gfloat) standard.frameperiod.denominator /
-        standard.frameperiod.numerator;
+    norm->label = g_strdup ((const gchar *) standard.name);
+    gst_value_set_fraction (&norm->framerate,
+        standard.frameperiod.denominator, standard.frameperiod.numerator);
     v4l2norm->index = standard.id;
 
-    v4l2element->norms = g_list_append (v4l2element->norms, (gpointer) norm);
+    v4l2element->stds = g_list_append (v4l2element->stds, (gpointer) norm);
   }
 
   /* and lastly, controls+menus (if appropriate) */
@@ -226,7 +218,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
       } else {
         GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
             ("Failed to get %d in control enumeration for %s: %s",
-                n, v4l2element->device, g_strerror (errno)));
+                n, v4l2element->videodev, g_strerror (errno)));
         return FALSE;
       }
     }
@@ -250,7 +242,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
         /* we only handle these for now */
         break;
       default:
-        DEBUG ("ControlID %s (%d) unhandled, FIXME", control.name, n);
+        GST_DEBUG ("ControlID %s (%d) unhandled, FIXME", control.name, n);
         control.id++;
         break;
     }
@@ -259,7 +251,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
 
     v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
     channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
-    channel->label = g_strdup (control.name);
+    channel->label = g_strdup ((const gchar *) control.name);
     v4l2channel->index = n;
 
 #if 0
@@ -276,7 +268,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
           else {
             GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
                 ("Failed to get %d in menu enumeration for %s: %s",
-                    n, v4l2element->device, g_strerror (errno)));
+                    n, v4l2element->videodev, g_strerror (errno)));
             return FALSE;
           }
         }
@@ -313,15 +305,15 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
 static void
 gst_v4l2_empty_lists (GstV4l2Element * v4l2element)
 {
-  DEBUG ("deleting enumerations");
+  GST_DEBUG ("deleting enumerations");
 
-  g_list_foreach (v4l2element->channels, (GFunc) g_object_unref, NULL);
-  g_list_free (v4l2element->channels);
-  v4l2element->channels = NULL;
+  g_list_foreach (v4l2element->inputs, (GFunc) g_object_unref, NULL);
+  g_list_free (v4l2element->inputs);
+  v4l2element->inputs = NULL;
 
-  g_list_foreach (v4l2element->norms, (GFunc) g_object_unref, NULL);
-  g_list_free (v4l2element->norms);
-  v4l2element->norms = NULL;
+  g_list_foreach (v4l2element->stds, (GFunc) g_object_unref, NULL);
+  g_list_free (v4l2element->stds);
+  v4l2element->stds = NULL;
 
   g_list_foreach (v4l2element->colors, (GFunc) g_object_unref, NULL);
   g_list_free (v4l2element->colors);
@@ -337,27 +329,27 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element)
   GstTunerChannel *channel = NULL;
   GstTuner *tuner = GST_TUNER (v4l2element);
 
-  if (v4l2element->norm)
-    norm = gst_tuner_find_norm_by_name (tuner, v4l2element->norm);
+  if (v4l2element->std)
+    norm = gst_tuner_find_norm_by_name (tuner, v4l2element->std);
   if (norm) {
     gst_tuner_set_norm (tuner, norm);
   } else {
     norm = GST_TUNER_NORM (gst_tuner_get_norm (GST_TUNER (v4l2element)));
-    v4l2element->norm = g_strdup (norm->label);
+    v4l2element->std = g_strdup (norm->label);
     gst_tuner_norm_changed (tuner, norm);
-    g_object_notify (G_OBJECT (v4l2element), "norm");
+    g_object_notify (G_OBJECT (v4l2element), "std");
   }
 
-  if (v4l2element->channel)
-    channel = gst_tuner_find_channel_by_name (tuner, v4l2element->channel);
+  if (v4l2element->input)
+    channel = gst_tuner_find_channel_by_name (tuner, v4l2element->input);
   if (channel) {
     gst_tuner_set_channel (tuner, channel);
   } else {
     channel =
         GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER (v4l2element)));
-    v4l2element->channel = g_strdup (channel->label);
+    v4l2element->input = g_strdup (channel->label);
     gst_tuner_channel_changed (tuner, channel);
-    g_object_notify (G_OBJECT (v4l2element), "channel");
+    g_object_notify (G_OBJECT (v4l2element), "input");
   }
 
   if (GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
@@ -378,27 +370,27 @@ gst_v4l2_set_defaults (GstV4l2Element * v4l2element)
 
 /******************************************************
  * gst_v4l2_open():
- *   open the video device (v4l2element->device)
+ *   open the video device (v4l2element->videodev)
  * return value: TRUE on success, FALSE on error
  ******************************************************/
 
 gboolean
 gst_v4l2_open (GstV4l2Element * v4l2element)
 {
-  DEBUG ("Trying to open device %s", v4l2element->device);
+  GST_DEBUG ("Trying to open device %s", v4l2element->videodev);
   GST_V4L2_CHECK_NOT_OPEN (v4l2element);
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
 
   /* be sure we have a device */
-  if (!v4l2element->device)
-    v4l2element->device = g_strdup ("/dev/video");
+  if (!v4l2element->videodev)
+    v4l2element->videodev = g_strdup ("/dev/video");
 
   /* open the device */
-  v4l2element->video_fd = open (v4l2element->device, O_RDWR);
+  v4l2element->video_fd = open (v4l2element->videodev, O_RDWR);
   if (!GST_V4L2_IS_OPEN (v4l2element)) {
     GST_ELEMENT_ERROR (v4l2element, RESOURCE, OPEN_READ_WRITE,
         (_("Could not open device \"%s\" for reading and writing."),
-            v4l2element->device), GST_ERROR_SYSTEM);
+            v4l2element->videodev), GST_ERROR_SYSTEM);
     goto error;
   }
 
@@ -411,7 +403,7 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
   if (GST_IS_V4L2SRC (v4l2element) &&
       !(v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
     GST_ELEMENT_ERROR (v4l2element, RESOURCE, NOT_FOUND,
-        (_("Device \"%s\" is not a capture device."), v4l2element->device),
+        (_("Device \"%s\" is not a capture device."), v4l2element->videodev),
         ("Capabilities: 0x%x", v4l2element->vcap.capabilities));
     goto error;
   }
@@ -424,7 +416,7 @@ gst_v4l2_open (GstV4l2Element * v4l2element)
   gst_v4l2_set_defaults (v4l2element);
 
   GST_INFO_OBJECT (v4l2element, "Opened device '%s' (%s) successfully\n",
-      v4l2element->vcap.card, v4l2element->device);
+      v4l2element->vcap.card, v4l2element->videodev);
 
   return TRUE;
 
@@ -450,7 +442,7 @@ error:
 gboolean
 gst_v4l2_close (GstV4l2Element * v4l2element)
 {
-  DEBUG ("Trying to close %s", v4l2element->device);
+  GST_DEBUG ("Trying to close %s", v4l2element->videodev);
   GST_V4L2_CHECK_OPEN (v4l2element);
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
 
@@ -474,13 +466,14 @@ gst_v4l2_close (GstV4l2Element * v4l2element)
 gboolean
 gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
 {
-  DEBUG ("getting norm");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("getting norm");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get the current norm for device %s: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get the current norm for device %s: %s",
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -497,14 +490,16 @@ gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
 gboolean
 gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
 {
-  DEBUG ("trying to set norm to %llx", norm);
-  GST_V4L2_CHECK_OPEN (v4l2element);
-  GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
+  GST_DEBUG ("trying to set norm to %llx", norm);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+  if (!GST_V4L2_IS_ACTIVE (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to set norm 0x%llx for device %s: %s",
-            norm, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to set norm 0x%llx for device %s: %s", norm,
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -523,13 +518,14 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
 {
   gint n;
 
-  DEBUG ("trying to get input");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("trying to get input");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get current input on device %s: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get current input on device %s: %s", v4l2element->videodev,
+        g_strerror (errno));
     return FALSE;
   }
 
@@ -548,14 +544,15 @@ gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
 gboolean
 gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
 {
-  DEBUG ("trying to set input to %d", input);
-  GST_V4L2_CHECK_OPEN (v4l2element);
-  GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
+  GST_DEBUG ("trying to set input to %d", input);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+  if (!GST_V4L2_IS_ACTIVE (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to set input %d on device %s: %s",
-            input, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element, "Failed to set input %d on device %s: %s",
+        input, v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -574,13 +571,14 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
 {
   gint n;
 
-  DEBUG ("trying to get output");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("trying to get output");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get current output on device %s: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get current output on device %s: %s", v4l2element->videodev,
+        g_strerror (errno));
     return FALSE;
   }
 
@@ -599,14 +597,16 @@ gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
 gboolean
 gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
 {
-  DEBUG ("trying to set output to %d", output);
-  GST_V4L2_CHECK_OPEN (v4l2element);
-  GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
+  GST_DEBUG ("trying to set output to %d", output);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+  if (!GST_V4L2_IS_ACTIVE (v4l2element))
+    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to set output %d on device %s: %s",
-            output, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to set current output on device %s to %d: %s",
+        v4l2element->videodev, output, g_strerror (errno));
     return FALSE;
   }
 
@@ -627,16 +627,17 @@ gst_v4l2_get_frequency (GstV4l2Element * v4l2element,
   struct v4l2_frequency freq;
   GstTunerChannel *channel;
 
-  DEBUG ("getting current tuner frequency");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("getting current tuner frequency");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
 
   freq.tuner = tunernum;
   if (ioctl (v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get current tuner frequency for device %s: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get current tuner frequency for device %s: %s",
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -659,9 +660,11 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
   struct v4l2_frequency freq;
   GstTunerChannel *channel;
 
-  DEBUG ("setting current tuner frequency to %lu", frequency);
-  GST_V4L2_CHECK_OPEN (v4l2element);
-  GST_V4L2_CHECK_NOT_ACTIVE (v4l2element);
+  GST_DEBUG ("setting current tuner frequency to %lu", frequency);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+  if (!GST_V4L2_IS_ACTIVE (v4l2element))
+    return FALSE;
 
   channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
 
@@ -671,9 +674,9 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
   freq.frequency = frequency / channel->freq_multiplicator;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to set tuner frequency to %lu for device %s: %s",
-            frequency, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to set current tuner frequency for device %s to %lu: %s",
+        v4l2element->videodev, frequency, g_strerror (errno));
     return FALSE;
   }
 
@@ -693,14 +696,15 @@ gst_v4l2_signal_strength (GstV4l2Element * v4l2element,
 {
   struct v4l2_tuner tuner;
 
-  DEBUG ("trying to get signal strength");
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  GST_DEBUG ("trying to get signal strength");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
   tuner.index = tunernum;
   if (ioctl (v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get signal strength for device %s: %s",
-            v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get signal strength for device %s: %s",
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -722,16 +726,17 @@ gst_v4l2_get_attribute (GstV4l2Element * v4l2element,
 {
   struct v4l2_control control;
 
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
-  DEBUG ("getting value of attribute %d", attribute_num);
+  GST_DEBUG ("getting value of attribute %d", attribute_num);
 
   control.id = attribute_num;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to get value for control %d on device %s: %s",
-            attribute_num, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get value for control %d on device %s: %s", attribute_num,
+        v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
@@ -753,17 +758,18 @@ gst_v4l2_set_attribute (GstV4l2Element * v4l2element,
 {
   struct v4l2_control control;
 
-  GST_V4L2_CHECK_OPEN (v4l2element);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
 
-  DEBUG ("setting value of attribute %d to %d", attribute_num, value);
+  GST_DEBUG ("setting value of attribute %d to %d", attribute_num, value);
 
   control.id = attribute_num;
   control.value = value;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
-    GST_ELEMENT_ERROR (v4l2element, RESOURCE, SETTINGS, (NULL),
-        ("Failed to set value %d for control %d on device %s: %s",
-            value, attribute_num, v4l2element->device, g_strerror (errno)));
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to set value %d for control %d on device %s: %s", value,
+        attribute_num, v4l2element->videodev, g_strerror (errno));
     return FALSE;
   }
 
index 5325ead..fcacf35 100644 (file)
 
 /* simple check whether the device is open */
 #define GST_V4L2_IS_OPEN(element) \
-  (element->video_fd > 0)
+  (GST_V4L2ELEMENT(element)->video_fd > 0)
 
 /* check whether the device is 'active' */
 #define GST_V4L2_IS_ACTIVE(element) \
-  (element->buffer != NULL)
+  (GST_V4L2ELEMENT(element)->buffer != NULL)
 
 #define GST_V4L2_IS_OVERLAY(element) \
-  (element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
+  (GST_V4L2ELEMENT(element)->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY)
 
 /* checks whether the current v4lelement has already been open()'ed or not */
-#define GST_V4L2_CHECK_OPEN(element)                            \
-  if (!GST_V4L2_IS_OPEN(element))                               \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
+#define GST_V4L2_CHECK_OPEN(element)                           \
+  if (!GST_V4L2_IS_OPEN(element))                              \
+  {                                                            \
+    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,            \
       (_("Device is not open.")), (NULL));                      \
-    return FALSE;                                               \
+    return FALSE;                                              \
   }
 
 /* checks whether the current v4lelement is close()'ed or whether it is still open */
-#define GST_V4L2_CHECK_NOT_OPEN(element)                        \
-  if (GST_V4L2_IS_OPEN(element))                                \
-  {                                                             \
-    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
+#define GST_V4L2_CHECK_NOT_OPEN(element)                       \
+  if (GST_V4L2_IS_OPEN(element))                               \
+  {                                                            \
+    GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,            \
       (_("Device is open.")), (NULL));                          \
-    return FALSE;                                               \
+    return FALSE;                                              \
   }
 
 /* checks whether the current v4lelement does video overlay */
-#define GST_V4L2_CHECK_OVERLAY(element)                         \
-  if (!GST_V4L2_IS_OVERLAY(element))                            \
-  {                                                             \
+#define GST_V4L2_CHECK_OVERLAY(element)                                \
+  if (!GST_V4L2_IS_OVERLAY(element))                           \
+  {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,             \
       (NULL), ("Device cannot handle overlay"));                \
-    return FALSE;                                               \
+    return FALSE;                                              \
   }
 
 /* checks whether we're in capture mode or not */
-#define GST_V4L2_CHECK_ACTIVE(element)                          \
-  if (!GST_V4L2_IS_ACTIVE(element))                             \
-  {                                                             \
+#define GST_V4L2_CHECK_ACTIVE(element)                         \
+  if (!GST_V4L2_IS_ACTIVE(element))                            \
+  {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,             \
       (NULL), ("Device is not in streaming mode"));             \
-    return FALSE;                                               \
+    return FALSE;                                              \
   }
 
 /* checks whether we're out of capture mode or not */
-#define GST_V4L2_CHECK_NOT_ACTIVE(element)                      \
-  if (GST_V4L2_IS_ACTIVE(element))                              \
-  {                                                             \
+#define GST_V4L2_CHECK_NOT_ACTIVE(element)                     \
+  if (GST_V4L2_IS_ACTIVE(element))                             \
+  {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,             \
       (NULL), ("Device is in streaming mode"));                 \
-    return FALSE;                                               \
+    return FALSE;                                              \
   }
 
 
 /* open/close the device */
-gboolean        gst_v4l2_open                   (GstV4l2Element *v4l2element);
-gboolean        gst_v4l2_close                  (GstV4l2Element *v4l2element);
+gboolean       gst_v4l2_open                   (GstV4l2Element *v4l2element);
+gboolean       gst_v4l2_close                  (GstV4l2Element *v4l2element);
 
 /* norm/input/output */
-gboolean        gst_v4l2_get_norm               (GstV4l2Element *v4l2element,
-                                                 v4l2_std_id    *norm);
-gboolean        gst_v4l2_set_norm               (GstV4l2Element *v4l2element,
-                                                 v4l2_std_id     norm);
-gboolean        gst_v4l2_get_input              (GstV4l2Element *v4l2element,
-                                                 gint           *input);
-gboolean        gst_v4l2_set_input              (GstV4l2Element *v4l2element,
-                                                 gint            input);
-gboolean        gst_v4l2_get_output             (GstV4l2Element *v4l2element,
-                                                 gint           *output);
-gboolean        gst_v4l2_set_output             (GstV4l2Element *v4l2element,
-                                                 gint            output);
+gboolean       gst_v4l2_get_norm               (GstV4l2Element *v4l2element,
+                                                v4l2_std_id    *norm);
+gboolean       gst_v4l2_set_norm               (GstV4l2Element *v4l2element,
+                                                v4l2_std_id     norm);
+gboolean       gst_v4l2_get_input              (GstV4l2Element *v4l2element,
+                                                gint           *input);
+gboolean       gst_v4l2_set_input              (GstV4l2Element *v4l2element,
+                                                gint            input);
+gboolean       gst_v4l2_get_output             (GstV4l2Element *v4l2element,
+                                                gint           *output);
+gboolean       gst_v4l2_set_output             (GstV4l2Element *v4l2element,
+                                                gint            output);
 
 /* frequency control */
-gboolean        gst_v4l2_get_frequency          (GstV4l2Element *v4l2element,
-                                                 gint            tunernum,
-                                                 gulong         *frequency);
-gboolean        gst_v4l2_set_frequency          (GstV4l2Element *v4l2element,
-                                                 gint            tunernum,
-                                                 gulong          frequency);
-gboolean        gst_v4l2_signal_strength        (GstV4l2Element *v4l2element,
-                                                 gint            tunernum,
-                                                 gulong         *signal);
+gboolean       gst_v4l2_get_frequency          (GstV4l2Element *v4l2element,
+                                                gint            tunernum,
+                                                gulong         *frequency);
+gboolean       gst_v4l2_set_frequency          (GstV4l2Element *v4l2element,
+                                                gint            tunernum,
+                                                gulong          frequency);
+gboolean       gst_v4l2_signal_strength        (GstV4l2Element *v4l2element,
+                                                gint            tunernum,
+                                                gulong         *signal);
 
 /* attribute control */
-gboolean        gst_v4l2_get_attribute          (GstV4l2Element *v4l2element,
-                                                 int             attribute,
-                                                 int            *value);
-gboolean        gst_v4l2_set_attribute          (GstV4l2Element *v4l2element,
-                                                 int             attribute,
-                                                 const int       value);
+gboolean       gst_v4l2_get_attribute          (GstV4l2Element *v4l2element,
+                                                int             attribute,
+                                                int            *value);
+gboolean       gst_v4l2_set_attribute          (GstV4l2Element *v4l2element,
+                                                int             attribute,
+                                                const int       value);
+
+gboolean        gst_v4l2_get_capabilities       (GstV4l2Element * v4l2element);
 
 #endif /* __V4L2_CALLS_H__ */
index 6971733..ae27de1 100644 (file)
@@ -33,6 +33,9 @@
 #include <sys/time.h>
 #include <unistd.h>
 
+#include "gstv4l2tuner.h"
+
+GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
 #define GST_CAT_DEFAULT v4l2src_debug
 
 /* lalala... */
@@ -40,9 +43,9 @@
 #define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
 
 #define DEBUG(format, args...) \
-        GST_CAT_DEBUG_OBJECT (\
-                v4l2src_debug, v4l2src, \
-                "V4L2SRC: " format, ##args)
+       GST_CAT_DEBUG_OBJECT (\
+               v4l2src_debug, v4l2src, \
+               "V4L2SRC: " format, ##args)
 
 /* On some systems MAP_FAILED seems to be missing */
 #ifndef MAP_FAILED
@@ -76,12 +79,12 @@ gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
       } else {
         GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
             ("failed to get number %d in pixelformat enumeration for %s: %s",
-                n, GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
+                n, GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
         g_free (format);
         return FALSE;
       }
     }
-    GST_LOG_OBJECT (v4l2src, "got format %" GST_FOURCC_FORMAT,
+    GST_LOG_OBJECT (v4l2src, "got format" GST_FOURCC_FORMAT,
         GST_FOURCC_ARGS (format->pixelformat));
     v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
   }
@@ -122,7 +125,7 @@ gst_v4l2src_queue_frame (GstV4l2Src * v4l2src, guint i)
           &v4l2src->pool->buffers[i].buffer) < 0) {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, WRITE,
         (_("Could not write to device \"%s\"."),
-            GST_V4L2ELEMENT (v4l2src)->device),
+            GST_V4L2ELEMENT (v4l2src)->videodev),
         ("Error queueing buffer %u on device %s", i, g_strerror (errno)));
     return FALSE;
   }
@@ -145,13 +148,46 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src)
   buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   while (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0) {
     /* if the sync() got interrupted, we can retry */
-    if (errno != EINTR) {
-      GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
-          ("could not sync on a buffer on device %s: %s",
-              GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
-      return -1;
+    switch (errno) {
+      case EAGAIN:
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("Non-blocking I/O has been selected using O_NONBLOCK and"
+                " no buffer was in the outgoing queue. device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        break;
+      case EINVAL:
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("The buffer type is not supported, or the index is out of bounds,"
+                " or no buffers have been allocated yet, or the userptr"
+                " or length are invalid. device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        break;
+      case ENOMEM:
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("isufficient memory to enqueue a user pointer buffer. device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        break;
+      case EIO:
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("VIDIOC_DQBUF failed due to an internal error."
+                " Can also indicate temporary problems like signal loss."
+                " Note the driver might dequeue an (empty) buffer despite"
+                " returning an error, or even stop capturing."
+                " device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        break;
+      case EINTR:
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, SYNC, (NULL),
+            ("could not sync on a buffer on device %s: %s",
+                GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+        break;
+      default:
+        GST_DEBUG_OBJECT (v4l2src, "grab got interrupted");
+        break;
     }
-    GST_DEBUG_OBJECT (v4l2src, "grab got interrupted");
+
+    return -1;
+
   }
 
   GST_LOG_OBJECT (v4l2src, "grabbed frame %d", buffer.index);
@@ -178,7 +214,7 @@ gst_v4l2src_get_capture (GstV4l2Src * v4l2src)
           &v4l2src->format) < 0) {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
         ("failed to get pixelformat for device %s: %s",
-            GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
+            GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
     return FALSE;
   }
 
@@ -213,8 +249,8 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
           &v4l2src->format) < 0) {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
         ("failed to set pixelformat to %s @ %dx%d for device %s: %s",
-            fmt->description, width, height, GST_V4L2ELEMENT (v4l2src)->device,
-            g_strerror (errno)));
+            fmt->description, width, height,
+            GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
     return FALSE;
   }
 
@@ -249,72 +285,92 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
     v4l2src->breq.count = GST_V4L2_MIN_BUFFERS;
   }
   v4l2src->breq.type = v4l2src->format.type;
-  v4l2src->breq.memory = V4L2_MEMORY_MMAP;
-  if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS,
-          &v4l2src->breq) < 0) {
+  if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_STREAMING) {
+    v4l2src->breq.memory = V4L2_MEMORY_MMAP;
+    if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_REQBUFS,
+            &v4l2src->breq) < 0) {
+      GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+          (_("Could not get buffers from device \"%s\"."),
+              GST_V4L2ELEMENT (v4l2src)->videodev),
+          ("error requesting %d buffers: %s", v4l2src->breq.count,
+              g_strerror (errno)));
+      return FALSE;
+    }
+    GST_LOG_OBJECT (v4l2src, "using default mmap method");
+  } else if (GST_V4L2ELEMENT (v4l2src)->vcap.capabilities & V4L2_CAP_READWRITE) {
+    v4l2src->breq.memory = 0;
+    GST_INFO_OBJECT (v4l2src, "using fallback read method");
+  } else {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
-        (_("Could not get buffers from device \"%s\"."),
-            GST_V4L2ELEMENT (v4l2src)->device),
-        ("error requesting %d buffers: %s", v4l2src->breq.count,
-            g_strerror (errno)));
+        (_("the driver of device \"%s\" is broken."),
+            GST_V4L2ELEMENT (v4l2src)->videodev),
+        ("no supported read capability from %s",
+            GST_V4L2ELEMENT (v4l2src)->videodev));
     return FALSE;
   }
 
-  if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
-        (_("Could not get enough buffers from device \"%s\"."),
-            GST_V4L2ELEMENT (v4l2src)->device),
-        ("we received %d, we want at least %d", v4l2src->breq.count,
-            GST_V4L2_MIN_BUFFERS));
-    v4l2src->breq.count = buffers;
-    return FALSE;
-  }
-  if (v4l2src->breq.count != buffers)
-    g_object_notify (G_OBJECT (v4l2src), "num_buffers");
-
-  GST_INFO_OBJECT (v4l2src,
-      "Got %d buffers (%" GST_FOURCC_FORMAT ") of size %d KB\n",
-      v4l2src->breq.count,
-      GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat),
-      v4l2src->format.fmt.pix.sizeimage / 1024);
-
-  /* Map the buffers */
-  v4l2src->pool = g_new (GstV4l2BufferPool, 1);
-  gst_atomic_int_init (&v4l2src->pool->refcount, 1);
-  v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd;
-  v4l2src->pool->buffer_count = v4l2src->breq.count;
-  v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count);
-
-  for (n = 0; n < v4l2src->breq.count; n++) {
-    GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n];
-
-    gst_atomic_int_init (&buffer->refcount, 1);
-    buffer->pool = v4l2src->pool;
-    buffer->buffer.index = n;
-    buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF,
-            &buffer->buffer) < 0) {
-      GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
-          ("Could not get buffer properties of buffer %d: %s", n,
-              g_strerror (errno)));
-      gst_v4l2src_capture_deinit (v4l2src);
+  if (v4l2src->breq.memory > 0) {
+    if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
+      GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+          (_("Could not get enough buffers from device \"%s\"."),
+              GST_V4L2ELEMENT (v4l2src)->videodev),
+          ("we received %d, we want at least %d", v4l2src->breq.count,
+              GST_V4L2_MIN_BUFFERS));
+      v4l2src->breq.count = buffers;
       return FALSE;
     }
-    buffer->start =
-        mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
-        GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset);
-    if (buffer->start == MAP_FAILED) {
-      GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
-          ("Could not mmap video buffer %d: %s", n, g_strerror (errno)));
-      buffer->start = 0;
-      gst_v4l2src_capture_deinit (v4l2src);
-      return FALSE;
-    }
-    buffer->length = buffer->buffer.length;
-    if (!gst_v4l2src_queue_frame (v4l2src, n)) {
-      gst_v4l2src_capture_deinit (v4l2src);
-      return FALSE;
+    if (v4l2src->breq.count != buffers)
+      g_object_notify (G_OBJECT (v4l2src), "num_buffers");
+
+    GST_INFO_OBJECT (v4l2src,
+        "Got %d buffers (" GST_FOURCC_FORMAT ") of size %d KB\n",
+        v4l2src->breq.count,
+        GST_FOURCC_ARGS (v4l2src->format.fmt.pix.pixelformat),
+        v4l2src->format.fmt.pix.sizeimage / 1024);
+
+    /* Map the buffers */
+    GST_LOG_OBJECT (v4l2src, "initiating buffer pool");
+
+    v4l2src->pool = g_new (GstV4l2BufferPool, 1);
+    g_atomic_int_set (&v4l2src->pool->refcount, 1);
+    v4l2src->pool->video_fd = GST_V4L2ELEMENT (v4l2src)->video_fd;
+    v4l2src->pool->buffer_count = v4l2src->breq.count;
+    v4l2src->pool->buffers = g_new0 (GstV4l2Buffer, v4l2src->breq.count);
+
+    for (n = 0; n < v4l2src->breq.count; n++) {
+      GstV4l2Buffer *buffer = &v4l2src->pool->buffers[n];
+
+      g_atomic_int_set (&buffer->refcount, 1);
+      buffer->pool = v4l2src->pool;
+      buffer->buffer.index = n;
+      buffer->buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+      if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_QUERYBUF,
+              &buffer->buffer) < 0) {
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
+            ("Could not get buffer properties of buffer %d: %s", n,
+                g_strerror (errno)));
+        gst_v4l2src_capture_deinit (v4l2src);
+        return FALSE;
+      }
+      buffer->start =
+          mmap (0, buffer->buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
+          GST_V4L2ELEMENT (v4l2src)->video_fd, buffer->buffer.m.offset);
+      if (buffer->start == MAP_FAILED) {
+        GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
+            ("Could not mmap video buffer %d: %s", n, g_strerror (errno)));
+        buffer->start = 0;
+        gst_v4l2src_capture_deinit (v4l2src);
+        return FALSE;
+      }
+      buffer->length = buffer->buffer.length;
+      if (!gst_v4l2src_queue_frame (v4l2src, n)) {
+        gst_v4l2src_capture_deinit (v4l2src);
+        return FALSE;
+      }
     }
+  } else {
+    GST_LOG_OBJECT (v4l2src, "no buffer pool used");
+    v4l2src->pool = NULL;
   }
 
   GST_V4L2_SET_ACTIVE (GST_V4L2ELEMENT (v4l2src));
@@ -338,17 +394,19 @@ gst_v4l2src_capture_start (GstV4l2Src * v4l2src)
 
   GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
   if (!GST_V4L2_IS_ACTIVE (GST_V4L2ELEMENT (v4l2src))) {
-    gst_pad_renegotiate (v4l2src->srcpad);
+    /* gst_pad_renegotiate (v4l2src->srcpad); FIX: is it still required in 0.10 */
   }
   GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
 
   v4l2src->quit = FALSE;
 
-  if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL),
-        ("Error starting streaming capture from device %s: %s",
-            GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
-    return FALSE;
+  if (v4l2src->breq.memory != 0) {
+    if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMON, &type) < 0) {
+      GST_ELEMENT_ERROR (v4l2src, RESOURCE, OPEN_READ, (NULL),
+          ("Error starting streaming capture from device %s: %s",
+              GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+      return FALSE;
+    }
   }
 
   v4l2src->is_capturing = TRUE;
@@ -372,13 +430,16 @@ gst_v4l2src_capture_stop (GstV4l2Src * v4l2src)
   GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
   GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
 
-  /* we actually need to sync on all queued buffers but not
-   * on the non-queued ones */
-  if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF, &type) < 0) {
-    GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL),
-        ("Error stopping streaming capture from device %s: %s",
-            GST_V4L2ELEMENT (v4l2src)->device, g_strerror (errno)));
-    return FALSE;
+  if (v4l2src->breq.memory != 0) {
+    /* we actually need to sync on all queued buffers but not
+     * on the non-queued ones */
+    if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_STREAMOFF,
+            &type) < 0) {
+      GST_ELEMENT_ERROR (v4l2src, RESOURCE, CLOSE, (NULL),
+          ("Error stopping streaming capture from device %s: %s",
+              GST_V4L2ELEMENT (v4l2src)->videodev, g_strerror (errno)));
+      return FALSE;
+    }
   }
 
   /* make an optional pending wait stop */
@@ -394,16 +455,18 @@ gst_v4l2src_buffer_pool_free (GstV4l2BufferPool * pool, gboolean do_close)
   guint i;
 
   for (i = 0; i < pool->buffer_count; i++) {
-    gst_atomic_int_destroy (&pool->buffers[i].refcount);
+    g_atomic_int_set (&pool->buffers[i].refcount, 0);
     munmap (pool->buffers[i].start, pool->buffers[i].length);
   }
   g_free (pool->buffers);
-  gst_atomic_int_destroy (&pool->refcount);
+  g_atomic_int_set (&pool->refcount, 0);
   if (do_close)
     close (pool->video_fd);
   g_free (pool);
 }
 
+#if 0
+
 void
 gst_v4l2src_free_buffer (GstBuffer * buffer)
 {
@@ -411,18 +474,21 @@ gst_v4l2src_free_buffer (GstBuffer * buffer)
 
   GST_LOG ("freeing buffer %p (nr. %d)", buffer, buf->buffer.index);
 
-  if (!gst_atomic_int_dec_and_test (&buf->refcount)) {
+  if (!g_atomic_int_dec_and_test (&buf->refcount)) {
     /* we're still in use, add to queue again 
        note: this might fail because the device is already stopped (race) */
     if (ioctl (buf->pool->video_fd, VIDIOC_QBUF, &buf->buffer) < 0)
       GST_INFO ("readding to queue failed, assuming video device is stopped");
   }
-  if (gst_atomic_int_dec_and_test (&buf->pool->refcount)) {
+  if (g_atomic_int_dec_and_test (&buf->pool->refcount)) {
     /* we're last thing that used all this */
     gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
   }
 }
 
+
+#endif
+
 /******************************************************
  * gst_v4l2src_capture_deinit():
  *   deinitialize the capture system
@@ -432,31 +498,44 @@ gst_v4l2src_free_buffer (GstBuffer * buffer)
 gboolean
 gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
 {
-  gint i, dequeue = 0;
+  gint i;
+  gboolean try_reinit = FALSE;
 
   GST_DEBUG_OBJECT (v4l2src, "deinitting capture system");
 
   GST_V4L2_CHECK_OPEN (GST_V4L2ELEMENT (v4l2src));
   GST_V4L2_CHECK_ACTIVE (GST_V4L2ELEMENT (v4l2src));
 
-  /* free the buffers */
-  for (i = 0; i < v4l2src->breq.count; i++) {
-    if (gst_atomic_int_dec_and_test (&v4l2src->pool->buffers[i].refcount))
-      dequeue++;
-  }
-  for (i = 0; i < dequeue; i++) {
-    struct v4l2_buffer buffer;
-
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF, &buffer) < 0)
-      GST_WARNING_OBJECT (v4l2src,
-          "Could not dequeue buffer on uninitialization");
-  }
-  if (gst_atomic_int_dec_and_test (&v4l2src->pool->refcount)) {
-    /* we're last thing that used all this */
-    gst_v4l2src_buffer_pool_free (v4l2src->pool, FALSE);
+  if (v4l2src->pool) {
+    /* free the buffers */
+    for (i = 0; i < v4l2src->breq.count; i++) {
+      if (g_atomic_int_dec_and_test (&v4l2src->pool->buffers[i].refcount)) {
+        if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_DQBUF,
+                &v4l2src->pool->buffers[i].buffer) < 0)
+          GST_WARNING_OBJECT (v4l2src,
+              "Could not dequeue buffer on uninitialization: %s - will try reinit instead",
+              g_strerror (errno));
+        try_reinit = TRUE;
+      }
+    }
+    if (g_atomic_int_dec_and_test (&v4l2src->pool->refcount)) {
+      /* we're last thing that used all this */
+      gst_v4l2src_buffer_pool_free (v4l2src->pool, FALSE);
+    }
+    v4l2src->pool = NULL;
+    /* This is our second try to get the buffers dequeued.
+     * Since buffers are normally dequeued automatically when capturing is
+     * stopped, but may be enqueued before capturing has started, you get
+     * a problem when you abort before capturing started but have enqueued
+     * the buffers. We avoid that by starting/stopping capturing once so
+     * they get auto-dequeued.
+     */
+    if (try_reinit) {
+      if (!gst_v4l2src_capture_start (v4l2src) ||
+          !gst_v4l2src_capture_stop (v4l2src))
+        return FALSE;
+    }
   }
-  v4l2src->pool = NULL;
 
   GST_V4L2_SET_INACTIVE (GST_V4L2ELEMENT (v4l2src));
   return TRUE;
@@ -474,8 +553,7 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
 {
   struct v4l2_format fmt;
 
-  GST_LOG_OBJECT (v4l2src,
-      "getting size limits with format %" GST_FOURCC_FORMAT,
+  GST_LOG_OBJECT (v4l2src, "getting size limits with format " GST_FOURCC_FORMAT,
       GST_FOURCC_ARGS (format->pixelformat));
 
   /* get size delimiters */
@@ -511,3 +589,212 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
 
   return TRUE;
 }
+
+gboolean
+gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d)
+{
+  v4l2_std_id std;
+  const GList *item;
+
+  if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src)))
+    return FALSE;
+
+  if (!gst_v4l2_get_norm (GST_V4L2ELEMENT (v4l2src), &std))
+    return FALSE;
+  for (item = GST_V4L2ELEMENT (v4l2src)->stds; item != NULL; item = item->next) {
+    GstV4l2TunerNorm *v4l2norm = item->data;
+
+    if (v4l2norm->index == std) {
+      *fps_n =
+          gst_value_get_fraction_numerator (&GST_TUNER_NORM (v4l2norm)->
+          framerate);
+      *fps_d =
+          gst_value_get_fraction_denominator (&GST_TUNER_NORM (v4l2norm)->
+          framerate);
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+
+}
+
+#if 0
+
+/* get a list of possible framerates
+ * this is only done for webcams;
+ * other devices return NULL here.
+ * this function takes a LONG time to execute.
+ */
+GValue *
+gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src)
+{
+  gint fps_index;
+  struct video_window *vwin = &GST_V4L2ELEMENT (v4l2src)->vwin;
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (v4l2src);
+
+  /* check if we have vwin window properties giving a framerate,
+   * as is done for webcams
+   * See http://www.smcc.demon.nl/webcam/api.html
+   * which is used for the Philips and qce-ga drivers */
+  fps_index = (vwin->flags >> 16) & 0x3F;       /* 6 bit index for framerate */
+
+  /* webcams have a non-zero fps_index */
+  if (fps_index == 0) {
+    GST_DEBUG_OBJECT (v4l2src, "fps_index is 0, no webcam");
+    return NULL;
+  }
+  GST_DEBUG_OBJECT (v4l2src, "fps_index is %d, so webcam", fps_index);
+
+  {
+    int i;
+    GValue *list = NULL;
+    GValue value = { 0 };
+
+    /* webcam detected, so try all framerates and return a list */
+
+    list = g_new0 (GValue, 1);
+    g_value_init (list, GST_TYPE_LIST);
+
+    /* index of 16 corresponds to 15 fps */
+    GST_DEBUG_OBJECT (v4l2src, "device reports fps of %d/%d (%.4f)",
+        fps_index * 15, 16, fps_index * 15.0 / 16);
+    for (i = 0; i < 63; ++i) {
+      /* set bits 16 to 21 to 0 */
+      vwin->flags &= (0x3F00 - 1);
+      /* set bits 16 to 21 to the index */
+      vwin->flags |= i << 16;
+      if (gst_v4l2_set_window_properties (v4l2element)) {
+        /* setting it succeeded.  FIXME: get it and check. */
+        g_value_init (&value, GST_TYPE_FRACTION);
+        gst_value_set_fraction (&value, i * 15, 16);
+        gst_value_list_append_value (list, &value);
+        g_value_unset (&value);
+      }
+    }
+    /* FIXME: set back the original fps_index */
+    vwin->flags &= (0x3F00 - 1);
+    vwin->flags |= fps_index << 16;
+    gst_v4l2_set_window_properties (v4l2element);
+    return list;
+  }
+  return NULL;
+}
+
+#endif
+
+#define GST_TYPE_V4L2SRC_BUFFER (gst_v4l2src_buffer_get_type())
+#define GST_IS_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2SRC_BUFFER))
+#define GST_V4L2SRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2SRC_BUFFER, GstV4l2SrcBuffer))
+
+typedef struct _GstV4l2SrcBuffer
+{
+  GstBuffer buffer;
+
+  GstV4l2Buffer *buf;
+} GstV4l2SrcBuffer;
+
+static void gst_v4l2src_buffer_class_init (gpointer g_class,
+    gpointer class_data);
+static void gst_v4l2src_buffer_init (GTypeInstance * instance,
+    gpointer g_class);
+static void gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer);
+
+GType
+gst_v4l2src_buffer_get_type (void)
+{
+  static GType _gst_v4l2src_buffer_type;
+
+  if (G_UNLIKELY (_gst_v4l2src_buffer_type == 0)) {
+    static const GTypeInfo v4l2src_buffer_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_v4l2src_buffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstV4l2SrcBuffer),
+      0,
+      gst_v4l2src_buffer_init,
+      NULL
+    };
+    _gst_v4l2src_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+        "GstV4l2SrcBuffer", &v4l2src_buffer_info, 0);
+  }
+  return _gst_v4l2src_buffer_type;
+}
+
+static void
+gst_v4l2src_buffer_class_init (gpointer g_class, gpointer class_data)
+{
+  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+      gst_v4l2src_buffer_finalize;
+}
+
+static void
+gst_v4l2src_buffer_init (GTypeInstance * instance, gpointer g_class)
+{
+
+}
+
+static void
+gst_v4l2src_buffer_finalize (GstV4l2SrcBuffer * v4l2src_buffer)
+{
+  GstV4l2Buffer *buf = v4l2src_buffer->buf;
+
+  if (buf) {
+
+    GST_LOG ("freeing buffer %p (nr. %d)", buf, buf->buffer.index);
+
+    if (!g_atomic_int_dec_and_test (&buf->refcount)) {
+      /* we're still in use, add to queue again 
+         note: this might fail because the device is already stopped (race) */
+      if (ioctl (buf->pool->video_fd, VIDIOC_QBUF, &buf->buffer) < 0)
+        GST_INFO ("readding to queue failed, assuming video device is stopped");
+    }
+    if (g_atomic_int_dec_and_test (&buf->pool->refcount)) {
+      /* we're last thing that used all this */
+      gst_v4l2src_buffer_pool_free (buf->pool, TRUE);
+    }
+
+  }
+}
+
+/* Create a V4l2Src buffer from our mmap'd data area */
+GstBuffer *
+gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data,
+    GstV4l2Buffer * srcbuf)
+{
+  GstBuffer *buf;
+  gint fps_n, fps_d;
+
+  GST_DEBUG_OBJECT (v4l2src, "creating buffer %d");
+
+  g_return_val_if_fail (gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d), NULL);
+
+  buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4L2SRC_BUFFER);
+
+  GST_V4L2SRC_BUFFER (buf)->buf = srcbuf;
+
+  if (data == NULL) {
+    GST_BUFFER_DATA (buf) = g_malloc (size);
+  } else {
+    GST_BUFFER_DATA (buf) = data;
+  }
+  GST_BUFFER_SIZE (buf) = size;
+
+  GST_BUFFER_TIMESTAMP (buf) =
+      gst_clock_get_time (GST_ELEMENT (v4l2src)->clock);
+  GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4l2src)->base_time;
+
+  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
+  GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND,
+      fps_n, fps_d);
+
+  /* the negotiate() method already set caps on the source pad */
+  gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4l2src)));
+
+  return buf;
+}
index d4f271b..8766761 100644 (file)
 #include "v4l2_calls.h"
 
 
-gboolean        gst_v4l2src_get_capture         (GstV4l2Src *v4l2src);
-gboolean        gst_v4l2src_set_capture         (GstV4l2Src *v4l2src,
-                                                 struct v4l2_fmtdesc *fmt,
-                                                 gint        width,
-                                                 gint        height);
-gboolean        gst_v4l2src_capture_init        (GstV4l2Src *v4l2src);
-gboolean        gst_v4l2src_capture_start       (GstV4l2Src *v4l2src);
-gint            gst_v4l2src_grab_frame          (GstV4l2Src *v4l2src);
-guint8 *        gst_v4l2src_get_buffer          (GstV4l2Src *v4l2src,
-                                                 gint        num);
-gboolean        gst_v4l2src_queue_frame         (GstV4l2Src *v4l2src,
-                                                 guint i);
-gboolean        gst_v4l2src_capture_stop        (GstV4l2Src *v4l2src);
-gboolean        gst_v4l2src_capture_deinit      (GstV4l2Src *v4l2src);
-
-gboolean        gst_v4l2src_fill_format_list    (GstV4l2Src *v4l2src);
-gboolean        gst_v4l2src_clear_format_list   (GstV4l2Src *v4l2src);
+gboolean       gst_v4l2src_get_capture         (GstV4l2Src *v4l2src);
+gboolean       gst_v4l2src_set_capture         (GstV4l2Src *v4l2src,
+                                                struct v4l2_fmtdesc *fmt,
+                                                gint        width,
+                                                gint        height);
+gboolean       gst_v4l2src_capture_init        (GstV4l2Src *v4l2src);
+gboolean       gst_v4l2src_capture_start       (GstV4l2Src *v4l2src);
+gint           gst_v4l2src_grab_frame          (GstV4l2Src *v4l2src);
+
+gboolean       gst_v4l2src_queue_frame         (GstV4l2Src *v4l2src,
+                                                guint i);
+gboolean       gst_v4l2src_capture_stop        (GstV4l2Src *v4l2src);
+gboolean       gst_v4l2src_capture_deinit      (GstV4l2Src *v4l2src);
+
+gboolean       gst_v4l2src_fill_format_list    (GstV4l2Src *v4l2src);
+gboolean       gst_v4l2src_clear_format_list   (GstV4l2Src *v4l2src);
 
 /* hacky */
-gboolean        gst_v4l2src_get_size_limits     (GstV4l2Src *v4l2src,
-                                                 struct v4l2_fmtdesc *fmt,
-                                                 gint *min_w, gint *max_w,
-                                                 gint *min_h, gint *max_h);
+gboolean       gst_v4l2src_get_size_limits     (GstV4l2Src *v4l2src,
+                                                struct v4l2_fmtdesc *fmt,
+                                                gint *min_w, gint *max_w,
+                                                gint *min_h, gint *max_h);
+
+void           gst_v4l2src_free_buffer         (GstBuffer *buffer);
+
+
+gboolean        gst_v4l2src_get_fps             (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d);
+
+GValue *        gst_v4l2src_get_fps_list        (GstV4l2Src * v4l2src);
 
-void            gst_v4l2src_free_buffer         (GstBuffer *buffer);
+GstBuffer *     gst_v4l2src_buffer_new          (GstV4l2Src * v4l2src,
+                                                guint size, guint8 * data,
+                                                GstV4l2Buffer * srcbuf);
   
 #endif /* __V4L2SRC_CALLS_H__ */