Some changes proposed by wingo in bug #338818 (but not everything yet). Patch from...
authorMartin Rubli <martin_rubli@logitech.com>
Fri, 5 May 2006 20:12:59 +0000 (20:12 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Fri, 5 May 2006 20:12:59 +0000 (20:12 +0000)
Original commit message from CVS:
Some changes proposed by wingo in bug #338818 (but not everything yet). Patch from Martin Rubli to fix framerate detection.

12 files changed:
ChangeLog
sys/v4l2/gstv4l2element.c
sys/v4l2/gstv4l2element.h
sys/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/gstv4l2tuner.c
sys/v4l2/gstv4l2tuner.h
sys/v4l2/v4l2_calls.c
sys/v4l2/v4l2_calls.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h
tests/icles/v4l2src-test.c

index 53d50c2..9e1e2da 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2006-05-05  Edgard Lima <edgard.lima@indt.org.br>
+
+       * sys/v4l2/gstv4l2element.c:
+       * sys/v4l2/gstv4l2element.h:
+       * sys/v4l2/gstv4l2src.c:
+       * sys/v4l2/gstv4l2src.h:
+       * sys/v4l2/gstv4l2tuner.c:
+       * sys/v4l2/gstv4l2tuner.h:
+       * sys/v4l2/v4l2_calls.c:
+       * sys/v4l2/v4l2_calls.h:
+       * sys/v4l2/v4l2src_calls.c:
+       * sys/v4l2/v4l2src_calls.h:
+       * tests/icles/v4l2src-test.c:
+       Some changes proposed by wingo in bug #338818 (but not everything
+       yet). Patch from Martin Rubli to fix framerate detection.
+
 2006-05-05  Tim-Philipp Müller  <tim at centricular dot net>
 
        * ext/sdl/sdlaudiosink.c: (gst_sdlaudio_sink_prepare):
index d6f14d4..5bbc260 100644 (file)
@@ -1,10 +1,11 @@
 /*
- * GStreamer gstv4l2element.c: base class for V4L2 elements Copyright
- * (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> This library 
- * is free software; you can redistribute it and/or modify it under the
- * terms of the GNU Library General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. This library is distributed in the hope
+ * GStreamer gstv4l2element.c: base class for V4L2 elements
+ * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version. This library is distributed in the hope
  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  * PURPOSE.  See the GNU Library General Public License for more details.
@@ -49,19 +50,19 @@ enum
 static void gst_v4l2element_init_interfaces (GType type);
 
 GST_BOILERPLATE_FULL (GstV4l2Element, gst_v4l2element, GstPushSrc,
-    GST_TYPE_PUSH_SRC, gst_v4l2element_init_interfaces)
-     static void gst_v4l2element_dispose (GObject * object);
-     static void gst_v4l2element_set_property (GObject * object,
+    GST_TYPE_PUSH_SRC, gst_v4l2element_init_interfaces);
+
+static void gst_v4l2element_dispose (GObject * object);
+static void gst_v4l2element_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
-     static void gst_v4l2element_get_property (GObject * object,
+static void gst_v4l2element_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
-     static gboolean gst_v4l2element_start (GstBaseSrc * src);
-     static gboolean gst_v4l2element_stop (GstBaseSrc * src);
+static gboolean gst_v4l2element_start (GstBaseSrc * src);
+static gboolean gst_v4l2element_stop (GstBaseSrc * src);
 
 
-     static gboolean
-         gst_v4l2_iface_supported (GstImplementsInterface * iface,
-    GType iface_type)
+static gboolean
+gst_v4l2_iface_supported (GstImplementsInterface * iface, GType iface_type)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (iface);
 
@@ -99,10 +100,16 @@ gst_v4l2_probe_get_properties (GstPropertyProbe * probe)
   GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
   static GList *list = NULL;
 
+  /* well, not perfect, but better than no locking at all.
+   * In the worst case we leak a list node, so who cares? */
+  GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
+
   if (!list) {
     list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
   }
 
+  GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
+
   return list;
 }
 
@@ -435,12 +442,13 @@ gst_v4l2element_set_property (GObject * object,
             g_value_get_string (value));
 
         if (norm) {
-          gst_tuner_set_norm (tuner, norm);
+          /* more generic would be gst_tuner_set_norm (tuner, norm)
+             without g_object_notify */
+          gst_v4l2_tuner_set_norm (tuner, norm);
         }
       } else {
         g_free (v4l2element->std);
         v4l2element->std = g_value_dup_string (value);
-        g_object_notify (object, "std");
       }
       break;
     case PROP_INPUT:
@@ -451,12 +459,13 @@ gst_v4l2element_set_property (GObject * object,
             g_value_get_string (value));
 
         if (channel) {
-          gst_tuner_set_channel (tuner, channel);
+          /* more generic would be gst_tuner_set_channel (tuner, channel)
+             without g_object_notify */
+          gst_v4l2_tuner_set_channel (tuner, channel);
         }
       } else {
         g_free (v4l2element->input);
         v4l2element->input = g_value_dup_string (value);
-        g_object_notify (object, "input");
       }
       break;
     case PROP_FREQUENCY:
@@ -466,11 +475,14 @@ gst_v4l2element_set_property (GObject * object,
 
         if (channel &&
             GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
-          gst_tuner_set_frequency (tuner, channel, g_value_get_ulong (value));
+          /* more generic would be
+             gst_tuner_set_frequency (tuner, channel, g_value_get_ulong (value))
+             without g_object_notify */
+          gst_v4l2_tuner_set_frequency (tuner, channel,
+              g_value_get_ulong (value));
         }
       } else {
         v4l2element->frequency = g_value_get_ulong (value);
-        g_object_notify (object, "frequency");
       }
       break;
     default:
index 742950a..b866769 100644 (file)
@@ -3,6 +3,7 @@
  * gstv4l2element.h: base class for V4L2 elements
  *
  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
index 126cd42..09767ea 100644 (file)
@@ -3,6 +3,7 @@
  * gstv4l2src.c: BT8x8/V4L2 source element
  *
  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -207,6 +208,8 @@ gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
   v4l2src->formats = NULL;
 
   /* fps */
+  v4l2src->fps_n = 0;
+  v4l2src->fps_d = 1;
   v4l2src->use_fixed_fps = TRUE;
 
   v4l2src->is_capturing = FALSE;
@@ -631,8 +634,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
   int min_w, max_w, min_h, max_h;
   GSList *walk;
   GstStructure *structure;
-  gint fps_n, fps_d;
-
+  guint fps_n, fps_d;
 
   if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src))) {
     return
@@ -647,6 +649,7 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
   caps = gst_caps_new_empty ();
   walk = v4l2src->formats;
   if (!gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d)) {
+    GST_DEBUG_OBJECT (v4l2src, "frame rate is unknown.");
     fps_n = 0;
     fps_d = 1;
   }
@@ -857,10 +860,8 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
 {
   GstV4l2Src *v4l2src = GST_V4L2SRC (src);
   GstFlowReturn ret;
-  gint fps_n, fps_d;
 
-  if (v4l2src->use_fixed_fps
-      && gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d) == 0) {
+  if (v4l2src->use_fixed_fps && v4l2src->fps_n == 0) {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL),
         ("could not get frame rate for element"));
     return GST_FLOW_ERROR;
index 3b3f96a..58815dd 100644 (file)
@@ -3,6 +3,7 @@
  * gstv4l2src.h: BT8x8/V4L2 video source element
  *
  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -97,6 +98,7 @@ struct _GstV4l2Src
   gint offset;
 
   /* how are we going to push buffers? */
+  guint fps_n, fps_d;
   gboolean use_fixed_fps;
 };
 
index 7910835..ff813b5 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer Tuner interface implementation
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * gstv4l2tuner.c: tuner interface implementation for V4L2
  *
@@ -28,6 +29,9 @@
 #include "gstv4l2tuner.h"
 #include "gstv4l2element.h"
 #include "v4l2_calls.h"
+#include "v4l2src_calls.h"
+
+#include <sys/ioctl.h>
 
 static void gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass *
     klass);
@@ -37,21 +41,35 @@ static void gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass * klass);
 static void gst_v4l2_tuner_norm_init (GstV4l2TunerNorm * norm);
 
 static const GList *gst_v4l2_tuner_list_channels (GstTuner * mixer);
-static void gst_v4l2_tuner_set_channel (GstTuner * mixer,
+
+static void
+gst_v4l2_tuner_set_channel_and_notify (GstTuner * mixer,
     GstTunerChannel * channel);
 static GstTunerChannel *gst_v4l2_tuner_get_channel (GstTuner * mixer);
 
 static const GList *gst_v4l2_tuner_list_norms (GstTuner * mixer);
-static void gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm);
+
+static void
+gst_v4l2_tuner_set_norm_and_notify (GstTuner * mixer, GstTunerNorm * norm);
 static GstTunerNorm *gst_v4l2_tuner_get_norm (GstTuner * mixer);
 
-static void gst_v4l2_tuner_set_frequency (GstTuner * mixer,
+static void
+gst_v4l2_tuner_set_frequency_and_notify (GstTuner * mixer,
     GstTunerChannel * channel, gulong frequency);
 static gulong gst_v4l2_tuner_get_frequency (GstTuner * mixer,
     GstTunerChannel * channel);
 static gint gst_v4l2_tuner_signal_strength (GstTuner * mixer,
     GstTunerChannel * channel);
 
+static gboolean gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input);
+static gboolean gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input);
+
+#if 0                           /* output not handled by now */
+static gboolean
+gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output);
+static gboolean gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output);
+#endif /* #if 0 - output not handled by now */
+
 static GstTunerNormClass *norm_parent_class = NULL;
 static GstTunerChannelClass *channel_parent_class = NULL;
 
@@ -140,18 +158,19 @@ gst_v4l2_tuner_interface_init (GstTunerClass * klass)
 {
   /* default virtual functions */
   klass->list_channels = gst_v4l2_tuner_list_channels;
-  klass->set_channel = gst_v4l2_tuner_set_channel;
+  klass->set_channel = gst_v4l2_tuner_set_channel_and_notify;
   klass->get_channel = gst_v4l2_tuner_get_channel;
 
   klass->list_norms = gst_v4l2_tuner_list_norms;
-  klass->set_norm = gst_v4l2_tuner_set_norm;
+  klass->set_norm = gst_v4l2_tuner_set_norm_and_notify;
   klass->get_norm = gst_v4l2_tuner_get_norm;
 
-  klass->set_frequency = gst_v4l2_tuner_set_frequency;
+  klass->set_frequency = gst_v4l2_tuner_set_frequency_and_notify;
   klass->get_frequency = gst_v4l2_tuner_get_frequency;
   klass->signal_strength = gst_v4l2_tuner_signal_strength;
 }
 
+#if 0                           /* output not handled by now */
 static gboolean
 gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
 {
@@ -159,6 +178,7 @@ gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
 
   return (dir == GST_PAD_SINK);
 }
+#endif /* #if 0 - output not handled by now */
 
 static G_GNUC_UNUSED gboolean
 gst_v4l2_tuner_contains_channel (GstV4l2Element * v4l2element,
@@ -176,29 +196,86 @@ gst_v4l2_tuner_contains_channel (GstV4l2Element * v4l2element,
 static const GList *
 gst_v4l2_tuner_list_channels (GstTuner * mixer)
 {
-  /* ... or output, if we're a sink... */
   return GST_V4L2ELEMENT (mixer)->inputs;
 }
 
 static void
+gst_v4l2_tuner_set_channel_and_notify (GstTuner * mixer,
+    GstTunerChannel * channel)
+{
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
+
+  if (gst_v4l2_tuner_set_channel (mixer, channel)) {
+    g_object_notify (G_OBJECT (v4l2element), "input");
+  }
+}
+
+gboolean
 gst_v4l2_tuner_set_channel (GstTuner * mixer, GstTunerChannel * channel)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
+  GstV4l2Src *v4l2src = GST_V4L2SRC (v4l2element);
   GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
 
   /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
-  g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel));
+  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), FALSE);
+  g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element,
+          v4l2channel), FALSE);
 
-  /* ... or output, if we're a sink... */
-  if (gst_v4l2_tuner_is_sink (v4l2element) ?
+  if (
+#if 0                           /* output not handled by now */
+      gst_v4l2_tuner_is_sink (v4l2element) ?
       gst_v4l2_set_output (v4l2element, v4l2channel->index) :
-      gst_v4l2_set_input (v4l2element, v4l2channel->index)) {
+#endif /* #if 0 - output not handled by now */
+      gst_v4l2_set_input (v4l2element, v4l2channel->index)
+      ) {
     gst_tuner_channel_changed (mixer, channel);
-    g_object_notify (G_OBJECT (v4l2element), "input");
+    gst_v4l2src_get_fps (v4l2src, &v4l2src->fps_n, &v4l2src->fps_d);
+    return TRUE;
   }
+
+  return FALSE;
+
+}
+
+static gboolean
+gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
+{
+  gint n;
+
+  GST_DEBUG_OBJECT (v4l2element, "trying to get input");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+
+  if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get current input on device %s: %s",
+        v4l2element->videodev, g_strerror (errno));
+    return FALSE;
+  }
+
+  *input = n;
+
+  return TRUE;
 }
 
+static gboolean
+gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
+{
+  GST_DEBUG_OBJECT (v4l2element, "trying to set input to %d", input);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+
+  if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
+    GST_WARNING_OBJECT (v4l2element, "Failed to set input %d on device %s: %s",
+        input, v4l2element->videodev, g_strerror (errno));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
 static GstTunerChannel *
 gst_v4l2_tuner_get_channel (GstTuner * mixer)
 {
@@ -209,10 +286,11 @@ gst_v4l2_tuner_get_channel (GstTuner * mixer)
   /* assert that we're opened and that we're using a known item */
   g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), NULL);
 
-  /* ... or output, if we're a sink... */
+#if 0                           /* output not handled by now */
   if (gst_v4l2_tuner_is_sink (v4l2element))
     gst_v4l2_get_output (v4l2element, &channel);
   else
+#endif /* #if 0 - output not handled by now */
     gst_v4l2_get_input (v4l2element, &channel);
 
   for (item = v4l2element->inputs; item != NULL; item = item->next) {
@@ -243,19 +321,35 @@ gst_v4l2_tuner_list_norms (GstTuner * mixer)
 }
 
 static void
+gst_v4l2_tuner_set_norm_and_notify (GstTuner * mixer, GstTunerNorm * norm)
+{
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
+
+  if (gst_v4l2_tuner_set_norm (mixer, norm)) {
+    g_object_notify (G_OBJECT (v4l2element), "std");
+  }
+}
+
+gboolean
 gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm)
 {
   GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
+  GstV4l2Src *v4l2src = GST_V4L2SRC (v4l2element);
   GstV4l2TunerNorm *v4l2norm = GST_V4L2_TUNER_NORM (norm);
 
   /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
-  g_return_if_fail (gst_v4l2_tuner_contains_norm (v4l2element, v4l2norm));
+  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), FALSE);
+  g_return_val_if_fail (gst_v4l2_tuner_contains_norm (v4l2element, v4l2norm),
+      FALSE);
 
   if (gst_v4l2_set_norm (v4l2element, v4l2norm->index)) {
     gst_tuner_norm_changed (mixer, norm);
-    g_object_notify (G_OBJECT (v4l2element), "std");
+    gst_v4l2src_get_fps (v4l2src, &v4l2src->fps_n, &v4l2src->fps_d);
+    return TRUE;
   }
+
+  return FALSE;
+
 }
 
 static GstTunerNorm *
@@ -279,6 +373,17 @@ gst_v4l2_tuner_get_norm (GstTuner * mixer)
 }
 
 static void
+gst_v4l2_tuner_set_frequency_and_notify (GstTuner * mixer,
+    GstTunerChannel * channel, gulong frequency)
+{
+  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
+
+  if (gst_v4l2_tuner_set_frequency (mixer, channel, frequency)) {
+    g_object_notify (G_OBJECT (v4l2element), "frequency");
+  }
+}
+
+gboolean
 gst_v4l2_tuner_set_frequency (GstTuner * mixer,
     GstTunerChannel * channel, gulong frequency)
 {
@@ -287,19 +392,21 @@ gst_v4l2_tuner_set_frequency (GstTuner * mixer,
   gint chan;
 
   /* assert that we're opened and that we're using a known item */
-  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
-  g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
-          GST_TUNER_CHANNEL_FREQUENCY));
-  g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel));
+  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), FALSE);
+  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
+          GST_TUNER_CHANNEL_FREQUENCY), FALSE);
+  g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element,
+          v4l2channel), FALSE);
 
   gst_v4l2_get_input (v4l2element, &chan);
   if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
       GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
     if (gst_v4l2_set_frequency (v4l2element, v4l2channel->tuner, frequency)) {
       gst_tuner_frequency_changed (mixer, channel, frequency);
-      g_object_notify (G_OBJECT (v4l2element), "frequency");
+      return TRUE;
     }
   }
+  return FALSE;
 }
 
 static gulong
@@ -349,3 +456,47 @@ gst_v4l2_tuner_signal_strength (GstTuner * mixer, GstTunerChannel * channel)
 
   return signal;
 }
+
+#if 0                           /* output not handled by now */
+
+static gboolean
+gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
+{
+  gint n;
+
+  GST_DEBUG_OBJECT (v4l2element, "trying to get output");
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+
+  if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to get current output on device %s: %s",
+        v4l2element->videodev, g_strerror (errno));
+    return FALSE;
+  }
+
+  *output = n;
+
+  return TRUE;
+}
+
+static gboolean
+gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
+{
+  GST_DEBUG_OBJECT (v4l2element, "trying to set output to %d", output);
+  if (!GST_V4L2_IS_OPEN (v4l2element))
+    return FALSE;
+  if (!GST_V4L2_IS_ACTIVE (v4l2element))
+    return FALSE;
+
+  if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
+    GST_WARNING_OBJECT (v4l2element,
+        "Failed to set current output on device %s to %d: %s",
+        v4l2element->videodev, output, g_strerror (errno));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+#endif /* #if 0 - output not handled by now */
index a7a5f43..ede9ab2 100644 (file)
@@ -1,5 +1,6 @@
 /* G-Streamer generic V4L2 element - Tuner interface implementation
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * gstv4l2tuner.h: tuner interface implementation for V4L2
  *
@@ -82,4 +83,14 @@ GType        gst_v4l2_tuner_norm_get_type    (void);
 
 void   gst_v4l2_tuner_interface_init   (GstTunerClass *klass);
 
+extern gboolean
+gst_v4l2_tuner_set_channel (GstTuner * mixer, GstTunerChannel * channel);
+
+gboolean
+gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm);
+
+extern gboolean
+gst_v4l2_tuner_set_frequency (GstTuner * mixer,
+                             GstTunerChannel * channel, gulong frequency);
+
 #endif /* __GST_V4L2_TUNER_H__ */
index a43811f..2ca2d86 100644 (file)
@@ -1,5 +1,6 @@
 /* G-Streamer generic V4L2 element - generic V4L2 calls handling
  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -73,12 +74,18 @@ static gboolean
 gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
 {
   gint n;
+
+#if 0                           /* output not handled by now */
   GstPadDirection dir = GST_PAD_UNKNOWN;
+#endif /* #if 0 - output not handled by now */
 
   GST_DEBUG_OBJECT (v4l2element, "getting enumerations");
   GST_V4L2_CHECK_OPEN (v4l2element);
 
+#if 0                           /* output not handled by now */
   if (dir != GST_PAD_SINK) {
+#endif /* #if 0 - output not handled by now */
+
     /* and now, the inputs */
     for (n = 0;; n++) {
       struct v4l2_input input;
@@ -134,6 +141,8 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
       v4l2element->inputs =
           g_list_append (v4l2element->inputs, (gpointer) channel);
     }
+
+#if 0                           /* output not handled by now */
   } else {
     /* outputs */
     for (n = 0;; n++) {
@@ -170,6 +179,7 @@ gst_v4l2_fill_lists (GstV4l2Element * v4l2element)
           g_list_append (v4l2element->inputs, (gpointer) channel);
     }
   }
+#endif /* #if 0 - output not handled by now */
 
   /* norms... */
   for (n = 0;; n++) {
@@ -501,6 +511,8 @@ gst_v4l2_get_norm (GstV4l2Element * v4l2element, v4l2_std_id * norm)
     return FALSE;
   }
 
+
+
   return TRUE;
 }
 
@@ -517,8 +529,6 @@ gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
   GST_DEBUG_OBJECT (v4l2element, "trying to set norm to %llx", norm);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
-  if (!GST_V4L2_IS_ACTIVE (v4l2element))
-    return FALSE;
 
   if (ioctl (v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) {
     GST_WARNING_OBJECT (v4l2element,
@@ -530,114 +540,6 @@ gst_v4l2_set_norm (GstV4l2Element * v4l2element, v4l2_std_id norm)
   return TRUE;
 }
 
-
-/******************************************************
- * gst_v4l2_get_input()
- *   Get the input of the current device
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l2_get_input (GstV4l2Element * v4l2element, gint * input)
-{
-  gint n;
-
-  GST_DEBUG_OBJECT (v4l2element, "trying to get input");
-  if (!GST_V4L2_IS_OPEN (v4l2element))
-    return FALSE;
-
-  if (ioctl (v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
-    GST_WARNING_OBJECT (v4l2element,
-        "Failed to get current input on device %s: %s",
-        v4l2element->videodev, g_strerror (errno));
-    return FALSE;
-  }
-
-  *input = n;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l2_set_input()
- *   Set the input of the current device
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l2_set_input (GstV4l2Element * v4l2element, gint input)
-{
-  GST_DEBUG_OBJECT (v4l2element, "trying to set input to %d", input);
-  if (!GST_V4L2_IS_OPEN (v4l2element))
-    return FALSE;
-  if (!GST_V4L2_IS_ACTIVE (v4l2element))
-    return FALSE;
-
-  if (ioctl (v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
-    GST_WARNING_OBJECT (v4l2element, "Failed to set input %d on device %s: %s",
-        input, v4l2element->videodev, g_strerror (errno));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l2_get_output()
- *   Get the output of the current device
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l2_get_output (GstV4l2Element * v4l2element, gint * output)
-{
-  gint n;
-
-  GST_DEBUG_OBJECT (v4l2element, "trying to get output");
-  if (!GST_V4L2_IS_OPEN (v4l2element))
-    return FALSE;
-
-  if (ioctl (v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
-    GST_WARNING_OBJECT (v4l2element,
-        "Failed to get current output on device %s: %s",
-        v4l2element->videodev, g_strerror (errno));
-    return FALSE;
-  }
-
-  *output = n;
-
-  return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l2_set_output()
- *   Set the output of the current device
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l2_set_output (GstV4l2Element * v4l2element, gint output)
-{
-  GST_DEBUG_OBJECT (v4l2element, "trying to set output to %d", output);
-  if (!GST_V4L2_IS_OPEN (v4l2element))
-    return FALSE;
-  if (!GST_V4L2_IS_ACTIVE (v4l2element))
-    return FALSE;
-
-  if (ioctl (v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
-    GST_WARNING_OBJECT (v4l2element,
-        "Failed to set current output on device %s to %d: %s",
-        v4l2element->videodev, output, g_strerror (errno));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
 /******************************************************
  * gst_v4l2_get_frequency():
  *   get the current frequency
@@ -688,8 +590,6 @@ gst_v4l2_set_frequency (GstV4l2Element * v4l2element,
       frequency);
   if (!GST_V4L2_IS_OPEN (v4l2element))
     return FALSE;
-  if (!GST_V4L2_IS_ACTIVE (v4l2element))
-    return FALSE;
 
   channel = gst_tuner_get_channel (GST_TUNER (v4l2element));
 
index fcacf35..35d80d5 100644 (file)
@@ -1,5 +1,6 @@
 /* G-Streamer generic V4L2 element - generic V4L2 calls handling
  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -90,10 +91,6 @@ gboolean     gst_v4l2_get_norm               (GstV4l2Element *v4l2element,
                                                 v4l2_std_id    *norm);
 gboolean       gst_v4l2_set_norm               (GstV4l2Element *v4l2element,
                                                 v4l2_std_id     norm);
-gboolean       gst_v4l2_get_input              (GstV4l2Element *v4l2element,
-                                                gint           *input);
-gboolean       gst_v4l2_set_input              (GstV4l2Element *v4l2element,
-                                                gint            input);
 gboolean       gst_v4l2_get_output             (GstV4l2Element *v4l2element,
                                                 gint           *output);
 gboolean       gst_v4l2_set_output             (GstV4l2Element *v4l2element,
index b1d9788..f28bc96 100644 (file)
@@ -1,5 +1,6 @@
 /* G-Streamer Video4linux2 video-capture plugin - system calls
  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -319,6 +320,13 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src)
     return FALSE;
   }
 
+  /* Determine the device's framerate */
+  if (!gst_v4l2src_get_fps (v4l2src, &v4l2src->fps_n, &v4l2src->fps_d)) {
+    GST_DEBUG_OBJECT (v4l2src, "frame rate is unknown.");
+    v4l2src->fps_d = 1;
+    v4l2src->fps_n = 0;
+  }
+
   if (v4l2src->breq.memory > 0) {
     if (v4l2src->breq.count < GST_V4L2_MIN_BUFFERS) {
       GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
@@ -588,7 +596,7 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
       fmt.fmt.pix.height);
 
   fmt.fmt.pix.width = G_MAXINT;
-  fmt.fmt.pix.height = 576;
+  fmt.fmt.pix.height = G_MAXINT;
   if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_TRY_FMT, &fmt) < 0) {
     return FALSE;
   }
@@ -604,14 +612,28 @@ gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
 }
 
 gboolean
-gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d)
+gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d)
 {
   v4l2_std_id std;
+  struct v4l2_streamparm stream;
   const GList *item;
 
   if (!GST_V4L2_IS_OPEN (GST_V4L2ELEMENT (v4l2src)))
     return FALSE;
 
+  /* Try to get the frame rate directly from the device using VIDIOC_G_PARM */
+  stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  if (ioctl (GST_V4L2ELEMENT (v4l2src)->video_fd, VIDIOC_G_PARM, &stream) == 0
+      && stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+    /* Note: V4L2 gives us the frame interval, we need the frame rate */
+    *fps_n = stream.parm.capture.timeperframe.denominator;
+    *fps_d = stream.parm.capture.timeperframe.numerator;
+    GST_DEBUG_OBJECT (v4l2src, "frame rate returned by G_PARM: %d/%d fps",
+        *fps_n, *fps_d);
+    return TRUE;
+  }
+
+  /* If G_PARM failed, try to get the same information from the video standard */
   if (!gst_v4l2_get_norm (GST_V4L2ELEMENT (v4l2src), &std))
     return FALSE;
   for (item = GST_V4L2ELEMENT (v4l2src)->stds; item != NULL; item = item->next) {
@@ -624,6 +646,8 @@ gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d)
       *fps_d =
           gst_value_get_fraction_denominator (&GST_TUNER_NORM (v4l2norm)->
           framerate);
+      GST_DEBUG_OBJECT (v4l2src, "frame rate returned by get_norm: %d/%d fps",
+          *fps_n, *fps_d);
       return TRUE;
     }
   }
@@ -780,14 +804,8 @@ gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data,
     GstV4l2Buffer * srcbuf)
 {
   GstBuffer *buf;
-  gint fps_n, fps_d;
-
-  GST_DEBUG_OBJECT (v4l2src, "creating buffer %d");
 
-  if (!gst_v4l2src_get_fps (v4l2src, &fps_n, &fps_d)) {
-    fps_n = 0;
-    fps_d = 1;
-  }
+  GST_LOG_OBJECT (v4l2src, "creating buffer %d");
 
   if (data == NULL) {
     buf = gst_buffer_new_and_alloc (size);
@@ -805,9 +823,9 @@ gst_v4l2src_buffer_new (GstV4l2Src * v4l2src, guint size, guint8 * data,
   GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4l2src)->base_time;
 
   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
-  if (fps_n > 0) {
-    GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND,
-        fps_n, fps_d);
+  if (v4l2src->fps_n > 0) {
+    GST_BUFFER_DURATION (buf) =
+        gst_util_uint64_scale_int (GST_SECOND, v4l2src->fps_n, v4l2src->fps_d);
   } else {
     GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE;
   }
index 1411083..3839ef2 100644 (file)
@@ -1,5 +1,6 @@
 /* G-Streamer Video4linux2 video-capture plugin - system calls
  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) 2006 Edgard Lima <edgard.lima@indt.org.br>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -48,7 +49,7 @@ gboolean gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
 void gst_v4l2src_free_buffer (GstBuffer * buffer);
 
 
-gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, gint * fps_n, gint * fps_d);
+gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d);
 
 GValue *gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src);
 
index b8f85e1..df6ad66 100644 (file)
@@ -199,7 +199,7 @@ main (int argc, char *argv[])
     return -1;
   }
 
-  if (argv < 2) {
+  if (argc < 2) {
     g_object_set (source, "device", "/dev/video0", NULL);
   } else {
     g_object_set (source, "device", argv[1], NULL);
@@ -222,7 +222,7 @@ main (int argc, char *argv[])
     return -1;
   }
 
-  if (argv < 2)
+  if (argc < 2)
     printf
         ("\nOpening /dev/video0. Launch ./v4l2src-test.c devname to try another one\n");