wtay gst-plugins-base: gst-plugins-base/ gst-plugins-base/gst/playback/

[email protected] Wed, 10 Dec 2008 09:39:47 -0800 (PST)
Newsgroups gmane.comp.video.gstreamer.cvs
Message-ID <[email protected]>
CVS Root:       /cvs/gstreamer
Module:         gst-plugins-base
Changes by:     wtay
Date:           Wed Dec 10 2008  17:39:47 UTC

Log message:
* gst/playback/gstplaysink.c: (gst_play_sink_class_init),
(gst_play_sink_dispose), (gst_play_sink_finalize), (try_element),
(gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure),
(gst_play_sink_send_event), (gst_play_sink_change_state):
Use G_DEFINE_TYPE.
Try to set the selected sink to READY before using it. This will allow
for detection of incompatible formats sooner.
Don't cause a fatal error when conversion elements are missing but post
a missing-element message and a warning instead because things might
still link and run fine.
Simplyfy the construction of audio and video sink chains.

Modified files:
    .               : ChangeLog
    gst/playback    : gstplaysink.c

Links:
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ChangeLog.diff?r1=1.4239&r2=1.4240
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst/playback/gstplaysink.c.diff?r1=1.20&r2=1.21

====Begin Diffs====
Index: ChangeLog
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ChangeLog,v
retrieving revision 1.4239
retrieving revision 1.4240
diff -u -d -r1.4239 -r1.4240
--- ChangeLog	10 Dec 2008 14:55:08 -0000	1.4239
+++ ChangeLog	10 Dec 2008 17:39:31 -0000	1.4240
@@ -1,5 +1,19 @@
 2008-12-10  Wim Taymans  <[email protected]>
 
+	* gst/playback/gstplaysink.c: (gst_play_sink_class_init),
+	(gst_play_sink_dispose), (gst_play_sink_finalize), (try_element),
+	(gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure),
+	(gst_play_sink_send_event), (gst_play_sink_change_state):
+	Use G_DEFINE_TYPE.
+	Try to set the selected sink to READY before using it. This will allow
+	for detection of incompatible formats sooner.
+	Don't cause a fatal error when conversion elements are missing but post
+	a missing-element message and a warning instead because things might
+	still link and run fine.
+	Simplyfy the construction of audio and video sink chains.
+
+2008-12-10  Wim Taymans  <[email protected]>
 	* ext/ogg/gstoggdemux.c: (gst_ogg_pad_class_init),
 	(gst_ogg_pad_dispose), (gst_ogg_pad_finalize):
 	Use G_DEFINE_TYPE for the OggPad to get some threadsafe type 
Index: gstplaysink.c
RCS file: /cvs/gstreamer/gst-plugins-base/gst/playback/gstplaysink.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- gstplaysink.c	22 Nov 2008 14:31:43 -0000	1.20
+++ gstplaysink.c	10 Dec 2008 17:39:32 -0000	1.21
@@ -170,8 +170,6 @@
 static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
     GstStateChange transition);
-static GstElementClass *parent_class;
-
 /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */
 static const GstElementDetails gst_play_sink_details =
@@ -180,31 +178,7 @@
     "Autoplug and play media from an uri",
     "Wim Taymans <[email protected]>");
-GType
-gst_play_sink_get_type (void)
-{
-  static GType gst_play_sink_type = 0;
-  if (!gst_play_sink_type) {
-    static const GTypeInfo gst_play_sink_info = {
-      sizeof (GstPlaySinkClass),
-      NULL,
-      (GClassInitFunc) gst_play_sink_class_init,
-      sizeof (GstPlaySink),
-      0,
-      (GInstanceInitFunc) gst_play_sink_init,
-      NULL
-    };
-    gst_play_sink_type = g_type_register_static (GST_TYPE_BIN,
-        "GstPlaySink", &gst_play_sink_info, 0);
-  }
-  return gst_play_sink_type;
-}
+G_DEFINE_TYPE (GstPlaySink, gst_play_sink, GST_TYPE_BIN);
 static void
 gst_play_sink_class_init (GstPlaySinkClass * klass)
@@ -217,8 +191,6 @@
   gstelement_klass = (GstElementClass *) klass;
   gstbin_klass = (GstBinClass *) klass;
-  parent_class = g_type_class_peek_parent (klass);
   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_sink_dispose);
   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_sink_finalize);
@@ -270,7 +242,7 @@
   g_free (playsink->font_desc);
   playsink->font_desc = NULL;
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object);
 }
@@ -282,7 +254,7 @@
   g_mutex_free (playsink->lock);
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gst_play_sink_parent_class)->finalize (object);
 void
@@ -636,6 +608,26 @@
   return result;
+/* try to change the state of an element. This function returns the element when
+ * the state change could be performed. When this function returns NULL an error
+ * occured and the element is unreffed. */
+static GstElement *
+try_element (GstPlaySink * playsink, GstElement * element)
+{
+  GstStateChangeReturn ret;
+  if (element) {
+    ret = gst_element_set_state (element, GST_STATE_READY);
+    if (ret == GST_STATE_CHANGE_FAILURE) {
+      GST_DEBUG_OBJECT (playsink, "failed state change..");
+      gst_element_set_state (element, GST_STATE_NULL);
+      gst_object_unref (element);
+      element = NULL;
+    }
+  }
+  return element;
+}
 /* make the element (bin) that contains the elements needed to perform
  * video display. 
  *
@@ -655,6 +647,7 @@
   GstPlayVideoChain *chain;
   GstBin *bin;
   GstPad *pad;
+  GstElement *prev, *elem;
   chain = g_new0 (GstPlayVideoChain, 1);
   chain->chain.playsink = gst_object_ref (playsink);
@@ -662,15 +655,22 @@
   GST_DEBUG_OBJECT (playsink, "making video chain %p", chain);
   if (playsink->video_sink) {
-    chain->sink = gst_object_ref (playsink->video_sink);
-  } else {
-    chain->sink = gst_element_factory_make ("autovideosink", "videosink");
-    if (chain->sink == NULL) {
-      chain->sink = gst_element_factory_make ("xvimagesink", "videosink");
-    }
-    if (chain->sink == NULL)
-      goto no_sinks;
+    GST_DEBUG_OBJECT (playsink, "trying configured videosink");
+    elem = gst_object_ref (playsink->video_sink);
+    chain->sink = try_element (playsink, elem);
+  if (chain->sink == NULL) {
+    GST_DEBUG_OBJECT (playsink, "trying autovideosink");
+    elem = gst_element_factory_make ("autovideosink", "videosink");
+    GST_DEBUG_OBJECT (playsink, "trying xvimagesink");
+    elem = gst_element_factory_make ("xvimagesink", "videosink");
   }
+  if (chain->sink == NULL)
+    goto no_sinks;
   /* if we can disable async behaviour of the sink, we can avoid adding a
    * queue for the audio chain. We can't use the deep property here because the
@@ -680,8 +680,10 @@
         async);
     g_object_set (chain->sink, "async", async, NULL);
     chain->async = async;
-  } else
+  } else {
+    GST_DEBUG_OBJECT (playsink, "no async property on the sink");
     chain->async = TRUE;
   /* create a bin to hold objects, as we create them we add them to this bin so
    * that when something goes wrong we only need to unref the bin */
@@ -691,18 +693,6 @@
   gst_object_sink (bin);
   gst_bin_add (bin, chain->sink);
-  if (raw) {
-    chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
-    if (chain->conv == NULL)
-      goto no_colorspace;
-    gst_bin_add (bin, chain->conv);
-    chain->scale = gst_element_factory_make ("videoscale", "vscale");
-    if (chain->scale == NULL)
-      goto no_videoscale;
-    gst_bin_add (bin, chain->scale);
   /* decouple decoder from sink, this improves playback quite a lot since the
    * decoder can continue while the sink blocks for synchronisation. We don't
    * need a lot of buffers as this consumes a lot of memory and we don't want
@@ -711,24 +701,49 @@
   g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3,
       "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL);
   gst_bin_add (bin, chain->queue);
+  prev = chain->queue;
   if (raw) {
-    gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
-    gst_element_link_pads (chain->conv, "src", chain->scale, "sink");
-    /* be more careful with the pad from the custom sink element, it might not
-     * be named 'sink' */
-    if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL))
-      goto link_failed;
+    GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace");
+    chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
+    if (chain->conv == NULL) {
+      post_missing_element_message (playsink, "ffmpegcolorspace");
+      GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+          (_("Missing element '%s' - check your GStreamer installation."),
+              "ffmpegcolorspace"), (NULL));
+    } else {
+      gst_bin_add (bin, chain->conv);
+      if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
+        goto link_failed;
-    pad = gst_element_get_static_pad (chain->queue, "sink");
-    if (!gst_element_link_pads (chain->queue, "src", chain->sink, NULL))
+      prev = chain->conv;
+    GST_DEBUG_OBJECT (playsink, "creating videoscale");
+    chain->scale = gst_element_factory_make ("videoscale", "vscale");
+    if (chain->scale == NULL) {
+      post_missing_element_message (playsink, "videoscale");
+              "videoscale"), ("possibly a liboil version mismatch?"));
+      gst_bin_add (bin, chain->scale);
+      if (!gst_element_link_pads (prev, "src", chain->scale, "sink"))
+      prev = chain->scale;
+  /* be more careful with the pad from the custom sink element, it might not
+   * be named 'sink' */
+  if (!gst_element_link_pads (prev, "src", chain->sink, NULL))
+    goto link_failed;
+  pad = gst_element_get_static_pad (chain->queue, "sink");
   chain->sinkpad = gst_ghost_pad_new ("sink", pad);
   gst_object_unref (pad);
   gst_element_add_pad (chain->chain.bin, chain->sinkpad);
   return chain;
@@ -743,24 +758,6 @@
     free_chain ((GstPlayChain *) chain);
     return NULL;
-no_colorspace:
-  {
-    post_missing_element_message (playsink, "ffmpegcolorspace");
-    GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
-        (_("Missing element '%s' - check your GStreamer installation."),
-            "ffmpegcolorspace"), (NULL));
-    free_chain ((GstPlayChain *) chain);
-    return NULL;
-no_videoscale:
-    post_missing_element_message (playsink, "videoscale");
-            "videoscale"), ("possibly a liboil version mismatch?"));
 link_failed:
   {
     GST_ELEMENT_ERROR (playsink, CORE, PAD,
@@ -879,8 +876,9 @@
 {
   GstPlayAudioChain *chain;
-  gboolean res, have_volume;
+  gboolean have_volume;
+  GstElement *head, *prev, *elem;
   chain = g_new0 (GstPlayAudioChain, 1);
@@ -888,15 +886,24 @@
   GST_DEBUG_OBJECT (playsink, "making audio chain %p", chain);
   if (playsink->audio_sink) {
-    chain->sink = gst_object_ref (playsink->audio_sink);
-    chain->sink = gst_element_factory_make ("autoaudiosink", "audiosink");
-      chain->sink = gst_element_factory_make ("alsasink", "audiosink");
+    GST_DEBUG_OBJECT (playsink, "trying configured audiosink");
+    elem = gst_object_ref (playsink->audio_sink);
+    GST_DEBUG_OBJECT (playsink, "trying autoaudiosink");
+    elem = gst_element_factory_make ("autoaudiosink", "audiosink");
+    GST_DEBUG_OBJECT (playsink, "trying alsasink");
+    elem = gst_element_factory_make ("alsasink", "audiosink");
   chain->chain.bin = gst_bin_new ("abin");
   bin = GST_BIN_CAST (chain->chain.bin);
   gst_object_ref (bin);
@@ -909,6 +916,10 @@
     GST_DEBUG_OBJECT (playsink, "adding audio queue");
     chain->queue = gst_element_factory_make ("queue", "aqueue");
     gst_bin_add (bin, chain->queue);
+    prev = head = chain->queue;
+    head = chain->sink;
+    prev = NULL;
   /* check if the sink has the volume property, if it does we don't need to
@@ -934,60 +945,80 @@
     chain->conv = gst_element_factory_make ("audioconvert", "aconv");
-      goto no_audioconvert;
+      post_missing_element_message (playsink, "audioconvert");
+              "audioconvert"), ("possibly a liboil version mismatch?"));
+      if (prev) {
+        if (!gst_element_link_pads (prev, "src", chain->conv, "sink"))
+          goto link_failed;
+      } else {
+        head = chain->conv;
+      }
     chain->resample = gst_element_factory_make ("audioresample", "aresample");
-    if (chain->resample == NULL)
-      goto no_audioresample;
-    gst_bin_add (bin, chain->resample);
-    res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
+    if (chain->resample == NULL) {
+      post_missing_element_message (playsink, "audioresample");
+              "audioresample"), ("possibly a liboil version mismatch?"));
+      gst_bin_add (bin, chain->resample);
+        if (!gst_element_link_pads (prev, "src", chain->resample, "sink"))
+        head = chain->resample;
+      prev = chain->resample;
     if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
       chain->volume = gst_element_factory_make ("volume", "volume");
-      if (chain->volume == NULL)
-        goto no_volume;
-      have_volume = TRUE;
-      /* volume also has the mute property */
-      chain->mute = gst_object_ref (chain->volume);
+      if (chain->volume == NULL) {
+        post_missing_element_message (playsink, "volume");
+        GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN,
+            (_("Missing element '%s' - check your GStreamer installation."),
+                "volume"), ("possibly a liboil version mismatch?"));
+        have_volume = TRUE;
-      /* configure with the latest volume and mute */
-      g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
-      g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL);
-      gst_bin_add (bin, chain->volume);
+        /* volume also has the mute property */
+        chain->mute = gst_object_ref (chain->volume);
-      res &=
-          gst_element_link_pads (chain->resample, "src", chain->volume, "sink");
-      res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL);
-    } else {
-      res &= gst_element_link_pads (chain->resample, "src", chain->sink, NULL);
-    if (!res)
+        /* configure with the latest volume and mute */
+        g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume,
+            NULL);
+        g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL);
+        gst_bin_add (bin, chain->volume);
-    if (queue) {
-      res = gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
-      pad = gst_element_get_static_pad (chain->queue, "sink");
-      pad = gst_element_get_static_pad (chain->conv, "sink");
-      res = gst_element_link_pads (chain->queue, "src", chain->sink, "sink");
-      pad = gst_element_get_static_pad (chain->sink, "sink");
+        if (prev) {
+          if (!gst_element_link_pads (prev, "src", chain->volume, "sink"))
+            goto link_failed;
+        } else {
+          head = chain->volume;
+        }
+        prev = chain->volume;
     }
   /* post a warning if we have no way to configure the volume */
   if (!have_volume) {
     GST_ELEMENT_WARNING (playsink, STREAM, NOT_IMPLEMENTED,
         (_("No volume control found")), ("No volume control found"));
+  /* and ghost the sinkpad of the headmost element */
+  pad = gst_element_get_static_pad (head, "sink");
@@ -1003,33 +1034,6 @@
-no_audioconvert:
-    post_missing_element_message (playsink, "audioconvert");
-            "audioconvert"), ("possibly a liboil version mismatch?"));
-no_audioresample:
-    post_missing_element_message (playsink, "audioresample");
-            "audioresample"), ("possibly a liboil version mismatch?"));
-no_volume:
-    post_missing_element_message (playsink, "volume");
-            "volume"), ("possibly a liboil version mismatch?"));
@@ -1175,7 +1179,8 @@
   /* figure out which components we need */
   if (flags & GST_PLAY_FLAG_TEXT && playsink->text_pad) {
-    /* we need video too */
+    /* we have a text_pad and we need text rendering, in this case we need a
+     * video_pad to combine the video with the text */
     if (!playsink->video_pad)
       goto subs_but_no_video;
@@ -1593,7 +1598,9 @@
       res = gst_play_sink_send_event_to_sink (GST_PLAY_SINK (element), event);
       break;
     default:
-      res = parent_class->send_event (element, event);
+      res =
+          GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element,
+          event);
   return res;
@@ -1614,7 +1621,9 @@
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  ret =
+      GST_ELEMENT_CLASS (gst_play_sink_parent_class)->change_state (element,
+      transition);
   if (ret == GST_STATE_CHANGE_FAILURE)
     return ret;

------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/