Update xvid plugin to latest xvid (1.0.0-beta3) API.

Original commit message from CVS:
2004-01-03  Ronald Bultje  <rbultje@ronald.bitfreak.net>

reviewed by: <delete if not using a buddy>

* configure.ac:
* ext/xvid/gstxvid.c: (gst_xvid_init), (gst_xvid_error),
(gst_xvid_structure_to_csp), (gst_xvid_csp_to_caps):
* ext/xvid/gstxvid.h:
* ext/xvid/gstxviddec.c: (gst_xviddec_class_init),
(gst_xviddec_init), (gst_xviddec_setup), (gst_xviddec_chain),
(gst_xviddec_src_link), (gst_xviddec_sink_link),
(gst_xviddec_change_state):
* ext/xvid/gstxviddec.h:
* ext/xvid/gstxvidenc.c: (gst_xvidenc_profile_get_type),
(gst_xvidenc_base_init), (gst_xvidenc_class_init),
(gst_xvidenc_init), (gst_xvidenc_setup), (gst_xvidenc_chain),
(gst_xvidenc_link), (gst_xvidenc_set_property),
(gst_xvidenc_get_property), (gst_xvidenc_change_state):
* ext/xvid/gstxvidenc.h:
Update xvid plugin to latest xvid (1.0.0-beta3) API.
diff --git a/ext/xvid/gstxviddec.c b/ext/xvid/gstxviddec.c
index 84af838..37abbed 100644
--- a/ext/xvid/gstxviddec.c
+++ b/ext/xvid/gstxviddec.c
@@ -22,14 +22,16 @@
 #endif
 
 #include <string.h>
-#include "gstxviddec.h"
+#include <xvid.h>
+
 #include <gst/video/video.h>
+#include "gstxviddec.h"
 
 /* elementfactory information */
 GstElementDetails gst_xviddec_details = {
   "Xvid decoder",
   "Codec/Video/Decoder",
-  "Xvid decoder based on xviddecore",
+  "Xvid decoder based on xvidcore",
   "Ronald Bultje <rbultje@ronald.bitfreak.net>",
 };
 
@@ -53,7 +55,11 @@
   GST_PAD_ALWAYS,
   GST_STATIC_CAPS (
     GST_VIDEO_YUV_PAD_TEMPLATE_CAPS ("{ I420, YUY2, YV12, YVYU, UYVY }") "; "
-    GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32 "; "
+    RGB_24_32_STATIC_CAPS (32, 0x00ff0000, 0x0000ff00, 0x000000ff) "; "
+    RGB_24_32_STATIC_CAPS (32, 0xff000000, 0x00ff0000, 0x0000ff00) "; "
+    RGB_24_32_STATIC_CAPS (32, 0x0000ff00, 0x00ff0000, 0xff000000) "; "
+    RGB_24_32_STATIC_CAPS (32, 0x000000ff, 0x0000ff00, 0x00ff0000) "; "
+    RGB_24_32_STATIC_CAPS (24, 0x0000ff, 0x00ff00, 0xff0000) "; "
     GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_15_16
   )
 );
@@ -70,15 +76,20 @@
   /* FILL ME */
 };
 
-static void             gst_xviddec_base_init    (gpointer g_class);
-static void             gst_xviddec_class_init   (GstXvidDecClass *klass);
-static void             gst_xviddec_init         (GstXvidDec      *xviddec);
-static void             gst_xviddec_dispose      (GObject         *object);
-static void             gst_xviddec_chain        (GstPad          *pad,
-                                                  GstData         *data);
-static GstPadLinkReturn gst_xviddec_link	 (GstPad          *pad,
-                                                  const GstCaps  *vscapslist);
-static GstPadLinkReturn	gst_xviddec_negotiate	 (GstXvidDec *xviddec);
+static void gst_xviddec_base_init    (gpointer g_class);
+static void gst_xviddec_class_init   (GstXvidDecClass *klass);
+static void gst_xviddec_init         (GstXvidDec      *xviddec);
+static void gst_xviddec_chain        (GstPad          *pad,
+                                      GstData         *data);
+static GstPadLinkReturn
+	    gst_xviddec_sink_link    (GstPad          *pad,
+                                      const GstCaps   *vscapslist);
+static GstPadLinkReturn
+	    gst_xviddec_src_link     (GstPad          *pad,
+                                      const GstCaps   *vscapslist);
+static GstElementStateReturn
+	    gst_xviddec_change_state (GstElement      *element);
+
 
 static GstElementClass *parent_class = NULL;
 /* static guint gst_xviddec_signals[LAST_SIGNAL] = { 0 }; */
@@ -125,19 +136,19 @@
 static void
 gst_xviddec_class_init (GstXvidDecClass *klass)
 {
-  GObjectClass *gobject_class = (GObjectClass *) klass;
-
-  gst_xvid_init();
+  GstElementClass *gstelement_class = (GstElementClass *) klass;
 
   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
 
-  gobject_class->dispose = gst_xviddec_dispose;
+  gstelement_class->change_state = gst_xviddec_change_state;
 }
 
 
 static void
 gst_xviddec_init (GstXvidDec *xviddec)
 {
+  gst_xvid_init();
+
   /* create the sink pad */
   xviddec->sinkpad = gst_pad_new_from_template(
                        gst_static_pad_template_get (&sink_template),
@@ -145,7 +156,7 @@
   gst_element_add_pad(GST_ELEMENT(xviddec), xviddec->sinkpad);
 
   gst_pad_set_chain_function(xviddec->sinkpad, gst_xviddec_chain);
-  gst_pad_set_link_function(xviddec->sinkpad, gst_xviddec_link);
+  gst_pad_set_link_function(xviddec->sinkpad, gst_xviddec_sink_link);
 
   /* create the src pad */
   xviddec->srcpad = gst_pad_new_from_template(
@@ -153,7 +164,9 @@
                       "src");
   gst_element_add_pad(GST_ELEMENT(xviddec), xviddec->srcpad);
 
-  /* bitrate, etc. */
+  gst_pad_set_link_function(xviddec->srcpad, gst_xviddec_src_link);
+
+  /* size, etc. */
   xviddec->width = xviddec->height = xviddec->csp = -1;
 
   /* set xvid handle to NULL */
@@ -173,16 +186,17 @@
 static gboolean
 gst_xviddec_setup (GstXvidDec *xviddec)
 {
-  XVID_DEC_PARAM xdec;
+  xvid_dec_create_t xdec;
   int ret;
 
   /* initialise parameters, see xvid documentation */
-  memset(&xdec, 0, sizeof(XVID_DEC_PARAM));
+  gst_xvid_init_struct (xdec);
   xdec.width = xviddec->width;
   xdec.height = xviddec->height;
+  xdec.handle = NULL;
 
   if ((ret = xvid_decore(NULL, XVID_DEC_CREATE,
-                         &xdec, NULL)) != XVID_ERR_OK) {
+                         &xdec, NULL)) < 0) {
     gst_element_error(GST_ELEMENT(xviddec),
 		      "Setting parameters %dx%d@%d failed: %s (%d)",
 	              xviddec->width, xviddec->height, xviddec->csp,
@@ -197,60 +211,59 @@
 
 
 static void
-gst_xviddec_dispose (GObject *object)
-{
-  GstXvidDec *xviddec = GST_XVIDDEC(object);
-
-  gst_xviddec_unset(xviddec);
-}
-
-
-static void
 gst_xviddec_chain (GstPad    *pad,
                    GstData *_data)
 {
   GstBuffer *buf = GST_BUFFER (_data);
-  GstXvidDec *xviddec;
+  GstXvidDec *xviddec = GST_XVIDDEC(GST_OBJECT_PARENT(pad));
   GstBuffer *outbuf;
-  XVID_DEC_FRAME xframe;
+  xvid_dec_frame_t xframe;
   int ret;
 
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
-  g_return_if_fail(buf != NULL);
-
-  xviddec = GST_XVIDDEC(GST_OBJECT_PARENT(pad));
 
   if (!xviddec->handle) {
-    if (!gst_xviddec_negotiate(xviddec)) {
-      gst_element_error(GST_ELEMENT(xviddec),
-                        "No format set - aborting");
-      gst_buffer_unref(buf);
-      return;
-    }
+    gst_element_error(GST_ELEMENT(xviddec),
+                      "No format set - aborting");
+    gst_buffer_unref(buf);
+    return;
   }
 
   outbuf = gst_buffer_new_and_alloc(xviddec->width *
                                     xviddec->height *
                                     xviddec->bpp / 8);
   GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
+  GST_BUFFER_DURATION(outbuf)  = GST_BUFFER_DURATION(buf);
   GST_BUFFER_SIZE(outbuf) = xviddec->width *
                             xviddec->height *
                             xviddec->bpp / 8;
 
-  /* encode and so ... */
+  /* decode and so ... */
+  gst_xvid_init_struct (xframe);
+  xframe.general = 0;
   xframe.bitstream = (void *) GST_BUFFER_DATA(buf);
-  xframe.image = (void *) GST_BUFFER_DATA(outbuf);
   xframe.length = GST_BUFFER_SIZE(buf);
-  xframe.stride = 0; /*xviddec->width * xviddec->bpp / 8;*/
-  xframe.colorspace = xviddec->csp;
+  xframe.output.csp = xviddec->csp;
+  if (xviddec->width == xviddec->stride) {
+    xframe.output.plane[0] = GST_BUFFER_DATA(outbuf);
+    xframe.output.plane[1] = xframe.output.plane[0] + (xviddec->width * xviddec->height);
+    xframe.output.plane[2] = xframe.output.plane[1] + (xviddec->width * xviddec->height / 4);
+    xframe.output.stride[0] = xviddec->width;
+    xframe.output.stride[1] = xviddec->width / 2;
+    xframe.output.stride[2] = xviddec->width / 2;
+  } else {
+    xframe.output.plane[0] = GST_BUFFER_DATA(outbuf);
+    xframe.output.stride[0] = xviddec->stride;
+  }
 
   if ((ret = xvid_decore(xviddec->handle, XVID_DEC_DECODE,
-                         &xframe, NULL))) {
+                         &xframe, NULL)) < 0) {
     gst_element_error(GST_ELEMENT(xviddec),
                       "Error decoding xvid frame: %s (%d)\n",
 		      gst_xvid_error(ret), ret);
     gst_buffer_unref(buf);
+    gst_buffer_unref(outbuf);
     return;
   }
 
@@ -258,112 +271,97 @@
   gst_buffer_unref(buf);
 }
 
+/*
+ * This function allows multiple structures because it
+ * can be called from sink_link().
+ */
 
 static GstPadLinkReturn
-gst_xviddec_negotiate (GstXvidDec *xviddec)
+gst_xviddec_src_link (GstPad        *pad,
+                      const GstCaps *vscaps)
 {
-  GstPadLinkReturn ret;
-  GstCaps *caps;
-  struct {
-    guint32 fourcc;
-    gint    depth, bpp;
-    gint    csp;
-  } fmt_list[] = {
-    { GST_MAKE_FOURCC('Y','U','Y','V'), 16, 16, XVID_CSP_YUY2   },
-    { GST_MAKE_FOURCC('U','Y','V','Y'), 16, 16, XVID_CSP_UYVY   },
-    { GST_MAKE_FOURCC('Y','V','Y','U'), 16, 16, XVID_CSP_YVYU   },
-    { GST_MAKE_FOURCC('Y','V','1','2'), 12, 12, XVID_CSP_YV12   },
-    { GST_MAKE_FOURCC('I','4','2','0'), 12, 12, XVID_CSP_I420   },
-    { GST_MAKE_FOURCC('R','G','B',' '), 32, 32, XVID_CSP_RGB32  },
-    { GST_MAKE_FOURCC('R','G','B',' '), 24, 24, XVID_CSP_RGB24  },
-    { GST_MAKE_FOURCC('R','G','B',' '), 16, 16, XVID_CSP_RGB555 },
-    { GST_MAKE_FOURCC('R','G','B',' '), 15, 16, XVID_CSP_RGB565 },
-    { 0, 0, 0 }
-  };
-  gint i;
+  GstXvidDec *xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
+  GstStructure *structure = gst_caps_get_structure (vscaps, 0);
 
-  for (i = 0; fmt_list[i].fourcc != 0; i++) {
-    xviddec->csp = fmt_list[i].csp;
+  if (!GST_PAD_CAPS (xviddec->sinkpad))
+    return GST_PAD_LINK_DELAYED;
 
-    /* try making a caps to set on the other side */
-    if (fmt_list[i].fourcc == GST_MAKE_FOURCC('R','G','B',' ')) {
-      guint32 r_mask = 0, b_mask = 0, g_mask = 0;
-      gint endianness = 0;
-      switch (fmt_list[i].depth) {
-        case 15:
-          endianness = G_BYTE_ORDER;
-          r_mask = 0xf800; g_mask = 0x07c0; b_mask = 0x003e;
-          break;
-        case 16:
-          endianness = G_BYTE_ORDER;
-          r_mask = R_MASK_16_INT; g_mask = G_MASK_16_INT; b_mask = B_MASK_16_INT;
-          break;
-        case 24:
-          endianness = G_BIG_ENDIAN;
-          r_mask = R_MASK_24_INT; g_mask = G_MASK_24_INT; b_mask = B_MASK_24_INT;
-          break;
-        case 32:
-          endianness = G_BIG_ENDIAN;
-          r_mask = R_MASK_32_INT; g_mask = G_MASK_32_INT; b_mask = B_MASK_32_INT;
-          break;
-      }
-      caps = gst_caps_new_simple (
-                          "video/x-raw-rgb",
-                            "width",      G_TYPE_INT, xviddec->width,
-                            "height",     G_TYPE_INT, xviddec->height,
-                            "depth",      G_TYPE_INT, fmt_list[i].depth,
-                            "bpp",        G_TYPE_INT, fmt_list[i].bpp,
-                            "endianness", G_TYPE_INT, endianness,
-                            "red_mask",   G_TYPE_INT, r_mask,
-                            "green_mask", G_TYPE_INT, g_mask,
-                            "blue_mask",  G_TYPE_INT, b_mask,
-			    "framerate",  G_TYPE_DOUBLE, xviddec->fps,
-                            NULL);
-    } else {
-      caps = gst_caps_new_simple (
-                          "video/x-raw-yuv",
-                            "width",      G_TYPE_INT, xviddec->width,
-                            "height",     G_TYPE_INT, xviddec->height,
-                            "format",     GST_TYPE_FOURCC, fmt_list[i].fourcc,
-			    "framerate",  G_TYPE_DOUBLE, xviddec->fps,
-                            NULL);
-    }
-
-    if ((ret = gst_pad_try_set_caps(xviddec->srcpad, caps)) > 0) {
-      xviddec->csp = fmt_list[i].csp;
-      xviddec->bpp = fmt_list[i].bpp;
-      if (gst_xviddec_setup(xviddec))
-        return GST_PAD_LINK_OK;
-    } else if (ret == GST_PAD_LINK_DELAYED) {
-      return ret; /* don't try further (yet) */
-    }
+  /* if there's something old around, remove it */
+  if (xviddec->handle) {
+    gst_xviddec_unset(xviddec);
   }
 
-  /* if we got here - it's not good */
-  return GST_PAD_LINK_REFUSED;
+  xviddec->csp = gst_xvid_structure_to_csp (structure, xviddec->width,
+					    &xviddec->stride,
+					    &xviddec->bpp);
+
+  if (xviddec->csp < 0)
+    return GST_PAD_LINK_REFUSED;
+
+  if (!gst_xviddec_setup(xviddec))
+    return GST_PAD_LINK_REFUSED;;
+
+  return GST_PAD_LINK_OK;
 }
 
-
 static GstPadLinkReturn
-gst_xviddec_link (GstPad  *pad,
-                  const GstCaps *vscaps)
+gst_xviddec_sink_link (GstPad        *pad,
+                       const GstCaps *vscaps)
 {
-  GstXvidDec *xviddec;
+  GstXvidDec *xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
   GstStructure *structure;
 
-  xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
-
   /* if there's something old around, remove it */
   if (xviddec->handle) {
     gst_xviddec_unset(xviddec);
   }
 
   /* if we get here, we know the input is xvid. we
-   * only need to bother with the output colorspace */
+   * only need to bother with the output colorspace,
+   * which the src_link function takes care of. */
   structure = gst_caps_get_structure (vscaps, 0);
   gst_structure_get_int(structure, "width", &xviddec->width);
   gst_structure_get_int(structure, "height", &xviddec->height);
   gst_structure_get_double(structure, "framerate", &xviddec->fps);
 
-  return gst_xviddec_negotiate(xviddec);
+  /* re-nego? or just await src nego? */
+  if (GST_PAD_CAPS(xviddec->srcpad)) {
+    GstPadLinkReturn ret;
+    GstCaps *vscaps = gst_pad_get_caps (GST_PAD_PEER (xviddec->srcpad)), *new;
+    gint i, csp;
+
+    for (i = 0; i < gst_caps_get_size (vscaps); i++) {
+      csp = gst_xvid_structure_to_csp (gst_caps_get_structure (vscaps, i),
+				       0, NULL, NULL);
+      new = gst_xvid_csp_to_caps (csp, xviddec->width, xviddec->height, xviddec->fps);
+      ret = gst_pad_try_set_caps(xviddec->srcpad, new);
+      if (ret != GST_PAD_LINK_REFUSED)
+        return ret;
+    }
+
+    return GST_PAD_LINK_REFUSED;
+  }
+
+  return GST_PAD_LINK_OK;
+}
+
+static GstElementStateReturn
+gst_xviddec_change_state (GstElement *element)
+{
+  GstXvidDec *xviddec = GST_XVIDDEC (element);
+
+  switch (GST_STATE_PENDING (element)) {
+    case GST_STATE_PAUSED_TO_READY:
+      if (xviddec->handle) {
+        gst_xviddec_unset (xviddec);
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (parent_class->change_state)
+    return parent_class->change_state (element);
+
+  return GST_STATE_SUCCESS;
 }