Updated all plugins to new capsnego format and added some small usability enhancement...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Tue, 15 Jan 2002 15:52:09 +0000 (15:52 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Tue, 15 Jan 2002 15:52:09 +0000 (15:52 +0000)
Original commit message from CVS:
Updated all plugins to new capsnego format and added some small usability enhancements to v4lelement

sys/v4l/gstv4lelement.c
sys/v4l/gstv4lelement.h
sys/v4l/gstv4lmjpegsink.c
sys/v4l/gstv4lmjpegsrc.c
sys/v4l/gstv4lmjpegsrc.h
sys/v4l/gstv4lsrc.c
sys/v4l/gstv4lsrc.h
sys/v4l/v4l_calls.c
sys/v4l/v4lsrc_calls.c

index b2930aa..930ba5f 100644 (file)
@@ -39,7 +39,9 @@ enum {
 enum {
   ARG_0,
   ARG_CHANNEL,
+  ARG_CHANNEL_NAME,
   ARG_NORM,
+  ARG_NORM_NAME,
   ARG_HAS_TUNER,
   ARG_FREQUENCY,
   ARG_HAS_AUDIO,
@@ -119,9 +121,15 @@ gst_v4lelement_class_init (GstV4lElementClass *klass)
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL,
     g_param_spec_int("channel","channel","channel",
     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL_NAME,
+    g_param_spec_string("channel_name","channel_name","channel_name",
+    NULL, G_PARAM_READABLE));
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM,
     g_param_spec_int("norm","norm","norm",
     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM_NAME,
+    g_param_spec_string("norm_name","norm_name","norm_name",
+    NULL, G_PARAM_READABLE));
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_TUNER,
     g_param_spec_boolean("has_tuner","has_tuner","has_tuner",
@@ -159,10 +167,9 @@ gst_v4lelement_class_init (GstV4lElementClass *klass)
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
     g_param_spec_string("device","device","device",
     NULL, G_PARAM_READWRITE));
-
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_NAME,
     g_param_spec_string("device_name","device_name","device_name",
-    NULL, G_PARAM_READWRITE));
+    NULL, G_PARAM_READABLE));
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_IS_CAPTURE,
     g_param_spec_boolean("can_capture","can_capture","can_capture",
@@ -326,7 +333,7 @@ gst_v4lelement_set_property (GObject      *object,
       v4lelement->videodev = g_strdup(g_value_get_string(value));
       break;
     default:
-      //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -353,11 +360,26 @@ gst_v4lelement_get_property (GObject    *object,
         gst_v4l_get_chan_norm(v4lelement, &temp_i, NULL);
       g_value_set_int(value, temp_i);
       break;
+    case ARG_CHANNEL_NAME:
+      if (GST_V4L_IS_OPEN(v4lelement))
+        g_value_set_string(value, g_strdup(v4lelement->vchan.name));
+      else
+        g_value_set_string(value, g_strdup("Unknown"));
+      break;
     case ARG_NORM:
       if (GST_V4L_IS_OPEN(v4lelement))
         gst_v4l_get_chan_norm(v4lelement, NULL, &temp_i);
       g_value_set_int(value, temp_i);
       break;
+    case ARG_NORM_NAME:
+      if (GST_V4L_IS_OPEN(v4lelement))
+      {
+        gst_v4l_get_chan_norm(v4lelement, NULL, &temp_i);
+        g_value_set_string(value, g_strdup(norm_name[temp_i]));
+      }
+      else
+        g_value_set_string(value, g_strdup("Unknwon"));
+      break;
     case ARG_HAS_TUNER:
       g_value_set_boolean(value, FALSE);
       if (GST_V4L_IS_OPEN(v4lelement))
@@ -454,7 +476,7 @@ gst_v4lelement_get_property (GObject    *object,
         g_value_set_boolean(value, v4lelement->vcap.type & VID_TYPE_MPEG_DECODER);
       break;
     default:
-      //G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
index b49ebad..276bb49 100644 (file)
@@ -58,6 +58,9 @@ struct _GstV4lElement {
   /* the video-device's capabilities */
   struct video_capability vcap;
 
+  /* some more info about the current input's capabilities */
+  struct video_channel vchan;
+
   /* caching values */
   gint channel;
   gint norm;
index f02a162..7c5e399 100644 (file)
@@ -46,24 +46,14 @@ enum {
   ARG_FRAME_TIME,
 };
 
-GST_PADTEMPLATE_FACTORY (sink_template,
-  "sink",
-  GST_PAD_SINK,
-  GST_PAD_ALWAYS,
-  GST_CAPS_NEW (
-    "v4lmjpegsink_caps",
-    "video/jpeg",
-        "width",       GST_PROPS_INT_RANGE (0, G_MAXINT),
-        "height",      GST_PROPS_INT_RANGE (0, G_MAXINT)
-  )
-)
-
 
 /* init functions */
 static void                  gst_v4lmjpegsink_class_init   (GstV4lMjpegSinkClass *klass);
 static void                  gst_v4lmjpegsink_init         (GstV4lMjpegSink      *v4lmjpegsink);
 
 /* the chain of buffers */
+static GstPadConnectReturn   gst_v4lmjpegsink_sinkconnect  (GstPad               *pad,
+                                                            GstCaps              *vscapslist);
 static void                  gst_v4lmjpegsink_chain        (GstPad               *pad,
                                                             GstBuffer            *buf);
 
@@ -79,6 +69,10 @@ static void                  gst_v4lmjpegsink_get_property (GObject
 static void                  gst_v4lmjpegsink_close        (GstV4lMjpegSink      *v4lmjpegsink);
 static GstElementStateReturn gst_v4lmjpegsink_change_state (GstElement           *element);
 
+
+static GstCaps *capslist = NULL;
+static GstPadTemplate *sink_template;
+
 static GstElementClass *parent_class = NULL;
 static guint gst_v4lmjpegsink_signals[LAST_SIGNAL] = { 0 };
 
@@ -155,37 +149,13 @@ gst_v4lmjpegsink_class_init (GstV4lMjpegSinkClass *klass)
   gstelement_class->change_state = gst_v4lmjpegsink_change_state;
 }
 
-static GstPadConnectReturn
-gst_v4lmjpegsink_sinkconnect (GstPad  *pad,
-                          GstCaps *caps)
-{
-  GstV4lMjpegSink *v4lmjpegsink;
-
-  v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad));
-
-  if (!GST_CAPS_IS_FIXED (caps))
-    return GST_PAD_CONNECT_DELAYED;
-
-  v4lmjpegsink->width =  gst_caps_get_int (caps, "width");
-  v4lmjpegsink->height =  gst_caps_get_int (caps, "height");
-
-  gst_v4lmjpegsink_set_playback(v4lmjpegsink,
-    v4lmjpegsink->width, v4lmjpegsink->height,
-    v4lmjpegsink->x_offset, v4lmjpegsink->y_offset,
-    GST_V4LELEMENT(v4lmjpegsink)->norm, 0); /* TODO: interlacing */
-
-  g_signal_emit (G_OBJECT (v4lmjpegsink), gst_v4lmjpegsink_signals[SIGNAL_HAVE_SIZE], 0,
-    v4lmjpegsink->width, v4lmjpegsink->height);
-
-  return GST_PAD_CONNECT_OK;
-}
-
 
 static void
 gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink)
 {
-  v4lmjpegsink->sinkpad = gst_pad_new_from_template(GST_PADTEMPLATE_GET (sink_template), "sink");
+  v4lmjpegsink->sinkpad = gst_pad_new_from_template (sink_template, "sink");
   gst_element_add_pad (GST_ELEMENT (v4lmjpegsink), v4lmjpegsink->sinkpad);
+
   gst_pad_set_chain_function (v4lmjpegsink->sinkpad, gst_v4lmjpegsink_chain);
   gst_pad_set_connect_function (v4lmjpegsink->sinkpad, gst_v4lmjpegsink_sinkconnect);
 
@@ -205,6 +175,39 @@ gst_v4lmjpegsink_init (GstV4lMjpegSink *v4lmjpegsink)
 }
 
 
+static GstPadConnectReturn
+gst_v4lmjpegsink_sinkconnect (GstPad  *pad,
+                              GstCaps *vscapslist)
+{
+  GstV4lMjpegSink *v4lmjpegsink;
+  GstCaps *caps;
+
+  v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad));
+
+  for (caps = capslist; caps != NULL; caps = vscapslist = vscapslist->next)
+  {
+    v4lmjpegsink->width =  gst_caps_get_int (caps, "width");
+    v4lmjpegsink->height =  gst_caps_get_int (caps, "height");
+
+    if (!gst_v4lmjpegsink_set_playback(v4lmjpegsink,
+         v4lmjpegsink->width, v4lmjpegsink->height,
+         v4lmjpegsink->x_offset, v4lmjpegsink->y_offset,
+         GST_V4LELEMENT(v4lmjpegsink)->norm, 0)) /* TODO: interlacing */
+      continue;
+
+    g_signal_emit (G_OBJECT (v4lmjpegsink), gst_v4lmjpegsink_signals[SIGNAL_HAVE_SIZE], 0,
+      v4lmjpegsink->width, v4lmjpegsink->height);
+
+    return GST_PAD_CONNECT_OK;
+  }
+
+  /* if we got here - it's not good */
+  gst_element_error(GST_ELEMENT(v4lmjpegsink),
+    "Failed to find acceptable caps");
+  return GST_PAD_CONNECT_REFUSED;
+}
+
+
 static void
 gst_v4lmjpegsink_chain (GstPad    *pad,
                         GstBuffer *buf)
@@ -281,7 +284,7 @@ gst_v4lmjpegsink_set_property (GObject      *object,
       v4lmjpegsink->y_offset = g_value_get_int(value);
       break;
     default:
-      /*parent_class->set_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -312,7 +315,7 @@ gst_v4lmjpegsink_get_property (GObject    *object,
       g_value_set_int (value, v4lmjpegsink->bufsize);
       break;
     default:
-      /*parent_class->get_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -379,14 +382,29 @@ plugin_init (GModule   *module,
              GstPlugin *plugin)
 {
   GstElementFactory *factory;
+  GstCaps *caps;
 
   /* create an elementfactory for the v4lmjpegsink element */
   factory = gst_elementfactory_new("v4lmjpegsink",GST_TYPE_V4LMJPEGSINK,
                                    &gst_v4lmjpegsink_details);
   g_return_val_if_fail(factory != NULL, FALSE);
 
-  gst_elementfactory_add_padtemplate (factory, 
-                 GST_PADTEMPLATE_GET (sink_template));
+  caps = gst_caps_new ("v4lmjpegsink_caps",
+                       "video/jpeg",
+                       gst_props_new (
+                          "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
+                          "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
+                          NULL       )
+                      );
+  capslist = gst_caps_append(capslist, caps);
+
+  sink_template = gst_padtemplate_new (
+                 "sink",
+                  GST_PAD_SINK,
+                 GST_PAD_ALWAYS,
+                 capslist, NULL);
+
+  gst_elementfactory_add_padtemplate (factory, sink_template);
 
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
 
index 88f9cc5..ee79775 100644 (file)
@@ -57,12 +57,8 @@ static void                  gst_v4lmjpegsrc_class_init   (GstV4lMjpegSrcClass *
 static void                  gst_v4lmjpegsrc_init         (GstV4lMjpegSrc *v4lmjpegsrc);
 
 /* pad/buffer functions */
-/*
-static GstPadNegotiateReturn gst_v4lmjpegsrc_negotiate    (GstPad         *pad,
-                                                           GstCaps        **caps,
-                                                           gpointer       *user_data);
-                                                          */
-static GstCaps*              gst_v4lmjpegsrc_create_caps  (GstV4lMjpegSrc *v4lmjpegsrc);
+static GstPadConnectReturn   gst_v4lmjpegsrc_srcconnect   (GstPad         *pad,
+                                                           GstCaps        *caps);
 static GstBuffer*            gst_v4lmjpegsrc_get          (GstPad         *pad);
 
 /* get/set params */
@@ -87,6 +83,9 @@ static GstBuffer*            gst_v4lmjpegsrc_buffer_copy  (GstBuffer      *srcbu
 static void                  gst_v4lmjpegsrc_buffer_free  (GstBuffer      *buf);
 
 
+static GstCaps *capslist = NULL;
+static GstPadTemplate *src_template;
+
 static GstElementClass *parent_class = NULL;
 //static guint gst_v4lmjpegsrc_signals[LAST_SIGNAL] = { 0 };
 
@@ -174,11 +173,11 @@ gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *klass)
 static void
 gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
 {
-  v4lmjpegsrc->srcpad = gst_pad_new("src", GST_PAD_SRC);
+  v4lmjpegsrc->srcpad = gst_pad_new_from_template (src_template, "src");
   gst_element_add_pad(GST_ELEMENT(v4lmjpegsrc), v4lmjpegsrc->srcpad);
 
   gst_pad_set_get_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_get);
-  //gst_pad_set_negotiate_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_negotiate);
+  gst_pad_set_connect_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_srcconnect);
 
   v4lmjpegsrc->bufferpool = gst_buffer_pool_new();
   gst_buffer_pool_set_buffer_new_function(v4lmjpegsrc->bufferpool, gst_v4lmjpegsrc_buffer_new);
@@ -202,46 +201,21 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
   v4lmjpegsrc->numbufs = 64;
   v4lmjpegsrc->bufsize = 256;
 
-  v4lmjpegsrc->init = TRUE;
+  v4lmjpegsrc->capslist = capslist;
 }
 
 
-
-/*
-static GstPadNegotiateReturn
-gst_v4lmjpegsrc_negotiate (GstPad   *pad,
-                           GstCaps  **caps,
-                           gpointer *user_data) 
+static GstPadConnectReturn
+gst_v4lmjpegsrc_srcconnect (GstPad  *pad,
+                            GstCaps *caps)
 {
   GstV4lMjpegSrc *v4lmjpegsrc;
 
   v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
 
-  if (!*caps) {
-    return GST_PAD_NEGOTIATE_FAIL;
-  }
-  else {
-    return GST_PAD_NEGOTIATE_AGREE;
-  }
-
-  return GST_PAD_NEGOTIATE_FAIL;
-}
-*/
-
-
-static GstCaps*
-gst_v4lmjpegsrc_create_caps (GstV4lMjpegSrc *v4lmjpegsrc)
-{
-  GstCaps *caps;
-
-  caps = GST_CAPS_NEW (
-    "v4lmjpegsrc_caps",
-    "video/jpeg", 
-    "width",            GST_PROPS_INT(v4lmjpegsrc->end_width),
-    "height",           GST_PROPS_INT(v4lmjpegsrc->end_height)
-  );
+  /* we will try_set_caps() with the actual size (wxh) when we know it */
 
-  return caps;
+  return GST_PAD_CONNECT_OK;
 }
 
 
@@ -256,17 +230,6 @@ gst_v4lmjpegsrc_get (GstPad *pad)
 
   v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
 
-  if (v4lmjpegsrc->init) {
-    gst_pad_try_set_caps (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_create_caps (v4lmjpegsrc));
-    v4lmjpegsrc->init = FALSE;
-  }
-  else {
-    if (!gst_pad_get_caps (v4lmjpegsrc->srcpad) && 
-        !gst_pad_renegotiate (v4lmjpegsrc->srcpad)) {
-      return NULL;
-    }
-  }
-
   buf = gst_buffer_new_from_pool(v4lmjpegsrc->bufferpool, 0, 0);
   if (!buf)
   {
@@ -326,7 +289,7 @@ gst_v4lmjpegsrc_set_property (GObject      *object,
       v4lmjpegsrc->bufsize = g_value_get_int(value);
       break;
     default:
-      /*parent_class->set_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -357,7 +320,7 @@ gst_v4lmjpegsrc_get_property (GObject    *object,
       g_value_set_int(value, v4lmjpegsrc->breq.size);
       break;
     default:
-      /*parent_class->get_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -368,6 +331,7 @@ gst_v4lmjpegsrc_change_state (GstElement *element)
 {
   GstV4lMjpegSrc *v4lmjpegsrc;
   GstElementStateReturn parent_value;
+  GstCaps *caps;
 
   g_return_val_if_fail(GST_IS_V4LMJPEGSRC(element), GST_STATE_FAILURE);
   
@@ -396,7 +360,19 @@ gst_v4lmjpegsrc_change_state (GstElement *element)
              v4lmjpegsrc->quality))
           return GST_STATE_FAILURE;
       }
-      v4lmjpegsrc->init = TRUE;
+      /* we now have an actual width/height - *set it* */
+      caps = gst_caps_new("v4lmjpegsrc_caps",
+                          "video/jpeg",
+                          gst_props_new(
+                            "width",  GST_PROPS_INT(v4lmjpegsrc->end_width),
+                            "height", GST_PROPS_INT(v4lmjpegsrc->end_height),
+                            NULL       ) );
+      if (!gst_pad_try_set_caps(v4lmjpegsrc->srcpad, caps))
+      {
+        gst_element_error(GST_ELEMENT(v4lmjpegsrc),
+          "Failed to set new caps");
+        return GST_STATE_FAILURE;
+      }
       if (!gst_v4lmjpegsrc_capture_init(v4lmjpegsrc))
         return GST_STATE_FAILURE;
       break;
@@ -509,11 +485,30 @@ static gboolean
 plugin_init (GModule *module, GstPlugin *plugin)
 {
   GstElementFactory *factory;
+  GstCaps *caps;
 
   /* create an elementfactory for the v4lmjpegsrcparse element */
   factory = gst_elementfactory_new("v4lmjpegsrc",GST_TYPE_V4LMJPEGSRC,
                                    &gst_v4lmjpegsrc_details);
   g_return_val_if_fail(factory != NULL, FALSE);
+
+  caps = gst_caps_new ("v4lmjpegsrc_caps",
+                       "video/jpeg",
+                       gst_props_new (
+                          "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
+                          "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
+                          NULL       )
+                      );
+  capslist = gst_caps_append(capslist, caps);
+
+  src_template = gst_padtemplate_new (
+                 "src",
+                  GST_PAD_SRC,
+                 GST_PAD_ALWAYS,
+                 capslist, NULL);
+
+  gst_elementfactory_add_padtemplate (factory, src_template);
+
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
 
   return TRUE;
index f250daa..e77da9b 100644 (file)
@@ -55,6 +55,9 @@ struct _GstV4lMjpegSrc {
   struct mjpeg_sync bsync;
   struct mjpeg_requestbuffers breq;
 
+  /* list of available caps */
+  GstCaps *capslist;
+
   /* caching values */
   gint x_offset;
   gint y_offset;
@@ -69,8 +72,6 @@ struct _GstV4lMjpegSrc {
   gint quality;
   gint numbufs;
   gint bufsize; /* in KB */
-
-  gboolean init;
 };
 
 struct _GstV4lMjpegSrcClass {
index a0723a8..4eb9874 100644 (file)
@@ -54,11 +54,8 @@ static void                  gst_v4lsrc_class_init   (GstV4lSrcClass *klass);
 static void                  gst_v4lsrc_init         (GstV4lSrc      *v4lsrc);
 
 /* pad/buffer functions */
-/*static GstPadNegotiateReturn gst_v4lsrc_negotiate    (GstPad         *pad,
-                                                      GstCaps        **caps,
-                                                      gpointer       *user_data);
-                                                     */
-static GstCaps*              gst_v4lsrc_create_caps  (GstV4lSrc      *v4lsrc);
+static GstPadConnectReturn   gst_v4lsrc_srcconnect   (GstPad         *pad,
+                                                      GstCaps        *caps);
 static GstBuffer*            gst_v4lsrc_get          (GstPad         *pad);
 
 /* get/set params */
@@ -83,6 +80,9 @@ static GstBuffer*            gst_v4lsrc_buffer_copy  (GstBuffer      *srcbuf);
 static void                  gst_v4lsrc_buffer_free  (GstBuffer      *buf);
 
 
+static GstCaps *capslist = NULL;
+static GstPadTemplate *src_template;
+
 static GstElementClass *parent_class = NULL;\
 //static guint gst_v4lsrc_signals[LAST_SIGNAL] = { 0 };
 
@@ -151,11 +151,11 @@ gst_v4lsrc_class_init (GstV4lSrcClass *klass)
 static void
 gst_v4lsrc_init (GstV4lSrc *v4lsrc)
 {
-  v4lsrc->srcpad = gst_pad_new("src", GST_PAD_SRC);
+  v4lsrc->srcpad = gst_pad_new_from_template (src_template, "src");
   gst_element_add_pad(GST_ELEMENT(v4lsrc), v4lsrc->srcpad);
 
   gst_pad_set_get_function (v4lsrc->srcpad, gst_v4lsrc_get);
-  //gst_pad_set_negotiate_function (v4lsrc->srcpad, gst_v4lsrc_negotiate);
+  gst_pad_set_connect_function (v4lsrc->srcpad, gst_v4lsrc_srcconnect);
 
   v4lsrc->bufferpool = gst_buffer_pool_new();
   gst_buffer_pool_set_buffer_new_function(v4lsrc->bufferpool, gst_v4lsrc_buffer_new);
@@ -163,192 +163,155 @@ gst_v4lsrc_init (GstV4lSrc *v4lsrc)
   gst_buffer_pool_set_buffer_free_function(v4lsrc->bufferpool, gst_v4lsrc_buffer_free);
   gst_buffer_pool_set_user_data(v4lsrc->bufferpool, v4lsrc);
 
-  v4lsrc->palette = VIDEO_PALETTE_YUV420P;
+  v4lsrc->palette = 0; /* means 'any' - user can specify a specific palette */
   v4lsrc->width = 160;
   v4lsrc->height = 120;
   v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
 
-  v4lsrc->init = TRUE;
+  v4lsrc->capslist = capslist;
 }
 
 
-#if 0
-static GstPadNegotiateReturn
-gst_v4lsrc_negotiate (GstPad   *pad,
-                      GstCaps  **caps,
-                      gpointer *user_data) 
+static GstPadConnectReturn
+gst_v4lsrc_srcconnect (GstPad  *pad,
+                       GstCaps *vscapslist)
 {
   GstV4lSrc *v4lsrc;
+  GstCaps *caps, *newcaps;
+  gint palette = v4lsrc->palette;
 
   v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
 
-  if (!*caps) {
-    return GST_PAD_NEGOTIATE_FAIL;
-  }
-  else {
-    gint width, height;
-    gulong format;
-
-    width  = gst_caps_get_int (*caps, "width");
-    height = gst_caps_get_int (*caps, "height");
-    format = gst_caps_get_fourcc_int (*caps, "format");
-
-    switch (format) {
-      case GST_MAKE_FOURCC ('R','G','B',' '):
-      {
-        gint depth;
-
-        depth = gst_caps_get_int (*caps, "depth");
-
-        switch (depth) {
-          case 15:
-            v4lsrc->palette = VIDEO_PALETTE_RGB555;
-            v4lsrc->buffer_size = width * height * 2;
-            break;
-          case 16:
-            v4lsrc->palette = VIDEO_PALETTE_RGB565;
-            v4lsrc->buffer_size = width * height * 2;
-            break;
-          case 24:
-            v4lsrc->palette = VIDEO_PALETTE_RGB24;
-            v4lsrc->buffer_size = width * height * 3;
-            break;
-          case 32:
-            v4lsrc->palette = VIDEO_PALETTE_RGB32;
-            v4lsrc->buffer_size = width * height * 4;
-            break;
-          default:
-            *caps = NULL;
-            return GST_PAD_NEGOTIATE_TRY;
-        }
-
-        break;
-      }
-
-      case GST_MAKE_FOURCC ('I','4','2','0'):
-        v4lsrc->palette = VIDEO_PALETTE_YUV420P;
-        v4lsrc->buffer_size = width * height * 1.5;
-        break;
-
-      case GST_MAKE_FOURCC ('U','Y','V','Y'):
-        v4lsrc->palette = VIDEO_PALETTE_UYVY; //YUV422?;
-        v4lsrc->buffer_size = width * height * 2;
-        break;
-
-      case GST_MAKE_FOURCC ('Y','U','Y','2'):
-        v4lsrc->palette = VIDEO_PALETTE_YUYV; //YUV422?;
-        v4lsrc->buffer_size = width * height * 2;
-        break;
-
-      /* TODO: add YUV4:2:2 planar and YUV4:2:0 packed, maybe also YUV4:1:1? */
-
-      default:
-        *caps = NULL;
-        return GST_PAD_NEGOTIATE_TRY;
-
-    }
-
-    /* if we get here, it's okay */
-    v4lsrc->width  = width;
-    v4lsrc->height = height;
-
-    return GST_PAD_NEGOTIATE_AGREE;
-  }
-
-  return GST_PAD_NEGOTIATE_FAIL;
-}
-#endif
-
-
-static GstCaps*
-gst_v4lsrc_create_caps (GstV4lSrc *v4lsrc)
-{
-  GstCaps *caps = NULL;
-  gulong fourcc = 0;
-
-  switch (v4lsrc->palette) {
-    case VIDEO_PALETTE_RGB555:
-    case VIDEO_PALETTE_RGB565:
-    case VIDEO_PALETTE_RGB24:
-    case VIDEO_PALETTE_RGB32:
+  /* TODO: caps = gst_caps_normalize(capslist); */
+  for (caps = vscapslist ; caps != NULL ; caps = vscapslist = vscapslist->next)
+  {
+    if (v4lsrc->palette > 0)
     {
-      int depth=0, bpp=0;
-
-      fourcc = GST_STR_FOURCC ("RGB ");
-
-      switch (v4lsrc->palette) {
+      switch (v4lsrc->palette)
+      {
+        case VIDEO_PALETTE_YUV420P:
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('I','4','2','0') &&
+              gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('I','Y','U','V'))
+            goto try_next;
+          goto try_caps;
+        case VIDEO_PALETTE_YUV422:
+        case VIDEO_PALETTE_YUYV:
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('Y','U','Y','2'))
+            goto try_next;
+          goto try_caps;
+        case VIDEO_PALETTE_UYVY:
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('U','Y','V','Y'))
+            goto try_next;
+          goto try_caps;
+        case VIDEO_PALETTE_YUV411:
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('Y','4','1','P'))
+            goto try_next;
+          goto try_caps;
         case VIDEO_PALETTE_RGB555:
-          depth = 15;
-          bpp = 2;
-          break;
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
+              gst_caps_get_int(caps, "depth") != 15)
+            goto try_next;
+          goto try_caps;
         case VIDEO_PALETTE_RGB565:
-          depth = 16;
-          bpp = 2;
-          break;
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
+              gst_caps_get_int(caps, "depth") != 16)
+            goto try_next;
+          goto try_caps;
         case VIDEO_PALETTE_RGB24:
-          depth = 24;
-          bpp = 3;
-          break;
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
+              gst_caps_get_int(caps, "depth") != 24)
+            goto try_next;
+          goto try_caps;
         case VIDEO_PALETTE_RGB32:
-          depth = 32;
-          bpp = 4;
-          break;
+          if (gst_caps_get_fourcc_int (caps, "format") != GST_MAKE_FOURCC('R','G','B',' ') ||
+              gst_caps_get_int(caps, "depth") != 32)
+            goto try_next;
+          goto try_caps;
+        default:
+          goto try_next;
       }
-
-      caps = GST_CAPS_NEW (
-        "v4lsrc_caps",
-        "video/raw",
-        "format",      GST_PROPS_FOURCC (fourcc),
-        "width",       GST_PROPS_INT (v4lsrc->width),
-        "height",      GST_PROPS_INT (v4lsrc->height),
-        "bpp",         GST_PROPS_INT (bpp),
-        "depth",       GST_PROPS_INT (depth)
-      );
-
-      v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * bpp;
-
-      break;
     }
-
-    case VIDEO_PALETTE_YUV422:
-    case VIDEO_PALETTE_YUV420P:
+    else
     {
-      switch (v4lsrc->palette) {
-        case VIDEO_PALETTE_YUV422:
-          fourcc = (G_BYTE_ORDER == G_BIG_ENDIAN) ?
-            GST_STR_FOURCC("UYVY") : GST_STR_FOURCC("YUY2");
-          v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          break;
-        case VIDEO_PALETTE_YUYV:
-          fourcc = GST_STR_FOURCC("YUY2");
-          v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          break;
-        case VIDEO_PALETTE_UYVY:
-          fourcc = GST_STR_FOURCC("UYVY");
-          v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          break;
-        case VIDEO_PALETTE_YUV420P:
-          fourcc = GST_STR_FOURCC("I420");
-          v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
-          break;
+      switch (gst_caps_get_fourcc_int(caps, "format"))
+      {
+        case GST_MAKE_FOURCC('I','4','2','0'):
+        case GST_MAKE_FOURCC('I','Y','U','V'):
+          palette = VIDEO_PALETTE_YUV420P;
+          goto try_caps;
+        case GST_MAKE_FOURCC('Y','U','Y','2'):
+          palette = VIDEO_PALETTE_YUV422;
+          goto try_caps;
+        case GST_MAKE_FOURCC('U','Y','V','Y'):
+          palette = VIDEO_PALETTE_UYVY;
+          goto try_caps;
+        case GST_MAKE_FOURCC('Y','4','1','P'):
+          palette = VIDEO_PALETTE_YUV411;
+          goto try_caps;
+        case GST_MAKE_FOURCC('R','G','B',' '):
+          switch (gst_caps_get_int(caps, "depth"))
+          {
+            case 15:
+              palette = VIDEO_PALETTE_RGB555;
+              goto try_caps;
+            case 16:
+              palette = VIDEO_PALETTE_RGB565;
+              goto try_caps;
+            case 24:
+              palette = VIDEO_PALETTE_RGB24;
+              goto try_caps;
+            case 32:
+              palette = VIDEO_PALETTE_RGB32;
+              goto try_caps;
+            default:
+              goto try_next;
+          }
+        default:
+          goto try_next;
       }
-
-      caps = GST_CAPS_NEW (
-        "v4lsrc_caps",
-        "video/raw",
-        "format",      GST_PROPS_FOURCC (fourcc),
-        "width",       GST_PROPS_INT (v4lsrc->width),
-        "height",      GST_PROPS_INT (v4lsrc->height)
-      );
-
-      break;
     }
 
-    default:
-      return NULL;
+  /* if this caps wasn't useful, try the next one */
+  try_next:
+    continue;
+
+  /* if this caps was useful, try it out */
+  try_caps:
+    /* TODO: try the current 'palette' out on the video device */
+
+    if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, palette))
+      continue;
+
+    /* try to connect the pad/caps with the actual width/height */
+    if (palette >= VIDEO_PALETTE_RGB565 && palette <= VIDEO_PALETTE_RGB555)
+       newcaps = gst_caps_new("v4lsrc_caps",
+                              "video/raw",
+                              gst_props_new(
+                                 "format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(caps, "format")),
+                                 "width",  GST_PROPS_INT(v4lsrc->width),
+                                 "width",  GST_PROPS_INT(v4lsrc->height),
+                                 "bpp",    GST_PROPS_INT(gst_caps_get_int(caps, "bpp")),
+                                 "depth",  GST_PROPS_INT(gst_caps_get_int(caps, "depth")),
+                                 NULL      ) );
+    else
+       newcaps = gst_caps_new("v4lsrc_caps",
+                              "video/raw",
+                              gst_props_new(
+                                 "format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(caps, "format")),
+                                 "width",  GST_PROPS_INT(v4lsrc->width),
+                                 "height", GST_PROPS_INT(v4lsrc->height),
+                                 NULL      ) );
+
+    if (!gst_pad_try_set_caps(v4lsrc->srcpad, newcaps))
+      continue;
+    else
+      return GST_PAD_CONNECT_DONE;
   }
 
-  return caps;
+  /* still nothing - no good caps */
+  gst_element_error(GST_ELEMENT(v4lsrc),
+    "Failed to find acceptable caps");
+  return GST_PAD_CONNECT_REFUSED;
 }
 
 
@@ -363,17 +326,6 @@ gst_v4lsrc_get (GstPad *pad)
 
   v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
 
-  if (v4lsrc->init) {
-    gst_pad_try_set_caps (v4lsrc->srcpad, gst_v4lsrc_create_caps (v4lsrc));
-    v4lsrc->init = FALSE;
-  }
-  else {
-    if (!gst_pad_get_caps (v4lsrc->srcpad) && 
-        !gst_pad_renegotiate (v4lsrc->srcpad)) {
-      return NULL;
-    }
-  }
-
   buf = gst_buffer_new_from_pool(v4lsrc->bufferpool, 0, 0);
   if (!buf)
   {
@@ -419,7 +371,7 @@ gst_v4lsrc_set_property (GObject      *object,
       break;
 
     default:
-      /*parent_class->set_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -462,7 +414,7 @@ gst_v4lsrc_get_property (GObject    *object,
       break;
 
     default:
-      /*parent_class->get_property(object, prop_id, value, pspec);*/
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -473,6 +425,7 @@ gst_v4lsrc_change_state (GstElement *element)
 {
   GstV4lSrc *v4lsrc;
   GstElementStateReturn parent_value;
+  GstCaps *caps;
 
   g_return_val_if_fail(GST_IS_V4LSRC(element), GST_STATE_FAILURE);
   
@@ -481,9 +434,120 @@ gst_v4lsrc_change_state (GstElement *element)
   switch (GST_STATE_TRANSITION(element)) {
     case GST_STATE_READY_TO_PAUSED:
       /* set capture parameters and mmap the buffers */
-      if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, v4lsrc->palette))
+      if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height,
+           v4lsrc->palette>0 ? v4lsrc->palette : v4lsrc->mmap.format))
+        return GST_STATE_FAILURE;
+      /* retry setting the video-palette */
+      if (v4lsrc->palette > 0)
+      {
+        switch (v4lsrc->palette)
+        {
+          case VIDEO_PALETTE_YUYV:
+          case VIDEO_PALETTE_UYVY:
+          case VIDEO_PALETTE_YUV422:
+          case VIDEO_PALETTE_YUV420P:
+          case VIDEO_PALETTE_YUV411:
+          {
+            gulong format;
+            switch (v4lsrc->palette)
+            {
+              case VIDEO_PALETTE_YUYV:
+                format = GST_MAKE_FOURCC('Y','U','Y','2');
+                break;
+              case VIDEO_PALETTE_UYVY:
+                format = GST_MAKE_FOURCC('U','Y','V','Y');
+                break;
+              case VIDEO_PALETTE_YUV422:
+                format = GST_MAKE_FOURCC('Y','U','Y','2');
+                break;
+              case VIDEO_PALETTE_YUV420P:
+                format = GST_MAKE_FOURCC('I','4','2','0');
+                break;
+              case VIDEO_PALETTE_YUV411:
+                format = GST_MAKE_FOURCC('Y','4','1','P');
+                break;
+            }
+            caps = gst_caps_new("v4lsrc_caps",
+                                "video/raw",
+                                gst_props_new(
+                                  "format", GST_PROPS_FOURCC(format),
+                                  "width",  GST_PROPS_INT(v4lsrc->width),
+                                  "height", GST_PROPS_INT(v4lsrc->height),
+                                  NULL       ) );
+            break;
+          }
+          case VIDEO_PALETTE_RGB555:
+          case VIDEO_PALETTE_RGB565:
+          case VIDEO_PALETTE_RGB24:
+          case VIDEO_PALETTE_RGB32:
+          {
+            gint depth, bpp;
+            switch (v4lsrc->palette)
+            {
+              case VIDEO_PALETTE_RGB555:
+                bpp = 2;
+                depth = 15;
+                break;
+              case VIDEO_PALETTE_RGB565:
+                bpp = 2;
+                depth = 16;
+                break;
+              case VIDEO_PALETTE_RGB24:
+                bpp = 3;
+                depth = 24;
+                break;
+              case VIDEO_PALETTE_RGB32:
+                bpp = 4;
+                depth = 32;
+                break;
+            }
+            caps = gst_caps_new("v4lsrc_caps",
+                                "video/raw",
+                               gst_props_new(
+                                  "format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
+                                  "width",  GST_PROPS_INT(v4lsrc->width),
+                                  "height", GST_PROPS_INT(v4lsrc->height),
+                                  "bpp",    GST_PROPS_INT(bpp),
+                                  "depth",  GST_PROPS_INT(depth),
+                                  NULL       ) );
+            break;
+          }
+          default:
+            gst_element_error(GST_ELEMENT(v4lsrc),
+              "Failed to find a fourcc code for palette %d (\'%s\')",
+              v4lsrc->palette, palette_name[v4lsrc->palette]);
+            return GST_STATE_FAILURE;
+        }
+      }
+      else
+      {
+        GstCaps *oldcaps = gst_pad_get_caps(v4lsrc->srcpad);
+
+        if (gst_caps_get_fourcc_int(oldcaps, "format") == GST_MAKE_FOURCC('R','G','B',' '))
+          caps = gst_caps_new("v4lsrc_caps",
+                              "video/raw",
+                              gst_props_new(
+                                "format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
+                                "width",  GST_PROPS_INT(v4lsrc->width),
+                                "height", GST_PROPS_INT(v4lsrc->height),
+                                "bpp",    GST_PROPS_INT(gst_caps_get_int(oldcaps, "bpp")),
+                                "depth",  GST_PROPS_INT(gst_caps_get_int(oldcaps, "depth")),
+                                NULL) );
+        else
+          caps = gst_caps_new("v4lsrc_caps",
+                              "video/raw",
+                              gst_props_new(
+                                "format", GST_PROPS_FOURCC(gst_caps_get_fourcc_int(oldcaps, "format")),
+                                "width",  GST_PROPS_INT(v4lsrc->width),
+                                "height", GST_PROPS_INT(v4lsrc->height),
+                                NULL) );
+      }
+      if (!gst_pad_try_set_caps(v4lsrc->srcpad, caps))
+      {
+        gst_element_error(GST_ELEMENT(v4lsrc),
+          "Failed to set new caps");
         return GST_STATE_FAILURE;
-      v4lsrc->init = TRUE;
+      }
       if (!gst_v4lsrc_capture_init(v4lsrc))
         return GST_STATE_FAILURE;
       break;
@@ -573,7 +637,7 @@ gst_v4lsrc_buffer_free (GstBuffer *buf)
     }
 
   gst_element_error(GST_ELEMENT(v4lsrc),
-    "Couldn't find the buffer");
+    "Couldn\'t find the buffer");
 }
 
 
@@ -582,11 +646,60 @@ plugin_init (GModule   *module,
              GstPlugin *plugin)
 {
   GstElementFactory *factory;
+  GstCaps *caps;
+  gint i;
+  gulong format[5] = { GST_MAKE_FOURCC('Y','U','Y','2'), /* VIDEO_PALETTE_YUV422/_YUYV */
+                       GST_MAKE_FOURCC('I','4','2','0'), /* VIDEO_PALETTE_YUV420P */
+                       GST_MAKE_FOURCC('I','Y','U','V'), /* VIDEO_PALETTE_YUV420P */
+                       GST_MAKE_FOURCC('U','Y','V','Y'), /* VIDEO_PALETTE_UYVY */
+                       GST_MAKE_FOURCC('Y','4','1','P')  /* VIDEO_PALETTE_YUV411 */
+                     };
+  gint rgb_bpp[4] = { 2, 2, 3, 4 };
+  gint rgb_depth[4] = { 15, 16, 24, 32 };
 
   /* create an elementfactory for the v4lsrc */
   factory = gst_elementfactory_new("v4lsrc",GST_TYPE_V4LSRC,
                                    &gst_v4lsrc_details);
   g_return_val_if_fail(factory != NULL, FALSE);
+
+  /* make a list of all available caps - first the YUV formats */
+  for (i=0;i<5;i++)
+  {
+    caps = gst_caps_new ("v4lsrc_caps",
+                         "video/raw",
+                         gst_props_new (
+                            "format", GST_PROPS_FOURCC(format[i]),
+                            "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
+                            "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
+                            NULL       )
+                        );
+    capslist = gst_caps_append(capslist, caps);
+  }
+
+  /* now all the RGB formats */
+  for (i=0;i<4;i++)
+  {
+    caps = gst_caps_new ("v4lsrc_caps",
+                         "video/raw",
+                         gst_props_new (
+                            "format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
+                            "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
+                            "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
+                            "bpp",    GST_PROPS_INT(rgb_bpp[i]),
+                            "depth",  GST_PROPS_INT(rgb_depth[i]),
+                            NULL       )
+                        );
+    capslist = gst_caps_append(capslist, caps);
+  }
+
+  src_template = gst_padtemplate_new (
+                 "src",
+                  GST_PAD_SRC,
+                 GST_PAD_ALWAYS,
+                 capslist, NULL);
+
+  gst_elementfactory_add_padtemplate (factory, src_template);
+
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
 
   return TRUE;
index e45ab6f..0912279 100644 (file)
@@ -49,9 +49,6 @@ struct _GstV4lSrc {
   /* bufferpool for the buffers we're gonna use */
   GstBufferPool *bufferpool;
 
-  /* whether we need to reset the GstPad */
-  gboolean init;
-
   /* capture/buffer info */
   struct video_mmap mmap;
   struct video_mbuf mbuf;
@@ -71,6 +68,9 @@ struct _GstV4lSrc {
   pthread_mutex_t mutex_queued_frames;
   pthread_cond_t cond_queued_frames;
 
+  /* list of available caps */
+  GstCaps *capslist;
+
   /* caching values */
   gint width;
   gint height;
index c16748c..b2c16ea 100644 (file)
@@ -161,26 +161,16 @@ gst_v4l_get_chan_norm (GstV4lElement *v4lelement,
                        gint          *channel,
                        gint          *norm)
 {
-  struct video_channel vchan;
-
 #ifdef DEBUG
   fprintf(stderr, "V4L: gst_v4l_get_chan_norm()\n");
 #endif
 
   GST_V4L_CHECK_OPEN(v4lelement);
 
-  if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
-  {
-    gst_element_error(GST_ELEMENT(v4lelement),
-      "Error getting the channel/norm settings: %s",
-      sys_errlist[errno]);
-    return FALSE;
-  }
-
   if (channel)
-    *channel = vchan.channel;
+    *channel = v4lelement->vchan.channel;
   if (norm)
-    *norm = vchan.norm;
+    *norm = v4lelement->vchan.norm;
 
   return TRUE;
 }
@@ -198,8 +188,6 @@ gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
                        gint          channel,
                        gint          norm)
 {
-  struct video_channel vchan;
-
 #ifdef DEBUG
   fprintf(stderr, "V4L: gst_v4l_set_chan_norm(), channel = %d, norm = %d (%s)\n",
     channel, norm, norm_name[norm]);
@@ -208,22 +196,21 @@ gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
   GST_V4L_CHECK_OPEN(v4lelement);
   GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
 
-#if 0
-  if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
+  v4lelement->vchan.channel = channel;
+  v4lelement->vchan.norm = norm;
+
+  if (ioctl(v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0)
   {
-    gst_error("V4lElement - Error getting the channel/norm settings: %s",
+    gst_element_error(GST_ELEMENT(v4lelement),
+      "Error setting the channel/norm settings: %s",
       sys_errlist[errno]);
     return FALSE;
   }
-#endif
-
-  vchan.channel = channel;
-  vchan.norm = norm;
 
-  if (ioctl(v4lelement->video_fd, VIDIOCSCHAN, &vchan) < 0)
+  if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0)
   {
     gst_element_error(GST_ELEMENT(v4lelement),
-      "Error setting the channel/norm settings: %s",
+      "Error getting the channel/norm settings: %s",
       sys_errlist[errno]);
     return FALSE;
   }
@@ -246,7 +233,8 @@ gst_v4l_has_tuner (GstV4lElement *v4lelement)
 
   GST_V4L_CHECK_OPEN(v4lelement);
 
-  return (v4lelement->vcap.type & VID_TYPE_TUNER);
+  return (v4lelement->vcap.type & VID_TYPE_TUNER &&
+          v4lelement->vchan.flags & VIDEO_VC_TUNER);
 }
 
 
@@ -442,7 +430,8 @@ gst_v4l_has_audio (GstV4lElement *v4lelement)
 
   GST_V4L_CHECK_OPEN(v4lelement);
 
-  return (v4lelement->vcap.audios > 0);
+  return (v4lelement->vcap.audios > 0 &&
+          v4lelement->vchan.flags & VIDEO_VC_AUDIO);
 }
 
 
index a71eed7..bc01266 100644 (file)
@@ -240,7 +240,7 @@ gst_v4lsrc_set_capture (GstV4lSrc *v4lsrc,
     width, height, palette);
 #endif
 
-  GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lsrc));
+  /*GST_V4L_CHECK_OPEN(GST_V4LELEMENT(v4lsrc));*/
   GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lsrc));
 
   v4lsrc->mmap.width = width;