sys/v4l/v4lsrc_calls.*: Remove sync-related stuff.
authorAndy Wingo <wingo@pobox.com>
Thu, 7 Jul 2005 11:29:29 +0000 (11:29 +0000)
committerAndy Wingo <wingo@pobox.com>
Thu, 7 Jul 2005 11:29:29 +0000 (11:29 +0000)
Original commit message from CVS:
2005-07-07  Andy Wingo  <wingo@pobox.com>

* sys/v4l/v4lsrc_calls.h:
* sys/v4l/v4lsrc_calls.c: Remove sync-related stuff.
(gst_v4lsrc_get_fps_list): Moved here from gstv4lsrc.c.
(gst_v4lsrc_buffer_new): Totally derive from GstBuffer.

* sys/v4l/v4l_calls.h: Cast to V4lElement.
* sys/v4l/v4l_calls.c: Header loc fixen, don't load mjpeg, all
v4lelements are sources.

* sys/v4l/gstv4lxoverlay.h:
* sys/v4l/gstv4lxoverlay.c:
* sys/v4l/gstv4ltuner.h:
* sys/v4l/gstv4ltuner.c: Header loc fixen.

* sys/v4l/gstv4lsrc.h:
* sys/v4l/gstv4lsrc.c: Crucial GPL update. Clean up a bit, port to
PushSrc/BaseSrc. Removed most sync-related properties, videorate
or something should handle that. Made a live source.

* sys/v4l/gstv4lelement.h:
* sys/v4l/gstv4lelement.c: Derive from GstPushSrc. No more
signals. Some cleanups.

* sys/v4l/gstv4lcolorbalance.h: Interface header update.

* sys/v4l/gstv4l.c: Don't register v4lelement, or the jpeg/mjpeg
stuff.

* sys/v4l/Makefile.am: Build everything except the jpeg/mjpeg
stuff.

* sys/Makefile.am (SUBDIRS): Hit the V4L crack pipe.

18 files changed:
ChangeLog
docs/libs/tmpl/gstringbuffer.sgml
sys/Makefile.am
sys/v4l/Makefile.am
sys/v4l/gstv4l.c
sys/v4l/gstv4lcolorbalance.h
sys/v4l/gstv4lelement.c
sys/v4l/gstv4lelement.h
sys/v4l/gstv4lsrc.c
sys/v4l/gstv4lsrc.h
sys/v4l/gstv4ltuner.c
sys/v4l/gstv4ltuner.h
sys/v4l/gstv4lxoverlay.c
sys/v4l/gstv4lxoverlay.h
sys/v4l/v4l_calls.c
sys/v4l/v4l_calls.h
sys/v4l/v4lsrc_calls.c
sys/v4l/v4lsrc_calls.h

index 3b241a2..2f9e4d8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2005-07-07  Andy Wingo  <wingo@pobox.com>
+
+       * sys/v4l/v4lsrc_calls.h:
+       * sys/v4l/v4lsrc_calls.c: Remove sync-related stuff.
+       (gst_v4lsrc_get_fps_list): Moved here from gstv4lsrc.c.
+       (gst_v4lsrc_buffer_new): Totally derive from GstBuffer.
+
+       * sys/v4l/v4l_calls.h: Cast to V4lElement.
+       * sys/v4l/v4l_calls.c: Header loc fixen, don't load mjpeg, all
+       v4lelements are sources.
+
+       * sys/v4l/gstv4lxoverlay.h:
+       * sys/v4l/gstv4lxoverlay.c:
+       * sys/v4l/gstv4ltuner.h:
+       * sys/v4l/gstv4ltuner.c: Header loc fixen.
+       
+       * sys/v4l/gstv4lsrc.h:
+       * sys/v4l/gstv4lsrc.c: Crucial GPL update. Clean up a bit, port to
+       PushSrc/BaseSrc. Removed most sync-related properties, videorate
+       or something should handle that. Made a live source.
+
+       * sys/v4l/gstv4lelement.h:
+       * sys/v4l/gstv4lelement.c: Derive from GstPushSrc. No more
+       signals. Some cleanups.
+
+       * sys/v4l/gstv4lcolorbalance.h: Interface header update.
+
+       * sys/v4l/gstv4l.c: Don't register v4lelement, or the jpeg/mjpeg
+       stuff.
+
+       * sys/v4l/Makefile.am: Build everything except the jpeg/mjpeg
+       stuff.
+
+       * sys/Makefile.am (SUBDIRS): Hit the V4L crack pipe.
+
 2005-07-07  Wim Taymans  <wim@fluendo.com>
 
        * ext/theora/theoradec.c: (theora_get_query_types),
index 463abfb..cea80fc 100644 (file)
@@ -27,7 +27,7 @@ an implementation of an audio ringbuffer
 @samples_per_seg: 
 @empty_seg: 
 @state: 
-@segplayed
+@segdone
 @waiting: 
 
 <!-- ##### STRUCT GstRingBufferClass ##### -->
@@ -38,7 +38,7 @@ an implementation of an audio ringbuffer
 @parent_class: 
 @acquire: 
 @release: 
-@play
+@start
 @pause: 
 @resume: 
 @stop: 
@@ -82,7 +82,7 @@ an implementation of an audio ringbuffer
 @Returns: 
 
 
-<!-- ##### FUNCTION gst_ringbuffer_play ##### -->
+<!-- ##### FUNCTION gst_ringbuffer_start ##### -->
 <para>
 
 </para>
@@ -118,7 +118,7 @@ an implementation of an audio ringbuffer
 @Returns: 
 
 
-<!-- ##### FUNCTION gst_ringbuffer_played_samples ##### -->
+<!-- ##### FUNCTION gst_ringbuffer_samples_done ##### -->
 <para>
 
 </para>
index 7ec8b96..cc10bd6 100644 (file)
@@ -18,9 +18,8 @@ endif
 
 SUBDIRS = \
   $(XIMAGE_DIR) \
-  $(XVIMAGE_DIR)
-
-#  $(V4L_DIR)
+  $(XVIMAGE_DIR) \
+  $(V4L_DIR)
 
 DIST_SUBDIRS = \
   v4l \
index 441a07c..53d0e9c 100644 (file)
@@ -9,18 +9,22 @@ xv_libs =
 endif
 
 libgstvideo4linux_la_SOURCES = \
-       gstv4lelement.c v4l_calls.c \
-       gstv4lsrc.c v4lsrc_calls.c \
-       gstv4ljpegsrc.c \
-       gstv4lmjpegsrc.c v4lmjpegsrc_calls.c \
-       gstv4lmjpegsink.c v4lmjpegsink_calls.c \
        gstv4l.c \
+       gstv4lcolorbalance.c \
+       gstv4lelement.c \
+       gstv4lsrc.c \
        gstv4ltuner.c \
-       $(xv_source) \
-       gstv4lcolorbalance.c
-libgstvideo4linux_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS)
+       v4l_calls.c \
+       v4lsrc_calls.c $(xv_source)
+
+#      gstv4ljpegsrc.c \
+#      gstv4lmjpegsrc.c v4lmjpegsrc_calls.c \
+#      gstv4lmjpegsink.c v4lmjpegsink_calls.c
+
+libgstvideo4linux_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) -I$(top_srcdir)/gst-libs
 libgstvideo4linux_la_LIBADD = \
-       $(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la
+       $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \
+       $(GST_BASE_LIBS)
 libgstvideo4linux_la_LDFLAGS = \
        $(GST_PLUGIN_LDFLAGS) \
        $(xv_libs)
index 5d64143..ae43eee 100644 (file)
@@ -30,9 +30,9 @@
 
 #include "gstv4lelement.h"
 #include "gstv4lsrc.h"
-#include "gstv4ljpegsrc.h"
-#include "gstv4lmjpegsrc.h"
-#include "gstv4lmjpegsink.h"
+/* #include "gstv4ljpegsrc.h" */
+/* #include "gstv4lmjpegsrc.h" */
+/* #include "gstv4lmjpegsink.h" */
 
 GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */
 
@@ -41,16 +41,13 @@ plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls");
 
-  if (!gst_element_register (plugin, "v4lelement",
-          GST_RANK_NONE, GST_TYPE_V4LELEMENT) ||
-      !gst_element_register (plugin, "v4lsrc",
-          GST_RANK_NONE, GST_TYPE_V4LSRC) ||
-      !gst_element_register (plugin, "v4ljpegsrc",
-          GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) ||
-      !gst_element_register (plugin, "v4lmjpegsrc",
-          GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) ||
-      !gst_element_register (plugin, "v4lmjpegsink",
-          GST_RANK_NONE, GST_TYPE_V4LMJPEGSINK))
+  if (!gst_element_register (plugin, "v4lsrc", GST_RANK_NONE, GST_TYPE_V4LSRC))
+/*       !gst_element_register (plugin, "v4ljpegsrc", */
+/*           GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) || */
+/*       !gst_element_register (plugin, "v4lmjpegsrc", */
+/*           GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) || */
+/*       !gst_element_register (plugin, "v4lmjpegsink", */
+/*           GST_RANK_NONE, GST_TYPE_V4LMJPEGSINK)) */
     return FALSE;
 
 #ifdef ENABLE_NLS
index f251a7c..2a14fb4 100644 (file)
@@ -24,7 +24,7 @@
 #define __GST_V4L_COLOR_BALANCE_H__
 
 #include <gst/gst.h>
-#include <gst/colorbalance/colorbalance.h>
+#include <gst/interfaces/colorbalance.h>
 #include "v4l_calls.h"
 
 G_BEGIN_DECLS
index b766c17..647e05e 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
-
 #include <string.h>
+
+#include <gst/interfaces/propertyprobe.h>
+
 #include "v4l_calls.h"
 #include "gstv4ltuner.h"
 #ifdef HAVE_XVIDEO
 #endif
 #include "gstv4lcolorbalance.h"
 
-#include <gst/propertyprobe/propertyprobe.h>
-
-/* elementfactory information */
-static GstElementDetails gst_v4lelement_details =
-GST_ELEMENT_DETAILS ("Generic video4linux Element",
-    "Generic/Video",
-    "Generic plugin for handling common video4linux calls",
-    "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 
-/* V4lElement signals and args */
 enum
 {
-  /* FILL ME */
-  SIGNAL_OPEN,
-  SIGNAL_CLOSE,
-  LAST_SIGNAL
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME,
+  PROP_FLAGS
 };
 
-enum
-{
-  ARG_0,
-  ARG_DEVICE,
-  ARG_DEVICE_NAME,
-  ARG_FLAGS
-};
 
+static void gst_v4lelement_init_interfaces (GType type);
 
-static void gst_v4lelement_base_init (gpointer g_class);
-static void gst_v4lelement_class_init (GstV4lElementClass * klass);
-static void gst_v4lelement_init (GstV4lElement * v4lelement);
-static void gst_v4lelement_dispose (GObject * object);
-static void gst_v4lelement_set_property (GObject * object,
+GST_BOILERPLATE_FULL (GstV4lElement, gst_v4lelement, GstPushSrc,
+    GST_TYPE_PUSHSRC, gst_v4lelement_init_interfaces)
+
+
+     static void gst_v4lelement_dispose (GObject * object);
+     static void gst_v4lelement_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4lelement_get_property (GObject * object,
+     static void gst_v4lelement_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
-static GstElementStateReturn gst_v4lelement_change_state (GstElement * element);
-
+     static gboolean gst_v4lelement_start (GstBaseSrc * src);
+     static gboolean gst_v4lelement_stop (GstBaseSrc * src);
 
-static GstElementClass *parent_class = NULL;
-static guint gst_v4lelement_signals[LAST_SIGNAL] = { 0 };
 
-static gboolean
-gst_v4l_iface_supported (GstImplementsInterface * iface, GType iface_type)
+     static gboolean
+         gst_v4l_iface_supported (GstImplementsInterface * iface,
+    GType iface_type)
 {
   GstV4lElement *v4lelement = GST_V4LELEMENT (iface);
 
@@ -176,7 +163,7 @@ gst_v4l_probe_probe_property (GstPropertyProbe * probe,
   GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       gst_v4l_class_probe_devices (klass, FALSE);
       break;
     default:
@@ -193,7 +180,7 @@ gst_v4l_probe_needs_probe (GstPropertyProbe * probe,
   gboolean ret = FALSE;
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       ret = !gst_v4l_class_probe_devices (klass, TRUE);
       break;
     default:
@@ -238,7 +225,7 @@ gst_v4l_probe_get_values (GstPropertyProbe * probe,
   GValueArray *array = NULL;
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       array = gst_v4l_class_list_devices (klass);
       break;
     default:
@@ -283,122 +270,82 @@ gst_v4l_device_get_type (void)
   return v4l_device_type;
 }
 
-
-GType
-gst_v4lelement_get_type (void)
+static void
+gst_v4lelement_init_interfaces (GType type)
 {
-  static GType v4lelement_type = 0;
-
-  if (!v4lelement_type) {
-    static const GTypeInfo v4lelement_info = {
-      sizeof (GstV4lElementClass),
-      gst_v4lelement_base_init,
-      NULL,
-      (GClassInitFunc) gst_v4lelement_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lElement),
-      0,
-      (GInstanceInitFunc) gst_v4lelement_init,
-      NULL
-    };
-    static const GInterfaceInfo v4liface_info = {
-      (GInterfaceInitFunc) gst_v4l_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo v4l_tuner_info = {
-      (GInterfaceInitFunc) gst_v4l_tuner_interface_init,
-      NULL,
-      NULL,
-    };
+  static const GInterfaceInfo v4liface_info = {
+    (GInterfaceInitFunc) gst_v4l_interface_init,
+    NULL,
+    NULL,
+  };
+  static const GInterfaceInfo v4l_tuner_info = {
+    (GInterfaceInitFunc) gst_v4l_tuner_interface_init,
+    NULL,
+    NULL,
+  };
 #ifdef HAVE_XVIDEO
-    static const GInterfaceInfo v4l_xoverlay_info = {
-      (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
-      NULL,
-      NULL,
-    };
+  static const GInterfaceInfo v4l_xoverlay_info = {
+    (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
+    NULL,
+    NULL,
+  };
 #endif
-    static const GInterfaceInfo v4l_colorbalance_info = {
-      (GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo v4l_propertyprobe_info = {
-      (GInterfaceInitFunc) gst_v4l_property_probe_interface_init,
-      NULL,
-      NULL,
-    };
-
-    v4lelement_type = g_type_register_static (GST_TYPE_ELEMENT,
-        "GstV4lElement", &v4lelement_info, 0);
-
-    g_type_add_interface_static (v4lelement_type,
-        GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
-    g_type_add_interface_static (v4lelement_type,
-        GST_TYPE_TUNER, &v4l_tuner_info);
+  static const GInterfaceInfo v4l_colorbalance_info = {
+    (GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
+    NULL,
+    NULL,
+  };
+  static const GInterfaceInfo v4l_propertyprobe_info = {
+    (GInterfaceInitFunc) gst_v4l_property_probe_interface_init,
+    NULL,
+    NULL,
+  };
+
+  g_type_add_interface_static (type,
+      GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
+  g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l_tuner_info);
 #ifdef HAVE_XVIDEO
-    g_type_add_interface_static (v4lelement_type,
-        GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
+  g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
 #endif
-    g_type_add_interface_static (v4lelement_type,
-        GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
-    g_type_add_interface_static (v4lelement_type,
-        GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info);
-  }
-
-  return v4lelement_type;
+  g_type_add_interface_static (type,
+      GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
+  g_type_add_interface_static (type,
+      GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info);
 }
 
 
 static void
 gst_v4lelement_base_init (gpointer g_class)
 {
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
 
   klass->devices = NULL;
-
-  gst_element_class_set_details (gstelement_class, &gst_v4lelement_details);
 }
 
 static void
 gst_v4lelement_class_init (GstV4lElementClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
+  GstBaseSrcClass *basesrc_class;
 
   gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
+  basesrc_class = (GstBaseSrcClass *) klass;
 
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  gobject_class->set_property = gst_v4lelement_set_property;
+  gobject_class->get_property = gst_v4lelement_get_property;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), 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 (G_OBJECT_CLASS (klass), ARG_DEVICE_NAME,
+  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), ARG_FLAGS,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
       g_param_spec_flags ("flags", "Flags", "Device type flags",
           GST_TYPE_V4L_DEVICE_FLAGS, 0, G_PARAM_READABLE));
 
-  /* signals */
-  gst_v4lelement_signals[SIGNAL_OPEN] =
-      g_signal_new ("open", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstV4lElementClass, open),
-      NULL, NULL, g_cclosure_marshal_VOID__STRING,
-      G_TYPE_NONE, 1, G_TYPE_STRING);
-  gst_v4lelement_signals[SIGNAL_CLOSE] =
-      g_signal_new ("close", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstV4lElementClass, close),
-      NULL, NULL, g_cclosure_marshal_VOID__STRING,
-      G_TYPE_NONE, 1, G_TYPE_STRING);
-
-  gobject_class->set_property = gst_v4lelement_set_property;
-  gobject_class->get_property = gst_v4lelement_get_property;
-
-  gstelement_class->change_state = gst_v4lelement_change_state;
+  basesrc_class->start = gst_v4lelement_start;
+  basesrc_class->stop = gst_v4lelement_stop;
 
   gobject_class->dispose = gst_v4lelement_dispose;
 }
@@ -439,13 +386,10 @@ static void
 gst_v4lelement_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  GstV4lElement *v4lelement;
-
-  g_return_if_fail (GST_IS_V4LELEMENT (object));
-  v4lelement = GST_V4LELEMENT (object);
+  GstV4lElement *v4lelement = GST_V4LELEMENT (object);
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       if (v4lelement->videodev)
         g_free (v4lelement->videodev);
       v4lelement->videodev = g_strdup (g_value_get_string (value));
@@ -461,16 +405,13 @@ static void
 gst_v4lelement_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec)
 {
-  GstV4lElement *v4lelement;
-
-  g_return_if_fail (GST_IS_V4LELEMENT (object));
-  v4lelement = GST_V4LELEMENT (object);
+  GstV4lElement *v4lelement = GST_V4LELEMENT (object);
 
   switch (prop_id) {
-    case ARG_DEVICE:
+    case PROP_DEVICE:
       g_value_set_string (value, v4lelement->videodev);
       break;
-    case ARG_DEVICE_NAME:{
+    case PROP_DEVICE_NAME:{
       gchar *new = NULL;
 
       if (GST_V4L_IS_OPEN (v4lelement))
@@ -478,7 +419,7 @@ gst_v4lelement_get_property (GObject * object,
       g_value_set_string (value, new);
       break;
     }
-    case ARG_FLAGS:{
+    case PROP_FLAGS:{
       guint flags = 0;
 
       if (GST_V4L_IS_OPEN (v4lelement)) {
@@ -495,47 +436,32 @@ gst_v4lelement_get_property (GObject * object,
   }
 }
 
-
-static GstElementStateReturn
-gst_v4lelement_change_state (GstElement * element)
+static gboolean
+gst_v4lelement_start (GstBaseSrc * src)
 {
-  GstV4lElement *v4lelement;
-
-  g_return_val_if_fail (GST_IS_V4LELEMENT (element), GST_STATE_FAILURE);
-
-  v4lelement = GST_V4LELEMENT (element);
+  GstV4lElement *v4lelement = GST_V4LELEMENT (src);
 
-  /* 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 (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_NULL_TO_READY:
-      if (!gst_v4l_open (v4lelement))
-        return GST_STATE_FAILURE;
+  if (!gst_v4l_open (v4lelement))
+    return FALSE;
 
 #ifdef HAVE_XVIDEO
-      gst_v4l_xoverlay_open (v4lelement);
+  gst_v4l_xoverlay_open (v4lelement);
 #endif
 
-      g_signal_emit (G_OBJECT (v4lelement),
-          gst_v4lelement_signals[SIGNAL_OPEN], 0, v4lelement->videodev);
-      break;
+  return TRUE;
+}
+
+static gboolean
+gst_v4lelement_stop (GstBaseSrc * src)
+{
+  GstV4lElement *v4lelement = GST_V4LELEMENT (src);
 
-    case GST_STATE_READY_TO_NULL:
 #ifdef HAVE_XVIDEO
-      gst_v4l_xoverlay_close (v4lelement);
+  gst_v4l_xoverlay_close (v4lelement);
 #endif
 
-      if (!gst_v4l_close (v4lelement))
-        return GST_STATE_FAILURE;
-
-      g_signal_emit (G_OBJECT (v4lelement),
-          gst_v4lelement_signals[SIGNAL_CLOSE], 0, v4lelement->videodev);
-      break;
-  }
-
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  if (!gst_v4l_close (v4lelement))
+    return FALSE;
 
-  return GST_STATE_SUCCESS;
+  return TRUE;
 }
index 6db12a8..515f783 100644 (file)
@@ -23,9 +23,6 @@
 #ifndef __GST_V4LELEMENT_H__
 #define __GST_V4LELEMENT_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
 #include <sys/types.h>
 #define _LINUX_TIME_H
 #include <linux/videodev.h>
+
 #include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
 
 G_BEGIN_DECLS
 
@@ -63,7 +63,7 @@ typedef struct _GstV4lElementClass GstV4lElementClass;
 typedef struct _GstV4lXv GstV4lXv;
 
 struct _GstV4lElement {
-  GstElement element;
+  GstPushSrc element;
 
   /* the video device */
   char *videodev;
@@ -94,17 +94,11 @@ struct _GstV4lElement {
 };
 
 struct _GstV4lElementClass {
-  GstElementClass parent_class;
+  GstPushSrcClass parent_class;
 
   /* probed devices */
   GList *devices;
 
-  /* signals */
-  void     (*open)           (GstElement  *element,
-                              const gchar *device);
-  void     (*close)          (GstElement  *element,
-                              const gchar *device);
-
   /* actions */
   gboolean (*get_attribute)   (GstElement  *element,
                                const gchar *attr_name,
index 53994cc..adcffb9 100644 (file)
@@ -17,7 +17,7 @@
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
e Boston, MA 02111-1307, USA.
* Boston, MA 02111-1307, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #include "v4lsrc_calls.h"
 #include <sys/ioctl.h>
 
-/* elementfactory information */
+
 static GstElementDetails gst_v4lsrc_details =
 GST_ELEMENT_DETAILS ("Video (video4linux/raw) Source",
     "Source/Video",
     "Reads raw frames from a video4linux (BT8x8) device",
     "Ronald Bultje <rbultje@ronald.bitfreak.net>");
 
+
 GST_DEBUG_CATEGORY (v4lsrc_debug);
 #define GST_CAT_DEFAULT v4lsrc_debug
 
-/* V4lSrc signals and args */
-enum
-{
-  /* FILL ME */
-  SIGNAL_FRAME_CAPTURE,
-  SIGNAL_FRAME_DROP,
-  SIGNAL_FRAME_INSERT,
-  LAST_SIGNAL
-};
 
-#define DEFAULT_SYNC_MODE GST_V4LSRC_SYNC_MODE_CLOCK
-#define DEFAULT_COPY_MODE FALSE
-/* arguments */
 enum
 {
-  ARG_0,
-  ARG_NUMBUFS,
-  ARG_BUFSIZE,
-  ARG_SYNC_MODE,
-  ARG_COPY_MODE,
-  ARG_AUTOPROBE,
-  ARG_AUTOPROBE_FPS,
-  ARG_LATENCY_OFFSET
+  PROP_0,
+  PROP_AUTOPROBE,
+  PROP_AUTOPROBE_FPS,
+  PROP_TIMESTAMP_OFFSET
 };
 
-GST_FORMATS_FUNCTION (GstPad *, gst_v4lsrc_get_formats,
-    GST_FORMAT_TIME, GST_FORMAT_DEFAULT);
-GST_QUERY_TYPE_FUNCTION (GstPad *, gst_v4lsrc_get_query_types,
-    GST_QUERY_POSITION);
 
-#define GST_TYPE_V4LSRC_SYNC_MODE (gst_v4lsrc_sync_mode_get_type())
-static GType
-gst_v4lsrc_sync_mode_get_type (void)
-{
-  static GType v4lsrc_sync_mode_type = 0;
-  static GEnumValue v4lsrc_sync_mode[] = {
-    {GST_V4LSRC_SYNC_MODE_CLOCK, "0", "Sync to the pipeline clock"},
-    {GST_V4LSRC_SYNC_MODE_PRIVATE_CLOCK, "1", "Sync to a private clock"},
-    {GST_V4LSRC_SYNC_MODE_FIXED_FPS, "2", "Use Fixed fps"},
-    {GST_V4LSRC_SYNC_MODE_NONE, "3", "No Sync"},
-    {0, NULL, NULL},
-  };
-
-  if (!v4lsrc_sync_mode_type) {
-    v4lsrc_sync_mode_type =
-        g_enum_register_static ("GstV4lSrcSyncMode", v4lsrc_sync_mode);
-  }
-  return v4lsrc_sync_mode_type;
-}
+GST_BOILERPLATE (GstV4lSrc, gst_v4lsrc, GstV4lElement, GST_TYPE_V4LELEMENT);
+
+
+/* basesrc methods */
+static gboolean gst_v4lsrc_start (GstBaseSrc * src);
+static gboolean gst_v4lsrc_stop (GstBaseSrc * src);
+static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
+static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
+static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
+
+static void gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps);
 
-/* structure for buffer private data referencing element and frame number */
-typedef struct
-{
-  GstV4lSrc *v4lsrc;
-  int num;
-}
-v4lsrc_private_t;
-
-/* init functions */
-static void gst_v4lsrc_base_init (gpointer g_class);
-static void gst_v4lsrc_class_init (GstV4lSrcClass * klass);
-static void gst_v4lsrc_init (GstV4lSrc * v4lsrc);
-
-/* parent class virtual functions */
-static void gst_v4lsrc_open (GstElement * element, const gchar * device);
-static void gst_v4lsrc_close (GstElement * element, const gchar * device);
-
-/* pad/info functions */
-static gboolean gst_v4lsrc_src_convert (GstPad * pad,
-    GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-static gboolean gst_v4lsrc_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * format, gint64 * value);
-
-/* buffer functions */
-static GstPadLinkReturn gst_v4lsrc_src_link (GstPad * pad,
-    const GstCaps * caps);
-static GstCaps *gst_v4lsrc_fixate (GstPad * pad, const GstCaps * caps);
-static GstCaps *gst_v4lsrc_getcaps (GstPad * pad);
-static GstData *gst_v4lsrc_get (GstPad * pad);
-
-/* get/set params */
 static void gst_v4lsrc_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
 static void gst_v4lsrc_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
-/* state handling */
-static GstElementStateReturn gst_v4lsrc_change_state (GstElement * element);
-
-/* set_clock function for a/V sync */
-static void gst_v4lsrc_set_clock (GstElement * element, GstClock * clock);
-
-/* requeue buffer if it's back available */
-static void gst_v4lsrc_buffer_free (GstBuffer * buffer);
-
-static GstElementClass *parent_class = NULL;
-static guint gst_v4lsrc_signals[LAST_SIGNAL] = { 0 };
-
-
-GType
-gst_v4lsrc_get_type (void)
-{
-  static GType v4lsrc_type = 0;
-
-  if (!v4lsrc_type) {
-    static const GTypeInfo v4lsrc_info = {
-      sizeof (GstV4lSrcClass),
-      gst_v4lsrc_base_init,
-      NULL,
-      (GClassInitFunc) gst_v4lsrc_class_init,
-      NULL,
-      NULL,
-      sizeof (GstV4lSrc),
-      0,
-      (GInstanceInitFunc) gst_v4lsrc_init,
-      NULL
-    };
-
-    v4lsrc_type =
-        g_type_register_static (GST_TYPE_V4LELEMENT, "GstV4lSrc", &v4lsrc_info,
-        0);
-  }
-  return v4lsrc_type;
-}
 
 static void
 gst_v4lsrc_base_init (gpointer g_class)
 {
-  GstPadTemplate *src_template;
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 
   gst_element_class_set_details (gstelement_class, &gst_v4lsrc_details);
 
-  src_template = gst_pad_template_new ("src",
-      GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_new_any ());
-
-  gst_element_class_add_pad_template (gstelement_class, src_template);
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+          gst_caps_new_any ()));
 }
 
 static void
 gst_v4lsrc_class_init (GstV4lSrcClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstV4lElementClass *v4lelement_class;
+  GstBaseSrcClass *basesrc_class;
+  GstPushSrcClass *pushsrc_class;
 
   gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-  v4lelement_class = (GstV4lElementClass *) klass;
-
-  parent_class = g_type_class_ref (GST_TYPE_V4LELEMENT);
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUMBUFS,
-      g_param_spec_int ("num_buffers", "Num Buffers", "Number of buffers",
-          0, G_MAXINT, 0, G_PARAM_READABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFSIZE,
-      g_param_spec_int ("buffer_size", "Buffer Size", "Size of buffers",
-          0, G_MAXINT, 0, G_PARAM_READABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC_MODE,
-      g_param_spec_enum ("sync_mode", "Sync mode",
-          "Method to use for timestamping captured frames",
-          GST_TYPE_V4LSRC_SYNC_MODE, DEFAULT_SYNC_MODE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPY_MODE,
-      g_param_spec_boolean ("copy_mode", "Copy mode",
-          "Don't send out HW buffers, send copy instead", DEFAULT_COPY_MODE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_AUTOPROBE,
+  basesrc_class = (GstBaseSrcClass *) klass;
+  pushsrc_class = (GstPushSrcClass *) klass;
+
+  gobject_class->set_property = gst_v4lsrc_set_property;
+  gobject_class->get_property = gst_v4lsrc_get_property;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE,
       g_param_spec_boolean ("autoprobe", "Autoprobe",
           "Whether the device should be probed for all possible features",
           TRUE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_AUTOPROBE_FPS,
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE_FPS,
       g_param_spec_boolean ("autoprobe-fps", "Autoprobe FPS",
           "Whether the device should be probed for framerates",
           TRUE, G_PARAM_READWRITE));
-  /* FIXME: this should have been a 64 bit int instead, because 3 seconds
-   * overflows 32 bit nanosecond values.  However, this is an ABI change,
-   * so we're saving it for 0.9, and then we can also rename the property
-   * to something that makes more sense, like, timestamp-offset */
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LATENCY_OFFSET,
-      g_param_spec_int ("latency-offset", "Latency offset",
-          "A latency offset subtracted from timestamps set on buffers (in ns)",
-          G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
-
-  /* signals */
-  gst_v4lsrc_signals[SIGNAL_FRAME_CAPTURE] =
-      g_signal_new ("frame-capture", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lSrcClass, frame_capture), NULL,
-      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-  gst_v4lsrc_signals[SIGNAL_FRAME_DROP] =
-      g_signal_new ("frame-drop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstV4lSrcClass, frame_drop), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-  gst_v4lsrc_signals[SIGNAL_FRAME_INSERT] =
-      g_signal_new ("frame-insert", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lSrcClass, frame_insert), NULL,
-      NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+  g_object_class_install_property (G_OBJECT_CLASS (klass),
+      PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
+          "Timestamp offset",
+          "A time offset subtracted from timestamps set on buffers (in ns)",
+          G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
 
   GST_DEBUG_CATEGORY_INIT (v4lsrc_debug, "v4lsrc", 0, "V4L source element");
-  gobject_class->set_property = gst_v4lsrc_set_property;
-  gobject_class->get_property = gst_v4lsrc_get_property;
-
-  gstelement_class->change_state = gst_v4lsrc_change_state;
 
-  gstelement_class->set_clock = gst_v4lsrc_set_clock;
+  basesrc_class->get_caps = gst_v4lsrc_get_caps;
+  basesrc_class->set_caps = gst_v4lsrc_set_caps;
+  basesrc_class->start = gst_v4lsrc_start;
+  basesrc_class->stop = gst_v4lsrc_stop;
 
-  v4lelement_class->open = gst_v4lsrc_open;
-  v4lelement_class->close = gst_v4lsrc_close;
+  pushsrc_class->create = gst_v4lsrc_create;
 }
 
 static void
 gst_v4lsrc_init (GstV4lSrc * v4lsrc)
 {
-  GstElementClass *klass = GST_ELEMENT_GET_CLASS (v4lsrc);
-
-  GST_FLAG_SET (GST_ELEMENT (v4lsrc), GST_ELEMENT_THREAD_SUGGESTED);
-
-  v4lsrc->srcpad =
-      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
-          "src"), "src");
-  gst_element_add_pad (GST_ELEMENT (v4lsrc), v4lsrc->srcpad);
-
-  gst_pad_set_get_function (v4lsrc->srcpad, gst_v4lsrc_get);
-  gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4lsrc_getcaps);
-  gst_pad_set_fixate_function (v4lsrc->srcpad, gst_v4lsrc_fixate);
-  gst_pad_set_link_function (v4lsrc->srcpad, gst_v4lsrc_src_link);
-  gst_pad_set_convert_function (v4lsrc->srcpad, gst_v4lsrc_src_convert);
-  gst_pad_set_formats_function (v4lsrc->srcpad, gst_v4lsrc_get_formats);
-  gst_pad_set_query_function (v4lsrc->srcpad, gst_v4lsrc_src_query);
-  gst_pad_set_query_type_function (v4lsrc->srcpad, gst_v4lsrc_get_query_types);
-
   v4lsrc->buffer_size = 0;
 
-  /* no clock */
-  v4lsrc->clock = NULL;
-
-  /* no colourspaces */
-  v4lsrc->colourspaces = NULL;
-
-  v4lsrc->syncmode = DEFAULT_SYNC_MODE;
-  v4lsrc->copy_mode = DEFAULT_COPY_MODE;
+  /* no colorspaces */
+  v4lsrc->colorspaces = NULL;
 
   v4lsrc->is_capturing = FALSE;
   v4lsrc->autoprobe = TRUE;
   v4lsrc->autoprobe_fps = TRUE;
 
-  v4lsrc->latency_offset = 0;
+  v4lsrc->timestamp_offset = 0;
 
   v4lsrc->fps_list = NULL;
-}
-
-static gint all_palettes[] = {
-  VIDEO_PALETTE_YUV422,
-  VIDEO_PALETTE_YUV420P,
-  VIDEO_PALETTE_UYVY,
-  VIDEO_PALETTE_YUV411P,
-  VIDEO_PALETTE_YUV422P,
-  VIDEO_PALETTE_YUV410P,
-  VIDEO_PALETTE_YUV411,
-  VIDEO_PALETTE_RGB555,
-  VIDEO_PALETTE_RGB565,
-  VIDEO_PALETTE_RGB24,
-  VIDEO_PALETTE_RGB32,
-  -1
-};
 
-static void
-gst_v4lsrc_open (GstElement * element, const gchar * device)
-{
-  GstV4lSrc *v4lsrc = GST_V4LSRC (element);
-  GstV4lElement *v4l = GST_V4LELEMENT (v4lsrc);
-  gint width = v4l->vcap.minwidth;
-  gint height = v4l->vcap.minheight;
-  gint i;
+  gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (v4lsrc),
+      gst_v4lsrc_fixate);
 
-  GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes");
-  for (i = 0; all_palettes[i] != -1; i++) {
-    /* try palette out */
-    if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i]))
-      continue;
-    GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
-        all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i]));
-    v4lsrc->colourspaces = g_list_append (v4lsrc->colourspaces,
-        GINT_TO_POINTER (all_palettes[i]));
-  }
-  GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported",
-      g_list_length (v4lsrc->colourspaces));
+  gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE);
 }
 
 static void
-gst_v4lsrc_close (GstElement * element, const gchar * device)
+gst_v4lsrc_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  GstV4lSrc *v4lsrc = GST_V4LSRC (element);
+  GstV4lSrc *v4lsrc = GST_V4LSRC (object);
 
-  g_list_free (v4lsrc->colourspaces);
-  v4lsrc->colourspaces = NULL;
-}
-
-/* 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.
- */
-static GValue *
-gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
-{
-  gint fps_index;
-  gfloat fps;
-  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-  GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc);
-
-  /* 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 (v4lsrc, "fps_index is 0, no webcam");
-    return NULL;
-  }
-  GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
-
-  {
-    gfloat current_fps;
-    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 */
-    current_fps = fps_index * 15.0 / 16;
-    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
-    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_v4l_set_window_properties (v4lelement)) {
-        /* setting it succeeded.  FIXME: get it and check. */
-        fps = i * 15.0 / 16;
-        g_value_init (&value, G_TYPE_DOUBLE);
-        g_value_set_double (&value, fps);
-        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_v4l_set_window_properties (v4lelement);
-    return list;
+  switch (prop_id) {
+    case PROP_AUTOPROBE:
+      g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
+      v4lsrc->autoprobe = g_value_get_boolean (value);
+      break;
+    case PROP_AUTOPROBE_FPS:
+      g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
+      v4lsrc->autoprobe_fps = g_value_get_boolean (value);
+      break;
+    case PROP_TIMESTAMP_OFFSET:
+      v4lsrc->timestamp_offset = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
-  return NULL;
 }
 
-static gboolean
-gst_v4lsrc_src_convert (GstPad * pad,
-    GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
-  GstV4lSrc *v4lsrc;
-  gdouble fps;
 
-  v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
-
-  if ((fps = gst_v4lsrc_get_fps (v4lsrc)) == 0)
-    return FALSE;
+static void
+gst_v4lsrc_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec)
+{
+  GstV4lSrc *v4lsrc = GST_V4LSRC (object);
 
-  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;
-      }
+  switch (prop_id) {
+    case PROP_AUTOPROBE:
+      g_value_set_boolean (value, v4lsrc->autoprobe);
       break;
-
-    case GST_FORMAT_DEFAULT:
-      switch (*dest_format) {
-        case GST_FORMAT_TIME:
-          *dest_value = src_value * GST_SECOND / fps;
-          break;
-        default:
-          return FALSE;
-      }
+    case PROP_AUTOPROBE_FPS:
+      g_value_set_boolean (value, v4lsrc->autoprobe_fps);
+      break;
+    case PROP_TIMESTAMP_OFFSET:
+      g_value_set_int (value, v4lsrc->timestamp_offset);
       break;
-
     default:
-      return FALSE;
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
-
-  return TRUE;
 }
 
-static gboolean
-gst_v4lsrc_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * format, gint64 * value)
+G_GNUC_UNUSED static void
+gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps)
 {
+  GstStructure *structure;
+  int i;
+  int targetwidth, targetheight;
   GstV4lSrc *v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
-  gboolean res = TRUE;
-  gdouble fps;
-
-  if ((fps = gst_v4lsrc_get_fps (v4lsrc)) == 0)
-    return FALSE;
+  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
+  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
 
-  switch (type) {
-    case GST_QUERY_POSITION:
-      switch (*format) {
-        case GST_FORMAT_TIME:
-          *value = v4lsrc->handled * GST_SECOND / fps;
-          break;
-        case GST_FORMAT_DEFAULT:
-          *value = v4lsrc->handled;
-          break;
-        default:
-          res = FALSE;
-          break;
-      }
-      break;
-    default:
-      res = FALSE;
-      break;
+  if (GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
+    GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d",
+        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight);
+    targetwidth = vcap->minwidth;
+    targetheight = vcap->minheight;
+    /* if we can get the current vwin settings, we use those to fixate */
+    if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc)))
+      GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities");
+    else {
+      targetwidth = vwin->width;
+      targetheight = vwin->height;
+    }
+  } else {
+    GST_DEBUG_OBJECT (v4lsrc, "device closed, guessing");
+    targetwidth = 320;
+    targetheight = 200;
   }
 
-  return res;
+  GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight);
+
+  for (i = 0; i < gst_caps_get_size (caps); ++i) {
+    structure = gst_caps_get_structure (caps, i);
+
+    gst_caps_structure_fixate_field_nearest_int (structure, "width",
+        targetwidth);
+    gst_caps_structure_fixate_field_nearest_int (structure, "height",
+        targetheight);
+  }
 }
 
+static gint all_palettes[] = {
+  VIDEO_PALETTE_YUV422,
+  VIDEO_PALETTE_YUV420P,
+  VIDEO_PALETTE_UYVY,
+  VIDEO_PALETTE_YUV411P,
+  VIDEO_PALETTE_YUV422P,
+  VIDEO_PALETTE_YUV410P,
+  VIDEO_PALETTE_YUV411,
+  VIDEO_PALETTE_RGB555,
+  VIDEO_PALETTE_RGB565,
+  VIDEO_PALETTE_RGB24,
+  VIDEO_PALETTE_RGB32,
+  -1
+};
+
 static GstCaps *
 gst_v4lsrc_palette_to_caps (int palette)
 {
@@ -539,8 +307,8 @@ gst_v4lsrc_palette_to_caps (int palette)
         break;
       case VIDEO_PALETTE_RGB32:
         caps = gst_caps_from_string ("video/x-raw-rgb, "
-            "bpp = (int) 24, "
-            "depth = (int) 32, "
+            "bpp = (int) 32, "
+            "depth = (int) 24, "
             "endianness = (int) BIG_ENDIAN, "
             "red_mask = 0xFF000000, "
             "green_mask = 0x00FF0000, " "blue_mask = 0x0000FF00");
@@ -571,41 +339,126 @@ gst_v4lsrc_get_any_caps ()
   return caps;
 }
 
-static GstPadLinkReturn
-gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
+static GstCaps *
+gst_v4lsrc_get_caps (GstBaseSrc * src)
+{
+  GstCaps *list;
+  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
+  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
+  gint width = GST_V4LELEMENT (src)->vcap.minwidth;
+  gint height = GST_V4LELEMENT (src)->vcap.minheight;
+  gint i;
+  gdouble fps;
+  GList *item;
+
+  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
+    return gst_v4lsrc_get_any_caps ();
+  }
+
+  if (!v4lsrc->autoprobe) {
+    /* FIXME: query current caps and return those, with _any appended */
+    return gst_v4lsrc_get_any_caps ();
+  }
+
+  if (!v4lsrc->colorspaces) {
+    GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes");
+    for (i = 0; all_palettes[i] != -1; i++) {
+      /* try palette out */
+      if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i]))
+        continue;
+      GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
+          all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i]));
+      v4lsrc->colorspaces = g_list_append (v4lsrc->colorspaces,
+          GINT_TO_POINTER (all_palettes[i]));
+    }
+    GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported",
+        g_list_length (v4lsrc->colorspaces));
+    if (v4lsrc->autoprobe_fps) {
+      GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates");
+      v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc);
+    }
+  }
+
+  fps = gst_v4lsrc_get_fps (v4lsrc);
+
+  list = gst_caps_new_empty ();
+  for (item = v4lsrc->colorspaces; item != NULL; item = item->next) {
+    GstCaps *one;
+
+    one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data));
+    if (!one) {
+      GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n",
+          GPOINTER_TO_INT (item->data));
+      continue;
+    }
+
+    GST_DEBUG_OBJECT (v4lsrc,
+        "Device reports w: %d-%d, h: %d-%d, fps: %f for palette %d",
+        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps,
+        GPOINTER_TO_INT (item->data));
+
+    if (vcap->minwidth < vcap->maxwidth) {
+      gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
+          vcap->maxwidth, NULL);
+    } else {
+      gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL);
+    }
+    if (vcap->minheight < vcap->maxheight) {
+      gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight,
+          vcap->maxheight, NULL);
+    } else {
+      gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL);
+    }
+
+    if (v4lsrc->autoprobe_fps) {
+      if (v4lsrc->fps_list) {
+        GstStructure *structure = gst_caps_get_structure (one, 0);
+
+        gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
+      } else {
+        gst_caps_set_simple (one, "framerate", G_TYPE_DOUBLE, fps, NULL);
+      }
+    } else {
+      gst_caps_set_simple (one, "framerate", GST_TYPE_DOUBLE_RANGE,
+          (gdouble) 1.0, (gdouble) 100.0, NULL);
+    }
+
+    GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
+    gst_caps_append (list, one);
+  }
+
+  return list;
+}
+
+static gboolean
+gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
 {
   GstV4lSrc *v4lsrc;
   guint32 fourcc;
   gint bpp, depth, w, h, palette = -1;
   gdouble fps;
   GstStructure *structure;
-  gboolean was_capturing;
   struct video_window *vwin;
 
-  /* if your fourcc stays sexy then something is wrong */
-  fourcc = GST_MAKE_FOURCC ('S', 'E', 'X', 'Y');
-
-  v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
+  v4lsrc = GST_V4LSRC (src);
   vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-  was_capturing = v4lsrc->is_capturing;
-
-  /* in case the buffers are active (which means that we already
-   * did capsnego before and didn't clean up), clean up anyways */
-  if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
-    if (was_capturing) {
-      if (!gst_v4lsrc_capture_stop (v4lsrc))
-        return GST_PAD_LINK_REFUSED;
-    }
+
+  /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
+  if (!GST_V4L_IS_OPEN (v4lsrc))
+    return FALSE;
+
+  /* make sure we stop capturing and dealloc buffers */
+  if (GST_V4L_IS_ACTIVE (v4lsrc)) {
+    if (!gst_v4lsrc_capture_stop (v4lsrc))
+      return FALSE;
     if (!gst_v4lsrc_capture_deinit (v4lsrc))
-      return GST_PAD_LINK_REFUSED;
-  } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
-    return GST_PAD_LINK_DELAYED;
+      return FALSE;
   }
 
-  /* FIXME: setting the first one is just stupid.  We should loop */
-  structure = gst_caps_get_structure (vscapslist, 0);
+  /* it's fixed, one struct */
+  structure = gst_caps_get_structure (caps, 0);
 
-  if (!strcmp (gst_structure_get_name (structure), "video/x-raw-yuv"))
+  if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0)
     gst_structure_get_fourcc (structure, "format", &fourcc);
   else
     fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
@@ -625,7 +478,7 @@ gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
     /* set bits 16 to 21 to the index */
     vwin->flags |= fps_index << 16;
     if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
-      return GST_PAD_LINK_REFUSED;
+      return FALSE;
     }
   }
 
@@ -695,7 +548,7 @@ gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
   if (palette == -1) {
     GST_WARNING_OBJECT (v4lsrc, "palette for fourcc " GST_FOURCC_FORMAT
         " is -1, refusing link", GST_FOURCC_ARGS (fourcc));
-    return GST_PAD_LINK_REFUSED;
+    return FALSE;
   }
 
   GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d",
@@ -704,553 +557,90 @@ gst_v4lsrc_src_link (GstPad * pad, const GstCaps * vscapslist)
   if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
     GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d",
         w, h, palette);
-    return GST_PAD_LINK_REFUSED;
+    return FALSE;
   }
 
   /* first try the negotiated settings using try_capture */
   if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
     GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette,
         w, h);
-    return GST_PAD_LINK_REFUSED;
+    return FALSE;
   }
 
   if (!gst_v4lsrc_capture_init (v4lsrc))
-    return GST_PAD_LINK_REFUSED;
-
-  if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) {
-    if (!gst_v4lsrc_capture_start (v4lsrc))
-      return GST_PAD_LINK_REFUSED;
-  }
-
-  return GST_PAD_LINK_OK;
-}
-
-static GstCaps *
-gst_v4lsrc_fixate (GstPad * pad, const GstCaps * caps)
-{
-  GstStructure *structure;
-  GstCaps *newcaps;
-  int i;
-  int targetwidth, targetheight;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
-  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
-  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
-  /* if device not yet open, no way to fixate */
-  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
-    GST_DEBUG_OBJECT (v4lsrc, "device closed, cannot fixate");
-    return NULL;
-  }
-
-  GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d",
-      vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight);
-  targetwidth = vcap->minwidth;
-  targetheight = vcap->minheight;
-
-  /* if we can get the current vwin settings, we use those to fixate */
-  if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc)))
-    GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities");
-  else {
-    targetwidth = vwin->width;
-    targetheight = vwin->height;
-  }
-  GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight);
+    return FALSE;
 
-  newcaps = gst_caps_copy (caps);
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    structure = gst_caps_get_structure (newcaps, i);
+  if (!gst_v4lsrc_capture_start (v4lsrc))
+    return FALSE;
 
-    if (gst_caps_structure_fixate_field_nearest_int (structure, "width",
-            targetwidth)) {
-      return newcaps;
-    }
-    if (gst_caps_structure_fixate_field_nearest_int (structure, "height",
-            targetheight)) {
-      return newcaps;
-    }
-  }
-  gst_caps_free (newcaps);
-  return NULL;
+  return TRUE;
 }
 
-static GstCaps *
-gst_v4lsrc_getcaps (GstPad * pad)
+/* 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_v4lsrc_start (GstBaseSrc * src)
 {
-  GstCaps *list;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
-  struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
-  gdouble fps;
-  GList *item;
-
-  if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
-    return gst_v4lsrc_get_any_caps ();
-  }
-  if (!v4lsrc->autoprobe) {
-    /* FIXME: query current caps and return those, with _any appended */
-    return gst_v4lsrc_get_any_caps ();
-  }
-  fps = gst_v4lsrc_get_fps (v4lsrc);
-
-  list = gst_caps_new_empty ();
-  for (item = v4lsrc->colourspaces; item != NULL; item = item->next) {
-    GstCaps *one;
+  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
 
-    one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data));
-    if (!one) {
-      GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n",
-          GPOINTER_TO_INT (item->data));
-      continue;
-    }
-
-    GST_DEBUG_OBJECT (v4lsrc,
-        "Device reports w: %d-%d, h: %d-%d, fps: %f for palette %d",
-        vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps,
-        GPOINTER_TO_INT (item->data));
-
-    if (vcap->minwidth < vcap->maxwidth) {
-      gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
-          vcap->maxwidth, NULL);
-    } else {
-      gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL);
-    }
-    if (vcap->minheight < vcap->maxheight) {
-      gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight,
-          vcap->maxheight, NULL);
-    } else {
-      gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL);
-    }
-
-    if (v4lsrc->autoprobe_fps) {
-      if (v4lsrc->fps_list) {
-        GstStructure *structure = gst_caps_get_structure (one, 0);
-
-        gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
-      } else {
-        gst_caps_set_simple (one, "framerate", G_TYPE_DOUBLE, fps, NULL);
-      }
-    } else {
-      gst_caps_set_simple (one, "framerate", GST_TYPE_DOUBLE_RANGE,
-          (gdouble) 1.0, (gdouble) 100.0, NULL);
-    }
+  if (!GST_BASE_SRC_CLASS (parent_class)->start (src))
+    return FALSE;
 
-    GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
-    gst_caps_append (list, one);
-  }
+  v4lsrc->offset = 0;
 
-  return list;
+  return TRUE;
 }
 
-
-static GstData *
-gst_v4lsrc_get (GstPad * pad)
+static gboolean
+gst_v4lsrc_stop (GstBaseSrc * src)
 {
-  GstV4lSrc *v4lsrc;
-  GstBuffer *buf;
-  gint num;
-  gdouble fps = 0.;
-  v4lsrc_private_t *v4lsrc_private = NULL;
-  GstClockTime now, until;
-  gboolean fixed_fps;
-
-  g_return_val_if_fail (pad != NULL, NULL);
-
-  v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
-  fps = gst_v4lsrc_get_fps (v4lsrc);
-
-  fixed_fps = v4lsrc->syncmode == GST_V4LSRC_SYNC_MODE_FIXED_FPS;
-
-  if (fixed_fps && fps == 0.0)
-    return NULL;
-
-  if (v4lsrc->need_writes > 0) {
-    /* use last frame */
-    num = v4lsrc->last_frame;
-    v4lsrc->need_writes--;
-  } else if (v4lsrc->clock && fixed_fps) {
-    GstClockTime time;
-    gboolean have_frame = FALSE;
-
-    do {
-      /* by default, we use the frame once */
-      v4lsrc->need_writes = 1;
-
-      /* grab a frame from the device */
-      if (!gst_v4lsrc_grab_frame (v4lsrc, &num))
-        return NULL;
-
-      v4lsrc->last_frame = num;
-      time = v4lsrc->timestamp_sync - v4lsrc->substract_time;
-
-      /* decide how often we're going to write the frame - set
-       * v4lsrc->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 (v4lsrc->handled * (GST_SECOND / fps) - time >
-          1.5 * (GST_SECOND / fps)) {
-        /* yo dude, we've got too many frames here! Drop! DROP! */
-        v4lsrc->need_writes--;  /* -= (v4lsrc->handled - (time / fps)); */
-        g_signal_emit (G_OBJECT (v4lsrc),
-            gst_v4lsrc_signals[SIGNAL_FRAME_DROP], 0);
-      } else if (v4lsrc->handled * (GST_SECOND / fps) - time <
-          -1.5 * (GST_SECOND / fps)) {
-        /* this means we're lagging far behind */
-        v4lsrc->need_writes++;  /* += ((time / fps) - v4lsrc->handled); */
-        g_signal_emit (G_OBJECT (v4lsrc),
-            gst_v4lsrc_signals[SIGNAL_FRAME_INSERT], 0);
-      }
+  GstV4lSrc *v4lsrc = GST_V4LSRC (src);
 
-      if (v4lsrc->need_writes > 0) {
-        have_frame = TRUE;
-        v4lsrc->use_num_times[num] = v4lsrc->need_writes;
-        v4lsrc->need_writes--;
-      } else {
-        gst_v4lsrc_requeue_frame (v4lsrc, num);
-      }
-    } while (!have_frame);
-  } else {
-    /* grab a frame from the device */
-    if (!gst_v4lsrc_grab_frame (v4lsrc, &num))
-      return NULL;
-
-    v4lsrc->use_num_times[num] = 1;
-  }
-
-  buf = gst_buffer_new ();
-  GST_BUFFER_FREE_DATA_FUNC (buf) = gst_v4lsrc_buffer_free;
-  /* to requeue buffers, we need a ref to the element, as well as the frame
-     number we got this buffer from */
-  v4lsrc_private = g_malloc (sizeof (v4lsrc_private_t));
-  v4lsrc_private->v4lsrc = v4lsrc;
-  v4lsrc_private->num = num;
-  GST_BUFFER_PRIVATE (buf) = v4lsrc_private;
-
-  /* don't | the flags, they are integers, not bits!! */
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY);
-  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
-  GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
-  GST_BUFFER_MAXSIZE (buf) = v4lsrc->mbuf.size / v4lsrc->mbuf.frames;
-  GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
-
-  if (v4lsrc->copy_mode) {
-    GstBuffer *copy = gst_buffer_copy (buf);
-
-    gst_buffer_unref (buf);
-    buf = copy;
-  }
-
-  switch (v4lsrc->syncmode) {
-    case GST_V4LSRC_SYNC_MODE_FIXED_FPS:
-      GST_BUFFER_TIMESTAMP (buf) = v4lsrc->handled * GST_SECOND / fps;
-      break;
-    case GST_V4LSRC_SYNC_MODE_PRIVATE_CLOCK:
-      /* calculate time based on our own clock */
-      GST_BUFFER_TIMESTAMP (buf) =
-          v4lsrc->timestamp_sync - v4lsrc->substract_time;
-      break;
-    case GST_V4LSRC_SYNC_MODE_CLOCK:
-      if (v4lsrc->clock) {
-        GstClockTime time = gst_element_get_time (GST_ELEMENT (v4lsrc));
-        GstClockTimeDiff target_ts = 0;
-
-        /* we can't go negative for timestamps.  FIXME: latency querying
-         * in the core generally should solve this */
-        target_ts = GST_CLOCK_DIFF (time, v4lsrc->latency_offset);
-        if (target_ts < 0)
-          target_ts = 0;
-        /* FIXME: create GST_TIME_DIFF_ARGS for target_ts */
-        GST_LOG_OBJECT (v4lsrc, "time: %" GST_TIME_FORMAT
-            ", latency-offset: %" GST_TIME_FORMAT
-            ", timestamp: %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (time), GST_TIME_ARGS (v4lsrc->latency_offset),
-            GST_TIME_ARGS (target_ts));
-        GST_BUFFER_TIMESTAMP (buf) = target_ts;
-      } else {
-        GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
-      }
-      break;
-    case GST_V4LSRC_SYNC_MODE_NONE:
-      GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
-      break;
-    default:
-      break;
-  }
-  GST_BUFFER_DURATION (buf) = GST_SECOND / fps;
-
-  GST_LOG_OBJECT (v4lsrc, "outgoing buffer duration: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
-
-  v4lsrc->handled++;
-  g_signal_emit (G_OBJECT (v4lsrc),
-      gst_v4lsrc_signals[SIGNAL_FRAME_CAPTURE], 0);
-
-  /* this is the current timestamp */
-  now = gst_element_get_time (GST_ELEMENT (v4lsrc));
-
-  until = GST_BUFFER_TIMESTAMP (buf);
-
-  GST_LOG_OBJECT (v4lsrc, "Current time %" GST_TIME_FORMAT
-      ", buffer timestamp %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (now), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-  if (now < until) {
-    GST_LOG_OBJECT (v4lsrc, "waiting until %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (until));
-    if (!gst_element_wait (GST_ELEMENT (v4lsrc), until))
-      GST_WARNING_OBJECT (v4lsrc, "waiting from now %" GST_TIME_FORMAT
-          " until %" GST_TIME_FORMAT " failed",
-          GST_TIME_ARGS (now), GST_TIME_ARGS (until));
-    GST_LOG_OBJECT (v4lsrc, "wait done.");
-  }
-  /* check for discont; we do it after grabbing so that we drop the
-   * first frame grabbed, but get an accurate discont event  */
-  if (v4lsrc->need_discont) {
-    GstEvent *event;
-
-    v4lsrc->need_discont = FALSE;
-
-    /* drop the buffer we made */
-    gst_buffer_unref (buf);
-
-    /* get time for discont */
-    now = gst_element_get_time (GST_ELEMENT (v4lsrc));
-    GST_DEBUG_OBJECT (v4lsrc, "sending time discont with %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (now));
-
-    /* store discont internally so we can wait when sending buffers too soon */
-    v4lsrc->last_discont = now;
+  if (!gst_v4lsrc_capture_stop (v4lsrc))
+    return FALSE;
 
-    /* return event */
-    event = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, now, NULL);
-    return GST_DATA (event);
+  if (GST_V4LELEMENT (v4lsrc)->buffer != NULL) {
+    if (!gst_v4lsrc_capture_deinit (v4lsrc))
+      return FALSE;
   }
-  return GST_DATA (buf);
-}
-
 
-static void
-gst_v4lsrc_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstV4lSrc *v4lsrc;
-
-  g_return_if_fail (GST_IS_V4LSRC (object));
-  v4lsrc = GST_V4LSRC (object);
-
-  switch (prop_id) {
-    case ARG_SYNC_MODE:
-      if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
-        v4lsrc->syncmode = g_value_get_enum (value);
-      }
-      break;
-
-    case ARG_COPY_MODE:
-      v4lsrc->copy_mode = g_value_get_boolean (value);
-      break;
-
-    case ARG_AUTOPROBE:
-      if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
-        v4lsrc->autoprobe = g_value_get_boolean (value);
-      }
-      break;
-
-    case ARG_AUTOPROBE_FPS:
-      if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) {
-        v4lsrc->autoprobe_fps = g_value_get_boolean (value);
-      }
-      break;
-
-
-    case ARG_LATENCY_OFFSET:
-      v4lsrc->latency_offset = g_value_get_int (value);
-      break;
+  if (!GST_BASE_SRC_CLASS (parent_class)->stop (src))
+    return FALSE;
 
+  g_list_free (v4lsrc->colorspaces);
+  v4lsrc->colorspaces = NULL;
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  if (v4lsrc->fps_list) {
+    g_value_unset (v4lsrc->fps_list);
+    g_free (v4lsrc->fps_list);
+    v4lsrc->fps_list = NULL;
   }
-}
-
 
-static void
-gst_v4lsrc_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstV4lSrc *v4lsrc;
-
-  g_return_if_fail (GST_IS_V4LSRC (object));
-  v4lsrc = GST_V4LSRC (object);
-
-  switch (prop_id) {
-    case ARG_NUMBUFS:
-      g_value_set_int (value, v4lsrc->mbuf.frames);
-      break;
-
-    case ARG_BUFSIZE:
-      if (v4lsrc->mbuf.frames == 0)
-        g_value_set_int (value, 0);
-      else
-        g_value_set_int (value,
-            v4lsrc->mbuf.size / (v4lsrc->mbuf.frames * 1024));
-      break;
-
-    case ARG_SYNC_MODE:
-      g_value_set_enum (value, v4lsrc->syncmode);
-      break;
-
-    case ARG_COPY_MODE:
-      g_value_set_boolean (value, v4lsrc->copy_mode);
-      break;
-
-    case ARG_AUTOPROBE:
-      g_value_set_boolean (value, v4lsrc->autoprobe);
-      break;
-
-    case ARG_AUTOPROBE_FPS:
-      g_value_set_boolean (value, v4lsrc->autoprobe_fps);
-      break;
-
-    case ARG_LATENCY_OFFSET:
-      g_value_set_int (value, v4lsrc->latency_offset);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+  return TRUE;
 }
 
-
-static GstElementStateReturn
-gst_v4lsrc_change_state (GstElement * element)
+static GstFlowReturn
+gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** buf)
 {
   GstV4lSrc *v4lsrc;
-  GTimeVal time;
-  gint transition = GST_STATE_TRANSITION (element);
-  GstElementStateReturn parent_ret = GST_STATE_SUCCESS;
-
-  g_return_val_if_fail (GST_IS_V4LSRC (element), GST_STATE_FAILURE);
-
-  v4lsrc = GST_V4LSRC (element);
-
-  /* pre-parent state change */
-  switch (transition) {
-    case GST_STATE_READY_TO_PAUSED:
-      v4lsrc->handled = 0;
-      v4lsrc->need_discont = TRUE;
-      v4lsrc->last_discont = 0;
-      v4lsrc->need_writes = 0;
-      v4lsrc->last_frame = 0;
-      v4lsrc->substract_time = 0;
-      /* buffer setup used to be done here, but I moved it to
-       * capsnego */
-      break;
-    case GST_STATE_PAUSED_TO_PLAYING:
-      /* queue all buffer, start streaming capture */
-      if (GST_V4LELEMENT (v4lsrc)->buffer != NULL &&
-          !gst_v4lsrc_capture_start (v4lsrc))
-        return GST_STATE_FAILURE;
-      g_get_current_time (&time);
-      v4lsrc->substract_time =
-          GST_TIMEVAL_TO_TIME (time) - v4lsrc->substract_time;
-      break;
-    case GST_STATE_PLAYING_TO_PAUSED:
-      /* de-queue all queued buffers */
-      if (v4lsrc->is_capturing && !gst_v4lsrc_capture_stop (v4lsrc))
-        return GST_STATE_FAILURE;
-      gst_v4lsrc_capture_stop (v4lsrc);
-      g_get_current_time (&time);
-      v4lsrc->substract_time =
-          GST_TIMEVAL_TO_TIME (time) - v4lsrc->substract_time;
-      break;
-    case GST_STATE_PAUSED_TO_READY:
-      /* stop capturing, unmap all buffers */
-      if (GST_V4LELEMENT (v4lsrc)->buffer != NULL &&
-          !gst_v4lsrc_capture_deinit (v4lsrc))
-        return GST_STATE_FAILURE;
-      break;
-    case GST_STATE_READY_TO_NULL:
-      break;
-  }
+  gint num;
 
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    parent_ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
-
-  /* post-parent change_state */
-  switch (transition) {
-    case GST_STATE_NULL_TO_READY:
-      GST_DEBUG_OBJECT (v4lsrc,
-          "Doing post-parent NULL_TO_READY, checking probes");
-      if (v4lsrc->autoprobe_fps) {
-        GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates");
-        v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc);
-      }
-    default:
-      break;
-  }
+  v4lsrc = GST_V4LSRC (src);
 
-  return parent_ret;
-}
+  /* grab a frame from the device */
+  if (!gst_v4lsrc_grab_frame (v4lsrc, &num))
+    return GST_FLOW_ERROR;
 
+  *buf = gst_v4lsrc_buffer_new (v4lsrc, num);
 
 #if 0
-static GstBuffer *
-gst_v4lsrc_buffer_new (GstBufferPool * pool,
-    guint64 offset, guint size, gpointer user_data)
-{
-  GstBuffer *buffer;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (user_data);
+  GstBuffer *copy = gst_buffer_copy (buf);
 
-  if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)))
-    return NULL;
-
-  buffer = gst_buffer_new ();
-  if (!buffer)
-    return NULL;
-
-  /* TODO: add interlacing info to buffer as metadata
-   * (height>288 or 240 = topfieldfirst, else noninterlaced) */
-  GST_BUFFER_MAXSIZE (buffer) = v4lsrc->mbuf.size / v4lsrc->mbuf.frames;
-  GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE);
-
-  return buffer;
-}
+  gst_buffer_unref (buf);
+  buf = copy;
 #endif
 
-static void
-gst_v4lsrc_buffer_free (GstBuffer * buf)
-{
-  v4lsrc_private_t *v4lsrc_private;
-  GstV4lSrc *v4lsrc;
-  int num;
-
-  v4lsrc_private = GST_BUFFER_PRIVATE (buf);
-  g_assert (v4lsrc_private);
-  v4lsrc = v4lsrc_private->v4lsrc;
-  num = v4lsrc_private->num;
-  g_free (v4lsrc_private);
-  GST_BUFFER_PRIVATE (buf) = 0;
-
-  GST_LOG_OBJECT (v4lsrc, "freeing buffer %p with refcount %d for frame %d",
-      buf, GST_BUFFER_REFCOUNT_VALUE (buf), num);
-  if (gst_element_get_state (GST_ELEMENT (v4lsrc)) != GST_STATE_PLAYING)
-    return;                     /* we've already cleaned up ourselves */
-
-  v4lsrc->use_num_times[num]--;
-  if (v4lsrc->use_num_times[num] <= 0) {
-    GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
-    gst_v4lsrc_requeue_frame (v4lsrc, num);
-  }
-}
-
-
-static void
-gst_v4lsrc_set_clock (GstElement * element, GstClock * clock)
-{
-  GST_V4LSRC (element)->clock = clock;
+  return GST_FLOW_OK;
 }
index 2105c36..6aec993 100644 (file)
 #ifndef __GST_V4LSRC_H__
 #define __GST_V4LSRC_H__
 
+
 #include <gstv4lelement.h>
 
+
 G_BEGIN_DECLS
+
+
 #define GST_TYPE_V4LSRC \
   (gst_v4lsrc_get_type())
 #define GST_V4LSRC(obj) \
@@ -36,9 +40,12 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LSRC))
 #define GST_IS_V4LSRC_CLASS(obj) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LSRC))
+
+
 typedef struct _GstV4lSrc GstV4lSrc;
 typedef struct _GstV4lSrcClass GstV4lSrcClass;
 
+
 enum
 {
   QUEUE_STATE_ERROR = -1,
@@ -47,13 +54,6 @@ enum
   QUEUE_STATE_SYNCED            /* the frame is captured */
 };
 
-typedef enum
-{
-  GST_V4LSRC_SYNC_MODE_CLOCK,
-  GST_V4LSRC_SYNC_MODE_PRIVATE_CLOCK,
-  GST_V4LSRC_SYNC_MODE_FIXED_FPS,
-  GST_V4LSRC_SYNC_MODE_NONE,
-} GstV4lSrcSyncMode;
 
 struct _GstV4lSrc
 {
@@ -76,34 +76,17 @@ struct _GstV4lSrc
   gint num_queued;
   gint sync_frame, queue_frame;
   gboolean is_capturing;
-  GstClockTimeDiff latency_offset;
+  GstClockTimeDiff timestamp_offset;
 
   /* True if we want to stop */
   gboolean quit;
 
-  /* A/V sync... frame counter and internal cache */
-  gulong handled;
-  gint last_frame;
-  gint need_writes;
-  gboolean need_discont;
-  GstClockTime last_discont;    /* gst_element_get_time () of last discont send */
+  gint offset;
+  gfloat fps;
 
-  /* clock */
-  GstClock *clock;
+  /* list of supported colorspaces (as integers) */
+  GList *colorspaces;
 
-  /* time to substract from clock time to get back to timestamp */
-  GstClockTime substract_time;
-
-  /* how often are we going to use each frame? */
-  gint *use_num_times;
-
-  /* list of supported colourspaces (as integers) */
-  GList *colourspaces;
-
-  /* how are we going to timestamp buffers? */
-  GstV4lSrcSyncMode syncmode;
-
-  gboolean copy_mode;
   gboolean autoprobe;           /* probe features on startup ? */
   gboolean autoprobe_fps;       /* probe fps on startup ? */
 
@@ -113,14 +96,13 @@ struct _GstV4lSrc
 struct _GstV4lSrcClass
 {
   GstV4lElementClass parent_class;
-
-  void (*frame_capture) (GObject * object);
-  void (*frame_drop) (GObject * object);
-  void (*frame_insert) (GObject * object);
 };
 
+
 GType gst_v4lsrc_get_type (void);
 
 
 G_END_DECLS
+
+
 #endif /* __GST_V4LSRC_H__ */
index 37a2748..2337eba 100644 (file)
@@ -25,7 +25,6 @@
 #endif
 
 #include <gst/gst.h>
-#include <gst/tuner/tuner.h>
 
 #include "gstv4ltuner.h"
 #include "gstv4lelement.h"
index c5337fe..0b42f81 100644 (file)
@@ -24,7 +24,7 @@
 #define __GST_V4L_TUNER_H__
 
 #include <gst/gst.h>
-#include <gst/tuner/tuner.h>
+#include <gst/interfaces/tuner.h>
 
 G_BEGIN_DECLS
 
index 5fe5cf7..b169b4a 100644 (file)
 #endif
 
 #include <string.h>
-#include <gst/gst.h>
-#include <gst/xoverlay/xoverlay.h>
+#include <sys/stat.h>
+
 #include <X11/X.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/Xv.h>
 #include <X11/extensions/Xvlib.h>
-#include <sys/stat.h>
 
 #include "gstv4lxoverlay.h"
 #include "gstv4lelement.h"
index 82c26f9..9f7993a 100644 (file)
@@ -24,7 +24,7 @@
 #define __GST_V4L_X_OVERLAY_H__
 
 #include <gst/gst.h>
-#include <gst/xoverlay/xoverlay.h>
+#include <gst/interfaces/xoverlay.h>
 
 #include "gstv4lelement.h"
 
index 6d28add..72fa567 100644 (file)
 #include <unistd.h>
 
 #include <gst/gst.h>
-#include <gst/tuner/tuner.h>
-#include <gst/colorbalance/colorbalance.h>
+#include <gst/interfaces/tuner.h>
+#include <gst/interfaces/colorbalance.h>
 
 #include "v4l_calls.h"
 #include "gstv4ltuner.h"
 #include "gstv4lcolorbalance.h"
 
 #include "gstv4lsrc.h"
-#include "gstv4lmjpegsrc.h"
-#include "gstv4lmjpegsink.h"
+/* #include "gstv4lmjpegsrc.h" */
+/* #include "gstv4lmjpegsink.h" */
 
 GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
 #define GST_CAT_DEFAULT v4l_debug
@@ -183,11 +183,11 @@ gst_v4l_open (GstV4lElement * v4lelement)
 
   /* device type check */
   if ((GST_IS_V4LSRC (v4lelement) &&
-          !(v4lelement->vcap.type & VID_TYPE_CAPTURE)) ||
-      (GST_IS_V4LMJPEGSRC (v4lelement) &&
-          !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) ||
-      (GST_IS_V4LMJPEGSINK (v4lelement) &&
-          !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) {
+          !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) {
+/*       (GST_IS_V4LMJPEGSRC (v4lelement) && */
+/*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */
+/*       (GST_IS_V4LMJPEGSINK (v4lelement) && */
+/*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */
     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
         ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type));
     close (v4lelement->video_fd);
@@ -286,7 +286,6 @@ GList *
 gst_v4l_get_chan_names (GstV4lElement * v4lelement)
 {
   struct video_channel vchan;
-  const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4lelement));
   GList *list = NULL;
   gint i;
 
@@ -295,11 +294,6 @@ gst_v4l_get_chan_names (GstV4lElement * v4lelement)
   if (!GST_V4L_IS_OPEN (v4lelement))
     return NULL;
 
-  /* sinks don't have inputs in v4l */
-  if (pads && g_list_length ((GList *) pads) == 1)
-    if (GST_PAD_DIRECTION (GST_PAD (pads->data)) == GST_PAD_SINK)
-      return NULL;
-
   for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) {
     GstV4lTunerChannel *v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL,
         NULL);
index 5af7f90..c3af3ed 100644 (file)
 #include "gstv4lelement.h"
 #include "gst/gst-i18n-plugin.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+
+G_BEGIN_DECLS
 
 
 /* simple check whether the device is open */
 #define GST_V4L_IS_OPEN(element) \
-  (element->video_fd > 0)
+  (GST_V4LELEMENT (element)->video_fd > 0)
 
 /* check whether the device is 'active' */
 #define GST_V4L_IS_ACTIVE(element) \
-  (element->buffer != NULL)
+  (GST_V4LELEMENT (element)->buffer != NULL)
 
 #define GST_V4L_IS_OVERLAY(element) \
-  (element->vcap.type & VID_TYPE_OVERLAY)
+  (GST_V4LELEMENT (element)->vcap.type & VID_TYPE_OVERLAY)
 
 /* checks whether the current v4lelement has already been open()'ed or not */
 #define GST_V4L_CHECK_OPEN(element)                            \
-  if (element->video_fd <= 0)                                  \
+  if (!GST_V4L_IS_OPEN (element))                              \
   {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,            \
       (_("Device is not open.")), (NULL));                     \
@@ -53,7 +52,7 @@ extern "C" {
 
 /* checks whether the current v4lelement is close()'ed or whether it is still open */
 #define GST_V4L_CHECK_NOT_OPEN(element)                                \
-  if (element->video_fd != -1)                                 \
+  if (GST_V4L_IS_OPEN (element))                               \
   {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY,            \
       (_("Device is open.")), (NULL));                         \
@@ -71,7 +70,7 @@ extern "C" {
 
 /* checks whether we're in capture mode or not */
 #define GST_V4L_CHECK_ACTIVE(element)                          \
-  if (element->buffer == NULL)                                 \
+  if (!GST_V4L_IS_ACTIVE (element))                            \
   {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,            \
       (NULL), ("Device is not in streaming mode"));            \
@@ -80,7 +79,7 @@ extern "C" {
 
 /* checks whether we're out of capture mode or not */
 #define GST_V4L_CHECK_NOT_ACTIVE(element)                      \
-  if (element->buffer != NULL)                                 \
+  if (GST_V4L_IS_ACTIVE (element))                             \
   {                                                            \
     GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS,            \
       (NULL), ("Device is in streaming mode"));                        \
@@ -148,8 +147,8 @@ gboolean gst_v4l_set_audio      (GstV4lElement *v4lelement,
 gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement);
 gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+
+G_END_DECLS
+
 
 #endif /* __V4L_CALLS_H__ */
index 91feeeb..fc4aa39 100644 (file)
@@ -128,15 +128,6 @@ gst_v4lsrc_sync_frame (GstV4lSrc * v4lsrc, gint num)
   }
   GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d done", num);
 
-  if (v4lsrc->clock) {
-    v4lsrc->timestamp_sync = gst_clock_get_time (v4lsrc->clock);
-  } else {
-    GTimeVal time;
-
-    g_get_current_time (&time);
-    v4lsrc->timestamp_sync = GST_TIMEVAL_TO_TIME (time);
-  }
-
   v4lsrc->frame_queue_state[num] = QUEUE_STATE_SYNCED;
   v4lsrc->num_queued--;
 
@@ -201,10 +192,6 @@ gst_v4lsrc_capture_init (GstV4lSrc * v4lsrc)
   v4lsrc->frame_queue_state = (gint8 *)
       g_malloc (sizeof (gint8) * v4lsrc->mbuf.frames);
 
-  /* track how often to use each frame */
-  v4lsrc->use_num_times = (gint *)
-      g_malloc (sizeof (gint) * v4lsrc->mbuf.frames);
-
   /* lock for the frame_state */
   v4lsrc->mutex_queue_state = g_mutex_new ();
   v4lsrc->cond_queue_state = g_cond_new ();
@@ -308,9 +295,6 @@ gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num)
   }
   v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames;
 
-  GST_LOG_OBJECT (v4lsrc, "(%" GST_TIME_FORMAT ") grabbed frame %d",
-      GST_TIME_ARGS (gst_clock_get_time (v4lsrc->clock)), *num);
-
   g_mutex_unlock (v4lsrc->mutex_queue_state);
 
   return TRUE;
@@ -427,8 +411,6 @@ gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc)
   v4lsrc->cond_queue_state = NULL;
   g_free (v4lsrc->frame_queue_state);
   v4lsrc->frame_queue_state = NULL;
-  g_free (v4lsrc->use_num_times);
-  v4lsrc->use_num_times = NULL;
 
   /* unmap the buffer */
   if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) {
@@ -542,13 +524,7 @@ gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
     return current_fps;
   }
 
-  if (!(v4lsrc->syncmode == GST_V4LSRC_SYNC_MODE_FIXED_FPS) &&
-      v4lsrc->clock != NULL && v4lsrc->handled > 0) {
-    /* try to get time from clock master and calculate fps */
-    GstClockTime time =
-        gst_clock_get_time (v4lsrc->clock) - v4lsrc->substract_time;
-    return v4lsrc->handled * GST_SECOND / time;
-  }
+  /* removed fps estimation code here */
 
   /* if that failed ... */
 
@@ -565,3 +541,175 @@ gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc)
 
   return fps;
 }
+
+/* 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_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
+{
+  gint fps_index;
+  gfloat fps;
+  struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
+  GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc);
+
+  /* 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 (v4lsrc, "fps_index is 0, no webcam");
+    return NULL;
+  }
+  GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
+
+  {
+    gfloat current_fps;
+    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 */
+    current_fps = fps_index * 15.0 / 16;
+    GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %.4f", current_fps);
+    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_v4l_set_window_properties (v4lelement)) {
+        /* setting it succeeded.  FIXME: get it and check. */
+        fps = i * 15.0 / 16;
+        g_value_init (&value, G_TYPE_DOUBLE);
+        g_value_set_double (&value, fps);
+        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_v4l_set_window_properties (v4lelement);
+    return list;
+  }
+  return NULL;
+}
+
+#define GST_TYPE_V4LSRC_BUFFER (gst_v4lsrc_buffer_get_type())
+#define GST_IS_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4LSRC_BUFFER))
+#define GST_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4LSRC_BUFFER, GstV4lSrcBuffer))
+
+typedef struct _GstV4lSrcBuffer
+{
+  GstBuffer buffer;
+
+  GstV4lSrc *v4lsrc;
+
+  gint num;
+} GstV4lSrcBuffer;
+
+static void gst_v4lsrc_buffer_class_init (gpointer g_class,
+    gpointer class_data);
+static void gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class);
+static void gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer);
+
+GType
+gst_v4lsrc_buffer_get_type (void)
+{
+  static GType _gst_v4lsrc_buffer_type;
+
+  if (G_UNLIKELY (_gst_v4lsrc_buffer_type == 0)) {
+    static const GTypeInfo v4lsrc_buffer_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_v4lsrc_buffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstV4lSrcBuffer),
+      0,
+      gst_v4lsrc_buffer_init,
+      NULL
+    };
+    _gst_v4lsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
+        "GstV4lSrcBuffer", &v4lsrc_buffer_info, 0);
+  }
+  return _gst_v4lsrc_buffer_type;
+}
+
+static void
+gst_v4lsrc_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_v4lsrc_buffer_finalize;
+}
+
+static void
+gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class)
+{
+
+}
+
+static void
+gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer)
+{
+  GstV4lSrc *v4lsrc;
+  gint num;
+
+  v4lsrc = v4lsrc_buffer->v4lsrc;
+  num = v4lsrc_buffer->num;
+
+  GST_LOG_OBJECT (v4lsrc, "freeing buffer %p for frame %d", v4lsrc_buffer, num);
+
+  /* only requeue if we still have an mmap buffer */
+  if (GST_V4LELEMENT (v4lsrc)->buffer) {
+    GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
+    gst_v4lsrc_requeue_frame (v4lsrc, num);
+  }
+
+  gst_object_unref (v4lsrc);
+}
+
+/* Create a V4lSrc buffer from our mmap'd data area */
+GstBuffer *
+gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
+{
+  GstBuffer *buf;
+
+  GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
+
+  buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4LSRC_BUFFER);
+
+  GST_V4LSRC_BUFFER (buf)->num = num;
+  GST_V4LSRC_BUFFER (buf)->v4lsrc = gst_object_ref (v4lsrc);
+
+  GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
+  GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
+  GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
+  GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
+  GST_BUFFER_TIMESTAMP (buf) = gst_clock_get_time (GST_ELEMENT (v4lsrc)->clock);
+  GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4lsrc)->base_time;
+  /* fixme: this is a most ghetto timestamp/duration */
+
+  if (!v4lsrc->fps)
+    v4lsrc->fps = gst_v4lsrc_get_fps (v4lsrc);
+  if (v4lsrc->fps)
+    GST_BUFFER_DURATION (buf) = GST_SECOND / v4lsrc->fps;
+
+  /* the negotiate() method already set caps on the source pad */
+  gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
+
+  return buf;
+}
index f26eb55..6b92542 100644 (file)
@@ -26,9 +26,8 @@
 #include "gstv4lsrc.h"
 #include "v4l_calls.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+
+G_BEGIN_DECLS
 
 
 /* frame grabbing/capture (palette = VIDEO_PALETTE_* - see videodev.h) */
@@ -41,6 +40,8 @@ gboolean gst_v4lsrc_requeue_frame  (GstV4lSrc *v4lsrc, gint  num);
 gboolean gst_v4lsrc_capture_stop   (GstV4lSrc *v4lsrc);
 gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
 gfloat   gst_v4lsrc_get_fps        (GstV4lSrc * v4lsrc);
+GValue * gst_v4lsrc_get_fps_list   (GstV4lSrc * v4lsrc);
+GstBuffer *gst_v4lsrc_buffer_new   (GstV4lSrc * v4lsrc, gint num);
 
 /* "the ugliest hack ever, now available at your local mirror" */
 gboolean gst_v4lsrc_try_capture    (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
@@ -48,8 +49,8 @@ gboolean gst_v4lsrc_try_capture    (GstV4lSrc *v4lsrc, gint width, gint height,
 /* For debug purposes, share the palette names */
 const char *gst_v4lsrc_palette_name (int i);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+
+G_END_DECLS
+
 
 #endif /* __V4L_SRC_CALLS_H__ */