playbin2: properly reconfigure upon subsequent no-more-pads
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Tue, 8 May 2012 13:42:02 +0000 (15:42 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 9 May 2012 08:28:35 +0000 (10:28 +0200)
... such as during switch in chained ogg.

gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstplaysink.h

index 365e138..c997104 100644 (file)
@@ -2715,6 +2715,9 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
      * the sink. */
     changed = FALSE;
     sinkpad = NULL;
+
+    /* store the selector for the pad */
+    g_object_set_data (G_OBJECT (pad), "playbin2.select", select);
   }
   GST_SOURCE_GROUP_UNLOCK (group);
 
@@ -2787,6 +2790,15 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
       "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
 
   GST_SOURCE_GROUP_LOCK (group);
+
+  if ((select = g_object_get_data (G_OBJECT (pad), "playbin2.select"))) {
+    g_assert (select->selector == NULL);
+    g_assert (select->srcpad == pad);
+    gst_object_unref (pad);
+    select->srcpad = NULL;
+    goto exit;
+  }
+
   /* get the selector sinkpad */
   if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin.sinkpad")))
     goto not_linked;
@@ -2804,6 +2816,16 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
     /* remove the pad from the array */
     g_ptr_array_remove (select->channels, peer);
     GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
+
+    if (!select->channels->len && select->selector) {
+      GST_DEBUG_OBJECT (playbin, "all selector sinkpads removed");
+      GST_DEBUG_OBJECT (playbin, "removing selector %p", select->selector);
+      gst_object_unref (select->srcpad);
+      select->srcpad = NULL;
+      gst_element_set_state (select->selector, GST_STATE_NULL);
+      gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
+      select->selector = NULL;
+    }
   }
 
   /* unlink the pad now (can fail, the pad is unlinked before it's removed) */
@@ -2823,6 +2845,7 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
   gst_object_unref (peer);
 
   gst_object_unref (selector);
+exit:
   GST_SOURCE_GROUP_UNLOCK (group);
 
   return;
@@ -2877,7 +2900,17 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
       GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
       select->sinkpad =
           gst_play_sink_request_pad (playbin->playsink, select->type);
-
+    } else if (select->srcpad && select->sinkpad) {
+      GST_DEBUG_OBJECT (playbin, "refreshing new sink pad %d", select->type);
+      gst_play_sink_refresh_pad (playbin->playsink, select->sinkpad,
+          select->type);
+    } else if (select->sinkpad && select->srcpad == NULL) {
+      GST_DEBUG_OBJECT (playbin, "releasing sink pad %d", select->type);
+      gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
+      select->sinkpad = NULL;
+    }
+    if (select->sinkpad && select->srcpad &&
+        !gst_pad_is_linked (select->srcpad)) {
       res = gst_pad_link (select->srcpad, select->sinkpad);
       GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
           select->media_list[0], res);
index be3f5e9..e441465 100644 (file)
@@ -3507,6 +3507,48 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink)
   }
 }
 
+void
+gst_play_sink_refresh_pad (GstPlaySink * playsink, GstPad * pad,
+    GstPlaySinkType type)
+{
+  GST_DEBUG_OBJECT (playsink, "refresh pad %" GST_PTR_FORMAT, pad);
+
+  GST_PLAY_SINK_LOCK (playsink);
+  if (pad == playsink->video_pad) {
+    if (type != GST_PLAY_SINK_TYPE_VIDEO_RAW &&
+        type != GST_PLAY_SINK_TYPE_VIDEO)
+      goto wrong_type;
+  } else if (pad == playsink->audio_pad) {
+    if (type != GST_PLAY_SINK_TYPE_AUDIO_RAW &&
+        type != GST_PLAY_SINK_TYPE_AUDIO)
+      goto wrong_type;
+  } else if (pad == playsink->text_pad) {
+    if (type != GST_PLAY_SINK_TYPE_TEXT)
+      goto wrong_type;
+  }
+
+  if (type != GST_PLAY_SINK_TYPE_FLUSHING) {
+    GstPad *blockpad =
+        GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (pad)));
+
+    gst_pad_set_blocked_async (blockpad, TRUE, sinkpad_blocked_cb, playsink);
+    PENDING_FLAG_SET (playsink, type);
+    gst_object_unref (blockpad);
+  }
+  GST_PLAY_SINK_UNLOCK (playsink);
+
+  return;
+
+  /* ERRORS */
+wrong_type:
+  {
+    GST_WARNING_OBJECT (playsink, "wrong type %d for pad %" GST_PTR_FORMAT,
+        pad);
+    GST_PLAY_SINK_UNLOCK (playsink);
+    return;
+  }
+}
+
 /**
  * gst_play_sink_request_pad
  * @playsink: a #GstPlaySink
@@ -3631,6 +3673,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type)
   return res;
 }
 
+
 static GstPad *
 gst_play_sink_request_new_pad (GstElement * element, GstPadTemplate * templ,
     const gchar * name, const GstCaps * caps)
index 51fe14b..6141c2c 100644 (file)
@@ -70,6 +70,7 @@ GType gst_play_sink_get_type (void);
 
 GstPad *         gst_play_sink_request_pad    (GstPlaySink *playsink, GstPlaySinkType type);
 void             gst_play_sink_release_pad    (GstPlaySink *playsink, GstPad *pad);
+void             gst_play_sink_refresh_pad    (GstPlaySink *playsink, GstPad *pad, GstPlaySinkType type);
 
 void             gst_play_sink_set_sink       (GstPlaySink * playsink, GstPlaySinkType type, GstElement * sink);
 GstElement *     gst_play_sink_get_sink       (GstPlaySink * playsink, GstPlaySinkType type);