dc1394src: port to 1.X
authorJoan Pau Beltran <joanpau.beltran@socib.cat>
Tue, 10 May 2016 16:30:35 +0000 (18:30 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Thu, 9 Jun 2016 20:47:58 +0000 (21:47 +0100)
The dc1394src is a PushSrc element for IIDC cameras based on libdc1394.
The implementation from the 0.x series is deffective:
caps negotiation does not work, and some video formats
provided by the camera are not supported.

Refactor the code to port it to 1.X and enhance the support
for the full set of video options of IIDC cameras:

  - The IIDC specification includes a set of camera video modes
    (video format, frame size, and frame rates).
    They do not map perfectly to Gstreamer formats, but those that
    do not match are very rare (if used at all by any camera).
    In addition, although the specification includes a raw format,
    some cameras use mono video formats to capture in Bayer format.
    Map corresponding video modes to Gstreamer formats in capabilities,
    allowing both gray raw and Bayer video formats for mono video modes.

  - The specification includes scalable video modes (Format7),
    where the frame size and rate can be set to arbitrary values
    (within the limits of the camera and the bus transport).
    Allow the use of such mode, using the frame size and rate
    from the negotiatied caps, and set the camera frame rate
    adjusting the packet size as in:
    <http://damien.douxchamps.net/ieee1394/libdc1394/faq/#How_do_I_set_the_frame_rate>

    The scalable modes also allow for a custom ROI offset.
    Support for it can be easily added later using properties.

  - Camera operation using libdc1394 is as follows:

      1. Enumerate cameras on the system and open the camera
         identified the enumeration index or by a GUID (64bit hex code).

      2. Query the video formats supported by the camera.

      3. Configure the camera for the desired video format.

      4. Setup the capture resources for the configured video format
         and start the camera transmission.

      5. Capture frames from the camera and release them when not used.

      6. Stop the camera transmission and clear the capture resources.

      7. Close the camera freeing its resources.

    Do steps 2 and 3 when getting and setting the caps respectively.
    Ideally 4 and 6 would be done when going from PAUSED to PLAYING
    and viceversa, but since caps might not be set yet, the video mode
    is not properly configured leaving the camera in a broken state.
    Hence, setup capture and start transmission in the set caps method,
    and consequently clear the capture and stop the transmission
    when going from PAUSED to READY (instead of PLAYING to PAUSED).
    Symmetrycally, open the camera when going from READY to PAUSED,
    allowing to probe the camera caps in the negotiation stage.
    Implement that using the `start` and `stop` methods of `GstBaseSrc`,
    instead of the `change-state` method of `GstElement`.
    Stop the camera before setting new caps and restarting it again
    to handle caps reconfiguration while in PLAYING (it has no effect
    if the camera is not started).

  - Create buffers copying the bytes of the captured frames.
    Alternatively, the buffers could just wrap the bytes of the frames,
    releasing the frame in the buffer's destroy notify function,
    if all buffers were destroyed before going from PLAYING to PAUSED.

  - No timestamp nor offset is set when creating buffers.
    Timestamping is delegated to the parent class BaseSrc,
    setting `gst_base_src_set_live` TRUE, `gst_base_src_set_format`
    with GST_FORMAT_TIME and `gst_base_src_set_do_timestamp`.
    Captured frames have a timestamp field with the system time
    at the completion of the transmission of the frame,
    but it is not sure that this comes from a monotonic clock,
    and it seems to be left NULL in Windows.

  - Use GUID and unit properties to select the camera to operate on.
    The camera number used in version 0.X does not uniquely identify
    the device (it depends on the set of cameras currently detected).
    Since the GUID is 64bit identifier (same as MAC address),
    handle it with a string property with its hexadecimal representation.
    For practicality, operate on the first camera available if the GUID
    is null (default) and match any camera unit number if unit is -1.
    Alternatively, the GUID could be handed with an unsigned 64 bit
    integer type property, using `0xffffffffffffffff` as default value
    to select the first camera available (it is not a valid GUID value).

  - Keep name `GstDc1394` and prefix `gst_dc1394` as in version 0.X,
    although `GstDC1394Src` and `gst_dc1394_src` are more descriptive.

  - Adjust build files to reenable the compilation of the plugin.

    Remove dc1394 from the list of unported plugins in configure.ac.

    Add the missing flags and libraries to Makefile.
    Use `$()` for variable substitution, as many plugins do,
    although other plugins use `@@` instead.

https://bugzilla.gnome.org/show_bug.cgi?id=763026

configure.ac
ext/dc1394/Makefile.am
ext/dc1394/gstdc1394.c
ext/dc1394/gstdc1394.h

index ce06ab6..833cfae 100644 (file)
@@ -450,7 +450,7 @@ GST_PLUGINS_NONPORTED=" cdxaparse \
  sdi tta \
  videomeasure \
  linsys \
- apexsink dc1394 \
+ apexsink \
  musepack nas sdl timidity \
  wininet \
  xvid sndio libvisual"
index eb1a4f7..e917415 100644 (file)
@@ -1,16 +1,22 @@
+plugin_LTLIBRARIES = \
+    libgstdc1394.la
 
-plugin_LTLIBRARIES =   libgstdc1394.la
+libgstdc1394_la_SOURCES = \
+    gstdc1394.c
+libgstdc1394_la_CFLAGS = \
+    $(LIBDC1394_CFLAGS) \
+    $(GST_PLUGINS_BASE_CFLAGS) \
+    $(GST_BASE_CFLAGS) \
+    $(GST_CFLAGS)
+libgstdc1394_la_LIBADD = \
+    $(LIBDC1394_LIBS) \
+    $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \
+    $(GST_BASE_LIBS) \
+    $(GST_LIBS)
+libgstdc1394_la_LDFLAGS = \
+    $(GST_PLUGIN_LDFLAGS)
+libgstdc1394_la_LIBTOOLFLAGS = \
+    $(GST_PLUGIN_LIBTOOLFLAGS)
 
-libgstdc1394_la_SOURCES =      gstdc1394.c 
-
-
-libgstdc1394_la_CFLAGS =       $(GST_CFLAGS) \
-                               $(LIBDC1394_CFLAGS)
-
-libgstdc1394_la_LDFLAGS =      $(GST_PLUGIN_LDFLAGS)
-libgstdc1394_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
-
-libgstdc1394_la_LIBADD =       $(GST_BASE_LIBS) \
-                               $(LIBDC1394_LIBS) 
-
-noinst_HEADERS = gstdc1394.h
+noinst_HEADERS = \
+    gstdc1394.h
index 4a403b4..b56c814 100644 (file)
  */
 
 /**
- * SECTION:element-dc1394
+ * SECTION:element-dc1394src
  *
  * Source for IIDC (Instrumentation & Industrial Digital Camera) firewire
- * cameras.
- * 
+ * cameras. If several cameras are connected to the system, the desired one
+ * can be selected by its GUID and an optional unit number (most cameras are
+ * single unit and do not require it). The frame size, rate and format are set
+ * from capabilities. Although the IIDC specification includes a raw video
+ * mode, many cameras use mono video modes to capture in Bayer format.
+ * Thus, for each mono video mode supported by a camera, both gray raw and Bayer
+ * corresponding video formats are exposed in the capabilities.
+ * The Bayer pattern is left unspecified.
+ *
  * <refsect2>
- * <title>Example launch line</title>
+ * <title>Example launch lines</title>
+ * |[
+ * gst-launch-1.0 -v dc1394src ! videoconvert ! autovideosink
+ * ]| Capture and display frames from the first camera available in the system.
  * |[
- * gst-launch -v dc1394 camera-number=0 ! xvimagesink
- * ]|
+ * gst-launch-1.0 dc1394src guid=00074813004DF937 \
+ *     ! "video/x-bayer,format=gbrg,width=1280,height=960,framerate=15/2" \
+ *     ! bayer2rgb ! videoconvert ! autovideosink
+ * ]| Capture and display frames from a specific camera in the desired format.
  * </refsect2>
  */
 
 #include "config.h"
 #endif
 #include "gstdc1394.h"
-#include <sys/time.h>
-#include <time.h>
-#include <string.h>
+#include <gst/video/video.h>
 
-GST_DEBUG_CATEGORY (dc1394_debug);
+GST_DEBUG_CATEGORY_STATIC (dc1394_debug);
 #define GST_CAT_DEFAULT dc1394_debug
 
+
 enum
 {
   PROP_0,
-  PROP_TIMESTAMP_OFFSET,
-  PROP_CAMNUM,
-  PROP_BUFSIZE,
-  PROP_ISO_SPEED
-      /* FILL ME */
+  PROP_CAMERA_GUID,
+  PROP_CAMERA_UNIT,
+  PROP_ISO_SPEED,
+  PROP_DMA_BUFFER_SIZE
 };
 
 
-GST_BOILERPLATE (GstDc1394, gst_dc1394, GstPushSrc, GST_TYPE_PUSH_SRC);
+#define GST_TYPE_DC1394_ISO_SPEED (gst_dc1394_iso_speed_get_type ())
+static GType
+gst_dc1394_iso_speed_get_type (void)
+{
+  static const GEnumValue iso_speeds[] = {
+    {100, "DC1394 ISO speed 100", "100"},
+    {200, "DC1394 ISO speed 200", "200"},
+    {400, "DC1394 ISO speed 400", "400"},
+    {800, "DC1394 ISO speed 800", "800"},
+    {1600, "DC1394 ISO speed 1600", "1600"},
+    {3200, "DC1394 ISO speed 3200", "3200"},
+    {0, NULL, NULL}
+  };
+  static GType type = 0;
+
+  if (!type) {
+    type = g_enum_register_static ("GstDC1394ISOSpeed", iso_speeds);
+  }
+  return type;
+}
+
+
+#define gst_dc1394_parent_class parent_class
+G_DEFINE_TYPE (GstDc1394, gst_dc1394, GST_TYPE_PUSH_SRC);
 
 static void gst_dc1394_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_dc1394_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-
-static GstCaps *gst_dc1394_getcaps (GstBaseSrc * bsrc);
-static gboolean gst_dc1394_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
-static void gst_dc1394_src_fixate (GstPad * pad, GstCaps * caps);
-
-static void gst_dc1394_get_times (GstBaseSrc * basesrc,
-    GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
-
+static gboolean gst_dc1394_start (GstBaseSrc * bsrc);
+static gboolean gst_dc1394_stop (GstBaseSrc * bsrc);
+static gboolean gst_dc1394_set_caps (GstBaseSrc * bsrc, GstCaps * caps);
+static GstCaps *gst_dc1394_get_caps (GstBaseSrc * bsrc, GstCaps * filter);
 static GstFlowReturn gst_dc1394_create (GstPushSrc * psrc, GstBuffer ** buffer);
 
-static GstStateChangeReturn
-gst_dc1394_change_state (GstElement * element, GstStateChange transition);
-
-static gboolean gst_dc1394_parse_caps (const GstCaps * caps,
-    gint * width,
-    gint * height,
-    gint * rate_numerator, gint * rate_denominator, gint * vmode, gint * bpp);
-
-static gint gst_dc1394_caps_set_format_vmode_caps (GstStructure * st,
-    gint mode);
-static gboolean gst_dc1394_set_caps_color (GstStructure * gs, gint mc);
-static void gst_dc1394_set_caps_framesize (GstStructure * gs, gint width,
-    gint height);
-static void gst_dc1394_set_caps_framesize_range (GstStructure * gs,
-    gint minwidth, gint maxwidth, gint incwidth,
-    gint minheight, gint maxheight, gint incheight);
-
-static gint gst_dc1394_caps_set_framerate_list (GstStructure * gs,
-    dc1394framerates_t * framerates);
-
-static GstCaps *gst_dc1394_get_all_dc1394_caps (void);
+static void gst_dc1394_set_prop_camera_guid (GstDc1394 * src,
+    const gchar * guid);
+static gchar *gst_dc1394_get_prop_camera_guid (GstDc1394 * src);
+static void gst_dc1394_set_prop_camera_unit (GstDc1394 * src, gint unit);
+static gint gst_dc1394_get_prop_camera_unit (GstDc1394 * src);
+static void gst_dc1394_set_prop_iso_speed (GstDc1394 * src, guint speed);
+static guint gst_dc1394_get_prop_iso_speed (GstDc1394 * src);
+static void gst_dc1394_set_prop_dma_buffer_size (GstDc1394 * src, guint size);
+static guint gst_dc1394_get_prop_dma_buffer_size (GstDc1394 * src);
+static gboolean gst_dc1394_open_cam (GstDc1394 * src);
+static void gst_dc1394_close_cam (GstDc1394 * src);
+static gboolean gst_dc1394_start_cam (GstDc1394 * src);
+static gboolean gst_dc1394_stop_cam (GstDc1394 * src);
+static gboolean gst_dc1394_set_cam_caps (GstDc1394 * src, GstCaps * caps);
 static GstCaps *gst_dc1394_get_cam_caps (GstDc1394 * src);
-static gboolean gst_dc1394_open_cam_with_best_caps (GstDc1394 * src);
-static gint gst_dc1394_framerate_frac_to_const (gint num, gint denom);
-static void gst_dc1394_framerate_const_to_frac (gint framerateconst,
-    GValue * framefrac);
-static gboolean
-gst_dc1394_change_camera_transmission (GstDc1394 * src, gboolean on);
-static gboolean gst_dc1394_query (GstBaseSrc * bsrc, GstQuery * query);
-
-static void
-gst_dc1394_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_set_static_metadata (element_class,
-      "1394 IIDC Video Source", "Source/Video",
-      "libdc1394 based source, supports 1394 IIDC cameras",
-      "Antoine Tremblay <hexa00@gmail.com>");
+static GstCaps *gst_dc1394_get_all_caps (void);
 
-  gst_element_class_add_pad_template (element_class,
-      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
-          gst_dc1394_get_all_dc1394_caps ()));
-
-}
+static GstCaps *gst_dc1394_build_caps (const dc1394color_codings_t *
+    supported_codings, const dc1394framerates_t * supported_rates,
+    guint width_min, guint width_max, guint width_step, guint height_min,
+    guint height_max, guint height_step);
+static gboolean gst_dc1394_parse_caps (const GstCaps * caps,
+    dc1394color_codings_t * color_codings, dc1394framerate_t * rate,
+    gdouble * rate_decimal, guint * width, guint * height);
 
 static void
 gst_dc1394_class_init (GstDc1394Class * klass)
 {
   GObjectClass *gobject_class;
-  GstBaseSrcClass *gstbasesrc_class;
-  GstPushSrcClass *gstpushsrc_class;
-  GstElementClass *gstelement_class;
+  GstElementClass *element_class;
+  GstBaseSrcClass *basesrc_class;
+  GstPushSrcClass *pushsrc_class;
 
-  gobject_class = (GObjectClass *) klass;
-  gstbasesrc_class = (GstBaseSrcClass *) klass;
-  gstpushsrc_class = (GstPushSrcClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
+  gobject_class = G_OBJECT_CLASS (klass);
+  element_class = GST_ELEMENT_CLASS (klass);
+  basesrc_class = GST_BASE_SRC_CLASS (klass);
+  pushsrc_class = GST_PUSH_SRC_CLASS (klass);
 
   gobject_class->set_property = gst_dc1394_set_property;
   gobject_class->get_property = gst_dc1394_get_property;
+  g_object_class_install_property (gobject_class, PROP_CAMERA_GUID,
+      g_param_spec_string ("guid", "Camera GUID",
+          "The hexadecimal representation of the GUID of the camera"
+          " (use first camera available if null)",
+          NULL,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
+          GST_PARAM_MUTABLE_READY));
+  g_object_class_install_property (gobject_class, PROP_CAMERA_UNIT,
+      g_param_spec_int ("unit", "Camera unit",
+          "The unit number of the camera (-1 if no unit number is used)",
+          -1, G_MAXINT, -1,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
+          GST_PARAM_MUTABLE_READY));
+  g_object_class_install_property (gobject_class, PROP_ISO_SPEED,
+      g_param_spec_enum ("iso", "ISO bandwidth",
+          "The ISO bandwidth in Mbps",
+          GST_TYPE_DC1394_ISO_SPEED, 400,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
+          GST_PARAM_MUTABLE_READY));
+  g_object_class_install_property (gobject_class, PROP_DMA_BUFFER_SIZE,
+      g_param_spec_uint ("dma", "DMA ring buffer size",
+          "The number of frames in the Direct Memory Access ring buffer",
+          1, G_MAXUINT, 10,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE |
+          GST_PARAM_MUTABLE_READY));
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
-          "Timestamp offset",
-          "An offset added to timestamps set on buffers (in ns)", G_MININT64,
-          G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_CAMNUM, g_param_spec_int ("camera-number",
-          "The number of the camera on the firewire bus",
-          "The number of the camera on the firewire bus", 0,
-          G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_BUFSIZE, g_param_spec_int ("buffer-size",
-          "The number of frames in the dma ringbuffer",
-          "The number of frames in the dma ringbuffer", 1,
-          G_MAXINT, 10, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass),
-      PROP_ISO_SPEED, g_param_spec_int ("iso-speed",
-          "The iso bandwidth in Mbps (100, 200, 400, 800, 1600, 3200)",
-          "The iso bandwidth in Mbps (100, 200, 400, 800, 1600, 3200)", 100,
-          3200, 400, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  gstbasesrc_class->get_caps = gst_dc1394_getcaps;
-  gstbasesrc_class->set_caps = gst_dc1394_setcaps;
-  gstbasesrc_class->query = gst_dc1394_query;
-
-  gstbasesrc_class->get_times = gst_dc1394_get_times;
-  gstpushsrc_class->create = gst_dc1394_create;
-
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dc1394_change_state);
-}
-
-static void
-gst_dc1394_init (GstDc1394 * src, GstDc1394Class * g_class)
-{
-
-  src->segment_start_frame = -1;
-  src->segment_end_frame = -1;
-  src->timestamp_offset = 0;
-  src->caps = gst_dc1394_get_all_dc1394_caps ();
-  src->bufsize = 10;
-  src->iso_speed = 400;
-  src->camnum = 0;
-  src->n_frames = 0;
+  gst_element_class_set_static_metadata (element_class,
+      "1394 IIDC Video Source", "Source/Video",
+      "libdc1394 based source for IIDC cameras",
+      "Antoine Tremblay <hexa00@gmail.com>");
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+          gst_dc1394_get_all_caps ()));
 
-  gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (src),
-      gst_dc1394_src_fixate);
+  basesrc_class->start = GST_DEBUG_FUNCPTR (gst_dc1394_start);
+  basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_dc1394_stop);
+  basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_dc1394_set_caps);
+  basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_dc1394_get_caps);
 
-  gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+  pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_dc1394_create);
 }
 
+
 static void
-gst_dc1394_src_fixate (GstPad * pad, GstCaps * caps)
+gst_dc1394_init (GstDc1394 * src)
 {
+  src->guid = -1;
+  src->unit = -1;
+  src->iso_speed = DC1394_ISO_SPEED_400;
+  src->dma_buffer_size = 10;
+  src->dc1394 = NULL;
+  src->camera = NULL;
+  src->caps = NULL;
 
-  GstDc1394 *src = GST_DC1394 (gst_pad_get_parent (pad));
-  GstStructure *structure;
-  int i;
-
-  GST_LOG_OBJECT (src, " fixating caps to closest to 320x240 , 30 fps");
-
-  for (i = 0; i < gst_caps_get_size (caps); ++i) {
-    structure = gst_caps_get_structure (caps, i);
-
-    gst_structure_fixate_field_nearest_int (structure, "width", 320);
-    gst_structure_fixate_field_nearest_int (structure, "height", 240);
-    gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
-  }
-  gst_object_unref (GST_OBJECT (src));
+  gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+  gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
+  gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
 }
 
-static gboolean
-gst_dc1394_query (GstBaseSrc * bsrc, GstQuery * query)
-{
-  gboolean res = TRUE;
-  GstDc1394 *src = GST_DC1394 (bsrc);
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_LATENCY:
-    {
-      GstClockTime min_latency, max_latency;
-
-      if (!src->camera) {
-        GST_WARNING_OBJECT (src,
-            "Can't give latency since device isn't open !");
-        res = FALSE;
-        goto done;
-      }
-
-      if (src->rate_denominator <= 0 || src->rate_numerator <= 0) {
-        GST_WARNING_OBJECT (bsrc,
-            "Can't give latency since framerate isn't fixated !");
-        res = FALSE;
-        goto done;
-      }
-
-      /* min latency is the time to capture one frame */
-      min_latency = gst_util_uint64_scale (GST_SECOND,
-          src->rate_denominator, src->rate_numerator);
-
-      /* max latency is total duration of the frame buffer */
-      max_latency = gst_util_uint64_scale (src->bufsize,
-          GST_SECOND * src->rate_denominator, src->rate_numerator);
-
-      GST_DEBUG_OBJECT (bsrc,
-          "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
-      /* we are always live, the min latency is 1 frame and the max latency is
-       * the complete buffer of frames. */
-      gst_query_set_latency (query, TRUE, min_latency, max_latency);
-
-      res = TRUE;
-      break;
-    }
-    default:
-      res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
-      break;
-  }
-
-done:
-  return res;
-}
 
 static void
-gst_dc1394_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
+gst_dc1394_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
 {
-  GstDc1394 *src = GST_DC1394 (object);
+  GstDc1394 *src;
 
+  src = GST_DC1394 (object);
   switch (prop_id) {
-    case PROP_TIMESTAMP_OFFSET:
-      src->timestamp_offset = g_value_get_int64 (value);
+    case PROP_CAMERA_GUID:
+      g_value_take_string (value, gst_dc1394_get_prop_camera_guid (src));
       break;
-    case PROP_CAMNUM:
-      src->camnum = g_value_get_int (value);
-      break;
-    case PROP_BUFSIZE:
-      src->bufsize = g_value_get_int (value);
+    case PROP_CAMERA_UNIT:
+      g_value_set_int (value, gst_dc1394_get_prop_camera_unit (src));
       break;
     case PROP_ISO_SPEED:
-      switch (g_value_get_int (value)) {
-        case 100:
-        case 200:
-        case 300:
-        case 400:
-        case 800:
-        case 1600:
-        case 3200:
-          // fallthrough
-          src->iso_speed = g_value_get_int (value);
-          break;
-        default:
-          g_warning ("%s: Invalid iso speed %d, ignoring",
-              GST_ELEMENT_NAME (src), g_value_get_int (value));
-          break;
-      }
+      g_value_set_enum (value, gst_dc1394_get_prop_iso_speed (src));
+      break;
+    case PROP_DMA_BUFFER_SIZE:
+      g_value_set_uint (value, gst_dc1394_get_prop_dma_buffer_size (src));
+      break;
     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
+
 static void
-gst_dc1394_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
+gst_dc1394_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec)
 {
-  GstDc1394 *src = GST_DC1394 (object);
+  GstDc1394 *src;
 
+  src = GST_DC1394 (object);
   switch (prop_id) {
-    case PROP_TIMESTAMP_OFFSET:
-      g_value_set_int64 (value, src->timestamp_offset);
+    case PROP_CAMERA_GUID:
+      gst_dc1394_set_prop_camera_guid (src, g_value_get_string (value));
       break;
-    case PROP_CAMNUM:
-      g_value_set_int (value, src->camnum);
-      break;
-    case PROP_BUFSIZE:
-      g_value_set_int (value, src->bufsize);
+    case PROP_CAMERA_UNIT:
+      gst_dc1394_set_prop_camera_unit (src, g_value_get_int (value));
       break;
     case PROP_ISO_SPEED:
-      g_value_set_int (value, src->iso_speed);
+      gst_dc1394_set_prop_iso_speed (src, g_value_get_enum (value));
+      break;
+    case PROP_DMA_BUFFER_SIZE:
+      gst_dc1394_set_prop_dma_buffer_size (src, g_value_get_uint (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -321,999 +252,956 @@ gst_dc1394_get_property (GObject * object, guint prop_id, GValue * value,
   }
 }
 
-static GstCaps *
-gst_dc1394_getcaps (GstBaseSrc * bsrc)
-{
-  GstDc1394 *gsrc;
-
-  gsrc = GST_DC1394 (bsrc);
 
-  g_return_val_if_fail (gsrc->caps, NULL);
+static gboolean
+gst_dc1394_start (GstBaseSrc * bsrc)
+{
+  GstDc1394 *src;
 
-  return gst_caps_copy (gsrc->caps);
+  src = GST_DC1394 (bsrc);
+  return gst_dc1394_open_cam (src);
 }
 
+
 static gboolean
-gst_dc1394_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
+gst_dc1394_stop (GstBaseSrc * bsrc)
 {
-  gboolean res = TRUE;
-  GstDc1394 *dc1394;
-  gint width, height, rate_denominator, rate_numerator;
-  gint bpp, vmode;
-
-  dc1394 = GST_DC1394 (bsrc);
+  GstDc1394 *src;
 
-  if (dc1394->caps) {
-    gst_caps_unref (dc1394->caps);
-  }
+  src = GST_DC1394 (bsrc);
+  if (!gst_dc1394_stop_cam (src))
+    return FALSE;
+  gst_dc1394_close_cam (src);
+  return TRUE;
+}
 
-  dc1394->caps = gst_caps_copy (caps);
 
-  res = gst_dc1394_parse_caps (caps, &width, &height,
-      &rate_numerator, &rate_denominator, &vmode, &bpp);
+static GstCaps *
+gst_dc1394_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
+{
+  GstDc1394 *src;
+  GstCaps *caps, *ret;
 
-  if (res) {
-    /* looks ok here */
-    dc1394->width = width;
-    dc1394->height = height;
-    dc1394->vmode = vmode;
-    dc1394->rate_numerator = rate_numerator;
-    dc1394->rate_denominator = rate_denominator;
-    dc1394->bpp = bpp;
+  src = GST_DC1394 (bsrc);
+  if (src->camera) {
+    caps = gst_dc1394_get_cam_caps (src);
+  } else {
+    caps = gst_dc1394_get_all_caps ();
   }
-
-  return res;
+  if (caps && filter) {
+    ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (caps);
+  } else {
+    ret = caps;
+  }
+  return ret;
 }
 
-static void
-gst_dc1394_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
-    GstClockTime * start, GstClockTime * end)
-{
-  /* for live sources, sync on the timestamp of the buffer */
-  if (gst_base_src_is_live (basesrc)) {
-    GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
-    if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-      /* get duration to calculate end time */
-      GstClockTime duration = GST_BUFFER_DURATION (buffer);
+static gboolean
+gst_dc1394_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
+{
+  GstDc1394 *src;
 
-      if (GST_CLOCK_TIME_IS_VALID (duration)) {
-        *end = timestamp + duration;
-      }
-      *start = timestamp;
-    }
-  } else {
-    *start = -1;
-    *end = -1;
-  }
+  src = GST_DC1394 (bsrc);
+  return gst_dc1394_stop_cam (src)
+      && gst_dc1394_set_cam_caps (src, caps)
+      && gst_dc1394_start_cam (src);
 }
 
+
 static GstFlowReturn
-gst_dc1394_create (GstPushSrc * psrc, GstBuffer ** buffer)
+gst_dc1394_create (GstPushSrc * psrc, GstBuffer ** obuf)
 {
   GstDc1394 *src;
-  GstBuffer *outbuf;
-  GstCaps *caps;
-  dc1394video_frame_t *frame[1];
-  GstFlowReturn res = GST_FLOW_OK;
-  dc1394error_t err;
+  GstBuffer *buffer;
+  dc1394video_frame_t *frame;
+  dc1394error_t ret;
 
   src = GST_DC1394 (psrc);
-
-  err = dc1394_capture_dequeue (src->camera, DC1394_CAPTURE_POLICY_WAIT, frame);
-
-  if (err != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-        ("failed to dequeue frame"), ("failed to dequeue frame"));
+  buffer = NULL;
+  ret = dc1394_capture_dequeue (src->camera, DC1394_CAPTURE_POLICY_WAIT,
+      &frame);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
+        ("Could not dequeue frame: %s.", dc1394_error_get_string (ret)));
     goto error;
   }
-
-  outbuf = gst_buffer_new_and_alloc (frame[0]->image_bytes);
-
-  memcpy (GST_BUFFER_MALLOCDATA (outbuf), (guchar *) frame[0]->image,
-      frame[0]->image_bytes * sizeof (guchar));
-
-  GST_BUFFER_DATA (outbuf) = GST_BUFFER_MALLOCDATA (outbuf);
-
-  caps = gst_pad_get_caps (GST_BASE_SRC_PAD (psrc));
-  gst_buffer_set_caps (outbuf, caps);
-  gst_caps_unref (caps);
-
-  GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time;
-  if (src->rate_numerator != 0) {
-    GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND,
-        src->rate_denominator, src->rate_numerator);
-  }
-
-  src->n_frames++;
-  if (src->rate_numerator != 0) {
-    src->running_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND,
-        src->rate_denominator, src->rate_numerator);
-  }
-
-  if (dc1394_capture_enqueue (src->camera, frame[0]) != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("failed to enqueue frame"),
-        ("failed to enqueue frame"));
-    goto error;
+  /*
+   * TODO: We could create the buffer by wrapping the image bytes in the frame
+   * (enqueing the frame in the notify function) to save the copy operation.
+   * It will only work if all the buffers are disposed before closing the camera
+   * when state changes from PAUSED to READY.
+   */
+  buffer = gst_buffer_new_allocate (NULL, frame->image_bytes, NULL);
+  gst_buffer_fill (buffer, 0, frame->image, frame->image_bytes);
+  /*
+   * TODO: There is a field timestamp in the frame structure,
+   * It is not sure if it could be used as PTS or DTS:
+   * we are not sure if it comes from a monotonic clock,
+   * and it seems to be left undefined under MS Windows.
+   */
+  ret = dc1394_capture_enqueue (src->camera, frame);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
+        ("Could not enqueue frame: %s.", dc1394_error_get_string (ret)));
   }
-
-  *buffer = outbuf;
-
-  return res;
+  *obuf = buffer;
+  return GST_FLOW_OK;
 
 error:
-  {
-    return GST_FLOW_ERROR;
-  }
+  if (buffer)
+    gst_buffer_unref (buffer);
+  return GST_FLOW_ERROR;
 }
 
 
-static gboolean
-gst_dc1394_parse_caps (const GstCaps * caps,
-    gint * width,
-    gint * height,
-    gint * rate_numerator, gint * rate_denominator, gint * vmode, gint * bpp)
+static void
+gst_dc1394_set_prop_camera_guid (GstDc1394 * src, const gchar * guid)
 {
-  const GstStructure *structure;
-  GstPadLinkReturn ret;
-  const GValue *framerate;
-
-  if (gst_caps_get_size (caps) < 1)
-    return FALSE;
-
-  structure = gst_caps_get_structure (caps, 0);
+  gchar *end;
 
-  ret = gst_structure_get_int (structure, "width", width);
-  ret &= gst_structure_get_int (structure, "height", height);
-
-  framerate = gst_structure_get_value (structure, "framerate");
-
-  ret &= gst_structure_get_int (structure, "vmode", vmode);
-
-  ret &= gst_structure_get_int (structure, "bpp", bpp);
-
-
-  if (framerate) {
-    *rate_numerator = gst_value_get_fraction_numerator (framerate);
-    *rate_denominator = gst_value_get_fraction_denominator (framerate);
-  } else {
-    ret = FALSE;
+  if (!guid) {
+    GST_DEBUG_OBJECT (src, "Null camera GUID value: %s.",
+        "first camera available will be used");
+    src->guid = -1;
+    return;
+  }
+  errno = 0;
+  src->guid = g_ascii_strtoull (guid, &end, 16);
+  if (errno == ERANGE || end == guid || *end != '\0') {
+    GST_ERROR_OBJECT (src, "Invalid camera GUID value: %s.", guid);
+    return;
   }
-
-  return ret;
 }
 
-static GstStateChangeReturn
-gst_dc1394_change_state (GstElement * element, GstStateChange transition)
-{
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-  GstDc1394 *src = GST_DC1394 (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      GST_LOG_OBJECT (src, "State change null to ready");
-      src->dc1394 = dc1394_new ();
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      GST_LOG_OBJECT (src, "State ready to paused");
-
-      if (src->caps) {
-        gst_caps_unref (src->caps);
-        src->caps = NULL;
-      }
-      src->caps = gst_dc1394_get_cam_caps (src);
-      if (src->caps == NULL) {
-        GST_LOG_OBJECT (src,
-            "Error : Set property  could not get cam caps ! , reverting to default");
-        src->caps = gst_dc1394_get_all_dc1394_caps ();
-        ret = GST_STATE_CHANGE_FAILURE;
-      }
-
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      GST_LOG_OBJECT (src, "State change paused to playing");
-
-      if (!gst_dc1394_open_cam_with_best_caps (src)) {
-        ret = GST_STATE_CHANGE_FAILURE;
-      }
-
-      if (src->camera && !gst_dc1394_change_camera_transmission (src, TRUE)) {
-        ret = GST_STATE_CHANGE_FAILURE;
-      }
 
-      break;
-    default:
-      break;
+static gchar *
+gst_dc1394_get_prop_camera_guid (GstDc1394 * src)
+{
+  if (src->guid == -1) {
+    return NULL;
   }
-  if (ret == GST_STATE_CHANGE_FAILURE)
-    return ret;
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      GST_LOG_OBJECT (src, "State change playing to paused");
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      GST_LOG_OBJECT (src, "State change paused to ready");
-
-      if (src->camera && !gst_dc1394_change_camera_transmission (src, FALSE)) {
-
-        if (src->camera) {
-          dc1394_camera_free (src->camera);
-        }
-        src->camera = NULL;
-
-        if (src->caps) {
-          gst_caps_unref (src->caps);
-          src->caps = NULL;
-        }
-
-        ret = GST_STATE_CHANGE_FAILURE;
-      }
-
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      GST_LOG_OBJECT (src, "State change ready to null");
-      if (src->camera) {
-        dc1394_camera_free (src->camera);
-      }
-      src->camera = NULL;
-
-      if (src->dc1394) {
-        dc1394_free (src->dc1394);
-      }
-      src->dc1394 = NULL;
+  return g_strdup_printf ("%016" G_GINT64_MODIFIER "X", src->guid);
+}
 
-      if (src->caps) {
-        gst_caps_unref (src->caps);
-        src->caps = NULL;
-      }
-      break;
-    default:
-      break;
-  }
 
-  return ret;
+static void
+gst_dc1394_set_prop_camera_unit (GstDc1394 * src, gint unit)
+{
+  src->unit = unit;
 }
 
 
 static gint
-gst_dc1394_caps_set_format_vmode_caps (GstStructure * gs, gint mode)
+gst_dc1394_get_prop_camera_unit (GstDc1394 * src)
 {
-  gint retval = 0;
-
-  switch (mode) {
-    case DC1394_VIDEO_MODE_160x120_YUV444:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV444);
-      gst_dc1394_set_caps_framesize (gs, 160, 120);
-      break;
-    case DC1394_VIDEO_MODE_320x240_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 320, 240);
-      break;
-    case DC1394_VIDEO_MODE_640x480_YUV411:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV411);
-      gst_dc1394_set_caps_framesize (gs, 640, 480);
-      break;
-    case DC1394_VIDEO_MODE_640x480_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 640, 480);
-      break;
-    case DC1394_VIDEO_MODE_640x480_RGB8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_RGB8);
-      gst_dc1394_set_caps_framesize (gs, 640, 480);
-      break;
-    case DC1394_VIDEO_MODE_640x480_MONO8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 640, 480);
-      break;
-    case DC1394_VIDEO_MODE_640x480_MONO16:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO16);
-      gst_dc1394_set_caps_framesize (gs, 640, 480);
-      break;
-    case DC1394_VIDEO_MODE_800x600_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 800, 600);
-      break;
-    case DC1394_VIDEO_MODE_800x600_RGB8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_RGB8);
-      gst_dc1394_set_caps_framesize (gs, 800, 600);
-      break;
-    case DC1394_VIDEO_MODE_800x600_MONO8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 800, 600);
-      break;
-    case DC1394_VIDEO_MODE_1024x768_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 1024, 768);
-      break;
-    case DC1394_VIDEO_MODE_1024x768_RGB8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_RGB8);
-      gst_dc1394_set_caps_framesize (gs, 1024, 768);
-      break;
-    case DC1394_VIDEO_MODE_1024x768_MONO8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 1024, 768);
-      break;
-    case DC1394_VIDEO_MODE_800x600_MONO16:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO16);
-      gst_dc1394_set_caps_framesize (gs, 800, 600);
-      break;
-    case DC1394_VIDEO_MODE_1024x768_MONO16:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO16);
-      gst_dc1394_set_caps_framesize (gs, 1024, 768);
-      break;
-    case DC1394_VIDEO_MODE_1280x960_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 1280, 960);
-      break;
-    case DC1394_VIDEO_MODE_1280x960_RGB8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_RGB8);
-      gst_dc1394_set_caps_framesize (gs, 1280, 960);
-      break;
-    case DC1394_VIDEO_MODE_1280x960_MONO8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 1280, 960);
-      break;
-    case DC1394_VIDEO_MODE_1600x1200_YUV422:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_YUV422);
-      gst_dc1394_set_caps_framesize (gs, 1600, 1200);
-      break;
-    case DC1394_VIDEO_MODE_1600x1200_RGB8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_RGB8);
-      gst_dc1394_set_caps_framesize (gs, 1600, 1200);
-      break;
-    case DC1394_VIDEO_MODE_1600x1200_MONO8:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 1600, 1200);
-      break;
-    case DC1394_VIDEO_MODE_1280x960_MONO16:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO16);
-      gst_dc1394_set_caps_framesize (gs, 1280, 960);
-      break;
-    case DC1394_VIDEO_MODE_1600x1200_MONO16:
-      gst_dc1394_set_caps_color (gs, DC1394_COLOR_CODING_MONO8);
-      gst_dc1394_set_caps_framesize (gs, 1600, 1200);
-      break;
-
-    default:
-      retval = -1;
-  }
-
-  return retval;
-
+  return src->unit;
 }
 
 
-static gboolean
-gst_dc1394_set_caps_color (GstStructure * gs, gint mc)
+static void
+gst_dc1394_set_prop_iso_speed (GstDc1394 * src, guint speed)
 {
-  gboolean ret = TRUE;
-  gint fourcc;
-
-  switch (mc) {
-    case DC1394_COLOR_CODING_YUV444:
-      gst_structure_set_name (gs, "video/x-raw-yuv");
-
-      fourcc = GST_MAKE_FOURCC ('I', 'Y', 'U', '2');
-      gst_structure_set (gs,
-          "format", GST_TYPE_FOURCC, fourcc, "bpp", G_TYPE_INT, 16, NULL);
+  switch (speed) {
+    case 100:
+      src->iso_speed = DC1394_ISO_SPEED_100;
       break;
-
-    case DC1394_COLOR_CODING_YUV422:
-      gst_structure_set_name (gs, "video/x-raw-yuv");
-      fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
-      gst_structure_set (gs,
-          "format", GST_TYPE_FOURCC, fourcc, "bpp", G_TYPE_INT, 16, NULL);
+    case 200:
+      src->iso_speed = DC1394_ISO_SPEED_200;
       break;
-
-    case DC1394_COLOR_CODING_YUV411:
-      gst_structure_set_name (gs, "video/x-raw-yuv");
-      fourcc = GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
-      gst_structure_set (gs,
-          "format", GST_TYPE_FOURCC, fourcc, "bpp", G_TYPE_INT, 12, NULL);
+    case 400:
+      src->iso_speed = DC1394_ISO_SPEED_400;
       break;
-    case DC1394_COLOR_CODING_RGB8:
-      gst_structure_set_name (gs, "video/x-raw-rgb");
-      gst_structure_set (gs,
-          "bpp", G_TYPE_INT, 24,
-          "depth", G_TYPE_INT, 24,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-          "red_mask", G_TYPE_INT, 0xFF0000,
-          "green_mask", G_TYPE_INT, 0x00FF00,
-          "blue_mask", G_TYPE_INT, 0x0000FF, NULL);
+    case 800:
+      src->iso_speed = DC1394_ISO_SPEED_800;
       break;
-    case DC1394_COLOR_CODING_MONO8:
-      gst_structure_set_name (gs, "video/x-raw-gray");
-      gst_structure_set (gs,
-          "bpp", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, NULL);
-
+    case 1600:
+      src->iso_speed = DC1394_ISO_SPEED_1600;
       break;
-    case DC1394_COLOR_CODING_MONO16:
-      gst_structure_set_name (gs, "video/x-raw-gray");
-      gst_structure_set (gs,
-          "bpp", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);
-      // there is no fourcc for this format
+    case 3200:
+      src->iso_speed = DC1394_ISO_SPEED_3200;
       break;
     default:
-      GST_DEBUG ("Ignoring unsupported color format %d", mc);
-      ret = FALSE;
-      break;
+      GST_ERROR_OBJECT (src, "Invalid ISO speed value: %d.", speed);
   }
-  return ret;
 }
 
 
-static void
-gst_dc1394_set_caps_framesize (GstStructure * gs, gint width, gint height)
+static guint
+gst_dc1394_get_prop_iso_speed (GstDc1394 * src)
 {
-  gst_structure_set (gs,
-      "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
+  switch (src->iso_speed) {
+    case DC1394_ISO_SPEED_100:
+      return 100;
+    case DC1394_ISO_SPEED_200:
+      return 200;
+    case DC1394_ISO_SPEED_400:
+      return 400;
+    case DC1394_ISO_SPEED_800:
+      return 800;
+    case DC1394_ISO_SPEED_1600:
+      return 1600;
+    case DC1394_ISO_SPEED_3200:
+      return 3200;
+    default:                   /* never reached */
+      return DC1394_ISO_SPEED_MIN - 1;
+  }
 }
 
+
 static void
-gst_dc1394_set_caps_framesize_range (GstStructure * gs,
-    gint minwidth,
-    gint maxwidth,
-    gint incwidth, gint minheight, gint maxheight, gint incheight)
+gst_dc1394_set_prop_dma_buffer_size (GstDc1394 * src, guint size)
 {
-  /* 
-     Format 7 cameras allow you to change the camera width/height in multiples
-     of incwidth/incheight up to some max. This sets the necessary
-     list structure in the gst caps structure
-   */
-
-  GValue widthlist = { 0 };
-  GValue widthval = { 0 };
-  GValue heightlist = { 0 };
-  GValue heightval = { 0 };
-  gint x = 0;
-
-  g_value_init (&widthlist, GST_TYPE_LIST);
-  g_value_init (&widthval, G_TYPE_INT);
-  for (x = minwidth; x <= maxwidth; x += incwidth) {
-    g_value_set_int (&widthval, x);
-    gst_value_list_append_value (&widthlist, &widthval);
-  }
-  gst_structure_set_value (gs, "width", &widthlist);
-
-  g_value_unset (&widthlist);
-  g_value_unset (&widthval);
-
-  g_value_init (&heightlist, GST_TYPE_LIST);
-  g_value_init (&heightval, G_TYPE_INT);
-  for (x = minheight; x <= maxheight; x += incheight) {
-    g_value_set_int (&heightval, x);
-    gst_value_list_append_value (&heightlist, &heightval);
-  }
-
-  gst_structure_set_value (gs, "height", &heightlist);
-
-  g_value_unset (&heightlist);
-  g_value_unset (&heightval);
+  src->dma_buffer_size = size;
 }
 
 
-static gint
-gst_dc1394_caps_set_framerate_list (GstStructure * gs,
-    dc1394framerates_t * framerates)
+static guint
+gst_dc1394_get_prop_dma_buffer_size (GstDc1394 * src)
 {
-  GValue framefrac = { 0 };
-  GValue frameratelist = { 0 };
-  gint f;
-
-  g_value_init (&frameratelist, GST_TYPE_LIST);
-  g_value_init (&framefrac, GST_TYPE_FRACTION);
-
-  // figure out the frame rate
-  for (f = framerates->num - 1; f >= 0; f--) {
-    /* reverse order so we place the faster frame rates higher in 
-       the sequence */
-    if (framerates->framerates[f]) {
-      gst_dc1394_framerate_const_to_frac (framerates->framerates[f],
-          &framefrac);
-
-      gst_value_list_append_value (&frameratelist, &framefrac);
-    }
-  }
-  gst_structure_set_value (gs, "framerate", &frameratelist);
-
-  g_value_unset (&framefrac);
-  g_value_unset (&frameratelist);
-  return 0;
+  return src->dma_buffer_size;
 }
 
 
-
-static void
-gst_dc1394_framerate_const_to_frac (gint framerateconst, GValue * framefrac)
+static gboolean
+gst_dc1394_open_cam (GstDc1394 * src)
 {
-
-  // frac must have been already initialized
-
-  switch (framerateconst) {
-    case DC1394_FRAMERATE_1_875:
-      gst_value_set_fraction (framefrac, 15, 8);
-      break;
-    case DC1394_FRAMERATE_3_75:
-      gst_value_set_fraction (framefrac, 15, 4);
-      break;
-    case DC1394_FRAMERATE_7_5:
-      gst_value_set_fraction (framefrac, 15, 2);
-      break;
-    case DC1394_FRAMERATE_15:
-      gst_value_set_fraction (framefrac, 15, 1);
-      break;
-    case DC1394_FRAMERATE_30:
-      gst_value_set_fraction (framefrac, 30, 1);
-      break;
-    case DC1394_FRAMERATE_60:
-      gst_value_set_fraction (framefrac, 60, 1);
-      break;
-    case DC1394_FRAMERATE_120:
-      gst_value_set_fraction (framefrac, 120, 1);
-      break;
-    case DC1394_FRAMERATE_240:
-      gst_value_set_fraction (framefrac, 240, 1);
-      break;
+  dc1394camera_list_t *cameras;
+  dc1394error_t ret;
+  int number;
+  uint64_t guid;
+  int unit;
+
+  src->dc1394 = dc1394_new ();
+  if (!src->dc1394) {
+    GST_ELEMENT_ERROR (src, LIBRARY, INIT, (NULL),
+        ("Could not initialize dc1394 library."));
+    goto error;
   }
-}
-
-static GstCaps *
-gst_dc1394_get_all_dc1394_caps (void)
-{
-  /* 
-     generate all possible caps
-
-   */
 
-  GstCaps *gcaps;
-  gint i = 0;
-
-  gcaps = gst_caps_new_empty ();
-  // first, the fixed mode caps
-  for (i = DC1394_VIDEO_MODE_MIN; i < DC1394_VIDEO_MODE_EXIF; i++) {
-    GstStructure *gs = gst_structure_empty_new ("video");
-    gint ret = gst_dc1394_caps_set_format_vmode_caps (gs, i);
-
-    gst_structure_set (gs,
-        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-    gst_structure_set (gs, "vmode", G_TYPE_INT, i, NULL);
-    if (ret >= 0) {
-      gst_caps_append_structure (gcaps, gs);
-    }
+  number = -1;
+  guid = -1;
+  unit = -1;
+  ret = dc1394_camera_enumerate (src->dc1394, &cameras);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL),
+        ("Could not enumerate cameras: %s.", dc1394_error_get_string (ret)));
+    goto error;
   }
-
-  // then Format 7 options
-
-  for (i = DC1394_COLOR_CODING_MIN; i <= DC1394_COLOR_CODING_MAX; i++) {
-    GstStructure *gs = gst_structure_empty_new ("video");
-
-    //int ret =  gst_dc1394_caps_set_format_vmode_caps(gs, i); 
-
-    gst_structure_set (gs, "vmode", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-
-    gst_structure_set (gs,
-        "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-    gst_structure_set (gs,
-        "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-        "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-
-    if (gst_dc1394_set_caps_color (gs, i)) {
-      gst_caps_append_structure (gcaps, gs);
+  for (int i = 0; i < cameras->num; i++) {
+    GST_DEBUG_OBJECT (src, "Camera %2d is %016" G_GINT64_MODIFIER "X %d.",
+        i, cameras->ids[i].guid, cameras->ids[i].unit);
+    if ((src->guid == -1 || src->guid == cameras->ids[i].guid) &&
+        (src->unit == -1 || src->unit == cameras->ids[i].unit)) {
+      number = i;
+      guid = cameras->ids[i].guid;
+      unit = cameras->ids[i].unit;
     }
   }
-  return gcaps;
-
-}
-
-GstCaps *
-gst_dc1394_get_cam_caps (GstDc1394 * src)
-{
-
-  dc1394camera_t *camera = NULL;
-  dc1394camera_list_t *cameras = NULL;
-  dc1394error_t camerr;
-  gint i, j;
-  dc1394video_modes_t modes;
-  dc1394framerates_t framerates;
-  GstCaps *gcaps = NULL;
-
-  gcaps = gst_caps_new_empty ();
-
-  camerr = dc1394_camera_enumerate (src->dc1394, &cameras);
-
-  if (camerr != DC1394_SUCCESS || cameras == NULL) {
-    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
-        ("Can't find cameras error : %d", camerr),
-        ("Can't find cameras error : %d", camerr));
+  dc1394_camera_free_list (cameras);
+  if (number < 0) {
+    if (src->guid == -1) {
+      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
+          ("No cameras found."));
+    } else {
+      GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
+          ("Camera %016" G_GINT64_MODIFIER "X %d not found.",
+              src->guid, src->unit));
+    }
     goto error;
   }
 
-  if (cameras->num == 0) {
-    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("There were no cameras"),
-        ("There were no cameras"));
+  GST_DEBUG_OBJECT (src, "Open camera %016" G_GINT64_MODIFIER "X %d.",
+      guid, unit);
+  src->camera = dc1394_camera_new_unit (src->dc1394, guid, unit);
+  if (!src->camera) {
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
+        ("Could not open camera %016" G_GINT64_MODIFIER "X %d.", guid, unit));
     goto error;
   }
-
-  if (src->camnum > (cameras->num - 1)) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Invalid camera number"),
-        ("Invalid camera number %d", src->camnum));
-    goto error;
+  GST_DEBUG_OBJECT (src,
+      "Camera %016" G_GINT64_MODIFIER "X %d opened: \"%s %s\".",
+      src->camera->guid, src->camera->unit,
+      src->camera->vendor, src->camera->model);
+
+  if (src->iso_speed > DC1394_ISO_SPEED_400) {
+    ret = dc1394_video_set_operation_mode (src->camera,
+        DC1394_OPERATION_MODE_1394B);
+    if (ret != DC1394_SUCCESS) {
+      GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+          ("Could not set 1394B operation mode: %s.",
+              dc1394_error_get_string (ret)));
+      goto error;
+    }
   }
-
-  camera =
-      dc1394_camera_new_unit (src->dc1394, cameras->ids[src->camnum].guid,
-      cameras->ids[src->camnum].unit);
-
-  dc1394_camera_free_list (cameras);
-  cameras = NULL;
-
-  camerr = dc1394_video_get_supported_modes (camera, &modes);
-  if (camerr != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Error getting supported modes"),
-        ("Error getting supported modes"));
+  ret = dc1394_video_set_iso_speed (src->camera, src->iso_speed);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Could not set ISO speed %d: %s.", src->iso_speed,
+            dc1394_error_get_string (ret)));
     goto error;
   }
 
-  for (i = modes.num - 1; i >= 0; i--) {
-    int m = modes.modes[i];
-
-    if (m < DC1394_VIDEO_MODE_EXIF) {
-
-      GstStructure *gs = gst_structure_empty_new ("video");
-
-      gst_structure_set (gs, "vmode", G_TYPE_INT, m, NULL);
+  return TRUE;
 
-      if (gst_dc1394_caps_set_format_vmode_caps (gs, m) < 0) {
-        GST_ELEMENT_ERROR (src, STREAM, FAILED,
-            ("attempt to set mode to %d failed", m),
-            ("attempt to set mode to %d failed", m));
-        goto error;
-      } else {
+error:
+  if (src->camera) {
+    dc1394_camera_free (src->camera);
+    src->camera = NULL;
+  }
+  if (src->dc1394) {
+    dc1394_free (src->dc1394);
+    src->dc1394 = NULL;
+  }
+  return FALSE;
+}
 
-        camerr = dc1394_video_get_supported_framerates (camera, m, &framerates);
-        gst_dc1394_caps_set_framerate_list (gs, &framerates);
-        gst_caps_append_structure (gcaps, gs);
 
-      }
-    } else {
-      // FORMAT 7
-      guint maxx, maxy;
-      GstStructure *gs = gst_structure_empty_new ("video");
-      dc1394color_codings_t colormodes;
-      guint xunit, yunit;
-
-      gst_structure_set (gs, "vmode", G_TYPE_INT, m, NULL);
-
-      // Get the maximum frame size
-      camerr = dc1394_format7_get_max_image_size (camera, m, &maxx, &maxy);
-      if (camerr != DC1394_SUCCESS) {
-        GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-            ("Error getting format 7 max image size"),
-            ("Error getting format 7 max image size"));
-        goto error;
-      }
-      GST_LOG_OBJECT (src, "Format 7 maxx=%d maxy=%d", maxx, maxy);
+static void
+gst_dc1394_close_cam (GstDc1394 * src)
+{
+  GST_DEBUG_OBJECT (src,
+      "Close camera %016" G_GINT64_MODIFIER "X %d: \"%s %s\".",
+      src->camera->guid, src->camera->unit,
+      src->camera->vendor, src->camera->model);
+  if (src->caps) {
+    gst_caps_unref (src->caps);
+    src->caps = NULL;
+  }
+  dc1394_camera_free (src->camera);
+  src->camera = NULL;
+  dc1394_free (src->dc1394);
+  src->dc1394 = NULL;
+  GST_DEBUG_OBJECT (src, "Camera closed.");
+}
 
-      camerr = dc1394_format7_get_unit_size (camera, m, &xunit, &yunit);
-      if (camerr != DC1394_SUCCESS) {
-        GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-            ("Error getting format 7 image unit size"),
-            ("Error getting format 7 image unit size"));
-        goto error;
-      }
-      GST_LOG_OBJECT (src, "Format 7 unitx=%d unity=%d", xunit, yunit);
-
-      gst_dc1394_set_caps_framesize_range (gs, xunit, maxx, xunit,
-          yunit, maxy, yunit);
-
-      // note that format 7 has no concept of a framerate, so we pass the 
-      // full range
-      gst_structure_set (gs,
-          "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-
-      // get the available color codings
-      camerr = dc1394_format7_get_color_codings (camera, m, &colormodes);
-      if (camerr != DC1394_SUCCESS) {
-        GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-            ("Error getting format 7 color modes"),
-            ("Error getting format 7 color modes"));
-        goto error;
-      }
 
-      for (j = 0; j < colormodes.num; j++) {
-        GstStructure *newgs = gst_structure_copy (gs);
+static gboolean
+gst_dc1394_start_cam (GstDc1394 * src)
+{
+  dc1394error_t ret;
+  dc1394switch_t status;
 
-        gst_dc1394_set_caps_color (newgs, colormodes.codings[j]);
-        GST_LOG_OBJECT (src, "Format 7 colormode set : %d",
-            colormodes.codings[j]);
-        // note that since there are multiple color modes, we append
-        // multiple structures.
-        gst_caps_append_structure (gcaps, newgs);
-      }
+  GST_DEBUG_OBJECT (src, "Setup capture with a DMA buffer of %d frames",
+      src->dma_buffer_size);
+  ret = dc1394_capture_setup (src->camera, src->dma_buffer_size,
+      DC1394_CAPTURE_FLAGS_DEFAULT);
+  if (ret == DC1394_NO_BANDWIDTH) {
+    GST_DEBUG_OBJECT (src,
+        "Could not setup capture with available ISO bandwidth,"
+        "releasing channels and bandwidth and retrying...");
+    ret = dc1394_iso_release_all (src->camera);
+    if (ret != DC1394_SUCCESS) {
+      GST_ELEMENT_WARNING (src, RESOURCE, FAILED, (NULL),
+          ("Could not release ISO channels and bandwidth: %s",
+              dc1394_error_get_string (ret)));
     }
+    ret = dc1394_capture_setup (src->camera, src->dma_buffer_size,
+        DC1394_CAPTURE_FLAGS_DEFAULT);
   }
-
-  if (camera) {
-    dc1394_camera_free (camera);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
+        ("Could not setup capture: %s", dc1394_error_get_string (ret)));
+    goto error_capture;
   }
 
-  return gcaps;
-
-error:
-
-  if (gcaps) {
-    gst_caps_unref (gcaps);
+  /*
+   * TODO: dc1394_capture_setup/stop can start/stop the transmission
+   * when called with DC1394_CAPTURE_FLAGS_AUTO_ISO in the flags.
+   * The repeated trials check is a leftover of the original code,
+   * and might not be needed.
+   */
+  GST_DEBUG_OBJECT (src, "Enable camera transmission.");
+  ret = dc1394_video_set_transmission (src->camera, DC1394_ON);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
+        ("Could not set transmission status: %s.",
+            dc1394_error_get_string (ret)));
+    goto error_transmission;
   }
-
-  if (cameras) {
-    dc1394_camera_free_list (cameras);
-    cameras = NULL;
+  ret = dc1394_video_get_transmission (src->camera, &status);
+  for (guint trials = 10;
+      (trials > 0) && !(ret == DC1394_SUCCESS && status == DC1394_ON);
+      trials--) {
+    GST_DEBUG_OBJECT (src,
+        "Wait for camera to start transmission (%d trials left).", trials);
+    g_usleep (50000);
+    ret = dc1394_video_get_transmission (src->camera, &status);
   }
-
-  if (camera) {
-    dc1394_camera_free (camera);
-    camera = NULL;
+  if (!(ret == DC1394_SUCCESS && status == DC1394_ON)) {
+    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
+        ("Could not get positive transmission status: %s.",
+            dc1394_error_get_string (ret)));
+    goto error_transmission;
   }
 
-  return NULL;
-}
-
-static gint
-gst_dc1394_framerate_frac_to_const (gint num, gint denom)
-{
-  // frac must have been already initialized
-  int retvalue = -1;
-
-  if (num == 15 && denom == 8)
-    retvalue = DC1394_FRAMERATE_1_875;
-
-  if (num == 15 && denom == 4)
-    retvalue = DC1394_FRAMERATE_3_75;
-
-  if (num == 15 && denom == 2)
-    retvalue = DC1394_FRAMERATE_7_5;
-
-  if (num == 15 && denom == 1)
-    retvalue = DC1394_FRAMERATE_15;
-
-
-  if (num == 30 && denom == 1)
-    retvalue = DC1394_FRAMERATE_30;
-
-  if (num == 60 && denom == 1)
-    retvalue = DC1394_FRAMERATE_60;
+  GST_DEBUG_OBJECT (src, "Capture successfully started.");
+  return TRUE;
 
-  return retvalue;
+error_transmission:
+  ret = dc1394_capture_stop (src->camera);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_WARNING (src, RESOURCE, FAILED, (NULL),
+        ("Could not stop capture: %s.", dc1394_error_get_string (ret)));
+  }
+error_capture:
+  return FALSE;
 }
 
 
 static gboolean
-gst_dc1394_open_cam_with_best_caps (GstDc1394 * src)
+gst_dc1394_stop_cam (GstDc1394 * src)
 {
-  dc1394camera_list_t *cameras = NULL;
-  gint err = 0;
-  int framerateconst;
-
-  GST_LOG_OBJECT (src, "Opening the camera!!!");
-
-
-  if (dc1394_camera_enumerate (src->dc1394, &cameras) != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Can't find cameras"),
-        ("Can't find cameras"));
-    goto error;
+  dc1394error_t ret;
+
+  GST_DEBUG_OBJECT (src, "Disable camera transmission.");
+  ret = dc1394_video_set_transmission (src->camera, DC1394_OFF);
+  if (ret != DC1394_SUCCESS) {
+    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
+        ("Could not set transmission status: %s.",
+            dc1394_error_get_string (ret)));
+    return FALSE;
   }
 
-  GST_LOG_OBJECT (src, "Found  %d  cameras", cameras->num);
-
-  if (src->camnum > (cameras->num - 1)) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Invalid camera number"),
-        ("Invalid camera number"));
-    goto error;
+  GST_DEBUG_OBJECT (src, "Clear capture resources.");
+  ret = dc1394_capture_stop (src->camera);
+  if (ret != DC1394_SUCCESS && ret != DC1394_CAPTURE_IS_NOT_SET) {
+    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, (NULL),
+        ("Could not clear capture: %s.", dc1394_error_get_string (ret)));
+    return FALSE;
   }
 
-  GST_LOG_OBJECT (src, "Opening camera : %d", src->camnum);
-
-  src->camera =
-      dc1394_camera_new_unit (src->dc1394, cameras->ids[src->camnum].guid,
-      cameras->ids[src->camnum].unit);
-
-  dc1394_camera_free_list (cameras);
-  cameras = NULL;
-
-  // figure out mode
-  framerateconst = gst_dc1394_framerate_frac_to_const (src->rate_numerator,
-      src->rate_denominator);
-
-  GST_LOG_OBJECT (src, "The dma buffer queue size is %d  buffers",
-      src->bufsize);
-
-  switch (src->iso_speed) {
-    case 100:
-      err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_100);
-      break;
-    case 200:
-      err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_200);
-      break;
-    case 400:
-      err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_400);
+  switch (ret) {
+    case DC1394_CAPTURE_IS_NOT_SET:
+      GST_DEBUG_OBJECT (src, "Capture was not set up.");
       break;
-    case 800:
-      if (src->camera->bmode_capable > 0) {
-        dc1394_video_set_operation_mode (src->camera,
-            DC1394_OPERATION_MODE_1394B);
-        err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_800);
-      }
-      break;
-    case 1600:
-      if (src->camera->bmode_capable > 0) {
-        dc1394_video_set_operation_mode (src->camera,
-            DC1394_OPERATION_MODE_1394B);
-        err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_1600);
-      }
-      break;
-    case 3200:
-      if (src->camera->bmode_capable > 0) {
-        dc1394_video_set_operation_mode (src->camera,
-            DC1394_OPERATION_MODE_1394B);
-        err = dc1394_video_set_iso_speed (src->camera, DC1394_ISO_SPEED_3200);
-      }
+    case DC1394_SUCCESS:
+      GST_DEBUG_OBJECT (src, "Capture successfully stopped.");
       break;
     default:
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Invalid ISO speed"),
-          ("Invalid ISO speed"));
-      goto error;
       break;
   }
 
-  if (err != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Could not set ISO speed"),
-        ("Could not set ISO speed"));
-    goto error;
-  }
-
-  GST_LOG_OBJECT (src, "Setting mode :  %d", src->vmode);
-  err = dc1394_video_set_mode (src->camera, src->vmode);
-
-  if (err != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Could not set video mode %d",
-            src->vmode), ("Could not set video mode %d", src->vmode));
-    goto error;
-  }
+  return TRUE;
+}
 
-  GST_LOG_OBJECT (src, "Setting framerate :  %d", framerateconst);
-  dc1394_video_set_framerate (src->camera, framerateconst);
 
-  if (err != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Could not set framerate to %d",
-            framerateconst), ("Could not set framerate to %d", framerateconst));
+static gboolean
+gst_dc1394_set_cam_caps (GstDc1394 * src, GstCaps * caps)
+{
+  GstCaps *mode_caps;
+  gboolean ok, supported;
+  dc1394video_modes_t supported_modes;
+  dc1394video_mode_t mode;
+  dc1394color_codings_t supported_codings;
+  dc1394color_coding_t coding;
+  dc1394framerates_t supported_rates;
+  dc1394framerate_t rate;
+  double rate_decimal;
+  uint64_t total_bytes;
+  uint32_t width, width_step, height, height_step;
+
+  ok = dc1394_video_get_supported_modes (src->camera,
+      &supported_modes) == DC1394_SUCCESS;
+  if (!ok) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Could not get supported modes."));
     goto error;
   }
-  // set any format-7 parameters if this is a format-7 mode
-  if (src->vmode >= DC1394_VIDEO_MODE_FORMAT7_MIN &&
-      src->vmode <= DC1394_VIDEO_MODE_FORMAT7_MAX) {
-    // the big thing we care about right now is frame size
-    err = dc1394_format7_set_image_size (src->camera, src->vmode,
-        src->width, src->height);
-    if (err != DC1394_SUCCESS) {
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-          ("Could not set format 7 image size to %d x %d", src->width,
-              src->height), ("Could not set format 7 image size to %d x %d",
-              src->width, src->height));
-
-      goto error;
+  supported = FALSE;
+  for (guint m = 0; m < supported_modes.num && !supported; m++) {
+    mode = supported_modes.modes[m];
+    mode_caps = gst_caps_new_empty ();
+    if (dc1394_is_video_mode_scalable (mode)) {
+      ok &= dc1394_format7_get_color_codings (src->camera, mode,
+          &supported_codings) == DC1394_SUCCESS;
+      ok &= dc1394_format7_get_max_image_size (src->camera, mode,
+          &width, &height) == DC1394_SUCCESS;
+      ok &= dc1394_format7_get_unit_size (src->camera, mode,
+          &width_step, &height_step) == DC1394_SUCCESS;
+    } else {
+      ok &= dc1394_get_color_coding_from_video_mode (src->camera, mode,
+          &coding) == DC1394_SUCCESS;
+      ok &= dc1394_get_image_size_from_video_mode (src->camera, mode,
+          &width, &height) == DC1394_SUCCESS;
+      ok &= dc1394_video_get_supported_framerates (src->camera, mode,
+          &supported_rates) == DC1394_SUCCESS;
     }
-
+    if (!ok) {
+      GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
+          ("Could not get video mode %d parameters.", mode));
+    } else if (dc1394_is_video_mode_scalable (mode)) {
+      gst_caps_append (mode_caps, gst_dc1394_build_caps (&supported_codings,
+              NULL, width_step, width, width_step, height_step, height,
+              height_step));
+    } else {
+      supported_codings.num = 1;
+      supported_codings.codings[0] = coding;
+      gst_caps_append (mode_caps, gst_dc1394_build_caps (&supported_codings,
+              &supported_rates, width, width, 1, height, height, 1));
+    }
+    supported = gst_caps_can_intersect (caps, mode_caps);
+    gst_caps_unref (mode_caps);
   }
-  err = dc1394_capture_setup (src->camera, src->bufsize,
-      DC1394_CAPTURE_FLAGS_DEFAULT);
-  if (err != DC1394_SUCCESS) {
-    GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Error setting capture mode"),
-        ("Error setting capture mode"));
+  ok = supported && gst_dc1394_parse_caps (caps, &supported_codings,
+      &rate, &rate_decimal, &width, &height);
+  if (!ok) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Unsupported caps %" GST_PTR_FORMAT, caps));
+    goto error;
   }
-  if (err != DC1394_SUCCESS) {
-    if (err == DC1394_NO_BANDWIDTH) {
-      GST_LOG_OBJECT (src, "Capture setup_dma failed."
-          "Trying to cleanup the iso_channels_and_bandwidth and retrying");
-
-      // try to cleanup the bandwidth and retry 
-      err = dc1394_iso_release_all (src->camera);
-      if (err != DC1394_SUCCESS) {
-        GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-            ("Could not cleanup bandwidth"), ("Could not cleanup bandwidth"));
-        goto error;
-      } else {
-        err =
-            dc1394_capture_setup (src->camera, src->bufsize,
-            DC1394_CAPTURE_FLAGS_DEFAULT);
-        if (err != DC1394_SUCCESS) {
-          GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-              ("unable to setup camera error %d", err),
-              ("unable to setup camera error %d", err));
-          goto error;
-        }
-      }
-    } else {
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-          ("unable to setup camera error %d", err),
-          ("unable to setup camera error %d", err));
-      goto error;
-
+  GST_DEBUG_OBJECT (src, "Set video mode %d.", mode);
+  ok = dc1394_video_set_mode (src->camera, mode) == DC1394_SUCCESS;
+  if (!ok) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Could not set video mode %d.", mode));
+    goto error;
+  }
+  if (dc1394_is_video_mode_scalable (mode)) {
+    ok = FALSE;
+    for (guint c = 0; c < supported_codings.num && !ok; c++) {
+      coding = supported_codings.codings[c];
+      GST_DEBUG_OBJECT (src,
+          "Try format7 video mode %d with coding %d, size %d %d, and rate %.4f Hz.",
+          mode, coding, width, height, rate_decimal);
+      ok = (dc1394_format7_set_color_coding (src->camera, mode,
+              coding) == DC1394_SUCCESS)
+          && (dc1394_format7_set_image_size (src->camera, mode,
+              width, height) == DC1394_SUCCESS)
+          && (dc1394_format7_get_total_bytes (src->camera, mode,
+              &total_bytes) == DC1394_SUCCESS)
+          && (dc1394_format7_set_packet_size (src->camera, mode,
+              total_bytes * rate_decimal * 0.000125) == DC1394_SUCCESS);
     }
+  } else {
+    GST_DEBUG_OBJECT (src, "Set fixed video mode %d rate %.4f Hz (%d).",
+        mode, rate_decimal, rate);
+    ok = dc1394_video_set_framerate (src->camera, rate) == DC1394_SUCCESS;
+  }
+  /* TODO: check feature framerate */
+  if (!ok) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Could not set video mode %d parameters.", mode));
+    goto error;
   }
-
-
   return TRUE;
 
 error:
+  return FALSE;
+}
 
-  if (src->camera) {
-    dc1394_camera_free (src->camera);
-    src->camera = NULL;
-  }
 
-  return FALSE;
+GstCaps *
+gst_dc1394_get_cam_caps (GstDc1394 * src)
+{
+  gboolean ok;
+  dc1394video_modes_t supported_modes;
+  dc1394video_mode_t mode;
+  dc1394color_codings_t supported_codings;
+  dc1394color_coding_t coding;
+  dc1394framerates_t supported_rates;
+  uint32_t width, width_step, height, height_step;
+
+  if (src->caps)
+    return gst_caps_ref (src->caps);
+
+  ok = dc1394_video_get_supported_modes (src->camera,
+      &supported_modes) == DC1394_SUCCESS;
+  if (!ok) {
+    GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+        ("Could not get supported modes."));
+    return NULL;
+  }
 
+  src->caps = gst_caps_new_empty ();
+  for (guint m = 0; m < supported_modes.num; m++) {
+    mode = supported_modes.modes[m];
+    if (dc1394_is_video_mode_scalable (mode)) {
+      ok &= dc1394_format7_get_color_codings (src->camera, mode,
+          &supported_codings) == DC1394_SUCCESS;
+      ok &= dc1394_format7_get_max_image_size (src->camera, mode,
+          &width, &height) == DC1394_SUCCESS;
+      ok &= dc1394_format7_get_unit_size (src->camera, mode,
+          &width_step, &height_step) == DC1394_SUCCESS;
+      if (!ok) {
+        GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
+            ("Could not get format7 video mode %d parameters.", mode));
+      } else {
+        gst_caps_append (src->caps, gst_dc1394_build_caps (&supported_codings,
+                NULL, width_step, width, width_step, height_step, height,
+                height_step));
+      }
+    } else {
+      ok &= dc1394_get_image_size_from_video_mode (src->camera, mode,
+          &width, &height) == DC1394_SUCCESS;
+      ok &= dc1394_video_get_supported_framerates (src->camera, mode,
+          &supported_rates) == DC1394_SUCCESS;
+      ok &= dc1394_get_color_coding_from_video_mode (src->camera, mode,
+          &coding) == DC1394_SUCCESS;
+      if (!ok) {
+        GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL),
+            ("Could not get fixed video mode %d parameters.", mode));
+      } else {
+        supported_codings.num = 1;
+        supported_codings.codings[0] = coding;
+        gst_caps_append (src->caps, gst_dc1394_build_caps (&supported_codings,
+                &supported_rates, width, width, 1, height, height, 1));
+      }
+    }
+  }
+  GST_DEBUG_OBJECT (src, "Camera capabilities: \"%" GST_PTR_FORMAT "\".",
+      src->caps);
+  return gst_caps_ref (src->caps);
 }
 
 
-gboolean
-gst_dc1394_change_camera_transmission (GstDc1394 * src, gboolean on)
+static GstCaps *
+gst_dc1394_get_all_caps (void)
 {
-  dc1394switch_t status = DC1394_OFF;
-  dc1394error_t err = DC1394_FAILURE;
-  gint i = 0;
-
-  g_return_val_if_fail (src->camera, FALSE);
+  GstCaps *caps;
+  dc1394color_coding_t coding;
+  dc1394color_codings_t video_codings;
+  uint32_t width, height;
+
+  const dc1394color_codings_t supported_codings = { 7, {
+          /* DC1394_COLOR_CODING_RGB16S, DC1394_COLOR_CODING_RGB16, */
+          DC1394_COLOR_CODING_RGB8, DC1394_COLOR_CODING_YUV444,
+          DC1394_COLOR_CODING_YUV422, DC1394_COLOR_CODING_YUV411,
+          /* DC1394_COLOR_CODING_RAW16, DC1394_COLOR_CODING_MONO16S */
+          DC1394_COLOR_CODING_MONO16, DC1394_COLOR_CODING_RAW8,
+      DC1394_COLOR_CODING_MONO8}
+  };
+  const dc1394framerates_t all_rates = { 8, {
+          DC1394_FRAMERATE_1_875, DC1394_FRAMERATE_3_75, DC1394_FRAMERATE_7_5,
+          DC1394_FRAMERATE_15, DC1394_FRAMERATE_30, DC1394_FRAMERATE_60,
+      DC1394_FRAMERATE_120, DC1394_FRAMERATE_240}
+  };
+
+  caps = gst_caps_new_empty ();
+  /* First caps for fixed video modes */
+  for (dc1394video_mode_t mode = DC1394_VIDEO_MODE_MIN;
+      mode < DC1394_VIDEO_MODE_EXIF; mode++) {
+    dc1394_get_image_size_from_video_mode (NULL, mode, &width, &height);
+    dc1394_get_color_coding_from_video_mode (NULL, mode, &coding);
+    video_codings.codings[0] = coding;
+    video_codings.num = 1;
+    gst_caps_append (caps, gst_dc1394_build_caps (&video_codings,
+            &all_rates, width, width, 1, height, height, 1));
+  }
+  /* Then caps for Format 7 modes */
+  gst_caps_append (caps, gst_dc1394_build_caps (&supported_codings,
+          NULL, 1, G_MAXINT, 1, 1, G_MAXINT, 1));
+  return caps;
+}
 
-  if (on) {
 
-    status = dc1394_video_set_transmission (src->camera, DC1394_ON);
+static GstCaps *
+gst_dc1394_build_caps (const dc1394color_codings_t * supported_codings,
+    const dc1394framerates_t * supported_rates,
+    uint32_t width_min, uint32_t width_max, uint32_t width_step,
+    uint32_t height_min, uint32_t height_max, uint32_t height_step)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+  GstVideoFormat video_format;
+  dc1394color_coding_t coding;
+  dc1394framerate_t rate;
+  GValue format = { 0 };
+  GValue formats = { 0 };
+  GValue width = { 0 };
+  GValue widths = { 0 };
+  GValue height = { 0 };
+  GValue heights = { 0 };
+  GValue framerate = { 0 };
+  GValue framerates = { 0 };
+
+  caps = gst_caps_new_empty ();
+  for (guint c = 0; c < supported_codings->num; c++) {
+    coding = supported_codings->codings[c];
+    switch (coding) {
+      case DC1394_COLOR_CODING_MONO8:
+        video_format = GST_VIDEO_FORMAT_GRAY8;
+        break;
+      case DC1394_COLOR_CODING_YUV411:
+        video_format = GST_VIDEO_FORMAT_IYU1;
+        break;
+      case DC1394_COLOR_CODING_YUV422:
+        video_format = GST_VIDEO_FORMAT_UYVY;
+        break;
+      case DC1394_COLOR_CODING_YUV444:
+        video_format = GST_VIDEO_FORMAT_IYU2;
+        break;
+      case DC1394_COLOR_CODING_RGB8:
+        video_format = GST_VIDEO_FORMAT_RGB;
+        break;
+      case DC1394_COLOR_CODING_RAW8:
+        video_format = GST_VIDEO_FORMAT_UNKNOWN;        /* GST_BAYER_FORMAT_XXXX8 */
+        break;
+      case DC1394_COLOR_CODING_MONO16:
+        video_format = GST_VIDEO_FORMAT_GRAY16_BE;
+        break;
+        /*
+         * The following formats do not exist in Gstreamer:
+         *case DC1394_COLOR_CODING_RGB16: // Unsigned RGB 16 bits per channel
+         *  video_format = GST_VIDEO_FORMAT_RGB48;
+         *  break;
+         *case DC1394_COLOR_CODING_MONO16S: // Signed grayscale 16 bits
+         *  video_format = GST_VIDEO_FORMAT_GRAY16_BE_SIGNED;
+         *  break;
+         *case DC1394_COLOR_CODING_RGB16S: // Signed RGB 16 bits per channel
+         *  video_format = GST_VIDEO_FORMAT_RGB48_SIGNED;
+         *  break;
+         *case DC1394_COLOR_CODING_RAW16: // Raw sensor output (bayer) 16 bits
+         *  video_format = GST_VIDEO_FORMAT_UNKNOWN; // GST_BAYER_FORMAT_XXXX16_BE
+         *  break;
+         */
+      default:
+        video_format = GST_VIDEO_FORMAT_UNKNOWN;
+        GST_DEBUG ("unsupported dc1394 video coding %d", coding);
+    }
+    if (video_format != GST_VIDEO_FORMAT_UNKNOWN) {
+      g_value_init (&formats, G_TYPE_STRING);
+      g_value_set_string (&formats, gst_video_format_to_string (video_format));
+      structure = gst_structure_new_empty ("video/x-raw");
+      gst_structure_set_value (structure, "format", &formats);
+      gst_caps_append_structure (caps, structure);
+      g_value_unset (&formats);
+    }
+    if (coding == DC1394_COLOR_CODING_MONO8 ||
+        coding == DC1394_COLOR_CODING_RAW8) {
+      g_value_init (&formats, GST_TYPE_LIST);
+      g_value_init (&format, G_TYPE_STRING);
+      g_value_set_static_string (&format, "bggr");
+      gst_value_list_append_value (&formats, &format);
+      g_value_set_static_string (&format, "rggb");
+      gst_value_list_append_value (&formats, &format);
+      g_value_set_static_string (&format, "grbg");
+      gst_value_list_append_value (&formats, &format);
+      g_value_set_static_string (&format, "gbrg");
+      gst_value_list_append_value (&formats, &format);
+      structure = gst_structure_new_empty ("video/x-bayer");
+      gst_structure_set_value (structure, "format", &formats);
+      gst_caps_append_structure (caps, structure);
+      g_value_unset (&format);
+      g_value_unset (&formats);
+    }
+  }
 
-    i = 0;
-    while (status == DC1394_OFF && i++ < 5) {
-      g_usleep (50000);
-      if (dc1394_video_get_transmission (src->camera,
-              &status) != DC1394_SUCCESS) {
-        if (status == DC1394_OFF) {
-          GST_LOG_OBJECT (src, "camera is still off , retrying");
-        }
+  if (width_min == width_max) {
+    g_value_init (&widths, G_TYPE_INT);
+    g_value_set_int (&widths, width_min);
+  } else if (width_step == 1) {
+    g_value_init (&widths, GST_TYPE_INT_RANGE);
+    gst_value_set_int_range (&widths, width_min, width_max);
+  } else {
+    g_value_init (&widths, GST_TYPE_LIST);
+    g_value_init (&width, G_TYPE_INT);
+    for (uint32_t w = width_min; w <= width_max; w += width_step) {
+      g_value_set_int (&width, w);
+      gst_value_list_append_value (&widths, &width);
+    }
+    g_value_unset (&width);
+  }
+  if (height_min == height_max) {
+    g_value_init (&heights, G_TYPE_INT);
+    g_value_set_int (&heights, height_min);
+  } else if (height_step == 1) {
+    g_value_init (&heights, GST_TYPE_INT_RANGE);
+    gst_value_set_int_range (&heights, height_min, height_max);
+  } else {
+    g_value_init (&heights, GST_TYPE_LIST);
+    g_value_init (&height, G_TYPE_INT);
+    for (uint32_t h = height_min; h <= height_max; h += height_step) {
+      g_value_set_int (&height, h);
+      gst_value_list_append_value (&heights, &height);
+    }
+    g_value_unset (&height);
+  }
+  gst_caps_set_value (caps, "width", &widths);
+  gst_caps_set_value (caps, "height", &heights);
+  g_value_unset (&widths);
+  g_value_unset (&heights);
+
+  if (supported_rates) {
+    g_value_init (&framerates, GST_TYPE_LIST);
+    g_value_init (&framerate, GST_TYPE_FRACTION);
+    for (guint r = 0; r < supported_rates->num; r++) {
+      rate = supported_rates->framerates[r];
+      switch (rate) {
+        case DC1394_FRAMERATE_1_875:
+          gst_value_set_fraction (&framerate, 240, 128);
+          break;
+        case DC1394_FRAMERATE_3_75:
+          gst_value_set_fraction (&framerate, 240, 64);
+          break;
+        case DC1394_FRAMERATE_7_5:
+          gst_value_set_fraction (&framerate, 240, 32);
+          break;
+        case DC1394_FRAMERATE_15:
+          gst_value_set_fraction (&framerate, 240, 16);
+          break;
+        case DC1394_FRAMERATE_30:
+          gst_value_set_fraction (&framerate, 240, 8);
+          break;
+        case DC1394_FRAMERATE_60:
+          gst_value_set_fraction (&framerate, 240, 4);
+          break;
+        case DC1394_FRAMERATE_120:
+          gst_value_set_fraction (&framerate, 240, 2);
+          break;
+        case DC1394_FRAMERATE_240:
+          gst_value_set_fraction (&framerate, 240, 1);
+          break;
       }
+      gst_value_list_append_value (&framerates, &framerate);
     }
+    g_value_unset (&framerate);
+  } else {
+    g_value_init (&framerates, GST_TYPE_FRACTION_RANGE);
+    gst_value_set_fraction_range_full (&framerates, 1, G_MAXINT, G_MAXINT, 1);
+  }
+  gst_caps_set_value (caps, "framerate", &framerates);
+  g_value_unset (&framerates);
+  return caps;
+}
 
-    if (i == 5) {
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED,
-          ("Camera doesn't seem to want to turn on!"),
-          ("Camera doesn't seem to want to turn on!"));
-      return FALSE;
-    }
 
-    GST_LOG_OBJECT (src, "got transmision status ON");
+static gboolean
+gst_dc1394_parse_caps (const GstCaps * caps,
+    dc1394color_codings_t * color_codings,
+    dc1394framerate_t * rate, double *rate_decimal,
+    uint32_t * width, uint32_t * height)
+{
+  const GstStructure *structure;
+  const gchar *format;
+  gint w, h, num, den;
+  gdouble dec;
 
+  structure = gst_caps_get_structure (caps, 0);
+  if (!structure)
+    goto error;
+
+  if (!width) {
+  } else if (!gst_structure_get_int (structure, "width", &w)) {
+    goto error;
   } else {
+    *width = w;
+  }
 
-    if (dc1394_video_set_transmission (src->camera,
-            DC1394_OFF) != DC1394_SUCCESS) {
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Unable to stop transmision"),
-          ("Unable to stop transmision"));
-      return FALSE;
-    }
+  if (!height) {
+  } else if (!gst_structure_get_int (structure, "height", &h)) {
+    goto error;
+  } else {
+    *height = h;
+  }
 
-    GST_LOG_OBJECT (src, "Stopping capture");
+  if (!(rate || rate_decimal)) {
+  } else if (!gst_structure_get_fraction (structure, "framerate", &num, &den)) {
+    goto error;
+  } else if (gst_util_fraction_compare (num, den, 240, 128) <= 0) {
+    *rate = DC1394_FRAMERATE_1_875;
+  } else if (gst_util_fraction_compare (num, den, 240, 64) <= 0) {
+    *rate = DC1394_FRAMERATE_3_75;
+  } else if (gst_util_fraction_compare (num, den, 240, 32) <= 0) {
+    *rate = DC1394_FRAMERATE_7_5;
+  } else if (gst_util_fraction_compare (num, den, 240, 16) <= 0) {
+    *rate = DC1394_FRAMERATE_15;
+  } else if (gst_util_fraction_compare (num, den, 240, 8) <= 0) {
+    *rate = DC1394_FRAMERATE_30;
+  } else if (gst_util_fraction_compare (num, den, 240, 4) <= 0) {
+    *rate = DC1394_FRAMERATE_60;
+  } else if (gst_util_fraction_compare (num, den, 240, 2) <= 0) {
+    *rate = DC1394_FRAMERATE_120;
+  } else if (gst_util_fraction_compare (num, den, 240, 1) <= 0) {
+    *rate = DC1394_FRAMERATE_240;
+  } else {
+    *rate = DC1394_FRAMERATE_240;
+  }
+  if (rate_decimal) {
+    gst_util_fraction_to_double (num, den, &dec);
+    *rate_decimal = dec;
+  }
 
-    err = dc1394_capture_stop (src->camera);
-    if (err > 0) {
-      GST_ELEMENT_ERROR (src, RESOURCE, FAILED, ("Capture stop error : %d ",
-              err), ("Capture stop error : %d ", err));
-      return FALSE;
-    } else {
-      GST_LOG_OBJECT (src, "Capture stoped successfully");
+  if (!color_codings) {
+  } else if (gst_structure_has_name (structure, "video/x-raw")) {
+    format = gst_structure_get_string (structure, "format");
+    switch (gst_video_format_from_string (format)) {
+      case GST_VIDEO_FORMAT_GRAY8:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_MONO8;
+        break;
+      case GST_VIDEO_FORMAT_IYU1:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_YUV411;
+        break;
+      case GST_VIDEO_FORMAT_UYVY:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_YUV422;
+        break;
+      case GST_VIDEO_FORMAT_IYU2:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_YUV444;
+        break;
+      case GST_VIDEO_FORMAT_RGB:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_RGB8;
+        break;
+      case GST_VIDEO_FORMAT_GRAY16_BE:
+        color_codings->num = 1;
+        color_codings->codings[0] = DC1394_COLOR_CODING_MONO16;
+        break;
+        /*
+         * The following formats do not exist in Gstreamer:
+         *case GST_VIDEO_FORMAT_RGB48: // Unsigned RGB format 16 bits per channel
+         *  color_codings->num = 1
+         *  color_codings->codings[0] = DC1394_COLOR_CODING_RGB16;
+         *  break;
+         *case GST_VIDEO_FORMAT_GRAY16_BE_SIGNED: // Signed grayscale format 16 bits
+         *  color_codings->num = 1
+         *  color_codings->codings[0] = DC1394_COLOR_CODING_MONO16S;
+         *  break;
+         *case GST_VIDEO_FORMAT_RGB48_SIGNED: // Signed RGB format 16 bits per channel
+         *  color_codings->num = 1
+         *  color_codings->codings[0] = DC1394_COLOR_CODING_RGB16S;
+         *  break;
+         */
+      default:
+        GST_ERROR ("unsupported raw video format %s", format);
+        goto error;
     }
+  } else if (gst_structure_has_name (structure, "video/x-bayer")) {
+    /*
+     * The following formats do not exist in Gstreamer:
+     *switch (gst_bayer_format_from_string(format)) {
+     *  case GST_BAYER_FORMAT_BGGR8:
+     *  case GST_BAYER_FORMAT_GBRG8:
+     *  case GST_BAYER_FORMAT_GRBG8:
+     *  case GST_BAYER_FORMAT_BGGR8:
+     *    *coding = DC1394_COLOR_CODING_RAW8;
+     *    break;
+     *  case GST_BAYER_FORMAT_BGGR16_BE:
+     *  case GST_BAYER_FORMAT_GBRG16_BE:
+     *  case GST_BAYER_FORMAT_GRBG16_BE:
+     *  case GST_BAYER_FORMAT_BGGR16_BE:
+     *    *coding = DC1394_COLOR_CODING_RAW16;
+     *    break;
+     *  default:
+     *    GST_ERROR("unsupported raw video format %s", format);
+     *    goto error;
+     *}
+     */
+    color_codings->num = 2;
+    color_codings->codings[0] = DC1394_COLOR_CODING_RAW8;
+    color_codings->codings[1] = DC1394_COLOR_CODING_MONO8;
+  } else {
+    goto error;
   }
 
   return TRUE;
+
+error:
+  return FALSE;
 }
 
 
@@ -1324,12 +1212,11 @@ plugin_init (GstPlugin * plugin)
 
   return gst_element_register (plugin, "dc1394src", GST_RANK_NONE,
       GST_TYPE_DC1394);
-
 }
 
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     dc1394,
-    "1394 IIDC Video Source",
+    "1394 IIDC video source",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
index a27b1f8..b7ee70f 100644 (file)
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_DC1394 \
-  (gst_dc1394_get_type())
-#define GST_DC1394(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DC1394,GstDc1394))
-#define GST_DC1394_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DC1394,GstDc1394))
-#define GST_IS_DC1394(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DC1394))
-#define GST_IS_DC1394_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DC1394))
+#define GST_TYPE_DC1394            (gst_dc1394_get_type())
+#define GST_DC1394(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DC1394,GstDc1394))
+#define GST_DC1394_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DC1394,GstDc1394))
+#define GST_IS_DC1394(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DC1394))
+#define GST_IS_DC1394_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DC1394))
 
 typedef struct _GstDc1394 GstDc1394;
 typedef struct _GstDc1394Class GstDc1394Class;
 
 struct _GstDc1394 {
-  GstPushSrc element;
+  GstPushSrc pushsrc;
 
-  /* video state */
-  gint width;
-  gint height;
-  gint vmode; 
-
-  gint bpp;
-  gint rate_numerator;
-  gint rate_denominator;
-
-  /* private */
-  gint64 timestamp_offset;             /* base offset */
-  GstClockTime running_time;           /* total running time */
-  gint64 n_frames;                     /* total frames sent */
-  gint64 segment_start_frame;
-  gint64 segment_end_frame;
-  gboolean segment;
-  gint camnum; 
-  gint bufsize; 
-  gint iso_speed;
+  GstCaps * caps;
 
+  uint64_t guid;
+  int unit;
+  dc1394speed_t iso_speed;
+  uint32_t dma_buffer_size;
+  dc1394camera_t * camera;
   dc1394_t * dc1394;
-  dc1394camera_t * camera; 
-
-  GstCaps *caps;
 };
 
 struct _GstDc1394Class {