I'm too lazy to comment this
authorEdgard Lima <edgard.lima@indt.org.br>
Fri, 24 Feb 2006 19:51:29 +0000 (19:51 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Fri, 24 Feb 2006 19:51:29 +0000 (19:51 +0000)
Original commit message from CVS:
Gdkpixbuf ported from 0.8 to 0.10 by Renato Filho <renato.filho@indt.org.br>. gst_loader and gdkpixbufanimation still need port.

ChangeLog
configure.ac
ext/Makefile.am
ext/gdk_pixbuf/Makefile.am
ext/gdk_pixbuf/gstgdkpixbuf.c
ext/gdk_pixbuf/gstgdkpixbuf.h
ext/gdk_pixbuf/pixbufscale.c
ext/gdk_pixbuf/pixbufscale.h

index de476b1..83b55a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2006-02-24  Edgard Lima  <edgard.lima@indt.org.br>
+
+       * configure.ac:
+       * ext/Makefile.am:
+       * ext/gdk_pixbuf/Makefile.am:
+       * ext/gdk_pixbuf/gstgdkpixbuf.c:
+       * ext/gdk_pixbuf/gstgdkpixbuf.h:
+       * ext/gdk_pixbuf/pixbufscale.c:
+       * ext/gdk_pixbuf/pixbufscale.h:
+         Gdkpixbuf ported from 0.8 to 0.10 by
+         Renato Filho <renato.filho@indt.org.br>.
+         gst_loader and gdkpixbufanimation still need port.
+
 2006-02-24  Michael Smith  <msmith@fluendo.com>
 
        * configure.ac:
index 87b8d69..4fac20d 100644 (file)
@@ -232,6 +232,9 @@ if test "x$HAVE_GTK_22" = "xyes"; then
   AC_SUBST(GTK_VERSION)
   GTK_PREFIX=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
   AC_SUBST(GTK_BASE_DIR)
+  GDK_PIXBUF_LIBDIR=`$PKG_CONFIG --variable=libdir gdk-pixbuf-2.0`
+  GDK_PIXBUF_PREFIXDIR=`$PKG_CONFIG --variable=prefix gdk-pixbuf-2.0`
+  AC_SUBST(GTK_BASE_DIR)
 else
   PKG_CHECK_MODULES(GTK2, gtk+-2.0, HAVE_GTK_20=yes, HAVE_GTK_20=no)
 fi
@@ -399,6 +402,12 @@ GST_CHECK_FEATURE(GCONF, [GConf libraries], , [
   AC_SUBST(GCONF_LIBS)
 ])
 
+dnl *** GDK pixbuf ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_GDK_PIXBUF, true)
+GST_CHECK_FEATURE(GDK_PIXBUF, [GDK pixbuf], gdkpixbufsrc, [
+  if test $HAVE_GTK_22 = "yes"; then HAVE_GDK_PIXBUF=yes; fi;
+])
+
 dnl *** HAL ***
 translit(dnm, m, l) AM_CONDITIONAL(USE_HAL, true)
 GST_CHECK_FEATURE(HAL, [HAL libraries], , [
@@ -639,6 +648,7 @@ ext/dv/Makefile
 ext/esd/Makefile
 ext/flac/Makefile
 ext/gconf/Makefile
+ext/gdk_pixbuf/Makefile
 ext/hal/Makefile
 ext/ladspa/Makefile
 ext/libcaca/Makefile
index e8bdd8c..bfc10cc 100644 (file)
@@ -40,11 +40,11 @@ else
 GCONF_DIR =
 endif
 
-if USE_GDK_PIXBUF
-GDK_PIXBUF_DIR = gdk_pixbuf
-else
+if USE_GDK_PIXBUF
+GDK_PIXBUF_DIR = gdk_pixbuf
+else
 GDK_PIXBUF_DIR =
-endif
+endif
 
 if USE_HAL
 HAL_DIR = hal
@@ -141,6 +141,7 @@ DIST_SUBDIRS = \
        esd \
        flac \
        gconf \
+       gdk_pixbuf \
        hal \
        jpeg \
        ladspa \
index ac18389..8d5abb0 100644 (file)
@@ -1,30 +1,31 @@
 plugin_LTLIBRARIES = libgstgdkpixbuf.la
 
 libgstgdkpixbuf_la_SOURCES = gstgdkpixbuf.c pixbufscale.c
-libgstgdkpixbuf_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS)
-libgstgdkpixbuf_la_LIBADD = $(GST_LIBS) $(GTK_LIBS)
+libgstgdkpixbuf_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) $(GST_BASE_CFLAGS)
+libgstgdkpixbuf_la_LIBADD = $(GTK_LIBS)  $(GST_BASE_LIBS)
 libgstgdkpixbuf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
-if HAVE_GDK_LOADERS
-loaderdir = $(DESTDIR)$(GDK_PIXBUF_LOADER_DIR)
-loader_LTLIBRARIES = gst_loader.la
 
-install-data-hook:
-       if test -z "$(DESTDIR)"  ; then \
-         $(mkinstalldirs) $(DESTDIR)$(GDK_PIXBUF_CONF_DIR) ; \
-         $(QUERYLOADERS) > $(DESTDIR)$(GDK_PIXBUF_CONF_DIR)/gdk-pixbuf.loaders ; \
-       fi
-
-gst_loader_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -DGDK_PIXBUF_ENABLE_BACKEND
-gst_loader_la_SOURCES =        \
-       gstgdkanimation.c       \
-       gst_loader.c
-gst_loader_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-gst_loader_la_LIBADD = $(GTK_LIBS) $(GST_LIBS)
-else
+#if 
+#loaderdir = $(DESTDIR)$(GDK_PIXBUF_LOADER_DIR)
+#loader_LTLIBRARIES = gst_loader.la
+#
+#install-data-hook:
+#      if test -z "$(DESTDIR)"  ; then \
+#        $(mkinstalldirs) $(DESTDIR)$(GDK_PIXBUF_CONF_DIR) ; \
+#        $(QUERYLOADERS) > $(DESTDIR)$(GDK_PIXBUF_CONF_DIR)/gdk-pixbuf.loaders ; \
+#      fi
+#
+#gst_loader_la_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -DGDK_PIXBUF_ENABLE_BACKEND
+#gst_loader_la_SOURCES =       \
+#      gstgdkanimation.c       \
+#      gst_loader.c
+#gst_loader_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) --avoid-version --module
+#gst_loader_la_LIBADD = $(GTK_LIBS) $(GST_LIBS)
+#else
 install-data-hook:
        true
-endif
+#endif
 
 noinst_HEADERS = gstgdkpixbuf.h \
        pixbufscale.h \
index 34a1678..34dcae9 100644 (file)
@@ -37,7 +37,7 @@ static GstElementDetails plugin_details = {
   "GdkPixbuf image decoder",
   "Codec/Decoder/Image",
   "Decodes images in a video stream using GdkPixbuf",
-  "David A. Schleef <ds@schleef.org>",
+  "David A. Schleef <ds@schleef.org>, Renato Filho <renato.filho@indt.org.br>",
 };
 
 /* Filter signals and args */
@@ -53,6 +53,8 @@ enum
   ARG_SILENT
 };
 
+
+
 static GstStaticPadTemplate gst_gdk_pixbuf_sink_template =
     GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -88,46 +90,53 @@ gboolean pixbufscale_init (GstPlugin * plugin);
 
 static void gst_gdk_pixbuf_base_init (gpointer g_class);
 static void gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass);
-static void gst_gdk_pixbuf_init (GstGdkPixbuf * filter);
+static void gst_gdk_pixbuf_init (GstGdkPixbuf * filter,
+    GstGdkPixbufClass * klass);
 
 static void gst_gdk_pixbuf_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_gdk_pixbuf_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void gst_gdk_pixbuf_chain (GstPad * pad, GstData * _data);
+static GstFlowReturn gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_gdk_pixbuf_event (GstPad * pad, GstEvent * event);
 
 #ifdef enable_typefind
 static void gst_gdk_pixbuf_type_find (GstTypeFind * tf, gpointer ignore);
 #endif
 
-static GstElementClass *parent_class = NULL;
 
-static GstPadLinkReturn
-gst_gdk_pixbuf_sink_link (GstPad * pad, const GstCaps * caps)
+GST_BOILERPLATE (GstGdkPixbuf, gst_gdk_pixbuf, GstElement, GST_TYPE_ELEMENT)
+
+     static gboolean gst_gdk_pixbuf_sink_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstGdkPixbuf *filter;
-  const GValue *fps;
+  const GValue *framerate;
+  GstStructure *s;
 
   filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad));
-  g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED);
-  g_return_val_if_fail (GST_IS_GDK_PIXBUF (filter), GST_PAD_LINK_REFUSED);
-
-  fps = gst_structure_get_value (gst_caps_get_structure (caps, 0), "framerate");
-  if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
-    filter->fps_n = gst_value_get_fraction_numerator (fps);
-    filter->fps_d = gst_value_get_fraction_denominator (fps);
-  } else
-    return GST_PAD_LINK_REFUSED;
+  s = gst_caps_get_structure (caps, 0);
+
+  filter->framerate_numerator = 0;
+  filter->framerate_denominator = 1;
+  if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
+    filter->framerate_numerator = gst_value_get_fraction_numerator (framerate);
+    filter->framerate_denominator =
+        gst_value_get_fraction_denominator (framerate);
+    GST_DEBUG ("got framerate of %d/%d fps => packetized mode",
+        filter->framerate_numerator, filter->framerate_denominator);
+  }
 
-  return GST_PAD_LINK_OK;
+  return TRUE;
 }
 
+
 #if GDK_PIXBUF_MAJOR == 2 && GDK_PIXBUF_MINOR < 2
 /* gdk-pixbuf prior to 2.2 didn't have gdk_pixbuf_get_formats().
  * These are just the formats that gdk-pixbuf is known to support.
  * But maybe not -- it may have been compiled without an external
  * library. */
+
 static GstCaps *
 gst_gdk_pixbuf_get_capslist (void)
 {
@@ -162,7 +171,7 @@ gst_gdk_pixbuf_get_capslist (void)
   return_caps = gst_caps_intersect (capslist,
       gst_static_caps_get (&gst_gdk_pixbuf_sink_template.static_caps));
 
-  gst_caps_free (capslist);
+  gst_caps_unref (capslist);
   return return_caps;
 }
 #endif
@@ -179,30 +188,6 @@ gst_gdk_pixbuf_sink_getcaps (GstPad * pad)
   return gst_gdk_pixbuf_get_capslist ();
 }
 
-GType
-gst_gdk_pixbuf_get_type (void)
-{
-  static GType plugin_type = 0;
-
-  if (!plugin_type) {
-    static const GTypeInfo plugin_info = {
-      sizeof (GstGdkPixbufClass),
-      gst_gdk_pixbuf_base_init,
-      NULL,
-      (GClassInitFunc) gst_gdk_pixbuf_class_init,
-      NULL,
-      NULL,
-      sizeof (GstGdkPixbuf),
-      0,
-      (GInstanceInitFunc) gst_gdk_pixbuf_init,
-    };
-
-    plugin_type = g_type_register_static (GST_TYPE_ELEMENT,
-        "GstGdkPixbuf", &plugin_info, 0);
-  }
-  return plugin_type;
-}
-
 static void
 gst_gdk_pixbuf_base_init (gpointer g_class)
 {
@@ -227,161 +212,189 @@ gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass)
 
   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
+  gobject_class->set_property = gst_gdk_pixbuf_set_property;
+  gobject_class->get_property = gst_gdk_pixbuf_get_property;
+
+
   g_object_class_install_property (gobject_class, ARG_SILENT,
       g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
           FALSE, G_PARAM_READWRITE));
 
-  gobject_class->set_property = gst_gdk_pixbuf_set_property;
-  gobject_class->get_property = gst_gdk_pixbuf_get_property;
 }
 
 static void
-gst_gdk_pixbuf_init (GstGdkPixbuf * filter)
+gst_gdk_pixbuf_init (GstGdkPixbuf * filter, GstGdkPixbufClass * klass)
 {
   filter->sinkpad =
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_gdk_pixbuf_sink_template), "sink");
-  gst_pad_set_link_function (filter->sinkpad, gst_gdk_pixbuf_sink_link);
+  gst_pad_set_setcaps_function (filter->sinkpad, gst_gdk_pixbuf_sink_setcaps);
   gst_pad_set_getcaps_function (filter->sinkpad, gst_gdk_pixbuf_sink_getcaps);
 
-  filter->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_gdk_pixbuf_src_template), "src");
-  gst_pad_use_explicit_caps (filter->srcpad);
+  gst_pad_set_chain_function (filter->sinkpad,
+      (GstPadChainFunction) gst_gdk_pixbuf_chain);
+
+  gst_pad_set_event_function (filter->sinkpad, gst_gdk_pixbuf_event);
+
 
   gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+
+
+  filter->srcpad = gst_pad_new_from_template (gst_static_pad_template_get
+      (&gst_gdk_pixbuf_src_template), "src");
+
+  gst_pad_use_fixed_caps (filter->srcpad);
   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
-  gst_pad_set_chain_function (filter->sinkpad, gst_gdk_pixbuf_chain);
 
-  GST_OBJECT_FLAG_SET (GST_ELEMENT (filter), GST_ELEMENT_EVENT_AWARE);
+  filter->last_timestamp = GST_CLOCK_TIME_NONE;
+  filter->pixbuf_loader = NULL;
 }
 
-static void
-gst_gdk_pixbuf_chain (GstPad * pad, GstData * _data)
+static GstFlowReturn
+gst_gdk_pixbuf_flush (GstGdkPixbuf * filter)
 {
-  GstBuffer *buf = GST_BUFFER (_data);
-  GstGdkPixbuf *filter;
-  GError *error = NULL;
-  gboolean push_buffer = FALSE;
-  gboolean dump_buffer = FALSE;
-  gboolean got_eos = FALSE;
-
-  GST_DEBUG ("gst_gdk_pixbuf_chain");
+  GstBuffer *outbuf;
+  GdkPixbuf *pixbuf;
+  int y;
+  guint8 *out_pix;
+  guint8 *in_pix;
+  int in_rowstride;
+  GstFlowReturn ret;
+  GstCaps *caps = NULL;
+
+  pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader);
+  if (pixbuf == NULL) {
+    GST_DEBUG ("error geting pixbuf");
+    return GST_FLOW_ERROR;
+  }
 
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
-
-  filter = GST_GDK_PIXBUF (GST_OBJECT_PARENT (pad));
-  g_return_if_fail (GST_IS_GDK_PIXBUF (filter));
-
-  if (GST_IS_EVENT (_data)) {
-    GstEvent *event = GST_EVENT (buf);
-
-    switch (GST_EVENT_TYPE (event)) {
-      case GST_EVENT_EOS:
-        push_buffer = TRUE;
-        got_eos = TRUE;
-        break;
-      case GST_EVENT_DISCONTINUOUS:
-        dump_buffer = TRUE;
-        break;
-      default:
-        gst_pad_event_default (pad, event);
-        return;
+  if (filter->image_size == 0) {
+    filter->width = gdk_pixbuf_get_width (pixbuf);
+    filter->height = gdk_pixbuf_get_height (pixbuf);
+    filter->rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+    filter->image_size = filter->rowstride * filter->height;
+
+    if (gdk_pixbuf_get_rowstride (pixbuf) / filter->width == 4) {
+      caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBA);
+    } else if (gdk_pixbuf_get_rowstride (pixbuf) / filter->width == 3) {
+      caps = gst_caps_from_string (GST_VIDEO_CAPS_RGB);
+    } else {
+      GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL),
+          ("Bpp %d not supported", gdk_pixbuf_get_bits_per_sample (pixbuf)));
+      return GST_FLOW_ERROR;
     }
+    gst_caps_set_simple (caps,
+        "width", G_TYPE_INT, filter->width,
+        "height", G_TYPE_INT, filter->height,
+        "framerate", GST_TYPE_FRACTION, filter->framerate_numerator,
+        filter->framerate_denominator, NULL);
+
+    GST_DEBUG ("Set size to %dx%d", filter->width, filter->height);
+    gst_pad_set_caps (filter->srcpad, caps);
+    gst_caps_unref (caps);
   }
 
-  if (filter->last_timestamp != GST_BUFFER_TIMESTAMP (buf)) {
-    push_buffer = TRUE;
+  ret = gst_pad_alloc_buffer_and_set_caps (filter->srcpad,
+      GST_BUFFER_OFFSET_NONE,
+      filter->image_size, GST_PAD_CAPS (filter->srcpad), &outbuf);
+
+  if (ret != GST_FLOW_OK) {
+    GST_DEBUG ("Failed to create outbuffer - %d", ret);
+    return GST_FLOW_ERROR;
   }
 
-  if (push_buffer) {
-    if (filter->pixbuf_loader != NULL) {
-      GstBuffer *outbuf;
-      GdkPixbuf *pixbuf;
-      GError *error = NULL;
+  gst_caps_unref (caps);
+  caps = gst_pad_get_negotiated_caps (filter->srcpad);
+  GST_DEBUG ("Caps negotiated %s", gst_caps_to_string (caps));
+  gst_caps_unref (caps);
 
-      if (!gdk_pixbuf_loader_close (filter->pixbuf_loader, &error)) {
-        GST_ELEMENT_ERROR (filter, LIBRARY, SHUTDOWN, (NULL), (error->message));
-        g_error_free (error);
-        return;
-      }
+  GST_BUFFER_TIMESTAMP (outbuf) = filter->last_timestamp;
+  GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
 
-      pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader);
+  in_pix = gdk_pixbuf_get_pixels (pixbuf);
+  in_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  out_pix = GST_BUFFER_DATA (outbuf);
 
-      if (filter->image_size == 0) {
-        GstCaps *caps;
+  for (y = 0; y < filter->height; y++) {
+    memcpy (out_pix, in_pix, filter->rowstride);
+    in_pix += in_rowstride;
+    out_pix += filter->rowstride;
+  }
 
-        filter->width = gdk_pixbuf_get_width (pixbuf);
-        filter->height = gdk_pixbuf_get_height (pixbuf);
-        /* gdk_pixbuf likes to pad rowstride to 4 byte boundaries which we can't do
-         * at the moment
-         */
-        filter->rowstride = filter->width * 3;
-        filter->image_size = filter->rowstride * filter->height;
+  GST_DEBUG ("pushing... %d bytes", GST_BUFFER_SIZE (outbuf));
+  return gst_pad_push (filter->srcpad, outbuf);
+}
 
-        caps = gst_caps_copy (gst_pad_get_pad_template_caps (filter->srcpad));
-        gst_caps_set_simple (caps,
-            "width", G_TYPE_INT, filter->width,
-            "height", G_TYPE_INT, filter->height,
-            "framerate", G_TYPE_DOUBLE, filter->framerate, NULL);
+static gboolean
+gst_gdk_pixbuf_event (GstPad * pad, GstEvent * event)
+{
+  GstFlowReturn res = GST_FLOW_OK;
+  gboolean ret = TRUE;
+  GstGdkPixbuf *pixbuf;
 
-        gst_pad_set_explicit_caps (filter->srcpad, caps);
-      }
+  pixbuf = GST_GDK_PIXBUF (gst_pad_get_parent (pad));
 
-      outbuf =
-          gst_pad_alloc_buffer_and_set_caps (filter->srcpad,
-          GST_BUFFER_OFFSET_NONE, filter->image_size);
-      GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
-      GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
-
-      {
-        int y;
-        guint8 *out_pix;
-        guint8 *in_pix;
-        int in_rowstride;
-
-        in_pix = gdk_pixbuf_get_pixels (pixbuf);
-        in_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-        out_pix = GST_BUFFER_DATA (outbuf);
-
-        for (y = 0; y < filter->height; y++) {
-          memcpy (out_pix, in_pix, filter->rowstride);
-          in_pix += in_rowstride;
-          out_pix += filter->rowstride;
-        }
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+      gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
+      res = gst_gdk_pixbuf_flush (pixbuf);
+      g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
+      break;
+    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_FLUSH_STOP:
+      if (pixbuf->pixbuf_loader != NULL) {
+        gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
+        g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
+        pixbuf->pixbuf_loader = NULL;
       }
-
-      gst_pad_push (filter->srcpad, GST_DATA (outbuf));
-
-      g_object_unref (G_OBJECT (filter->pixbuf_loader));
-      filter->pixbuf_loader = NULL;
-      dump_buffer = FALSE;
-    }
+      break;
+    default:
+      break;
   }
 
-  if (dump_buffer) {
-    if (filter->pixbuf_loader != NULL) {
-      gdk_pixbuf_loader_close (filter->pixbuf_loader, NULL);
-      g_object_unref (G_OBJECT (filter->pixbuf_loader));
-      filter->pixbuf_loader = NULL;
-    }
+  if (res == GST_FLOW_OK) {
+    ret = gst_pad_event_default (pad, event);
+  } else {
+    ret = FALSE;
   }
 
-  if (GST_IS_BUFFER (_data)) {
-    if (filter->pixbuf_loader == NULL) {
-      filter->pixbuf_loader = gdk_pixbuf_loader_new ();
-      filter->last_timestamp = GST_BUFFER_TIMESTAMP (buf);
-    }
+  gst_object_unref (pixbuf);
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buf)
+{
+  GstGdkPixbuf *filter;
+  GstFlowReturn ret = GST_FLOW_OK;
+  GError *error = NULL;
+  GstClockTime timestamp;
 
-    gdk_pixbuf_loader_write (filter->pixbuf_loader, GST_BUFFER_DATA (buf),
-        GST_BUFFER_SIZE (buf), &error);
-    gst_buffer_unref (buf);
+  GST_DEBUG ("gst_gdk_pixbuf_chain");
+  filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad));
+
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+
+  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    filter->last_timestamp = timestamp;
   }
 
-  if (got_eos) {
-    gst_pad_event_default (pad, GST_EVENT (_data));
+  if (filter->pixbuf_loader == NULL) {
+    filter->pixbuf_loader = gdk_pixbuf_loader_new ();
   }
+
+  GST_DEBUG ("Writing buffer size %d", GST_BUFFER_SIZE (buf));
+  if (gdk_pixbuf_loader_write (filter->pixbuf_loader, GST_BUFFER_DATA (buf),
+          GST_BUFFER_SIZE (buf), &error) == FALSE) {
+    GST_DEBUG ("gst_gdk_pixbuf_chain ERROR: %s", error->message);
+    ret = GST_FLOW_ERROR;
+    goto need_more_data;
+  }
+
+need_more_data:
+  gst_object_unref (filter);
+  return ret;
 }
 
 static void
@@ -395,7 +408,7 @@ gst_gdk_pixbuf_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case ARG_SILENT:
-      //filter->silent = g_value_get_boolean (value);
+      /* filter->silent = g_value_get_boolean (value); */
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -414,7 +427,7 @@ gst_gdk_pixbuf_get_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case ARG_SILENT:
-      //g_value_set_boolean (value, filter->silent);
+      /* g_value_set_boolean (value, filter->silent); */
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -496,10 +509,11 @@ plugin_init (GstPlugin * plugin)
   return TRUE;
 }
 
+
 /* this is the structure that gst-register looks for
  * so keep the name plugin_desc, or you cannot get your plug-in registered */
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "gdkpixbuf",
-    "GDK Pixbuf decoder & scaler", plugin_init, VERSION, "LGPL",
-    GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
+    "GDK Pixbuf decoder & scaler",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
index 4a1f9a3..a6f527a 100644 (file)
 G_BEGIN_DECLS
 
 /* #define's don't like whitespacey bits */
-#define GST_TYPE_GDK_PIXBUF \
+#define GST_TYPE_GDK_PIXBUF                    \
   (gst_gdk_pixbuf_get_type())
-#define GST_GDK_PIXBUF(obj) \
+#define GST_GDK_PIXBUF(obj)                                            \
   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GDK_PIXBUF,GstGdkPixbuf))
-#define GST_GDK_PIXBUF_CLASS(klass) \
+#define GST_GDK_PIXBUF_CLASS(klass)                                    \
   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GDK_PIXBUF,GstGdkPixbuf))
-#define GST_IS_GDK_PIXBUF(obj) \
+#define GST_IS_GDK_PIXBUF(obj)                                 \
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GDK_PIXBUF))
-#define GST_IS_GDK_PIXBUF_CLASS(obj) \
+#define GST_IS_GDK_PIXBUF_CLASS(obj)                           \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GDK_PIXBUF))
 
 typedef struct _GstGdkPixbuf      GstGdkPixbuf;
@@ -56,8 +56,8 @@ struct _GstGdkPixbuf
   int rowstride;
   unsigned int image_size;
 
-  gint fps_n;
-  gint fps_d;
+  gint framerate_numerator;
+  gint framerate_denominator;
 };
 
 struct _GstGdkPixbufClass 
index 6b52b42..77b955b 100644 (file)
@@ -36,7 +36,6 @@
 #define GST_RGB24_SIZE(width,height)  ((height)*GST_RGB24_ROWSTRIDE(width))
 
 
-/* debug variable definition */
 GST_DEBUG_CATEGORY (pixbufscale_debug);
 #define GST_CAT_DEFAULT pixbufscale_debug
 
@@ -45,7 +44,9 @@ static GstElementDetails pixbufscale_details =
 GST_ELEMENT_DETAILS ("Gdk Pixbuf scaler",
     "Filter/Effect/Video",
     "Resizes video",
-    "Jan Schmidt <thaytan@mad.scientist.com>\nWim Taymans <wim.taymans@chello.be>");
+    "Jan Schmidt <thaytan@mad.scientist.com>\n"
+    "Wim Taymans <wim.taymans@chello.be>\n"
+    "Renato Filho <renato.filho@indt.org.br>");
 
 /* GstPixbufScale signals and args */
 enum
@@ -81,10 +82,10 @@ gst_pixbufscale_method_get_type (void)
 {
   static GType pixbufscale_method_type = 0;
   static GEnumValue pixbufscale_methods[] = {
-    {GST_PIXBUFSCALE_NEAREST, "Nearest Neighbour", "nearest"},
-    {GST_PIXBUFSCALE_TILES, "Tiles", "tiles"},
-    {GST_PIXBUFSCALE_BILINEAR, "Bilinear", "bilinear"},
-    {GST_PIXBUFSCALE_HYPER, "Hyper", "hyper"},
+    {GST_PIXBUFSCALE_NEAREST, "0", "Nearest Neighbour"},
+    {GST_PIXBUFSCALE_TILES, "1", "Tiles"},
+    {GST_PIXBUFSCALE_BILINEAR, "2", "Bilinear"},
+    {GST_PIXBUFSCALE_HYPER, "3", "Hyper"},
     {0, NULL, NULL},
   };
 
@@ -97,46 +98,33 @@ gst_pixbufscale_method_get_type (void)
 
 static void gst_pixbufscale_base_init (gpointer g_class);
 static void gst_pixbufscale_class_init (GstPixbufScaleClass * klass);
-static void gst_pixbufscale_init (GstPixbufScale * pixbufscale);
-static gboolean gst_pixbufscale_handle_src_event (GstPad * pad,
-    GstEvent * event);
-
+static void gst_pixbufscale_init (GstPixbufScale * pixbufscale,
+    GstPixbufScaleClass * kclass);
 static void gst_pixbufscale_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_pixbufscale_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
-static void gst_pixbufscale_chain (GstPad * pad, GstData * _data);
+static GstCaps *gst_pixbufscale_transform_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps);
+static gboolean gst_pixbufscale_set_caps (GstBaseTransform * trans,
+    GstCaps * in, GstCaps * out);
+static gboolean gst_pixbufscale_get_unit_size (GstBaseTransform * trans,
+    GstCaps * caps, guint * size);
+static void gst_pixbufscale_fixate_caps (GstBaseTransform * base,
+    GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
+static GstFlowReturn gst_pixbufscale_transform (GstBaseTransform * trans,
+    GstBuffer * in, GstBuffer * out);
+static gboolean gst_pixbufscale_handle_src_event (GstPad * pad,
+    GstEvent * event);
 
-static GstElementClass *parent_class = NULL;
 
-GType
-gst_pixbufscale_get_type (void)
-{
-  static GType pixbufscale_type = 0;
-
-  if (!pixbufscale_type) {
-    static const GTypeInfo pixbufscale_info = {
-      sizeof (GstPixbufScaleClass),
-      gst_pixbufscale_base_init,
-      NULL,
-      (GClassInitFunc) gst_pixbufscale_class_init,
-      NULL,
-      NULL,
-      sizeof (GstPixbufScale),
-      0,
-      (GInstanceInitFunc) gst_pixbufscale_init,
-    };
-
-    pixbufscale_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstPixbufScale",
-        &pixbufscale_info, 0);
-  }
-  return pixbufscale_type;
-}
+static gboolean parse_caps (GstCaps * caps, gint * width, gint * height);
 
-static void
-gst_pixbufscale_base_init (gpointer g_class)
+GST_BOILERPLATE (GstPixbufScale, gst_pixbufscale, GstBaseTransform,
+    GST_TYPE_BASE_TRANSFORM)
+
+     static void gst_pixbufscale_base_init (gpointer g_class)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
@@ -151,42 +139,110 @@ static void
 gst_pixbufscale_class_init (GstPixbufScaleClass * klass)
 {
   GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
+  GstBaseTransformClass *trans_class;
 
   gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
+  trans_class = (GstBaseTransformClass *) klass;
+
+  gobject_class->set_property = gst_pixbufscale_set_property;
+  gobject_class->get_property = gst_pixbufscale_get_property;
 
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD,
+  g_object_class_install_property (gobject_class,
+      ARG_METHOD,
       g_param_spec_enum ("method", "method", "method",
           GST_TYPE_PIXBUFSCALE_METHOD, GST_PIXBUFSCALE_BILINEAR,
           G_PARAM_READWRITE));
 
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  trans_class->transform_caps =
+      GST_DEBUG_FUNCPTR (gst_pixbufscale_transform_caps);
+  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_pixbufscale_set_caps);
+  trans_class->get_unit_size =
+      GST_DEBUG_FUNCPTR (gst_pixbufscale_get_unit_size);
+  trans_class->transform = GST_DEBUG_FUNCPTR (gst_pixbufscale_transform);
+  trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_pixbufscale_fixate_caps);
+  trans_class->passthrough_on_same_caps = TRUE;
 
-  gobject_class->set_property = gst_pixbufscale_set_property;
-  gobject_class->get_property = gst_pixbufscale_get_property;
+  parent_class = g_type_class_peek_parent (klass);
 }
 
+static void
+gst_pixbufscale_init (GstPixbufScale * pixbufscale,
+    GstPixbufScaleClass * kclass)
+{
+  GST_DEBUG_OBJECT (pixbufscale, "_init");
+  GstBaseTransform *trans = GST_BASE_TRANSFORM (pixbufscale);
+
+  gst_pad_set_event_function (trans->srcpad, gst_pixbufscale_handle_src_event);
+
+  pixbufscale->method = GST_PIXBUFSCALE_TILES;
+  pixbufscale->gdk_method = GDK_INTERP_TILES;
+}
+
+static void
+gst_pixbufscale_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstPixbufScale *src;
+
+  g_return_if_fail (GST_IS_PIXBUFSCALE (object));
+  src = GST_PIXBUFSCALE (object);
+
+  switch (prop_id) {
+    case ARG_METHOD:
+      src->method = g_value_get_enum (value);
+      switch (src->method) {
+        case GST_PIXBUFSCALE_NEAREST:
+          src->gdk_method = GDK_INTERP_NEAREST;
+          break;
+        case GST_PIXBUFSCALE_TILES:
+          src->gdk_method = GDK_INTERP_TILES;
+          break;
+        case GST_PIXBUFSCALE_BILINEAR:
+          src->gdk_method = GDK_INTERP_BILINEAR;
+          break;
+        case GST_PIXBUFSCALE_HYPER:
+          src->gdk_method = GDK_INTERP_HYPER;
+          break;
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_pixbufscale_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstPixbufScale *src;
+
+  g_return_if_fail (GST_IS_PIXBUFSCALE (object));
+  src = GST_PIXBUFSCALE (object);
+
+  switch (prop_id) {
+    case ARG_METHOD:
+      g_value_set_enum (value, src->method);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
 static GstCaps *
-gst_pixbufscale_getcaps (GstPad * pad)
+gst_pixbufscale_transform_caps (GstBaseTransform * trans,
+    GstPadDirection direction, GstCaps * caps)
 {
   GstPixbufScale *pixbufscale;
-  GstCaps *othercaps;
-  GstCaps *caps;
-  GstPad *otherpad;
+  GstCaps *ret;
   int i;
 
-  pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad));
-
-  otherpad = (pad == pixbufscale->srcpad) ? pixbufscale->sinkpad :
-      pixbufscale->srcpad;
-  othercaps = gst_pad_get_allowed_caps (otherpad);
+  pixbufscale = GST_PIXBUFSCALE (trans);
+  ret = gst_caps_copy (caps);
 
-  caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
-  gst_caps_free (othercaps);
-
-  for (i = 0; i < gst_caps_get_size (caps); i++) {
-    GstStructure *structure = gst_caps_get_structure (caps, i);
+  for (i = 0; i < gst_caps_get_size (ret); i++) {
+    GstStructure *structure = gst_caps_get_structure (ret, i);
 
     gst_structure_set (structure,
         "width", GST_TYPE_INT_RANGE, 16, 4096,
@@ -194,288 +250,235 @@ gst_pixbufscale_getcaps (GstPad * pad)
     gst_structure_remove_field (structure, "pixel-aspect-ratio");
   }
 
-  GST_DEBUG ("getcaps are: %" GST_PTR_FORMAT, caps);
-  return caps;
+  GST_DEBUG_OBJECT (trans, "returning caps: %", ret);
+  return ret;
 }
 
-static GstPadLinkReturn
-gst_pixbufscale_link (GstPad * pad, const GstCaps * caps)
+static gboolean
+parse_caps (GstCaps * caps, gint * width, gint * height)
 {
-  GstPixbufScale *pixbufscale;
-  GstPadLinkReturn ret;
-  GstPad *otherpad;
+  gboolean ret;
   GstStructure *structure;
-  int height, width;
-  gchar *caps_string;
 
-  caps_string = gst_caps_to_string (caps);
-  GST_DEBUG ("gst_pixbufscale_link %s\n", caps_string);
-  g_free (caps_string);
+  structure = gst_caps_get_structure (caps, 0);
+  ret = gst_structure_get_int (structure, "width", width);
+  ret &= gst_structure_get_int (structure, "height", height);
 
-  pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad));
+  return ret;
+}
 
-  otherpad = (pad == pixbufscale->srcpad) ? pixbufscale->sinkpad :
-      pixbufscale->srcpad;
+static gboolean
+gst_pixbufscale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
+{
+  GstPixbufScale *pixbufscale;
+  gboolean ret;
 
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "width", &width);
-  ret &= gst_structure_get_int (structure, "height", &height);
+  pixbufscale = GST_PIXBUFSCALE (trans);
+  ret = parse_caps (in, &pixbufscale->from_width, &pixbufscale->from_height);
+  ret &= parse_caps (out, &pixbufscale->to_width, &pixbufscale->to_height);
+  if (!ret)
+    goto done;
 
-  ret = gst_pad_try_set_caps (otherpad, caps);
-  if (ret == GST_PAD_LINK_OK) {
-    /* cool, we can use passthru */
+  pixbufscale->from_stride = GST_ROUND_UP_4 (pixbufscale->from_width * 3);
+  pixbufscale->from_buf_size =
+      pixbufscale->from_stride * pixbufscale->from_height;
 
-    pixbufscale->to_width = width;
-    pixbufscale->to_height = height;
-    pixbufscale->from_width = width;
-    pixbufscale->from_height = height;
+  pixbufscale->to_stride = GST_ROUND_UP_4 (pixbufscale->to_width * 3);
+  pixbufscale->to_buf_size = pixbufscale->to_stride * pixbufscale->to_height;
 
-    pixbufscale->from_buf_size = GST_RGB24_SIZE (width, height);
-    pixbufscale->to_buf_size = GST_RGB24_SIZE (width, height);
-    pixbufscale->from_stride = GST_RGB24_ROWSTRIDE (width);
-    pixbufscale->to_stride = GST_RGB24_ROWSTRIDE (width);
+  GST_DEBUG_OBJECT (pixbufscale, "from=%dx%d, size %d -> to=%dx%d, size %d",
+      pixbufscale->from_width, pixbufscale->from_height,
+      pixbufscale->from_buf_size, pixbufscale->to_width, pixbufscale->to_height,
+      pixbufscale->to_buf_size);
 
-    pixbufscale->inited = TRUE;
+done:
+  return ret;
+}
 
-    return GST_PAD_LINK_OK;
-  }
 
-  if (gst_pad_is_negotiated (otherpad)) {
-    GstCaps *newcaps = gst_caps_copy (caps);
+static gboolean
+gst_pixbufscale_get_unit_size (GstBaseTransform * trans,
+    GstCaps * caps, guint * size)
+{
+  GstPixbufScale *pixbufscale;
+  gint width, height;
 
-    if (pad == pixbufscale->srcpad) {
-      gst_caps_set_simple (newcaps,
-          "width", G_TYPE_INT, pixbufscale->from_width,
-          "height", G_TYPE_INT, pixbufscale->from_height, NULL);
-    } else {
-      gst_caps_set_simple (newcaps,
-          "width", G_TYPE_INT, pixbufscale->to_width,
-          "height", G_TYPE_INT, pixbufscale->to_height, NULL);
-    }
-    ret = gst_pad_try_set_caps (otherpad, newcaps);
-    if (GST_PAD_LINK_FAILED (ret)) {
-      return GST_PAD_LINK_REFUSED;
-    }
-  }
+  g_return_val_if_fail (size, FALSE);
 
-  pixbufscale->passthru = FALSE;
+  pixbufscale = GST_PIXBUFSCALE (trans);
 
-  if (pad == pixbufscale->srcpad) {
-    pixbufscale->to_width = width;
-    pixbufscale->to_height = height;
-  } else {
-    pixbufscale->from_width = width;
-    pixbufscale->from_height = height;
-  }
+  if (!parse_caps (caps, &width, &height))
+    return FALSE;
 
-  if (gst_pad_is_negotiated (otherpad)) {
-    pixbufscale->from_buf_size =
-        GST_RGB24_SIZE (pixbufscale->from_width, pixbufscale->from_height);
-    pixbufscale->to_buf_size =
-        GST_RGB24_SIZE (pixbufscale->to_width, pixbufscale->to_height);
-    pixbufscale->from_stride = GST_RGB24_ROWSTRIDE (pixbufscale->from_width);
-    pixbufscale->to_stride = GST_RGB24_ROWSTRIDE (pixbufscale->to_width);
-    pixbufscale->inited = TRUE;
-  }
+  *size = GST_ROUND_UP_4 (width * 3) * height;
 
-  return GST_PAD_LINK_OK;
+  return TRUE;
 }
 
 static void
-gst_pixbufscale_init (GstPixbufScale * pixbufscale)
+gst_pixbufscale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
+    GstCaps * caps, GstCaps * othercaps)
 {
-  GST_DEBUG_OBJECT (pixbufscale, "_init");
-  pixbufscale->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_pixbufscale_sink_template), "sink");
-  gst_element_add_pad (GST_ELEMENT (pixbufscale), pixbufscale->sinkpad);
-  gst_pad_set_chain_function (pixbufscale->sinkpad, gst_pixbufscale_chain);
-  gst_pad_set_link_function (pixbufscale->sinkpad, gst_pixbufscale_link);
-  gst_pad_set_getcaps_function (pixbufscale->sinkpad, gst_pixbufscale_getcaps);
-
-  pixbufscale->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_pixbufscale_src_template), "src");
-  gst_element_add_pad (GST_ELEMENT (pixbufscale), pixbufscale->srcpad);
-  gst_pad_set_event_function (pixbufscale->srcpad,
-      gst_pixbufscale_handle_src_event);
-  gst_pad_set_link_function (pixbufscale->srcpad, gst_pixbufscale_link);
-  gst_pad_set_getcaps_function (pixbufscale->srcpad, gst_pixbufscale_getcaps);
-
-  pixbufscale->inited = FALSE;
-
-  pixbufscale->method = GST_PIXBUFSCALE_TILES;
-  pixbufscale->gdk_method = GDK_INTERP_TILES;
-}
-
-static gboolean
-gst_pixbufscale_handle_src_event (GstPad * pad, GstEvent * event)
-{
-  GstPixbufScale *pixbufscale;
-  double a;
-  GstStructure *structure;
-  GstEvent *new_event;
+  GstStructure *ins, *outs;
+  const GValue *from_par, *to_par;
+
+  g_return_if_fail (gst_caps_is_fixed (caps));
+
+  GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
+      " based on caps %" GST_PTR_FORMAT, othercaps, caps);
+
+  ins = gst_caps_get_structure (caps, 0);
+  outs = gst_caps_get_structure (othercaps, 0);
+
+  from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
+  to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");
+
+  if (from_par && to_par) {
+    GValue to_ratio = { 0, };   /* w/h of output video */
+    int from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
+    int count = 0, w = 0, h = 0, num, den;
+
+    /* if both width and height are already fixed, we can't do anything
+     *      * about it anymore */
+    if (gst_structure_get_int (outs, "width", &w))
+      ++count;
+    if (gst_structure_get_int (outs, "height", &h))
+      ++count;
+    if (count == 2) {
+      GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
+          w, h);
+      return;
+    }
 
-  pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad));
+    gst_structure_get_int (ins, "width", &from_w);
+    gst_structure_get_int (ins, "height", &from_h);
+    from_par_n = gst_value_get_fraction_numerator (from_par);
+    from_par_d = gst_value_get_fraction_denominator (from_par);
+    to_par_n = gst_value_get_fraction_numerator (to_par);
+    to_par_d = gst_value_get_fraction_denominator (to_par);
+
+    g_value_init (&to_ratio, GST_TYPE_FRACTION);
+    gst_value_set_fraction (&to_ratio, from_w * from_par_n * to_par_d,
+        from_h * from_par_d * to_par_n);
+    num = gst_value_get_fraction_numerator (&to_ratio);
+    den = gst_value_get_fraction_denominator (&to_ratio);
+    GST_DEBUG_OBJECT (base,
+        "scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
+        from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
+    GST_DEBUG_OBJECT (base,
+        "resulting output should respect ratio of %d/%d", num, den);
+
+    /* now find a width x height that respects this display ratio.
+     *      * prefer those that have one of w/h the same as the incoming video
+     *           * using wd / hd = num / den */
+
+    /* start with same height, because of interlaced video */
+    /* check hd / den is an integer scale factor, and scale wd with the PAR */
+    if (from_h % den == 0) {
+      GST_DEBUG_OBJECT (base, "keeping video height");
+      h = from_h;
+      w = h * num / den;
+    } else if (from_w % num == 0) {
+      GST_DEBUG_OBJECT (base, "keeping video width");
+      w = from_w;
+      h = w * den / num;
+    } else {
+      GST_DEBUG_OBJECT (base, "approximating but keeping video height");
+      h = from_h;
+      w = h * num / den;
+    }
+    GST_DEBUG_OBJECT (base, "scaling to %dx%d", w, h);
+    /* now fixate */
+    gst_structure_fixate_field_nearest_int (outs, "width", w);
+    gst_structure_fixate_field_nearest_int (outs, "height", h);
+  } else {
+    gint width, height;
 
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NAVIGATION:
-      structure = gst_structure_copy (event->event_data.structure.structure);
-      if (gst_structure_get_double (event->event_data.structure.structure,
-              "pointer_x", &a)) {
-        gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
-            a * pixbufscale->from_width / pixbufscale->to_width, NULL);
+    if (gst_structure_get_int (ins, "width", &width)) {
+      if (gst_structure_has_field (outs, "width")) {
+        gst_structure_fixate_field_nearest_int (outs, "width", width);
       }
-      if (gst_structure_get_double (event->event_data.structure.structure,
-              "pointer_y", &a)) {
-        gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
-            a * pixbufscale->from_height / pixbufscale->to_height, NULL);
+    }
+    if (gst_structure_get_int (ins, "height", &height)) {
+      if (gst_structure_has_field (outs, "height")) {
+        gst_structure_fixate_field_nearest_int (outs, "height", height);
       }
-      gst_event_unref (event);
-      new_event = gst_event_new (GST_EVENT_NAVIGATION);
-      new_event->event_data.structure.structure = structure;
-      return gst_pad_event_default (pad, new_event);
-      break;
-    default:
-      return gst_pad_event_default (pad, event);
-      break;
+    }
   }
+
+  GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
 }
 
-static void
-pixbufscale_scale (GstPixbufScale * scale, unsigned char *dest,
-    unsigned char *src)
+static GstFlowReturn
+gst_pixbufscale_transform (GstBaseTransform * trans,
+    GstBuffer * in, GstBuffer * out)
 {
+  GstPixbufScale *scale;
   GdkPixbuf *src_pixbuf, *dest_pixbuf;
 
-  src_pixbuf = gdk_pixbuf_new_from_data
-      (src, GDK_COLORSPACE_RGB, FALSE,
+  scale = GST_PIXBUFSCALE (trans);
+
+  src_pixbuf =
+      gdk_pixbuf_new_from_data (GST_BUFFER_DATA (in), GDK_COLORSPACE_RGB, FALSE,
       8, scale->from_width, scale->from_height,
       GST_RGB24_ROWSTRIDE (scale->from_width), NULL, NULL);
-  dest_pixbuf = gdk_pixbuf_new_from_data
-      (dest, GDK_COLORSPACE_RGB, FALSE,
-      8, scale->to_width, scale->to_height,
+
+  dest_pixbuf =
+      gdk_pixbuf_new_from_data (GST_BUFFER_DATA (out), GDK_COLORSPACE_RGB,
+      FALSE, 8, scale->to_width, scale->to_height,
       GST_RGB24_ROWSTRIDE (scale->to_width), NULL, NULL);
-  gdk_pixbuf_scale (src_pixbuf, dest_pixbuf, 0, 0, scale->to_width,
+
+  gdk_pixbuf_scale (src_pixbuf, dest_pixbuf, 0, 0,
+      scale->to_width,
       scale->to_height, 0, 0,
       (double) scale->to_width / scale->from_width,
       (double) scale->to_height / scale->from_height, scale->gdk_method);
 
-  dest_pixbuf = gdk_pixbuf_scale_simple
-      (src_pixbuf, scale->to_width, scale->to_height, scale->gdk_method);
-
   g_object_unref (src_pixbuf);
   g_object_unref (dest_pixbuf);
+
+  return GST_FLOW_OK;
 }
 
-static void
-gst_pixbufscale_chain (GstPad * pad, GstData * _data)
+static gboolean
+gst_pixbufscale_handle_src_event (GstPad * pad, GstEvent * event)
 {
-  GstBuffer *buf = GST_BUFFER (_data);
   GstPixbufScale *pixbufscale;
-  guchar *data;
-  gulong size;
-  GstBuffer *outbuf;
-
-  g_return_if_fail (pad != NULL);
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
+  gboolean ret;
+  double a;
+  GstStructure *structure;
 
   pixbufscale = GST_PIXBUFSCALE (gst_pad_get_parent (pad));
-  g_return_if_fail (pixbufscale->inited);
-
-  data = GST_BUFFER_DATA (buf);
-  size = GST_BUFFER_SIZE (buf);
-
-  if (pixbufscale->passthru) {
-    GST_LOG_OBJECT (pixbufscale, "passing through buffer of %ld bytes in '%s'",
-        size, GST_OBJECT_NAME (pixbufscale));
-    gst_pad_push (pixbufscale->srcpad, GST_DATA (buf));
-    return;
-  }
-
-  GST_LOG_OBJECT (pixbufscale, "got buffer of %ld bytes in '%s'", size,
-      GST_OBJECT_NAME (pixbufscale));
-  GST_LOG_OBJECT (pixbufscale,
-      "size=%ld from=%dx%d to=%dx%d fromsize=%ld (should be %d) tosize=%d",
-      size, pixbufscale->from_width, pixbufscale->from_height,
-      pixbufscale->to_width, pixbufscale->to_height, size,
-      pixbufscale->from_buf_size, pixbufscale->to_buf_size);
-
-  if (size != pixbufscale->from_buf_size) {
-    GST_ERROR ("Incoming RGB data is %d bytes (expected: %d bytes) (%dx%d)\n",
-        size, pixbufscale->from_buf_size, pixbufscale->from_width,
-        pixbufscale->from_height);
-    return;
-  }
-
-  outbuf = gst_pad_alloc_buffer_and_set_caps (pixbufscale->srcpad,
-      GST_BUFFER_OFFSET_NONE, pixbufscale->to_buf_size);
-
-  gst_buffer_stamp (outbuf, buf);
-
-  pixbufscale_scale (pixbufscale, GST_BUFFER_DATA (outbuf), data);
-
-  GST_DEBUG_OBJECT (pixbufscale, "pushing buffer of %d bytes in '%s'",
-      GST_BUFFER_SIZE (outbuf), GST_OBJECT_NAME (pixbufscale));
 
-  gst_pad_push (pixbufscale->srcpad, GST_DATA (outbuf));
+  GST_DEBUG_OBJECT (pixbufscale, "handling %s event",
+      GST_EVENT_TYPE_NAME (event));
 
-  gst_buffer_unref (buf);
-}
-
-static void
-gst_pixbufscale_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstPixbufScale *src;
-
-  g_return_if_fail (GST_IS_PIXBUFSCALE (object));
-  src = GST_PIXBUFSCALE (object);
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_NAVIGATION:
+      event =
+          GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));
 
-  switch (prop_id) {
-    case ARG_METHOD:
-      src->method = g_value_get_enum (value);
-      switch (src->method) {
-        case GST_PIXBUFSCALE_NEAREST:
-          src->gdk_method = GDK_INTERP_NEAREST;
-          break;
-        case GST_PIXBUFSCALE_TILES:
-          src->gdk_method = GDK_INTERP_TILES;
-          break;
-        case GST_PIXBUFSCALE_BILINEAR:
-          src->gdk_method = GDK_INTERP_BILINEAR;
-          break;
-        case GST_PIXBUFSCALE_HYPER:
-          src->gdk_method = GDK_INTERP_HYPER;
-          break;
+      structure = (GstStructure *) gst_event_get_structure (event);
+      if (gst_structure_get_double (structure, "pointer_x", &a)) {
+        gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
+            a * pixbufscale->from_width / pixbufscale->to_width, NULL);
+      }
+      if (gst_structure_get_double (structure, "pointer_y", &a)) {
+        gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
+            a * pixbufscale->from_height / pixbufscale->to_height, NULL);
       }
       break;
     default:
       break;
   }
-}
 
-static void
-gst_pixbufscale_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstPixbufScale *src;
+  ret = gst_pad_event_default (pad, event);
 
-  g_return_if_fail (GST_IS_PIXBUFSCALE (object));
-  src = GST_PIXBUFSCALE (object);
+  gst_object_unref (pixbufscale);
 
-  switch (prop_id) {
-    case ARG_METHOD:
-      g_value_set_enum (value, src->method);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+  return ret;
 }
 
-
 gboolean
 pixbufscale_init (GstPlugin * plugin)
 {
index 0d9b10f..275a0b7 100644 (file)
 
 #include <gtk/gtk.h>
 #include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
 
 G_BEGIN_DECLS
 
+#define GST_TYPE_PIXBUFSCALE                   \
+  (gst_pixbufscale_get_type())
+#define GST_PIXBUFSCALE(obj)                                           \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIXBUFSCALE,GstPixbufScale))
+#define GST_PIXBUFSCALE_CLASS(klass)                                   \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIXBUFSCALE,GstPixbufScale))
+#define GST_IS_PIXBUFSCALE(obj)                                        \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIXBUFSCALE))
+#define GST_IS_PIXBUFSCALE_CLASS(obj)                          \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIXBUFSCALE))
+
 typedef enum {
   GST_PIXBUFSCALE_NEAREST,
   GST_PIXBUFSCALE_TILES,
@@ -35,27 +47,14 @@ typedef enum {
   GST_PIXBUFSCALE_HYPER
 } GstPixbufScaleMethod;
 
-#define GST_TYPE_PIXBUFSCALE \
-  (gst_pixbufscale_get_type())
-#define GST_PIXBUFSCALE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PIXBUFSCALE,GstPixbufScale))
-#define GST_PIXBUFSCALE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PIXBUFSCALE,GstPixbufScale))
-#define GST_IS_PIXBUFSCALE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PIXBUFSCALE))
-#define GST_IS_PIXBUFSCALE_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PIXBUFSCALE))
 
 typedef struct _GstPixbufScale GstPixbufScale;
 typedef struct _GstPixbufScaleClass GstPixbufScaleClass;
 
 struct _GstPixbufScale {
-  GstElement element;
-
-  GstPad *sinkpad,*srcpad;
+  GstBaseTransform element;
 
   /* video state */
-  gboolean inited;
   gint to_width;
   gint to_height;
   gint from_width;
@@ -73,7 +72,7 @@ struct _GstPixbufScale {
 };
 
 struct _GstPixbufScaleClass {
-  GstElementClass parent_class;
+  GstBaseTransformClass parent_class;
 };
 
 static GType gst_pixbufscale_get_type(void);