? caps
Index: gstxvidenc.c
===================================================================
RCS file: /cvsroot/gstreamer/gst-plugins/ext/xvid/gstxvidenc.c,v
retrieving revision 1.2
diff -u -r1.2 gstxvidenc.c
--- gstxvidenc.c	22 Apr 2003 14:55:12 -0000	1.2
+++ gstxvidenc.c	22 May 2003 16:44:07 -0000
@@ -85,8 +85,10 @@
 static void             gst_xvidenc_init         (GstXvidEnc      *xvidenc);
 static void             gst_xvidenc_chain        (GstPad          *pad,
                                                   GstBuffer       *buf);
-static GstPadLinkReturn gst_xvidenc_connect      (GstPad          *pad,
-                                                  GstCaps         *vscapslist);
+static GstPadLinkReturn gst_xvidenc_connect_sink (GstPad          *pad,
+						  GstCaps         *vscapslist);
+static GstPadLinkReturn gst_xvidenc_connect_src  (GstPad          *pad,
+						  GstCaps         *vscapslist);
 
 /* properties */
 static void             gst_xvidenc_set_property (GObject         *object,
@@ -128,6 +130,73 @@
 }
 
 
+static const GstFormat*
+get_src_formats (GstPad *pad)
+{
+  static const GstFormat formats[] = {
+    GST_FORMAT_BYTES,
+    GST_FORMAT_TIME,
+    GST_FORMAT_UNITS,
+    0
+  };
+  return formats;
+}
+
+static gboolean
+convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
+	     GstFormat *dest_format, gint64 *dest_value)
+{
+  GstXvidEnc *xvidenc;
+
+  xvidenc = GST_XVIDENC(GST_OBJECT_PARENT(pad));
+	      
+  if (xvidenc->handle == NULL) {
+    g_warning ("xvidenc: attempt to do conversion before media is sampled (ignored)");
+    return FALSE;
+  }
+
+  switch (src_format) {
+    case GST_FORMAT_BYTES:
+      switch (*dest_format) {
+        case GST_FORMAT_DEFAULT:
+          *dest_format = GST_FORMAT_TIME;
+        case GST_FORMAT_TIME:
+	  *dest_value = (GST_SECOND * 8 * src_value) / xvidenc->bitrate;
+	  return TRUE;
+        default: break;
+      }
+      break;
+    case GST_FORMAT_TIME:
+      switch (*dest_format) {
+        case GST_FORMAT_DEFAULT:
+          *dest_format = GST_FORMAT_BYTES;
+        case GST_FORMAT_BYTES:
+	  *dest_format = src_value * xvidenc->bitrate / (GST_SECOND * 8);
+	  return TRUE;
+        case GST_FORMAT_UNITS:
+	  *dest_value = src_value * xvidenc->fps / GST_SECOND;
+	  return TRUE;
+        default: break;
+      }
+      break;
+    case GST_FORMAT_UNITS:
+      switch (*dest_format) {
+        case GST_FORMAT_DEFAULT:
+          *dest_format = GST_FORMAT_TIME;
+        case GST_FORMAT_TIME:
+          *dest_value = src_value * GST_SECOND / xvidenc->fps;
+	  return TRUE;
+        case GST_FORMAT_BYTES:
+	  *dest_value = xvidenc->bitrate * src_value / (8 * xvidenc->fps);
+	  return TRUE;
+        default: break;
+      }
+      break;
+    default: break;
+  }
+  return FALSE;
+}
+
 static void
 gst_xvidenc_class_init (GstXvidEncClass *klass)
 {
@@ -188,13 +257,19 @@
   gst_element_add_pad(GST_ELEMENT(xvidenc), xvidenc->sinkpad);
 
   gst_pad_set_chain_function(xvidenc->sinkpad, gst_xvidenc_chain);
-  gst_pad_set_link_function(xvidenc->sinkpad, gst_xvidenc_connect);
+  gst_pad_set_link_function(xvidenc->sinkpad, gst_xvidenc_connect_sink);
 
   /* create the src pad */
   xvidenc->srcpad = gst_pad_new_from_template(
                       GST_PAD_TEMPLATE_GET(src_template),
                       "src");
   gst_element_add_pad(GST_ELEMENT(xvidenc), xvidenc->srcpad);
+  gst_pad_set_link_function    (xvidenc->srcpad,
+				gst_xvidenc_connect_src);
+  gst_pad_set_formats_function (xvidenc->srcpad,
+				GST_DEBUG_FUNCPTR (get_src_formats));
+  gst_pad_set_convert_function (xvidenc->srcpad,
+				GST_DEBUG_FUNCPTR (convert_src));
 
   /* bitrate, etc. */
   xvidenc->width = xvidenc->height = xvidenc->csp = -1;
@@ -211,17 +286,16 @@
 gst_xvidenc_setup (GstXvidEnc *xvidenc)
 {
   XVID_ENC_PARAM xenc;
-  gdouble fps;
   int ret;
 
-  fps = gst_video_frame_rate(GST_PAD_PEER(xvidenc->sinkpad));
+  xvidenc->fps = gst_video_frame_rate(GST_PAD_PEER(xvidenc->sinkpad));
 
   /* set up xvid codec parameters - grab docs from
    * xvid.org for more info */
   memset(&xenc, 0, sizeof(XVID_ENC_PARAM));
   xenc.width = xvidenc->width;
   xenc.height = xvidenc->height;
-  xenc.fincr = (int)(fps * 1000);
+  xenc.fincr = (int)(xvidenc->fps * 1000);
   xenc.fbase = 1000;
   xenc.rc_bitrate = xvidenc->bitrate;
   xenc.rc_reaction_delay_factor = -1;
@@ -312,8 +386,26 @@
 
 
 static GstPadLinkReturn
-gst_xvidenc_connect (GstPad  *pad,
-                     GstCaps *vscaps)
+gst_xvidenc_connect_src (GstPad  *pad,
+			 GstCaps *caps)
+{
+  GstXvidEnc *xvidenc;
+
+  xvidenc = GST_XVIDENC (gst_pad_get_parent (pad));
+
+  if (xvidenc->width < 0)
+    return GST_PAD_LINK_DELAYED;
+
+  return gst_pad_try_set_caps (xvidenc->srcpad,
+			       GST_CAPS_NEW("xvidenc_src_caps",
+					    "video/xvid",
+					    "width",  GST_PROPS_INT (xvidenc->width),
+					    "height", GST_PROPS_INT (xvidenc->height)));
+}
+
+static GstPadLinkReturn
+gst_xvidenc_connect_sink (GstPad  *pad,
+			  GstCaps *vscaps)
 {
   GstXvidEnc *xvidenc;
   GstCaps *caps;
@@ -327,8 +419,9 @@
   }
 
   /* we are not going to act on variable caps */
-  if (!GST_CAPS_IS_FIXED(vscaps))
+  if (!GST_CAPS_IS_FIXED(vscaps)) {
     return GST_PAD_LINK_DELAYED;
+  }
 
   for (caps = vscaps; caps != NULL; caps = caps->next)
   {
@@ -386,11 +479,7 @@
     xvidenc->csp = xvid_cs;
     xvidenc->width = w;
     xvidenc->height = h;
-    return gst_pad_try_set_caps(xvidenc->srcpad,
-                                GST_CAPS_NEW("xvidenc_src_caps",
-                                             "video/xvid",
-                                               "width",  GST_PROPS_INT(w),
-                                               "height", GST_PROPS_INT(h)));
+    return GST_PAD_LINK_OK;
 
 trynext:
     continue;
Index: gstxvidenc.h
===================================================================
RCS file: /cvsroot/gstreamer/gst-plugins/ext/xvid/gstxvidenc.h,v
retrieving revision 1.2
diff -u -r1.2 gstxvidenc.h
--- gstxvidenc.h	22 Apr 2003 14:55:12 -0000	1.2
+++ gstxvidenc.h	22 May 2003 16:44:07 -0000
@@ -60,6 +60,7 @@
   void *handle;
   int csp;
   int width, height;
+  double fps;
 };
 
 struct _GstXvidEncClass {
