[Swfdec] libswfdec/swfdec_codec_audio.c libswfdec/swfdec_codec_gst.c

Benjamin Otte company at kemper.freedesktop.org
Sun Apr 8 03:32:48 PDT 2007


 libswfdec/swfdec_codec_audio.c |    8 -
 libswfdec/swfdec_codec_gst.c   |  271 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 270 insertions(+), 9 deletions(-)

New commits:
diff-tree 68a17dfade3397478342d4c88fa9b9e3dc13f329 (from 01bf0e400ee99da0e96707f606d41bb23d5a8b48)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 12:32:39 2007 +0200

    make GStreamer do MP3 audio

diff --git a/libswfdec/swfdec_codec_audio.c b/libswfdec/swfdec_codec_audio.c
index b5d00fb..9bd091c 100644
--- a/libswfdec/swfdec_codec_audio.c
+++ b/libswfdec/swfdec_codec_audio.c
@@ -118,6 +118,10 @@ extern SwfdecAudioDecoderNewFunc swfdec_
 extern SwfdecAudioDecoderNewFunc swfdec_audio_decoder_ffmpeg_new;
 #endif
 
+#ifdef HAVE_FFMPEG
+extern SwfdecAudioDecoderNewFunc swfdec_audio_decoder_gst_new;
+#endif
+
 /*** PUBLIC API ***/
 
 /**
@@ -137,6 +141,7 @@ swfdec_audio_decoder_new (SwfdecAudioFor
   ret = swfdec_audio_decoder_uncompressed_new (format, width, data_format);
   if (ret == NULL)
     ret = swfdec_audio_decoder_adpcm_new (format, width, data_format);
+#if 0
 #ifdef HAVE_MAD
   if (ret == NULL)
     ret = swfdec_audio_decoder_mad_new (format, width, data_format);
@@ -145,12 +150,11 @@ swfdec_audio_decoder_new (SwfdecAudioFor
   if (ret == NULL)
     ret = swfdec_audio_decoder_ffmpeg_new (format, width, data_format);
 #endif
-#if 0
+#endif
 #ifdef HAVE_GST
   if (ret == NULL)
     ret = swfdec_audio_decoder_gst_new (format, width, data_format);
 #endif
-#endif
   if (ret) {
     ret->format = format;
     g_return_val_if_fail (ret->out_format != 0, NULL);
diff --git a/libswfdec/swfdec_codec_gst.c b/libswfdec/swfdec_codec_gst.c
index cd4f517..64c335c 100644
--- a/libswfdec/swfdec_codec_gst.c
+++ b/libswfdec/swfdec_codec_gst.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <gst/gst.h>
 
+#include "swfdec_codec_audio.h"
 #include "swfdec_codec_video.h"
 #include "swfdec_debug.h"
 
@@ -36,6 +37,262 @@
 #define swfdec_cond_wait g_cond_wait
 #endif
 
+/*** AUDIO ***/
+
+typedef struct _SwfdecGstAudio SwfdecGstAudio;
+struct _SwfdecGstAudio {
+  SwfdecAudioDecoder	decoder;
+
+  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 */
+  SwfdecBufferQueue *	out;		/* all the stored output buffers */
+  GstCaps *		srccaps;	/* caps to set on buffers */
+  gboolean		eof;      	/* we've pushed EOF */
+  gboolean		done;		/* TRUE after decoding stopped (error or EOF) */
+};
+
+static void
+swfdec_gst_audio_unref (gpointer data, GObject *unused)
+{
+  SwfdecGstAudio *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);
+  swfdec_buffer_queue_unref (player->out);
+  g_slice_free (SwfdecGstAudio, player);
+}
+
+static void
+swfdec_audio_decoder_gst_free (SwfdecAudioDecoder *dec)
+{
+  SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
+  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_audio_unref (player, NULL);
+}
+
+static void
+swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
+{
+  SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
+
+  g_mutex_lock (player->mutex);
+  g_return_if_fail (!player->eof);
+  while (player->in != NULL && !player->done) {
+    swfdec_cond_wait (player->cond, player->mutex);
+  }
+  if (buffer) {
+    player->in = buffer;
+  } else {
+    player->eof = TRUE;
+  }
+  g_cond_signal (player->cond);
+  g_mutex_unlock (player->mutex);
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_gst_pull (SwfdecAudioDecoder *dec)
+{
+  SwfdecGstAudio *player = (SwfdecGstAudio *) dec;
+  SwfdecBuffer *buffer;
+
+  g_mutex_lock (player->mutex);
+  if (player->eof) {
+    while (!player->done)
+      swfdec_cond_wait (player->cond, player->mutex);
+  }
+  buffer = swfdec_buffer_queue_pull_buffer (player->out);
+  g_mutex_unlock (player->mutex);
+  return buffer;
+}
+
+static void
+swfdec_audio_decoder_gst_fakesrc_handoff (GstElement *fakesrc, GstBuffer *buf, 
+    GstPad *pad, SwfdecGstAudio *player)
+{
+  g_mutex_lock (player->mutex);
+  while (player->pipeline != NULL && player->in == NULL && player->eof == FALSE)
+    swfdec_cond_wait (player->cond, player->mutex);
+  if (player->pipeline == NULL) {
+    g_mutex_unlock (player->mutex);
+    return;
+  }
+  if (player->eof) {
+    //doesn't work: g_object_set (fakesrc, "num-buffers", 1, NULL);
+    /* HACK: just tell everyone we're done, that'll probably lose data in the
+     * gst stream, since we can't properly push EOF, but that's life... */
+    player->done = TRUE;
+  }
+  if (player->in) {
+    buf->data = g_memdup (player->in->data, player->in->length);
+    buf->malloc_data = buf->data;
+    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_audio_decoder_gst_fakesink_handoff (GstElement *fakesrc, GstBuffer *buf, 
+    GstPad *pad, SwfdecGstAudio *player)
+{
+  SwfdecBuffer *buffer;
+
+  g_mutex_lock (player->mutex);
+
+  while (player->pipeline == NULL && player->out != NULL)
+    swfdec_cond_wait (player->cond, player->mutex);
+  buffer = swfdec_buffer_new_for_data (
+      g_memdup (buf->data, buf->size), buf->size);
+  swfdec_buffer_queue_push (player->out, buffer);
+  g_cond_signal (player->cond);
+  g_mutex_unlock (player->mutex);
+}
+
+static void
+swfdec_audio_decoder_gst_link (GstElement *src, GstPad *pad, GstElement *sink)
+{
+  if (!gst_element_link (src, sink)) {
+    SWFDEC_ERROR ("no delayed link");
+  }
+}
+
+GstBusSyncReply
+swfdec_audio_decoder_gst_handle_bus (GstBus *bus, GstMessage *message, gpointer data)
+{
+  SwfdecGstAudio *player = data;
+
+  switch (message->type) {
+    case GST_MESSAGE_EOS:
+    case GST_MESSAGE_ERROR:
+      g_mutex_lock (player->mutex);
+      g_cond_signal (player->cond);
+      player->done = TRUE;
+      g_mutex_unlock (player->mutex);
+      break;
+    default:
+      break;
+  }
+  return GST_BUS_PASS;
+}
+
+SwfdecAudioDecoder *
+swfdec_audio_decoder_gst_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
+{
+  SwfdecGstAudio *player;
+  GstElement *fakesrc, *fakesink, *decoder, *convert;
+  GstBus *bus;
+  GstCaps *caps;
+
+  if (!gst_init_check (NULL, NULL, NULL))
+    return NULL;
+
+  switch (type) {
+    case SWFDEC_AUDIO_FORMAT_MP3:
+      caps = gst_caps_from_string ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
+      break;
+    default:
+      return NULL;
+  }
+  g_assert (caps);
+
+  player = g_slice_new0 (SwfdecGstAudio);
+  player->decoder.out_format = SWFDEC_AUDIO_OUT_STEREO_44100;
+  player->decoder.pull = swfdec_audio_decoder_gst_pull;
+  player->decoder.push = swfdec_audio_decoder_gst_push;
+  player->decoder.free = swfdec_audio_decoder_gst_free;
+  player->pipeline = gst_pipeline_new ("pipeline");
+  player->refcount = 1;
+  g_assert (player->pipeline);
+  bus = gst_element_get_bus (player->pipeline);
+  g_atomic_int_inc (&player->refcount);
+  g_object_weak_ref (G_OBJECT (bus), swfdec_gst_audio_unref, player);
+  gst_bus_set_sync_handler (bus, swfdec_audio_decoder_gst_handle_bus, player);
+  player->mutex = g_mutex_new ();
+  player->cond = g_cond_new ();
+  player->out = swfdec_buffer_queue_new ();
+  player->srccaps = caps;
+  fakesrc = gst_element_factory_make ("fakesrc", NULL);
+  if (fakesrc == NULL) {
+    SWFDEC_ERROR ("failed to create fakesrc");
+    swfdec_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+  g_object_set (fakesrc, "signal-handoffs", TRUE, 
+      "can-activate-pull", FALSE, NULL);
+  g_signal_connect (fakesrc, "handoff", 
+      G_CALLBACK (swfdec_audio_decoder_gst_fakesrc_handoff), player);
+  g_atomic_int_inc (&player->refcount);
+  g_object_weak_ref (G_OBJECT (fakesrc), swfdec_gst_audio_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_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+  g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
+  g_signal_connect (fakesink, "handoff", 
+      G_CALLBACK (swfdec_audio_decoder_gst_fakesink_handoff), player);
+  g_atomic_int_inc (&player->refcount);
+  g_object_weak_ref (G_OBJECT (fakesink), swfdec_gst_audio_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_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+  gst_bin_add (GST_BIN (player->pipeline), decoder);
+  convert = gst_element_factory_make ("audioconvert", NULL);
+  if (convert == NULL) {
+    SWFDEC_ERROR ("failed to create audioconvert");
+    swfdec_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+  gst_bin_add (GST_BIN (player->pipeline), convert);
+  g_signal_connect (decoder, "pad-added", 
+      G_CALLBACK (swfdec_audio_decoder_gst_link), convert);
+
+  caps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
+  g_assert (caps);
+  if (!gst_element_link_filtered (fakesrc, decoder, player->srccaps) ||
+      !gst_element_link_filtered (convert, fakesink, caps)) {
+    SWFDEC_ERROR ("linking failed");
+    swfdec_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+  gst_caps_unref (caps);
+  if (gst_element_set_state (player->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+    SWFDEC_ERROR ("failed to change sate");
+    swfdec_audio_decoder_gst_free (&player->decoder);
+    return NULL;
+  }
+
+  return &player->decoder;
+}
+
+/*** VIDEO ***/
+
 typedef struct _SwfdecGstVideo SwfdecGstVideo;
 struct _SwfdecGstVideo {
   SwfdecVideoDecoder	decoder;
@@ -88,7 +345,7 @@ swfdec_video_decoder_gst_free (SwfdecVid
   swfdec_gst_video_unref (player, NULL);
 }
 
-SwfdecBuffer *
+static SwfdecBuffer *
 swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer,
     guint *width, guint *height, guint *rowstride)
 {
@@ -117,7 +374,7 @@ swfdec_video_decoder_gst_decode (SwfdecV
 }
 
 static void
-swfdec_codec_gst_fakesrc_handoff (GstElement *fakesrc, GstBuffer *buf, 
+swfdec_video_decoder_gst_fakesrc_handoff (GstElement *fakesrc, GstBuffer *buf, 
     GstPad *pad, SwfdecGstVideo *player)
 {
   g_mutex_lock (player->mutex);
@@ -144,7 +401,7 @@ swfdec_codec_gst_fakesrc_handoff (GstEle
 }
 
 static void
-swfdec_codec_gst_fakesink_handoff (GstElement *fakesrc, GstBuffer *buf, 
+swfdec_video_decoder_gst_fakesink_handoff (GstElement *fakesrc, GstBuffer *buf, 
     GstPad *pad, SwfdecGstVideo *player)
 {
   GstCaps *caps;
@@ -180,7 +437,7 @@ swfdec_codec_gst_fakesink_handoff (GstEl
 }
 
 static void
-swfdec_codec_gst_do_link (GstElement *src, GstPad *pad, GstElement *sink)
+swfdec_video_decoder_gst_link (GstElement *src, GstPad *pad, GstElement *sink)
 {
   if (!gst_element_link (src, sink)) {
     SWFDEC_ERROR ("no delayed link");
@@ -227,7 +484,7 @@ swfdec_video_decoder_gst_new (SwfdecVide
   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_CALLBACK (swfdec_video_decoder_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);
@@ -239,7 +496,7 @@ swfdec_video_decoder_gst_new (SwfdecVide
   }
   g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
   g_signal_connect (fakesink, "handoff", 
-      G_CALLBACK (swfdec_codec_gst_fakesink_handoff), player);
+      G_CALLBACK (swfdec_video_decoder_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);
@@ -258,7 +515,7 @@ swfdec_video_decoder_gst_new (SwfdecVide
   }
   gst_bin_add (GST_BIN (player->pipeline), csp);
   g_signal_connect (decoder, "pad-added", 
-      G_CALLBACK (swfdec_codec_gst_do_link), csp);
+      G_CALLBACK (swfdec_video_decoder_gst_link), csp);
 
 #if G_BYTE_ORDER == G_BIG_ENDIAN
   caps = gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, "


More information about the Swfdec mailing list