[Swfdec] configure.ac libswfdec/Makefile.am libswfdec/swfdec_codec.c libswfdec/swfdec_codec_gst.c

Benjamin Otte company at kemper.freedesktop.org
Thu Apr 5 07:45:44 PDT 2007


 configure.ac                 |   20 +++
 libswfdec/Makefile.am        |   10 +
 libswfdec/swfdec_codec.c     |    9 +
 libswfdec/swfdec_codec_gst.c |  260 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 294 insertions(+), 5 deletions(-)

New commits:
diff-tree 9367afafdc43e320b2689237f9f302e52d8fac0e (from 1906bf5a380edbbb4b808543cf3da0e9e836dbf4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 5 16:46:57 2007 +0200

    implement first try at GStreamer codecs
    
    It's disabled by default since it crashes far too often

diff --git a/configure.ac b/configure.ac
index fdf2a31..899cfef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -204,6 +204,26 @@ else
 	AC_MSG_WARN([*** ffmpeg support was not enabled. ***])
 fi
 AM_CONDITIONAL(HAVE_FFMPEG, [test "x$HAVE_FFMPEG" = xyes])
+AC_ARG_ENABLE(gstreamer,
+	AS_HELP_STRING([--enable-gstreamer],
+			[enable GStreamer support (default=no)])],
+	enable_gstreamer=$enableval,
+	enable_gstreamer="no")
+
+if test "$enable_gstreamer" = "yes"; then
+	dnl I used my own version here, it might work with lower versions
+	GST_REQUIRED=0.10.10
+	PKG_CHECK_MODULES(GST, gstreamer-0.10 >= $GST_REQUIRED, HAVE_GST=yes, HAVE_GST=no)
+	if test "x$HAVE_GST" = xyes; then
+	  AC_DEFINE(HAVE_GST, 1, [Define if GStreamer is enabled])
+	else
+	  AC_MSG_ERROR([Couldn't find GStreamer $GST_REQUIRED.])
+	fi
+else
+	AC_MSG_WARN([*** GStreamer support was not enabled. ***])
+fi
+AM_CONDITIONAL(HAVE_GST, [test "x$HAVE_GST" = xyes])
+
 
 AC_ARG_ENABLE(gnome-vfs,
 	AS_HELP_STRING([--enable-gnome-vfs],
diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index f7be47f..0ad15c5 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -10,6 +10,9 @@ endif
 if HAVE_FFMPEG
 CODECS += swfdec_codec_ffmpeg.c
 endif
+if HAVE_GST
+CODECS += swfdec_codec_gst.c
+endif
 
 lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJORMINOR@.la
 
@@ -86,13 +89,14 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
-	-I$(srcdir)/jpeg/ $(js_cflags) $(LIBOIL_CFLAGS) $(FFMPEG_CFLAGS) \
+	-I$(srcdir)/jpeg/ $(js_cflags) $(LIBOIL_CFLAGS) \
+	$(GST_CFLAGS) $(FFMPEG_CFLAGS) $(MAD_CFLAGS) \
 	-DG_LOG_DOMAIN=\"Swfdec\"
 libswfdec_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	-version-info $(SWFDEC_LIBVERSION) \
 	-export-symbols-regex '^(swfdec_.*)' \
-	$(CAIRO_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) $(MAD_LIBS) $(FFMPEG_LIBS) \
-	$(LIBOIL_LIBS) -lz
+	$(CAIRO_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) $(LIBOIL_LIBS) -lz \
+	$(MAD_LIBS) $(FFMPEG_LIBS) $(GST_LIBS)
 
 public_headers = \
 	swfdec.h \
diff --git a/libswfdec/swfdec_codec.c b/libswfdec/swfdec_codec.c
index d0f048f..1875572 100644
--- a/libswfdec/swfdec_codec.c
+++ b/libswfdec/swfdec_codec.c
@@ -27,6 +27,7 @@
 /*** DECODER LIST ***/
 
 extern const SwfdecAudioCodec swfdec_codec_adpcm;
+extern const SwfdecVideoCodec swfdec_codec_screen;
 
 #ifdef HAVE_MAD
 extern const SwfdecAudioCodec swfdec_codec_mad;
@@ -39,7 +40,7 @@ extern const SwfdecVideoCodec swfdec_cod
 extern const SwfdecVideoCodec swfdec_codec_ffmpeg_screen;
 #endif
 
-extern const SwfdecVideoCodec swfdec_codec_screen;
+extern const SwfdecVideoCodec swfdec_codec_gst_h263;
 
 /*** UNCOMPRESSED SOUND ***/
 
@@ -157,12 +158,16 @@ swfdec_codec_get_video (SwfdecVideoForma
       SWFDEC_ERROR ("Screen video requires ffmpeg");
       return NULL;
     case SWFDEC_VIDEO_FORMAT_H263:
+#ifdef HAVE_GST
+      return &swfdec_codec_gst_h263;
+#else
 #ifdef HAVE_FFMPEG
       return &swfdec_codec_ffmpeg_h263;
 #else
-      SWFDEC_ERROR ("H263 video requires ffmpeg");
+      SWFDEC_ERROR ("H263 video requires ffmpeg or GStreamer");
       return NULL;
 #endif
+#endif
     default:
       SWFDEC_ERROR ("video codec %u not implemented yet", (guint) format);
       return NULL;
diff --git a/libswfdec/swfdec_codec_gst.c b/libswfdec/swfdec_codec_gst.c
new file mode 100644
index 0000000..c4313aa
--- /dev/null
+++ b/libswfdec/swfdec_codec_gst.c
@@ -0,0 +1,260 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+#include <gst/gst.h>
+
+#include "swfdec_codec.h"
+#include "swfdec_debug.h"
+
+#define swfdec_cond_wait(cond, mutex) G_STMT_START { \
+  g_print ("waiting at %s\n", G_STRLOC); \
+  g_cond_wait (cond, mutex); \
+  g_print ("   done at %s\n", G_STRLOC); \
+}G_STMT_END
+
+typedef struct _SwfdecGstVideo SwfdecGstVideo;
+struct _SwfdecGstVideo {
+  GMutex *	  	mutex;		/* mutex that blocks everything below */
+  GCond *		cond;		/* cond used to signal when stuff below changes */
+  volatile int		refcount;	/* refcount (d'oh) */
+
+  GstElement *		pipeline;	/* pipeline that is playing or NULL when done */
+  SwfdecBuffer *	in;		/* next input buffer or NULL */
+  SwfdecBuffer *	out;		/* available output or NULL */
+  int			width;		/* width of last output buffer */
+  int			height;		/* height of last output buffer */
+  GstCaps *		srccaps;	/* caps to set on buffers */
+};
+
+static void
+swfdec_gst_video_unref (gpointer data, GObject *unused)
+{
+  SwfdecGstVideo *player = data;
+
+  if (!g_atomic_int_dec_and_test (&player->refcount))
+    return;
+  g_cond_free (player->cond);
+  g_mutex_free (player->mutex);
+  gst_caps_unref (player->srccaps);
+  if (player->in)
+    swfdec_buffer_unref (player->in);
+  if (player->out)
+    swfdec_buffer_unref (player->out);
+  g_slice_free (SwfdecGstVideo, player);
+}
+
+static void
+swfdec_codec_gst_video_finish (gpointer codec_data)
+{
+  SwfdecGstVideo *player = codec_data;
+  GstElement *pipeline;
+
+  g_mutex_lock (player->mutex);
+  pipeline = player->pipeline;
+  player->pipeline = NULL;
+  g_cond_signal (player->cond);
+  g_mutex_unlock (player->mutex);
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  g_object_unref (pipeline);
+
+  swfdec_gst_video_unref (player, NULL);
+}
+
+static void
+swfdec_codec_gst_fakesrc_handoff (GstElement *fakesrc, GstBuffer *buf, 
+    GstPad *pad, SwfdecGstVideo *player)
+{
+  g_mutex_lock (player->mutex);
+  while (player->pipeline != NULL && player->in == NULL)
+    swfdec_cond_wait (player->cond, player->mutex);
+  if (player->pipeline == NULL) {
+    g_mutex_unlock (player->mutex);
+    return;
+  }
+  buf->data = g_memdup (player->in->data, player->in->length);
+  buf->size = player->in->length;
+  gst_buffer_set_caps (buf, player->srccaps);
+  player->in = NULL;
+  g_cond_signal (player->cond);
+  g_mutex_unlock (player->mutex);
+}
+
+static void
+swfdec_codec_gst_fakesink_handoff (GstElement *fakesrc, GstBuffer *buf, 
+    GstPad *pad, SwfdecGstVideo *player)
+{
+  GstCaps *caps;
+
+  g_mutex_lock (player->mutex);
+  caps = gst_buffer_get_caps (buf);
+  if (caps) {
+    GstStructure *structure = gst_caps_get_structure (caps, 0);
+    if (!gst_structure_get_int (structure, "width", &player->width) ||
+        !gst_structure_get_int (structure, "height", &player->height)) {
+      player->width = 0;
+      player->height = 0;
+    }
+    gst_caps_unref (caps);
+  }
+  while (player->pipeline != NULL && player->out != NULL)
+    swfdec_cond_wait (player->cond, player->mutex);
+  if (player->pipeline == NULL)
+    return;
+  player->out = swfdec_buffer_new ();
+  player->out->data = g_memdup (buf->data, buf->size);
+  player->out->length = buf->size;
+  g_cond_signal (player->cond);
+  g_mutex_unlock (player->mutex);
+}
+
+static void
+do_the_link (GstElement *src, GstPad *pad, GstElement *sink)
+{
+  if (!gst_element_link (src, sink)) {
+    SWFDEC_ERROR ("no delayed link");
+  }
+}
+
+static gpointer
+swfdec_codec_gst_h263_init (void)
+{
+  SwfdecGstVideo *player;
+  GstElement *fakesrc, *fakesink, *decoder, *csp;
+  GstCaps *sinkcaps;
+
+  if (!gst_init_check (NULL, NULL, NULL))
+    return FALSE;
+
+  player = g_slice_new0 (SwfdecGstVideo);
+  player->pipeline = gst_pipeline_new ("pipeline");
+  player->refcount = 1;
+  g_assert (player->pipeline);
+  player->mutex = g_mutex_new ();
+  player->cond = g_cond_new ();
+  player->srccaps = gst_caps_from_string ("video/x-flash-video");
+  g_assert (player->srccaps);
+  fakesrc = gst_element_factory_make ("fakesrc", NULL);
+  if (fakesrc == NULL) {
+    SWFDEC_ERROR ("failed to create fakesrc");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+  g_object_set (fakesrc, "signal-handoffs", TRUE, 
+      "can-activate-pull", FALSE, NULL);
+  g_signal_connect (fakesrc, "handoff", 
+      G_CALLBACK (swfdec_codec_gst_fakesrc_handoff), player);
+  g_atomic_int_inc (&player->refcount);
+  g_object_weak_ref (G_OBJECT (fakesrc), swfdec_gst_video_unref, player);
+  gst_bin_add (GST_BIN (player->pipeline), fakesrc);
+  fakesink = gst_element_factory_make ("fakesink", NULL);
+  if (fakesink == NULL) {
+    SWFDEC_ERROR ("failed to create fakesink");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+  g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
+  g_signal_connect (fakesink, "handoff", 
+      G_CALLBACK (swfdec_codec_gst_fakesink_handoff), player);
+  g_atomic_int_inc (&player->refcount);
+  g_object_weak_ref (G_OBJECT (fakesink), swfdec_gst_video_unref, player);
+  gst_bin_add (GST_BIN (player->pipeline), fakesink);
+  decoder = gst_element_factory_make ("decodebin", NULL);
+  if (decoder == NULL) {
+    SWFDEC_ERROR ("failed to create decoder");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+  gst_bin_add (GST_BIN (player->pipeline), decoder);
+  csp = gst_element_factory_make ("ffmpegcolorspace", NULL);
+  if (csp == NULL) {
+    SWFDEC_ERROR ("failed to create colorspace");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+  gst_bin_add (GST_BIN (player->pipeline), csp);
+  g_signal_connect (decoder, "pad-added", G_CALLBACK (do_the_link), csp);
+
+  sinkcaps = gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "
+      "red_mask=16711680, green_mask=65280, blue_mask=255");
+  g_assert (sinkcaps);
+  if (!gst_element_link_filtered (fakesrc, decoder, player->srccaps) ||
+#if 0
+      !gst_element_link (decoder, csp) ||
+#endif
+      !gst_element_link_filtered (csp, fakesink, sinkcaps)) {
+    SWFDEC_ERROR ("linking failed");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+  gst_caps_unref (sinkcaps);
+  if (gst_element_set_state (player->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+    SWFDEC_ERROR ("failed to change sate");
+    swfdec_codec_gst_video_finish (player);
+    return NULL;
+  }
+
+  return player;
+}
+
+static gboolean
+swfdec_codec_gst_video_get_size (gpointer codec_data,
+    guint *width, guint *height)
+{
+  SwfdecGstVideo *player = codec_data;
+
+  g_mutex_lock (player->mutex);
+  if (player->width == 0 || player->height == 0) {
+    g_mutex_unlock (player->mutex);
+    return FALSE;
+  }
+  *width = player->width;
+  *height = player->height;
+  g_mutex_unlock (player->mutex);
+  return TRUE;
+}
+
+SwfdecBuffer *
+swfdec_codec_gst_video_decode (gpointer codec_data, SwfdecBuffer *buffer)
+{
+  SwfdecGstVideo *player = codec_data;
+
+  g_mutex_lock (player->mutex);
+  g_assert (player->in == NULL);
+  player->in = buffer;
+  while (player->out == NULL) {
+    swfdec_cond_wait (player->cond, player->mutex);
+  }
+  g_print ("processing buffer\n");
+  buffer = player->out;
+  player->out = NULL;
+  g_mutex_unlock (player->mutex);
+  return buffer;
+}
+
+const SwfdecVideoCodec swfdec_codec_gst_h263 = {
+  swfdec_codec_gst_h263_init,
+  swfdec_codec_gst_video_get_size,
+  swfdec_codec_gst_video_decode,
+  swfdec_codec_gst_video_finish
+};
+


More information about the Swfdec mailing list