[Swfdec-commits] 8 commits - configure.ac swfdec/swfdec_codec_gst.c swfdec/swfdec_flv_decoder.c swfdec/swfdec_internal.h swfdec/swfdec_player.c swfdec/swfdec_player.h swfdec/swfdec_player_internal.h swfdec/swfdec_sound.c swfdec/swfdec_video.c test/sound test/swfdec_test_plugin.c tools/crashfinder.c

Benjamin Otte company at kemper.freedesktop.org
Fri Feb 8 01:23:13 PST 2008


 configure.ac                    |    3 
 swfdec/swfdec_codec_gst.c       |  150 ++++++++++++++++++++++++++++++++--------
 swfdec/swfdec_flv_decoder.c     |   12 ++-
 swfdec/swfdec_internal.h        |    7 +
 swfdec/swfdec_player.c          |  133 +++++++++++++++++++++++++++++------
 swfdec/swfdec_player.h          |    4 -
 swfdec/swfdec_player_internal.h |    7 +
 swfdec/swfdec_sound.c           |    5 +
 swfdec/swfdec_video.c           |    2 
 test/sound/Makefile.am          |    6 -
 test/swfdec_test_plugin.c       |    3 
 tools/crashfinder.c             |    4 -
 12 files changed, 267 insertions(+), 69 deletions(-)

New commits:
commit 0d69659987848bcd2e22f200a866b98dd1044521
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 10:18:10 2008 +0100

    add how swfdec_player_advance() works
    
    It used to tigger all the timeouts that were necessary to advance the specified
    msecs. Now it just advances to the first event. This was necessary to allow
    easy abort on events like missing plugins.
    
    Ilike that it has surprisingly little impact on the code we have already
    written, because that one advances by swfdec_player_get_next_event()'s return
    value, which is exactly what this change enforces. I guess the only app not
    doing this will be the thumbnailer, and I haven't looked at it yet.

diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 03e3cbd..ba499f8 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -243,7 +243,12 @@ swfdec_player_get_next_event_time (SwfdecPlayer *player)
   SwfdecPlayerPrivate *priv = player->priv;
 
   if (priv->timeouts) {
-    return ((SwfdecTimeout *) priv->timeouts->data)->timestamp - priv->time;
+    SwfdecTick next = ((SwfdecTimeout *) priv->timeouts->data)->timestamp;
+    /* This can happen because advancing only uses millisecond granularity */
+    if (next < priv->time)
+      return 0;
+    else
+      return next - priv->time;
   } else {
     return G_MAXUINT64;
   }
@@ -1443,36 +1448,26 @@ swfdec_player_do_advance (SwfdecPlayer *player, gulong msecs, guint audio_sample
   SwfdecPlayerPrivate *priv = player->priv;
   SwfdecTimeout *timeout;
   SwfdecTick target_time;
-  guint frames_now;
   
   if (!swfdec_player_lock (player))
     return;
 
+  g_assert (priv->timeouts != NULL);
+
   target_time = priv->time + SWFDEC_MSECS_TO_TICKS (msecs);
   SWFDEC_DEBUG ("advancing %lu msecs (%u audio frames)", msecs, audio_samples);
 
-  for (timeout = priv->timeouts ? priv->timeouts->data : NULL;
-       timeout && timeout->timestamp <= target_time; 
-       timeout = priv->timeouts ? priv->timeouts->data : NULL) {
+  timeout = priv->timeouts->data;
+  swfdec_player_advance_audio (player, audio_samples);
+  if (timeout->timestamp <= target_time) {
     priv->timeouts = g_list_remove (priv->timeouts, timeout);
-    frames_now = SWFDEC_TICKS_TO_SAMPLES (timeout->timestamp) -
-      SWFDEC_TICKS_TO_SAMPLES (priv->time);
     priv->time = timeout->timestamp;
-    swfdec_player_advance_audio (player, frames_now);
-    audio_samples -= frames_now;
-    SWFDEC_LOG ("activating timeout %p now (timeout is %"G_GUINT64_FORMAT", target time is %"G_GUINT64_FORMAT,
-	timeout, timeout->timestamp, target_time);
+    SWFDEC_LOG ("activating timeout %p now (timeout is %"G_GUINT64_FORMAT,
+	timeout, timeout->timestamp);
     timeout->callback (timeout);
     swfdec_player_perform_actions (player);
   }
-  if (target_time > priv->time) {
-    frames_now = SWFDEC_TICKS_TO_SAMPLES (target_time) -
-      SWFDEC_TICKS_TO_SAMPLES (priv->time);
-    priv->time = target_time;
-    swfdec_player_advance_audio (player, frames_now);
-    audio_samples -= frames_now;
-  }
-  g_assert (audio_samples == 0);
+  priv->time = target_time;
   
   g_object_notify (G_OBJECT (player), "next-event");
   swfdec_player_unlock (player);
@@ -2548,23 +2543,36 @@ swfdec_player_render (SwfdecPlayer *player, cairo_t *cr,
 /**
  * swfdec_player_advance:
  * @player: the #SwfdecPlayer to advance
- * @msecs: number of milliseconds to advance
+ * @msecs: number of milliseconds to advance at maximum
  *
- * Advances @player by @msecs. You should make sure to call this function as
- * often as the SwfdecPlayer::next-event property indicates.
+ * Advances @player by @msecs or at most one event, whatever happens first in
+ * the player's timeline. You should make sure to call this function as often 
+ * as swfdec_player_get_next_event() indicates or your player will not appear 
+ * smooth.
+ *
+ * Returns: actual number of milliseconds advanced.
  **/
-void
+gulong
 swfdec_player_advance (SwfdecPlayer *player, gulong msecs)
 {
   SwfdecPlayerPrivate *priv;
   guint frames;
+  glong max;
 
-  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), 0);
 
+  /* find the max time to advance */
+  max = swfdec_player_get_next_event (player);
+  if (max < 0)
+    msecs = 0;
+  else
+    msecs = MIN ((gulong) max, msecs);
   priv = player->priv;
   frames = SWFDEC_TICKS_TO_SAMPLES (priv->time + SWFDEC_MSECS_TO_TICKS (msecs))
     - SWFDEC_TICKS_TO_SAMPLES (priv->time);
   g_signal_emit (player, signals[ADVANCE], 0, msecs, frames);
+
+  return msecs;
 }
 
 /**
diff --git a/swfdec/swfdec_player.h b/swfdec/swfdec_player.h
index 881de79..a77addf 100644
--- a/swfdec/swfdec_player.h
+++ b/swfdec/swfdec_player.h
@@ -149,7 +149,7 @@ void		swfdec_player_render		(SwfdecPlayer *	player,
 						 double		y,
 						 double		width,
 						 double		height);
-void		swfdec_player_advance		(SwfdecPlayer *	player,
+gulong		swfdec_player_advance		(SwfdecPlayer *	player,
 						 gulong		msecs);
 gboolean	swfdec_player_mouse_move	(SwfdecPlayer *	player, 
 						 double		x,
diff --git a/test/swfdec_test_plugin.c b/test/swfdec_test_plugin.c
index 62768a7..24719fb 100644
--- a/test/swfdec_test_plugin.c
+++ b/test/swfdec_test_plugin.c
@@ -37,8 +37,7 @@ swfdec_test_plugin_swfdec_advance (SwfdecTestPlugin *plugin, unsigned int msecs)
       if (next_event < 0)
 	break;
       next_event = MIN (next_event, (long) msecs);
-      swfdec_player_advance (plugin->data, next_event);
-      msecs -= next_event;
+      msecs -= swfdec_player_advance (plugin->data, next_event);
     }
   }
 }
diff --git a/tools/crashfinder.c b/tools/crashfinder.c
index 7c3898a..4d8f36d 100644
--- a/tools/crashfinder.c
+++ b/tools/crashfinder.c
@@ -119,11 +119,9 @@ main (int argc, char **argv)
       advance = swfdec_player_get_next_event (player);
       if (advance == -1)
 	break;
-      swfdec_player_advance (player, advance);
+      played += swfdec_player_advance (player, advance);
 
       swfdec_player_render (player, cr, 0, 0, 0, 0);
-
-      played += advance;
     }
 
     if (elapsed >= max_per_file ||
commit cd24919277a7c5af723145972c85d88318306dbb
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 09:47:13 2008 +0100

    fix various bugs
    
    - SEGV when factory was NULL
    - need to keep a reference to the element factory
    - SwfdecPlayerClass now has a vfunc for missing plugins
    - run gst_init() from swfdec_init()

diff --git a/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index 8736a55..ade7277 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -173,6 +173,7 @@ swfdec_gst_get_element_factory (GstCaps *caps)
 
   list = g_list_sort (list, swfdec_gst_compare_features);
   ret = list->data;
+  gst_object_ref (ret);
   gst_plugin_feature_list_free (list);
   return ret;
 }
@@ -259,7 +260,10 @@ swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srcca
     dec->decoder = gst_element_factory_make (name, "decoder");
   } else {
     GstElementFactory *factory = swfdec_gst_get_element_factory (srccaps);
-    dec->decoder = gst_element_factory_create (factory, "decoder");
+    if (factory) {
+      dec->decoder = gst_element_factory_create (factory, "decoder");
+      gst_object_unref (factory);
+    }
   }
   if (dec->decoder == NULL) {
     SWFDEC_ERROR ("failed to create decoder");
@@ -445,10 +449,6 @@ swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
   SwfdecGstAudio *player;
   GstCaps *srccaps, *sinkcaps;
 
-  if (!gst_init_check (NULL, NULL, NULL))
-    return NULL;
-  gst_pb_utils_init ();
-
   srccaps = swfdec_audio_decoder_get_caps (type, format);
   if (srccaps == NULL)
     return NULL;
@@ -611,10 +611,6 @@ swfdec_video_decoder_gst_new (guint codec)
   SwfdecGstVideo *player;
   GstCaps *srccaps, *sinkcaps;
 
-  if (!gst_init_check (NULL, NULL, NULL))
-    return NULL;
-  gst_pb_utils_init ();
-
   srccaps = swfdec_video_decoder_get_caps (codec);
   if (srccaps == NULL)
     return NULL;
@@ -652,8 +648,10 @@ swfdec_audio_decoder_gst_missing (guint codec, SwfdecAudioFormat format)
 
   /* If we can already handle it, woohoo! */
   factory = swfdec_gst_get_element_factory (caps);
-  if (factory != NULL)
+  if (factory != NULL) {
+    gst_object_unref (factory);
     return NULL;
+  }
 
   /* need to install plugins... */
   ret = gst_missing_decoder_installer_detail_new (caps);
@@ -679,8 +677,10 @@ swfdec_video_decoder_gst_missing (guint	codec)
 
   /* If we can already handle it, woohoo! */
   factory = swfdec_gst_get_element_factory (caps);
-  if (factory != NULL)
+  if (factory != NULL) {
+    gst_object_unref (factory);
     return NULL;
+  }
 
   /* need to install plugins... */
   ret = gst_missing_decoder_installer_detail_new (caps);
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 6b2de97..03e3cbd 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -22,6 +22,8 @@
 #endif
 
 #include <errno.h>
+#include <gst/gst.h>
+#include <gst/pbutils/pbutils.h>
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
@@ -1844,7 +1846,8 @@ swfdec_player_class_init (SwfdecPlayerClass *klass)
    *
    */
   signals[MISSING_PLUGINS] = g_signal_new ("missing-plugins", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED,
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SwfdecPlayerClass, missing_plugins),
+      NULL, NULL, g_cclosure_marshal_VOID__BOXED,
       G_TYPE_NONE, 1, G_TYPE_STRV);
 
   context_class->mark = swfdec_player_mark;
@@ -2329,6 +2332,10 @@ swfdec_init (void)
     g_thread_init (NULL);
   g_type_init ();
   oil_init ();
+#ifdef HAVE_GST
+  gst_init (NULL, NULL);
+  gst_pb_utils_init ();
+#endif
 
   s = g_getenv ("SWFDEC_DEBUG");
   if (s && s[0]) {
diff --git a/swfdec/swfdec_player.h b/swfdec/swfdec_player.h
index 5c32f59..881de79 100644
--- a/swfdec/swfdec_player.h
+++ b/swfdec/swfdec_player.h
@@ -89,6 +89,8 @@ struct _SwfdecPlayerClass
 						 double			x,
 						 double			y,
 						 int			button);
+  void			(* missing_plugins)	(SwfdecPlayer *		player,
+						 const char **		details);
 };
 
 void		swfdec_init			(void);
commit d699d72e33affe548dad3c309a6ef0eeeb77a46c
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 09:45:32 2008 +0100

    advertise video and audio codec

diff --git a/swfdec/swfdec_flv_decoder.c b/swfdec/swfdec_flv_decoder.c
index 52f14e2..9652e90 100644
--- a/swfdec/swfdec_flv_decoder.c
+++ b/swfdec/swfdec_flv_decoder.c
@@ -25,6 +25,7 @@
 #include "swfdec_audio_internal.h"
 #include "swfdec_bits.h"
 #include "swfdec_debug.h"
+#include "swfdec_player_internal.h"
 
 enum {
   SWFDEC_STATE_HEADER,			/* need to parse header */
@@ -252,6 +253,7 @@ swfdec_flv_decoder_parse_video_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, gui
   }
   if (flv->video->len == 0) {
     g_array_append_val (flv->video, tag);
+    swfdec_player_use_video_codec (SWFDEC_DECODER (flv)->player, tag.format);
   } else if (g_array_index (flv->video, SwfdecFlvVideoTag, 
 	flv->video->len - 1).timestamp < tag.timestamp) {
     g_array_append_val (flv->video, tag);
@@ -266,7 +268,7 @@ swfdec_flv_decoder_parse_video_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, gui
   return SWFDEC_STATUS_IMAGE;
 }
 
-static void
+static SwfdecStatus
 swfdec_flv_decoder_parse_audio_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, guint timestamp)
 {
   SwfdecFlvAudioTag tag;
@@ -274,7 +276,7 @@ swfdec_flv_decoder_parse_audio_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, gui
   if (flv->audio == NULL) {
     SWFDEC_INFO ("audio tags even though header didn't decalre them. Initializing...");
     flv->audio = g_array_new (FALSE, FALSE, sizeof (SwfdecFlvAudioTag));
-    return;
+    return SWFDEC_STATUS_OK;
   }
 
   tag.timestamp = timestamp;
@@ -285,10 +287,11 @@ swfdec_flv_decoder_parse_audio_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, gui
   SWFDEC_LOG ("  format: %s", swfdec_audio_format_to_string (tag.original_format));
   if (tag.buffer == NULL) {
     SWFDEC_WARNING ("no buffer, ignoring");
-    return;
+    return SWFDEC_STATUS_OK;
   }
   if (flv->audio->len == 0) {
     g_array_append_val (flv->audio, tag);
+    swfdec_player_use_audio_codec (SWFDEC_DECODER (flv)->player, tag.format, tag.original_format);
   } else if (g_array_index (flv->audio, SwfdecFlvAudioTag, 
 	flv->audio->len - 1).timestamp < tag.timestamp) {
     g_array_append_val (flv->audio, tag);
@@ -300,6 +303,7 @@ swfdec_flv_decoder_parse_audio_tag (SwfdecFlvDecoder *flv, SwfdecBits *bits, gui
     idx = swfdec_flv_decoder_find_audio (flv, tag.timestamp);
     g_array_insert_val (flv->audio, idx, tag);
   }
+  return SWFDEC_STATUS_OK;
 }
 
 static void
@@ -364,7 +368,7 @@ swfdec_flv_decoder_parse_tag (SwfdecFlvDecoder *flv)
   SWFDEC_LOG ("  timestamp %u", timestamp);
   switch (type) {
     case 8:
-      swfdec_flv_decoder_parse_audio_tag (flv, &bits, timestamp);
+      ret = swfdec_flv_decoder_parse_audio_tag (flv, &bits, timestamp);
       break;
     case 9:
       ret = swfdec_flv_decoder_parse_video_tag (flv, &bits, timestamp);
commit 6c8e47fbf2dae7cdc4b711cc1b9947ffe9332f76
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 09:39:43 2008 +0100

    advertise the audio codec

diff --git a/swfdec/swfdec_sound.c b/swfdec/swfdec_sound.c
index cb1e97c..96fc1fd 100644
--- a/swfdec/swfdec_sound.c
+++ b/swfdec/swfdec_sound.c
@@ -29,6 +29,7 @@
 #include "swfdec_buffer.h"
 #include "swfdec_button.h"
 #include "swfdec_debug.h"
+#include "swfdec_player_internal.h"
 #include "swfdec_sprite.h"
 #include "swfdec_swf_decoder.h"
 
@@ -160,6 +161,8 @@ tag_func_define_sound (SwfdecSwfDecoder * s, guint tag)
   }
   sound->n_samples *= swfdec_audio_format_get_granularity (sound->format);
 
+  swfdec_player_use_audio_codec (SWFDEC_DECODER (s)->player, sound->codec, sound->format);
+
   return SWFDEC_STATUS_OK;
 }
 
@@ -286,6 +289,8 @@ tag_func_sound_stream_head (SwfdecSwfDecoder * s, guint tag)
       sound->codec = SWFDEC_AUDIO_CODEC_UNDEFINED;
   }
 
+  swfdec_player_use_audio_codec (SWFDEC_DECODER (s)->player, sound->codec, sound->format);
+
   return SWFDEC_STATUS_OK;
 }
 
commit 407168c83abbf725e4e7160f6191b9683383b5ad
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 09:39:23 2008 +0100

    advertise usage of the video codec

diff --git a/swfdec/swfdec_video.c b/swfdec/swfdec_video.c
index 7ff8d8f..215c6dd 100644
--- a/swfdec/swfdec_video.c
+++ b/swfdec/swfdec_video.c
@@ -26,6 +26,7 @@
 #include "swfdec_video.h"
 #include "swfdec_debug.h"
 #include "swfdec_font.h"
+#include "swfdec_player_internal.h"
 #include "swfdec_swf_decoder.h"
 #include "swfdec_video_movie.h"
 
@@ -239,6 +240,7 @@ tag_func_define_video (SwfdecSwfDecoder *s, guint tag)
   SWFDEC_LOG ("  deblocking: %d", deblocking);
   SWFDEC_LOG ("  smoothing: %d", smoothing);
   SWFDEC_LOG ("  format: %d", (int) video->format);
+  swfdec_player_use_video_codec (SWFDEC_DECODER (s)->player, video->format);
   return SWFDEC_STATUS_OK;
 }
 
commit 0fd15057d2daa3ead3042104c933d715a7179a56
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Feb 8 09:37:41 2008 +0100

    update GStreamer requirements for missing plugin stuff
    
    Yes, it requires GStreamer 0.10.17 now (actually 0.10.15 is fine, but would
    bloat configure.ac). It's a bit unfortunate, just like libsoup-2.4, but should
    be solved with the next round of distros. Hardy, unstable and rawhide pretty
    likely have packages for this. Hardy does, and it's easy to just grab them for
    Gutsy.

diff --git a/configure.ac b/configure.ac
index cac18b7..d5222cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -250,7 +250,8 @@ AC_ARG_ENABLE(gstreamer,
 
 if test "$enable_gstreamer" = "yes"; then
 	GST_REQUIRED=0.10.11
-	PKG_CHECK_MODULES(GST, gstreamer-0.10 >= $GST_REQUIRED, HAVE_GST=yes, HAVE_GST=no)
+	GST_PB_REQUIRED=0.10.15
+	PKG_CHECK_MODULES(GST, gstreamer-0.10 >= $GST_REQUIRED gstreamer-pbutils-0.10 >= $GST_PB_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
commit 55475e671b34180d2bfada1badab2967edfbe985
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Feb 7 21:46:06 2008 +0100

    implement functions for notifying of missing functions
    
    THey're not used yet though

diff --git a/swfdec/swfdec_codec_gst.c b/swfdec/swfdec_codec_gst.c
index ebcd75f..8736a55 100644
--- a/swfdec/swfdec_codec_gst.c
+++ b/swfdec/swfdec_codec_gst.c
@@ -22,12 +22,62 @@
 #endif
 #include <string.h>
 #include <gst/gst.h>
+#include <gst/pbutils/pbutils.h>
 
 #include "swfdec_codec_audio.h"
 #include "swfdec_codec_video.h"
 #include "swfdec_debug.h"
 #include "swfdec_internal.h"
 
+/*** CAPS MATCHING ***/
+
+static GstCaps *
+swfdec_audio_decoder_get_caps (guint codec, SwfdecAudioFormat format)
+{
+  GstCaps *caps;
+  char *s;
+
+  switch (codec) {
+    case SWFDEC_AUDIO_CODEC_MP3:
+      s = g_strdup ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
+      break;
+    case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
+      s = g_strdup ("audio/x-nellymoser, rate=8000, channels=1");
+      break;
+    case SWFDEC_AUDIO_CODEC_NELLYMOSER:
+      s = g_strdup_printf ("audio/x-nellymoser, rate=%d, channels=%d",
+	  swfdec_audio_format_get_rate (format), 
+	  swfdec_audio_format_get_channels (format));
+      break;
+    default:
+      return NULL;
+  }
+
+  caps = gst_caps_from_string (s);
+  g_assert (caps);
+  g_free (s);
+  return caps;
+}
+
+static GstCaps *
+swfdec_video_decoder_get_caps (guint codec)
+{
+  GstCaps *caps;
+
+  switch (codec) {
+    case SWFDEC_VIDEO_CODEC_H263:
+      caps = gst_caps_from_string ("video/x-flash-video");
+      break;
+    case SWFDEC_VIDEO_CODEC_VP6:
+      caps = gst_caps_from_string ("video/x-vp6-flash");
+      break;
+    default:
+      return NULL;
+  }
+  g_assert (caps);
+  return caps;
+}
+
 /*** BUFFER ***/
 
 /* NB: references argument more than once */
@@ -110,10 +160,10 @@ swfdec_gst_compare_features (gconstpointer a_, gconstpointer b_)
   return strcmp (gst_plugin_feature_get_name (a), gst_plugin_feature_get_name (b));
 }
 
-static GstElement *
-swfdec_gst_get_element (GstCaps *caps)
+static GstElementFactory *
+swfdec_gst_get_element_factory (GstCaps *caps)
 {
-  GstElement *element;
+  GstElementFactory *ret;
   GList *list;
 
   list = gst_registry_feature_filter (gst_registry_get_default (), 
@@ -122,9 +172,9 @@ swfdec_gst_get_element (GstCaps *caps)
     return NULL;
 
   list = g_list_sort (list, swfdec_gst_compare_features);
-  element = gst_element_factory_create (list->data, "decoder");
+  ret = list->data;
   gst_plugin_feature_list_free (list);
-  return element;
+  return ret;
 }
 
 /*** PADS ***/
@@ -208,7 +258,8 @@ swfdec_gst_decoder_init (SwfdecGstDecoder *dec, const char *name, GstCaps *srcca
   if (name) {
     dec->decoder = gst_element_factory_make (name, "decoder");
   } else {
-    dec->decoder = swfdec_gst_get_element (srccaps);
+    GstElementFactory *factory = swfdec_gst_get_element_factory (srccaps);
+    dec->decoder = gst_element_factory_create (factory, "decoder");
   }
   if (dec->decoder == NULL) {
     SWFDEC_ERROR ("failed to create decoder");
@@ -396,15 +447,11 @@ swfdec_audio_decoder_gst_new (guint type, SwfdecAudioFormat format)
 
   if (!gst_init_check (NULL, NULL, NULL))
     return NULL;
+  gst_pb_utils_init ();
 
-  switch (type) {
-    case SWFDEC_AUDIO_CODEC_MP3:
-      srccaps = gst_caps_from_string ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
-      break;
-    default:
-      return NULL;
-  }
-  g_assert (srccaps);
+  srccaps = swfdec_audio_decoder_get_caps (type, format);
+  if (srccaps == NULL)
+    return NULL;
 
   player = g_slice_new0 (SwfdecGstAudio);
   player->decoder.format = SWFDEC_AUDIO_FORMAT_INVALID;
@@ -566,18 +613,11 @@ swfdec_video_decoder_gst_new (guint codec)
 
   if (!gst_init_check (NULL, NULL, NULL))
     return NULL;
+  gst_pb_utils_init ();
 
-  switch (codec) {
-    case SWFDEC_VIDEO_CODEC_H263:
-      srccaps = gst_caps_from_string ("video/x-flash-video");
-      break;
-    case SWFDEC_VIDEO_CODEC_VP6:
-      srccaps = gst_caps_from_string ("video/x-vp6-flash");
-      break;
-    default:
-      return NULL;
-  }
-  g_assert (srccaps);
+  srccaps = swfdec_video_decoder_get_caps (codec);
+  if (srccaps == NULL)
+    return NULL;
   sinkcaps = swfdec_video_decoder_get_sink_caps (codec);
 
   player = g_slice_new0 (SwfdecGstVideo);
@@ -596,3 +636,55 @@ swfdec_video_decoder_gst_new (guint codec)
   return &player->decoder;
 }
 
+/*** MISSING PLUGIN SUPPORT ***/
+  
+char *
+swfdec_audio_decoder_gst_missing (guint codec, SwfdecAudioFormat format)
+{
+  GstElementFactory *factory;
+  GstCaps *caps;
+  char *ret;
+
+  /* Check if we can handle the format at all. If not, no plugin will help us. */
+  caps = swfdec_audio_decoder_get_caps (codec, format);
+  if (caps == NULL)
+    return NULL;
+
+  /* If we can already handle it, woohoo! */
+  factory = swfdec_gst_get_element_factory (caps);
+  if (factory != NULL)
+    return NULL;
+
+  /* need to install plugins... */
+  ret = gst_missing_decoder_installer_detail_new (caps);
+  gst_caps_unref (caps);
+  return ret;
+}
+
+char *
+swfdec_video_decoder_gst_missing (guint	codec)
+{
+  GstElementFactory *factory;
+  GstCaps *caps;
+  char *ret;
+
+  /* This is necessary because the VP6 alpha decoder uses 2 VP6 decoders */
+  if (codec == SWFDEC_VIDEO_CODEC_VP6_ALPHA)
+    codec = SWFDEC_VIDEO_CODEC_VP6;
+
+  /* Check if we can handle the format at all. If not, no plugin will help us. */
+  caps = swfdec_video_decoder_get_caps (codec);
+  if (caps == NULL)
+    return NULL;
+
+  /* If we can already handle it, woohoo! */
+  factory = swfdec_gst_get_element_factory (caps);
+  if (factory != NULL)
+    return NULL;
+
+  /* need to install plugins... */
+  ret = gst_missing_decoder_installer_detail_new (caps);
+  gst_caps_unref (caps);
+  return ret;
+}
+
diff --git a/swfdec/swfdec_internal.h b/swfdec/swfdec_internal.h
index 41d8664..479397a 100644
--- a/swfdec/swfdec_internal.h
+++ b/swfdec/swfdec_internal.h
@@ -44,6 +44,10 @@ SwfdecAudioDecoder *	swfdec_audio_decoder_ffmpeg_new		(guint			type,
 #ifdef HAVE_GST
 SwfdecAudioDecoder *	swfdec_audio_decoder_gst_new		(guint			type, 
 								 SwfdecAudioFormat	format);
+char *			swfdec_audio_decoder_gst_missing      	(guint			codec,
+								 SwfdecAudioFormat	format);
+#else
+#define swfdec_audio_decoder_gst_missing(codec) NULL
 #endif
 
 /* video codecs */
@@ -55,6 +59,9 @@ SwfdecVideoDecoder *	swfdec_video_decoder_ffmpeg_new		(guint			format);
 #endif
 #ifdef HAVE_GST
 SwfdecVideoDecoder *	swfdec_video_decoder_gst_new		(guint			format);
+char *			swfdec_video_decoder_gst_missing      	(guint			codec);
+#else
+#define swfdec_video_decoder_gst_missing(codec) NULL
 #endif
 
 /* AS engine setup code */
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index e0c59ac..6b2de97 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -36,6 +36,7 @@
 #include "swfdec_debug.h"
 #include "swfdec_enums.h"
 #include "swfdec_event.h"
+#include "swfdec_internal.h"
 #include "swfdec_loader_internal.h"
 #include "swfdec_marshal.h"
 #include "swfdec_movie.h"
@@ -597,6 +598,7 @@ enum {
   AUDIO_REMOVED,
   LAUNCH,
   FSCOMMAND,
+  MISSING_PLUGINS,
   LAST_SIGNAL
 };
 
@@ -1268,6 +1270,22 @@ swfdec_player_emit_signals (SwfdecPlayer *player)
     g_signal_emit (player, signals[AUDIO_ADDED], 0, audio);
     audio->added = TRUE;
   }
+
+  /* emit missing-plugin signal for newly discovered plugins */
+  if (priv->missing_plugins) {
+    GSList *swalk;
+    guint i = 0;
+    char **details = g_new (char *, g_slist_length (priv->missing_plugins) + 1);
+
+    for (swalk = priv->missing_plugins; swalk; swalk = swalk->next) {
+      details[i++] = swalk->data;
+    }
+    details[i] = NULL;
+    g_slist_free (priv->missing_plugins);
+    priv->missing_plugins = NULL;
+    g_signal_emit (player, signals[MISSING_PLUGINS], 0, details);
+    g_strfreev (details);
+  }
 }
 
 static gboolean
@@ -1819,6 +1837,15 @@ swfdec_player_class_init (SwfdecPlayerClass *klass)
       G_SIGNAL_RUN_LAST, 0, NULL, NULL, swfdec_marshal_VOID__ENUM_STRING_STRING_BOXED,
       G_TYPE_NONE, 4, SWFDEC_TYPE_LOADER_REQUEST, G_TYPE_STRING, G_TYPE_STRING, 
       SWFDEC_TYPE_BUFFER);
+  /**
+   * SwfdecPlayer::missing-plugins:
+   * @player: the #SwfdecPlayer missing plugins
+   * @details: the details strigs for all missing plugins
+   *
+   */
+  signals[MISSING_PLUGINS] = g_signal_new ("missing-plugins", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED,
+      G_TYPE_NONE, 1, G_TYPE_STRV);
 
   context_class->mark = swfdec_player_mark;
   context_class->get_time = swfdec_player_get_time;
@@ -2207,6 +2234,49 @@ swfdec_player_load (SwfdecPlayer *player, const char *url,
   return loader;
 }
 
+void
+swfdec_player_use_audio_codec (SwfdecPlayer *player, guint codec, 
+    SwfdecAudioFormat format)
+{
+  SwfdecPlayerPrivate *priv;
+  char *detail;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+
+  detail = swfdec_audio_decoder_gst_missing (codec, format);
+  if (detail == NULL)
+    return;
+
+  priv = player->priv;
+  if (g_slist_find_custom (priv->missing_plugins, detail, (GCompareFunc) strcmp)) {
+    g_free (detail);
+    return;
+  }
+
+  priv->missing_plugins = g_slist_prepend (priv->missing_plugins, detail);
+}
+
+void
+swfdec_player_use_video_codec (SwfdecPlayer *player, guint codec)
+{
+  SwfdecPlayerPrivate *priv;
+  char *detail;
+
+  g_return_if_fail (SWFDEC_IS_PLAYER (player));
+
+  detail = swfdec_video_decoder_gst_missing (codec);
+  if (detail == NULL)
+    return;
+
+  priv = player->priv;
+  if (g_slist_find_custom (priv->missing_plugins, detail, (GCompareFunc) strcmp)) {
+    g_free (detail);
+    return;
+  }
+
+  priv->missing_plugins = g_slist_prepend (priv->missing_plugins, detail);
+}
+
 /** PUBLIC API ***/
 
 /**
diff --git a/swfdec/swfdec_player_internal.h b/swfdec/swfdec_player_internal.h
index e371391..71569be 100644
--- a/swfdec/swfdec_player_internal.h
+++ b/swfdec/swfdec_player_internal.h
@@ -22,6 +22,7 @@
 
 #include <swfdec/swfdec_player.h>
 #include <swfdec/swfdec_audio.h>
+#include <swfdec/swfdec_audio_internal.h>
 #include <swfdec/swfdec_event.h>
 #include <swfdec/swfdec_function_list.h>
 #include <swfdec/swfdec_loader.h>
@@ -123,6 +124,7 @@ struct _SwfdecPlayerPrivate
 
   /* audio */
   GList *		audio;		 	/* list of playing SwfdecAudio */
+  GSList *		missing_plugins;	/* list of GStreamer detail strings for missing plugins */
 
   /* events and advancing */
   SwfdecTick		time;			/* current time */
@@ -243,6 +245,11 @@ void		swfdec_player_global_to_stage	(SwfdecPlayer *		player,
 						 double *		y);
 void		swfdec_player_update_scale	(SwfdecPlayer *		player);
 
+void		swfdec_player_use_audio_codec	(SwfdecPlayer *		player,
+						 guint			codec, 
+						 SwfdecAudioFormat	format);
+void		swfdec_player_use_video_codec	(SwfdecPlayer *		player,
+						 guint			codec);
 /* in swfdec_policy_file.c */
 gboolean	swfdec_player_allow_now		(SwfdecPlayer *		player,
 						 const SwfdecURL *	url);
commit 7576b2417f17b885204e0345045638736c00d0bb
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Feb 7 16:20:36 2008 +0100

    don't list nonexisting files

diff --git a/test/sound/Makefile.am b/test/sound/Makefile.am
index 96e859a..73a6643 100644
--- a/test/sound/Makefile.am
+++ b/test/sound/Makefile.am
@@ -36,10 +36,6 @@ EXTRA_DIST = \
 	adpcm-5-2.swf.1.0.raw \
 	crash-0.5.3-no-samples.c \
 	crash-0.5.3-no-samples.swf \
-	crash-0.5.3-no-samples.swf.1.0.raw \
-	crash-0.5.3-no-samples.swf.3.0.raw \
-	crash-0.5.3-no-samples.swf.5.0.raw \
-	crash-0.5.3-no-samples.swf.7.0.raw \
-	crash-0.5.3-no-samples.swf.9.0.raw
+	crash-0.5.3-no-samples.swf.1.0.raw
 
 CLEANFILES = tmp


More information about the Swfdec-commits mailing list