Update xvid plugin to latest xvid (1.0.0-beta3) API.
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 3 Jan 2004 19:38:40 +0000 (19:38 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 3 Jan 2004 19:38:40 +0000 (19:38 +0000)
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.

configure.ac
ext/xvid/gstxvid.c
ext/xvid/gstxvid.h
ext/xvid/gstxviddec.c
ext/xvid/gstxviddec.h
ext/xvid/gstxvidenc.c
ext/xvid/gstxvidenc.h

index e096694f618e59fc63e90d0893bf20c601a9a38a..716a156242c9cd6736fc6efee5993fa1c87a1f7c 100644 (file)
@@ -1289,21 +1289,30 @@ GST_CHECK_FEATURE(VORBIS, [vorbis plug-in], vorbisenc vorbisdec, [
 dnl *** XVID ***
 translit(dnm, m, l) AM_CONDITIONAL(USE_XVID, true)
 GST_CHECK_FEATURE(XVID, [xvid plugins], xvid, [
-  HAVE_XVID=yes
-  AC_CHECK_HEADER(xvid.h, ,
-                  [ AC_MSG_WARN([Xvid headers not found]) &&
-                    HAVE_XVID=no ] )
-  LIBS="-lm"
-  AC_CHECK_LIB(xvidcore, xvid_encore, ,
-               [ AC_MSG_WARN([Xvid encore libs not found]) &&
-                 HAVE_XVID=no ] )
-  AC_CHECK_LIB(xvidcore, xvid_decore, ,
-               [ AC_MSG_WARN([Xvid decore libs not found]) &&
-                 HAVE_XVID=no ] )
-  if test x$HAVE_XVID = xyes; then
-    XVID_LIBS="-lxvidcore -lm"
-    AC_SUBST(XVID_LIBS)
-  fi
+  HAVE_XVID=no
+  AC_CHECK_HEADER(xvid.h, [
+    OLD_LIBS="$LIBS"
+    LIBS="-lm"
+    AC_CHECK_LIB(xvidcore, xvid_encore, [
+      AC_CHECK_LIB(xvidcore, xvid_decore, [
+        AC_CHECK_LIB(xvidcore, xvid_global, [
+          AC_MSG_CHECKING([for uptodate XviD API version])
+          AC_TRY_RUN([
+#include <xvid.h>
+#if XVID_API != XVID_MAKE_API(4,0)
+#error "Incompatible XviD API version"
+#endif
+int main () { return 0; }
+          ],[ AC_MSG_RESULT(yes)
+            XVID_LIBS="-lxvidcore -lm"
+            AC_SUBST(XVID_LIBS)
+            HAVE_XVID=yes
+          ], AC_MSG_RESULT(no) )
+        ], )
+      ], )
+    ], )
+    LIBS="$OLD_LIBS"
+  ], )
 ])
 
 
index 4ed5733cb6af8323475e435393ae0fb40f2dec5c..64ab2f564380a718d3f5b77bd72f9966d48e5366 100644 (file)
@@ -1,4 +1,4 @@
-/* GStreamer xvid decoder plugin
+/* GStreamer xvid encoder/decoder plugin
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
 #endif
 
 #include <string.h>
+#include <xvid.h>
 
+#include <gst/video/video.h>
 #include "gstxviddec.h"
 #include "gstxvidenc.h"
 
 gboolean
 gst_xvid_init (void)
 {
-  XVID_INIT_PARAM xinit;
+  xvid_gbl_init_t xinit;
   gint ret;
   static gboolean is_init = FALSE;
 
@@ -39,20 +41,18 @@ gst_xvid_init (void)
   }
 
   /* set up xvid initially (function pointers, CPU flags) */
-  memset(&xinit, 0, sizeof(XVID_INIT_PARAM));
-  xinit.cpu_flags = 0;
-  if ((ret = xvid_init(NULL, 0, &xinit, NULL)) != XVID_ERR_OK) {
+  gst_xvid_init_struct (xinit);
+  if ((ret = xvid_global(NULL, XVID_GBL_INIT, &xinit, NULL)) < 0) {
     g_warning("Failed to initialize XviD: %s (%d)",
              gst_xvid_error(ret), ret);
     return FALSE;
   }
-  
-  if (xinit.api_version != API_VERSION) {
-    g_warning("Xvid API version mismatch! %d.%d (that's us) != %d.%d (lib)",
-              (API_VERSION >> 8) & 0xff, API_VERSION & 0xff,
-              (xinit.api_version >> 8) & 0xff, xinit.api_version & 0xff);
-    return FALSE;
-  }
+
+  GST_LOG ("Initted XviD version %d.%d.%d (API %d.%d)",
+          XVID_VERSION_MAJOR (XVID_VERSION),
+          XVID_VERSION_MINOR (XVID_VERSION),
+          XVID_VERSION_PATCH (XVID_VERSION),
+          XVID_API_MAJOR (XVID_API), XVID_API_MINOR (XVID_API));
 
   is_init = TRUE;
   return TRUE;
@@ -67,14 +67,17 @@ gst_xvid_error (int errorcode)
     case XVID_ERR_FAIL:
       error = "Operation failed";
       break;
-    case XVID_ERR_OK:
+    case 0:
       error = "No error";
       break;
     case XVID_ERR_MEMORY:
-      error = "Memory error";
+      error = "Memory allocation error";
       break;
     case XVID_ERR_FORMAT:
-      error = "Invalid format";
+      error = "File format not supported";
+      break;
+    case XVID_ERR_VERSION:
+      error = "Structure version not supported";
       break;
     default:
       error = "Unknown error";
@@ -84,6 +87,193 @@ gst_xvid_error (int errorcode)
   return error;
 }
 
+gint
+gst_xvid_structure_to_csp (GstStructure *structure,
+                          gint w, gint *_stride, gint *_bpp)
+{
+  const gchar *mime = gst_structure_get_name (structure);
+  gint xvid_cs = -1, stride = -1, bpp = -1;
+
+  if (!strcmp (mime, "video/x-raw-yuv")) {
+    guint32 fourcc;
+
+    gst_structure_get_fourcc (structure, "format", &fourcc);
+    switch (fourcc) {
+      case GST_MAKE_FOURCC('I','4','2','0'):
+        xvid_cs = XVID_CSP_I420;
+        stride = w;
+        bpp = 12;
+        break;
+      case GST_MAKE_FOURCC('Y','U','Y','2'):
+        xvid_cs = XVID_CSP_YUY2;
+        stride = w * 2;
+        bpp = 16;
+        break;
+      case GST_MAKE_FOURCC('Y','V','1','2'):
+        xvid_cs = XVID_CSP_YV12;
+        stride = w;
+        bpp = 12;
+        break;
+      case GST_MAKE_FOURCC('U','Y','V','Y'):
+        xvid_cs = XVID_CSP_UYVY;
+        stride = w * 2;
+        bpp = 16;
+        break;
+      case GST_MAKE_FOURCC('Y','V','Y','U'):
+        xvid_cs = XVID_CSP_YVYU;
+        stride = w * 2;
+        bpp = 16;
+        break;
+    }
+  } else {
+    gint depth, r_mask;
+
+    gst_structure_get_int(structure, "depth", &depth);
+    gst_structure_get_int(structure, "bpp", &bpp);
+    gst_structure_get_int(structure, "red_mask", &r_mask);
+
+    switch (depth) {
+      case 15:
+        xvid_cs = XVID_CSP_RGB555;
+        break;
+      case 16:
+        xvid_cs = XVID_CSP_RGB565;
+        break;
+      case 24:
+        if (bpp == 24) {
+          xvid_cs = XVID_CSP_BGR;
+        } else {
+          switch (r_mask) {
+            case 0xff000000:
+              xvid_cs = XVID_CSP_RGBA;
+              break;
+            case 0x00ff0000:
+              xvid_cs = XVID_CSP_ARGB;
+              break;
+            case 0x0000ff00:
+              xvid_cs = XVID_CSP_BGRA;
+              break;
+            case 0x000000ff:
+              xvid_cs = XVID_CSP_ABGR;
+              break;
+          }
+        }
+        break;
+      default:
+        break;
+    }
+
+    stride = w * bpp / 8;
+  }
+
+  if (_stride)
+    *_stride = stride;
+  if (_bpp)
+    *_bpp = bpp;
+
+  return xvid_cs;
+}
+
+GstCaps *
+gst_xvid_csp_to_caps (gint csp, gint w, gint h, gdouble fps)
+{
+  GstCaps *caps = NULL;
+
+  switch (csp) {
+    case XVID_CSP_RGB555:
+    case XVID_CSP_RGB565:
+    case XVID_CSP_BGR:
+    case XVID_CSP_ABGR:
+    case XVID_CSP_BGRA:
+    case XVID_CSP_ARGB:
+    case XVID_CSP_RGBA: {
+      gint r_mask = 0, b_mask = 0, g_mask = 0,
+          endianness = 0, bpp = 0, depth = 0;
+
+      switch (csp) {
+        case XVID_CSP_RGB555:
+          r_mask = R_MASK_15_INT; g_mask = G_MASK_15_INT; b_mask = B_MASK_15_INT;
+          endianness = G_BYTE_ORDER; depth = 15; bpp = 16;
+          break;
+        case XVID_CSP_RGB565:
+          r_mask = R_MASK_16_INT; g_mask = G_MASK_16_INT; b_mask = B_MASK_16_INT;
+          endianness = G_BYTE_ORDER; depth = 16; bpp = 16;
+          break;
+        case XVID_CSP_BGR:
+          r_mask = 0x0000ff; g_mask = 0x00ff00; b_mask = 0xff0000;
+          endianness = G_BIG_ENDIAN; depth = 24; bpp = 24;
+          break;
+        case XVID_CSP_ABGR:
+          r_mask = 0x000000ff; g_mask = 0x0000ff00; b_mask = 0x00ff0000;
+          endianness = G_BIG_ENDIAN; depth = 24; bpp = 32;
+          break;
+        case XVID_CSP_BGRA:
+          r_mask = 0x0000ff00; g_mask = 0x00ff0000; b_mask = 0xff000000;
+          endianness = G_BIG_ENDIAN; depth = 24; bpp = 32;
+          break;
+        case XVID_CSP_ARGB:
+          r_mask = 0x00ff0000; g_mask = 0x0000ff00; b_mask = 0x000000ff;
+          endianness = G_BIG_ENDIAN; depth = 24; bpp = 32;
+          break;
+        case XVID_CSP_RGBA:
+          r_mask = 0xff000000; g_mask = 0x00ff0000; b_mask = 0x0000ff00;
+          endianness = G_BIG_ENDIAN; depth = 24; bpp = 32;
+          break;
+      }
+
+      caps = gst_caps_new_simple ("video/x-raw-rgb",
+                            "width",      G_TYPE_INT, w,
+                            "height",     G_TYPE_INT, h,
+                            "depth",      G_TYPE_INT, depth,
+                            "bpp",        G_TYPE_INT, 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, fps,
+                            NULL);
+      break;
+    }
+
+    case XVID_CSP_YUY2:
+    case XVID_CSP_YVYU:
+    case XVID_CSP_UYVY:
+    case XVID_CSP_I420:
+    case XVID_CSP_YV12: {
+      guint32 fourcc = 0;
+
+      switch (csp) {
+        case XVID_CSP_YUY2:
+          fourcc = GST_MAKE_FOURCC ('Y','U','Y','2');
+          break;
+        case XVID_CSP_YVYU:
+          fourcc = GST_MAKE_FOURCC ('Y','V','Y','U');
+          break;
+        case XVID_CSP_UYVY:
+          fourcc = GST_MAKE_FOURCC ('U','Y','V','Y');
+          break;
+        case XVID_CSP_I420:
+          fourcc = GST_MAKE_FOURCC ('I','4','2','0');
+          break;
+        case XVID_CSP_YV12:
+          fourcc = GST_MAKE_FOURCC ('Y','V','1','2');
+          break;
+      }
+
+      caps = gst_caps_new_simple ("video/x-raw-yuv",
+                            "width",      G_TYPE_INT, w,
+                            "height",     G_TYPE_INT, h,
+                            "format",     GST_TYPE_FOURCC, fourcc,
+                           "framerate",  G_TYPE_DOUBLE, fps,
+                            NULL);
+      break;
+    }
+  }
+
+  return caps;
+}
+
+
 static gboolean
 plugin_init (GstPlugin *plugin)
 {
@@ -97,9 +287,10 @@ GST_PLUGIN_DEFINE (
   GST_VERSION_MAJOR,
   GST_VERSION_MINOR,
   "xvid",
-  "XVid plugin library",
+  "XviD plugin library",
   plugin_init,
   VERSION,
   "GPL",
   GST_PACKAGE,
-  GST_ORIGIN)
+  GST_ORIGIN
+)
index 6e444f5f02e91be7c039e202fb76990d80d1a8b1..100f93b8a7bdb677482884d26759f58d8cba43b2 100644 (file)
@@ -1,4 +1,4 @@
-/* GStreamer xvid decoder plugin
+/* GStreamer xvid encoder/decoder plugin
  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
  *
  * This library is free software; you can redistribute it and/or
 
 #include <gst/gst.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
+
+#define gst_xvid_init_struct(s) \
+  do { \
+    memset (&s, 0, sizeof(s)); \
+    s.version = XVID_VERSION; \
+  } while (0);
+
+#define RGB_24_32_STATIC_CAPS(bpp, r_mask,g_mask,b_mask) \
+  "video/x-raw-rgb, " \
+  "width = (int) [ 0, MAX ], " \
+  "height = (int) [ 0, MAX], " \
+  "framerate = (double) [ 0.0, MAX], " \
+  "depth = (int) 24, " \
+  "bpp = (int) " G_STRINGIFY (bpp) ", " \
+  "endianness = (int) BIG_ENDIAN, " \
+  "red_mask = (int) " G_STRINGIFY (r_mask) ", " \
+  "green_mask = (int) " G_STRINGIFY (g_mask) ", " \
+  "blue_mask = (int) " G_STRINGIFY (b_mask)
 
 extern gchar * gst_xvid_error (int errorcode);
 extern gboolean        gst_xvid_init  (void);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+extern gint     gst_xvid_structure_to_csp (GstStructure *structure,
+                                          gint w, gint *stride, gint *bpp);
+extern GstCaps *gst_xvid_csp_to_caps      (gint csp, gint w, gint h, gdouble fps);
+
+G_END_DECLS
 
 #endif /* __GST_XVID_H__ */
index 84af838d57ea2206d39fdcc82ba77ab67740f096..37abbed51e687810195abf88b5703bcd6a961bda 100644 (file)
 #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_STATIC_PAD_TEMPLATE (
   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 @@ enum {
   /* 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 @@ gst_xviddec_base_init (gpointer g_class)
 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_xviddec_init (GstXvidDec *xviddec)
   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 @@ gst_xviddec_init (GstXvidDec *xviddec)
                       "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 @@ gst_xviddec_unset (GstXvidDec *xviddec)
 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,
@@ -196,61 +210,60 @@ gst_xviddec_setup (GstXvidDec *xviddec)
 }
 
 
-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_xviddec_chain (GstPad    *pad,
   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;
-
-  for (i = 0; fmt_list[i].fourcc != 0; i++) {
-    xviddec->csp = fmt_list[i].csp;
-
-    /* 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);
-    }
+  GstXvidDec *xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
+  GstStructure *structure = gst_caps_get_structure (vscaps, 0);
 
-    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 (!GST_PAD_CAPS (xviddec->sinkpad))
+    return GST_PAD_LINK_DELAYED;
+
+  /* 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;
 }
index a614bd81d4cb7839fbcbaefc524864097f341a80..fa90d06afb20cfd296c750480f10e32048b4658a 100644 (file)
@@ -21,7 +21,6 @@
 #define __GST_XVIDDEC_H__
 
 #include <gst/gst.h>
-#include <xvid.h>
 #include "gstxvid.h"
 
 #ifdef __cplusplus
@@ -53,7 +52,7 @@ struct _GstXvidDec {
   void *handle;
 
   /* video (output) settings */
-  gint csp, bpp;
+  gint csp, bpp, stride;
   gint width, height;
   double fps;
 };
index ce2e71e9efd56b1e9e6c20f50a6c539f998f9cba..72ec9d7807ef35c78222e48936247923cc7df5be 100644 (file)
 #endif
 
 #include <string.h>
-#include "gstxvidenc.h"
-#include <gst/video/video.h>
+
 #include <xvid.h>
 
+#include <gst/video/video.h>
+#include "gstxvidenc.h"
+
 /* elementfactory information */
 GstElementDetails gst_xvidenc_details = {
   "Xvid encoder",
   "Codec/Video/Encoder",
-  "Xvid encoder based on xvidencore",
+  "Xvid encoder based on xvidcore",
   "Ronald Bultje <rbultje@ronald.bitfreak.net>",
 };
 
@@ -41,7 +43,11 @@ GST_STATIC_PAD_TEMPLATE (
   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
   )
 );
@@ -68,32 +74,75 @@ enum {
 
 enum {
   ARG_0,
+  ARG_PROFILE,
   ARG_BITRATE,
   ARG_MAXKEYINTERVAL,
   ARG_BUFSIZE
+  /* FILL ME:
+   *  - ME
+   *  - VOP
+   *  - VOL
+   *  - PAR
+   *  - max b frames
+   */
 };
 
-static void             gst_xvidenc_base_init    (gpointer g_class);
-static void             gst_xvidenc_class_init   (GstXvidEncClass *klass);
-static void             gst_xvidenc_init         (GstXvidEnc      *xvidenc);
-static void             gst_xvidenc_chain        (GstPad          *pad,
-                                                  GstData         *data);
-static GstPadLinkReturn gst_xvidenc_link        (GstPad          *pad,
-                                                  const GstCaps  *vscapslist);
+static void gst_xvidenc_base_init    (gpointer g_class);
+static void gst_xvidenc_class_init   (GstXvidEncClass *klass);
+static void gst_xvidenc_init         (GstXvidEnc      *xvidenc);
+static void gst_xvidenc_chain        (GstPad          *pad,
+                                      GstData         *data);
+static GstPadLinkReturn
+           gst_xvidenc_link         (GstPad          *pad,
+                                      const GstCaps   *vscapslist);
 
 /* properties */
-static void             gst_xvidenc_set_property (GObject         *object,
-                                                  guint            prop_id,
-                                                  const GValue    *value,
-                                                  GParamSpec      *pspec);
-static void             gst_xvidenc_get_property (GObject         *object,
-                                                  guint            prop_id,
-                                                  GValue          *value,
-                                                  GParamSpec      *pspec);
+static void gst_xvidenc_set_property (GObject         *object,
+                                      guint            prop_id,
+                                      const GValue    *value,
+                                      GParamSpec      *pspec);
+static void gst_xvidenc_get_property (GObject         *object,
+                                      guint            prop_id,
+                                      GValue          *value,
+                                      GParamSpec      *pspec);
+static GstElementStateReturn
+           gst_xvidenc_change_state (GstElement      *element);
 
 static GstElementClass *parent_class = NULL;
 static guint gst_xvidenc_signals[LAST_SIGNAL] = { 0 };
 
+#define GST_TYPE_XVIDENC_PROFILE (gst_xvidenc_profile_get_type ())
+
+static GType
+gst_xvidenc_profile_get_type (void)
+{
+  static GType xvidenc_profile_type = 0;
+
+  if (!xvidenc_profile_type) {
+    static const GEnumValue xvidenc_profiles[] = {
+      { XVID_PROFILE_S_L0,    "S_L0",    "Simple profile, L0" },
+      { XVID_PROFILE_S_L1,    "S_L1",    "Simple profile, L1" },
+      { XVID_PROFILE_S_L2,    "S_L2",    "Simple profile, L2" },
+      { XVID_PROFILE_S_L3,    "S_L3",    "Simple profile, L3" },
+      { XVID_PROFILE_ARTS_L1, "ARTS_L1", "Advanced real-time simple profile, L1" },
+      { XVID_PROFILE_ARTS_L2, "ARTS_L2", "Advanced real-time simple profile, L2" },
+      { XVID_PROFILE_ARTS_L3, "ARTS_L3", "Advanced real-time simple profile, L3" },
+      { XVID_PROFILE_ARTS_L4, "ARTS_L4", "Advanced real-time simple profile, L4" },
+      { XVID_PROFILE_AS_L0,   "AS_L0",   "Advanced simple profile, L0" },
+      { XVID_PROFILE_AS_L1,   "AS_L1",   "Advanced simple profile, L1" },
+      { XVID_PROFILE_AS_L2,   "AS_L2",   "Advanced simple profile, L2" },
+      { XVID_PROFILE_AS_L3,   "AS_L3",   "Advanced simple profile, L3" },
+      { XVID_PROFILE_AS_L4,   "AS_L4",   "Advanced simple profile, L4" },
+      { 0, NULL, NULL },
+    };
+
+    xvidenc_profile_type =
+       g_enum_register_static ("GstXvidEncProfiles",
+                               xvidenc_profiles);
+  }
+
+  return xvidenc_profile_type;
+}
 
 GType
 gst_xvidenc_get_type(void)
@@ -125,8 +174,10 @@ gst_xvidenc_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
-  gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_template));
-  gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_template));
+  gst_element_class_add_pad_template (element_class,
+       gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+       gst_static_pad_template_get (&src_template));
   gst_element_class_set_details (element_class, &gst_xvidenc_details);
 }
 
@@ -136,30 +187,37 @@ gst_xvidenc_class_init (GstXvidEncClass *klass)
   GstElementClass *gstelement_class;
   GObjectClass *gobject_class;
 
-  gst_xvid_init();
-
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
 
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BITRATE,
-    g_param_spec_ulong("bitrate","Bitrate",
-                       "Target video bitrate",
-                       0,G_MAXULONG,0,G_PARAM_READWRITE));
+  /* encoding profile */
+  g_object_class_install_property(gobject_class, ARG_PROFILE,
+    g_param_spec_enum("profile", "Profile", "XviD/MPEG-4 encoding profile",
+                      GST_TYPE_XVIDENC_PROFILE, XVID_PROFILE_S_L0,
+                     G_PARAM_READWRITE));
+
+  /* bitrate */
+  g_object_class_install_property(gobject_class, ARG_BITRATE,
+    g_param_spec_int("bitrate","Bitrate",
+                     "Target video bitrate (kbps)",
+                     0,G_MAXINT,512,G_PARAM_READWRITE));
 
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MAXKEYINTERVAL,
+  /* keyframe interval */
+  g_object_class_install_property(gobject_class, ARG_MAXKEYINTERVAL,
     g_param_spec_int("max_key_interval","Max. Key Interval",
                      "Maximum number of frames between two keyframes",
                      0,G_MAXINT,0,G_PARAM_READWRITE));
 
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFSIZE,
+  g_object_class_install_property(gobject_class, ARG_BUFSIZE,
     g_param_spec_ulong("buffer_size", "Buffer Size",
                        "Size of the video buffers",
                        0,G_MAXULONG,0,G_PARAM_READWRITE));
 
   gobject_class->set_property = gst_xvidenc_set_property;
   gobject_class->get_property = gst_xvidenc_get_property;
+  gstelement_class->change_state = gst_xvidenc_change_state;
 
   gst_xvidenc_signals[FRAME_ENCODED] =
     g_signal_new ("frame_encoded", G_TYPE_FROM_CLASS(klass),
@@ -173,6 +231,8 @@ gst_xvidenc_class_init (GstXvidEncClass *klass)
 static void
 gst_xvidenc_init (GstXvidEnc *xvidenc)
 {
+  gst_xvid_init();
+
   /* create the sink pad */
   xvidenc->sinkpad = gst_pad_new_from_template(
                        gst_static_pad_template_get (&sink_template),
@@ -189,10 +249,12 @@ gst_xvidenc_init (GstXvidEnc *xvidenc)
   gst_element_add_pad(GST_ELEMENT(xvidenc), xvidenc->srcpad);
 
   /* bitrate, etc. */
-  xvidenc->width = xvidenc->height = xvidenc->csp = -1;
-  xvidenc->bitrate = 512 * 1024;
+  xvidenc->width = xvidenc->height = xvidenc->csp = xvidenc->stride = -1;
+  xvidenc->profile = XVID_PROFILE_S_L0;
+  xvidenc->bitrate = 512;
+  xvidenc->max_b_frames = 2;
   xvidenc->max_key_interval = -1; /* default - 2*fps */
-  xvidenc->buffer_size = 512 * 1024;
+  xvidenc->buffer_size = 512;
 
   /* set xvid handle to NULL */
   xvidenc->handle = NULL;
@@ -202,29 +264,40 @@ gst_xvidenc_init (GstXvidEnc *xvidenc)
 static gboolean
 gst_xvidenc_setup (GstXvidEnc *xvidenc)
 {
-  XVID_ENC_PARAM xenc;
-  int ret;
-
-  /* set up xvid codec parameters - grab docs from
-   * xvid.org for more info */
-  memset(&xenc, 0, sizeof(XVID_ENC_PARAM));
+  xvid_enc_create_t xenc;
+  xvid_enc_plugin_t xplugin;
+  xvid_plugin_single_t xsingle;
+  gint ret;
+
+  /* see xvid.h for the meaning of all this. */
+  gst_xvid_init_struct (xenc);
+  xenc.profile = xvidenc->profile;
   xenc.width = xvidenc->width;
   xenc.height = xvidenc->height;
-  xenc.fincr = (int)(xvidenc->fps * 1000);
-  xenc.fbase = 1000;
-  xenc.rc_bitrate = xvidenc->bitrate;
-  xenc.rc_reaction_delay_factor = -1;
-  xenc.rc_averaging_period = -1;
-  xenc.rc_buffer = -1;
-  xenc.min_quantizer = 1;
-  xenc.max_quantizer = 31;
+  xenc.max_bframes = xvidenc->max_b_frames;
+  xenc.global = XVID_GLOBAL_PACKED;
+  xenc.fbase = 1000000;
+  xenc.fincr = (int)(xenc.fbase / xvidenc->fps);
   xenc.max_key_interval = (xvidenc->max_key_interval == -1) ?
-                            (2 * xenc.fincr / xenc.fbase) :
+                            (2 * xenc.fbase / xenc.fincr) :
                               xvidenc->max_key_interval;
   xenc.handle = NULL;
 
+  /* CBR bitrate/quant for now */
+  gst_xvid_init_struct (xsingle);
+  xsingle.bitrate = xvidenc->bitrate << 10;
+  xsingle.reaction_delay_factor = -1;
+  xsingle.averaging_period = -1;
+  xsingle.buffer = -1;
+
+  /* set CBR plugin */
+  xenc.num_plugins = 1;
+  xenc.plugins = &xplugin;
+  xenc.plugins[0].func = xvid_plugin_single;
+  xenc.plugins[0].param = &xsingle;
+
   if ((ret = xvid_encore(NULL, XVID_ENC_CREATE,
-                         &xenc, NULL)) != XVID_ERR_OK) {
+                         &xenc, NULL)) < 0) {
     gst_element_error(GST_ELEMENT(xvidenc),
                       "Error setting up xvid encoder: %s (%d)",
                      gst_xvid_error(ret), ret);
@@ -242,47 +315,55 @@ gst_xvidenc_chain (GstPad    *pad,
                    GstData *_data)
 {
   GstBuffer *buf = GST_BUFFER (_data);
-  GstXvidEnc *xvidenc;
+  GstXvidEnc *xvidenc = GST_XVIDENC(GST_OBJECT_PARENT(pad));
   GstBuffer *outbuf;
-  XVID_ENC_FRAME xframe;
-  int ret;
+  xvid_enc_frame_t xframe;
+  xvid_enc_stats_t xstats;
+  gint ret;
 
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
-  g_return_if_fail(buf != NULL);
 
-  xvidenc = GST_XVIDENC(GST_OBJECT_PARENT(pad));
-
-  outbuf = gst_buffer_new_and_alloc(xvidenc->buffer_size);
+  outbuf = gst_buffer_new_and_alloc(xvidenc->buffer_size << 10);
   GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
+  GST_BUFFER_DURATION(outbuf)  = GST_BUFFER_DURATION(buf);
 
   /* encode and so ... */
-  xframe.image = GST_BUFFER_DATA(buf);
+  gst_xvid_init_struct (xframe);
+  xframe.vol_flags = XVID_VOL_MPEGQUANT |
+                    XVID_VOL_GMC;
+  xframe.par = XVID_PAR_11_VGA;
+  xframe.vop_flags = XVID_VOP_TRELLISQUANT;
+  xframe.motion = 0;
+  xframe.input.csp = xvidenc->csp;
+  if (xvidenc->width == xvidenc->stride) {
+    xframe.input.plane[0] = GST_BUFFER_DATA(buf);
+    xframe.input.plane[1] = xframe.input.plane[0] + (xvidenc->width * xvidenc->height);
+    xframe.input.plane[2] = xframe.input.plane[1] + (xvidenc->width * xvidenc->height / 4);
+    xframe.input.stride[0] = xvidenc->width;
+    xframe.input.stride[1] = xvidenc->width / 2;
+    xframe.input.stride[2] = xvidenc->width / 2;
+  } else {
+    xframe.input.plane[0] = GST_BUFFER_DATA(buf);
+    xframe.input.stride[0] = xvidenc->stride;
+  }
+  xframe.type = XVID_TYPE_AUTO;
   xframe.bitstream = (void *) GST_BUFFER_DATA(outbuf);
   xframe.length = GST_BUFFER_MAXSIZE(outbuf);
-  xframe.intra = -1;
-  xframe.quant = 0;
-  xframe.colorspace = xvidenc->csp;
-  xframe.general = XVID_H263QUANT |
-                   XVID_INTER4V |
-                   XVID_HALFPEL;
-  xframe.motion = PMV_EARLYSTOP16 |
-                  PMV_HALFPELREFINE16 |
-                  PMV_EXTSEARCH16 |
-                  PMV_EARLYSTOP8 |
-                  PMV_HALFPELREFINE8;
+  gst_xvid_init_struct (xstats);
 
   if ((ret = xvid_encore(xvidenc->handle, XVID_ENC_ENCODE,
-                         &xframe, NULL)) != XVID_ERR_OK) {
+                         &xframe, &xstats)) < 0) {
     gst_element_error(GST_ELEMENT(xvidenc),
                       "Error encoding xvid frame: %s (%d)",
                      gst_xvid_error(ret), ret);
     gst_buffer_unref(buf);
+    gst_buffer_unref(outbuf);
     return;
   }
 
-  GST_BUFFER_SIZE(outbuf) = xframe.length;
-  if (xframe.intra)
+  GST_BUFFER_SIZE(outbuf) = xstats.length;
+  if (xframe.out_flags & XVID_KEYFRAME)
     GST_BUFFER_FLAG_SET(outbuf, GST_BUFFER_KEY_UNIT);
 
   /* go out, multiply! */
@@ -302,10 +383,10 @@ gst_xvidenc_link (GstPad  *pad,
 {
   GstXvidEnc *xvidenc;
   GstStructure *structure;
-  gint w,h,d;
+  const gchar *mime;
+  gint w, h;
   double fps;
-  guint32 fourcc;
-  gint xvid_cs = -1;
+  gint xvid_cs = -1, stride = -1;
 
   xvidenc = GST_XVIDENC(gst_pad_get_parent (pad));
 
@@ -321,68 +402,27 @@ gst_xvidenc_link (GstPad  *pad,
   gst_structure_get_int (structure, "width", &w);
   gst_structure_get_int (structure, "height", &h);
   gst_structure_get_double (structure, "framerate", &fps);
-  if (gst_structure_has_field_typed (structure, "format", GST_TYPE_FOURCC))
-    gst_structure_get_fourcc (structure, "format", &fourcc);
-  else
-    fourcc = GST_MAKE_FOURCC('R','G','B',' ');
-
-  switch (fourcc)
-  {
-    case GST_MAKE_FOURCC('I','4','2','0'):
-    case GST_MAKE_FOURCC('I','Y','U','V'):
-      xvid_cs = XVID_CSP_I420;
-      break;
-    case GST_MAKE_FOURCC('Y','U','Y','2'):
-      xvid_cs = XVID_CSP_YUY2;
-      break;
-    case GST_MAKE_FOURCC('Y','V','1','2'):
-      xvid_cs = XVID_CSP_YV12;
-      break;
-    case GST_MAKE_FOURCC('U','Y','V','Y'):
-      xvid_cs = XVID_CSP_UYVY;
-      break;
-    case GST_MAKE_FOURCC('Y','V','Y','U'):
-      xvid_cs = XVID_CSP_YVYU;
-      break;
-    case GST_MAKE_FOURCC('R','G','B',' '):
-      gst_structure_get_int(structure, "depth", &d);
-      switch (d) {
-        case 15:
-          xvid_cs = XVID_CSP_RGB555;
-          break;
-        case 16:
-          xvid_cs = XVID_CSP_RGB565;
-          break;
-        case 24:
-          xvid_cs = XVID_CSP_RGB24;
-          break;
-        case 32:
-          xvid_cs = XVID_CSP_RGB32;
-          break;
-      }
-      break;
-  }
+  mime = gst_structure_get_name (structure);
 
+  xvid_cs = gst_xvid_structure_to_csp (structure, w, &stride, NULL);
   g_return_val_if_fail (xvid_cs != -1, GST_PAD_LINK_REFUSED);
 
   xvidenc->csp = xvid_cs;
   xvidenc->width = w;
   xvidenc->height = h;
+  xvidenc->stride = stride;
   xvidenc->fps = fps;
 
   if (gst_xvidenc_setup(xvidenc)) {
     GstPadLinkReturn ret;
     GstCaps *new_caps;
 
-    new_caps = gst_caps_new_simple(
-                            "video/x-xvid",
-                            "width",  G_TYPE_INT, w,
-                            "height", G_TYPE_INT, h,
-                           "framerate", G_TYPE_DOUBLE, fps);
-
+    new_caps = gst_caps_new_simple("video/x-xvid",
+                                  "width",     G_TYPE_INT, w,
+                                  "height",    G_TYPE_INT, h,
+                                  "framerate", G_TYPE_DOUBLE, fps, NULL);
     ret = gst_pad_try_set_caps(xvidenc->srcpad, new_caps);
-
-    if (ret <= 0) {
+    if (GST_PAD_LINK_FAILED (ret)) {
       if (xvidenc->handle) {
         xvid_encore(xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL);
         xvidenc->handle = NULL;
@@ -411,11 +451,14 @@ gst_xvidenc_set_property (GObject      *object,
 
   switch (prop_id)
   {
+    case ARG_PROFILE:
+      xvidenc->profile = g_value_get_enum(value);
+      break;
     case ARG_BITRATE:
-      xvidenc->bitrate = g_value_get_ulong(value);
+      xvidenc->bitrate = g_value_get_int(value);
       break;
     case ARG_BUFSIZE:
-      xvidenc->buffer_size = g_value_get_ulong(value);
+      xvidenc->buffer_size = g_value_get_int(value);
       break;
     case ARG_MAXKEYINTERVAL:
       xvidenc->max_key_interval = g_value_get_int(value);
@@ -440,11 +483,14 @@ gst_xvidenc_get_property (GObject    *object,
   xvidenc = GST_XVIDENC(object);
 
   switch (prop_id) {
+    case ARG_PROFILE:
+      g_value_set_enum(value, xvidenc->profile);
+      break;
     case ARG_BITRATE:
-      g_value_set_ulong(value, xvidenc->bitrate);
+      g_value_set_int(value, xvidenc->bitrate);
       break;
     case ARG_BUFSIZE:
-      g_value_set_ulong(value, xvidenc->buffer_size);
+      g_value_set_int(value, xvidenc->buffer_size);
       break;
     case ARG_MAXKEYINTERVAL:
       g_value_set_int(value, xvidenc->max_key_interval);
@@ -454,3 +500,25 @@ gst_xvidenc_get_property (GObject    *object,
       break;
   }
 }
+
+static GstElementStateReturn
+gst_xvidenc_change_state (GstElement *element)
+{
+  GstXvidEnc *xvidenc = GST_XVIDENC (element);
+
+  switch (GST_STATE_PENDING (element)) {
+    case GST_STATE_PAUSED_TO_READY:
+      if (xvidenc->handle) {
+        xvid_encore(xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL);
+        xvidenc->handle = NULL;
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (parent_class->change_state)
+    return parent_class->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
index 12f4d2fd665acc6e9f7ff9987808555fcc285b44..356ce53f66dc7a6c6e5caa149be53423612aa715 100644 (file)
@@ -48,11 +48,15 @@ struct _GstXvidEnc {
   /* pads */
   GstPad *sinkpad, *srcpad;
 
-  /* quality of encoded JPEG image */
-  gulong bitrate;
+  /* encoding profile */
+  gint profile;
 
-  /* size of the JPEG buffers */
-  gulong buffer_size;
+  /* quality of encoded image */
+  gint bitrate;
+  gint buffer_size;
+
+  /* max number of B frames between I/P */
+  gint max_b_frames;
 
   /* max key interval */
   gint max_key_interval;
@@ -60,8 +64,8 @@ struct _GstXvidEnc {
   /* xvid handle */
   void *handle;
   gint csp;
-  gint width, height;
-  double fps;
+  gint width, height, stride;
+  gdouble fps;
 };
 
 struct _GstXvidEncClass {