Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / playback / gstplaysinkconvertbin.c
index 99a2e38..ba5efaa 100644 (file)
@@ -32,6 +32,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_play_sink_convert_bin_debug);
 
 #define parent_class gst_play_sink_convert_bin_parent_class
 
+static gboolean gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin *
+    self, GstCaps * caps);
+
 G_DEFINE_TYPE (GstPlaySinkConvertBin, gst_play_sink_convert_bin, GST_TYPE_BIN);
 
 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
@@ -82,17 +85,9 @@ distribute_running_time (GstElement * element, const GstSegment * segment)
   pad = gst_element_get_static_pad (element, "sink");
 
   gst_pad_send_event (pad, gst_event_new_flush_start ());
-  gst_pad_send_event (pad, gst_event_new_flush_stop ());
-
-  if (segment->accum) {
-    event = gst_event_new_new_segment_full (FALSE, segment->rate,
-        segment->applied_rate, segment->format, 0, segment->accum, 0);
-    gst_pad_send_event (pad, event);
-  }
+  gst_pad_send_event (pad, gst_event_new_flush_stop (FALSE));
 
-  event = gst_event_new_new_segment_full (FALSE, segment->rate,
-      segment->applied_rate, segment->format,
-      segment->start, segment->stop, segment->time);
+  event = gst_event_new_segment (segment);
   gst_pad_send_event (pad, event);
 
   gst_object_unref (pad);
@@ -142,6 +137,7 @@ gst_play_sink_convert_bin_add_identity (GstPlaySinkConvertBin * self)
 
         );
   } else {
+    g_object_set (self->identity, "silent", TRUE, NULL);
     gst_bin_add (GST_BIN_CAST (self), self->identity);
   }
 }
@@ -200,24 +196,22 @@ gst_play_sink_convert_bin_on_element_added (GstElement * element,
   distribute_running_time (element, &self->segment);
 }
 
-static void
-pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkConvertBin * self)
+static GstPadProbeReturn
+pad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
 {
+  GstPlaySinkConvertBin *self = user_data;
   GstPad *peer;
   GstCaps *caps;
   gboolean raw;
 
   GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
-  self->sink_proxypad_blocked = blocked;
-  GST_DEBUG_OBJECT (self, "Pad blocked: %d", blocked);
-  if (!blocked)
-    goto done;
+  GST_DEBUG_OBJECT (self, "Pad blocked");
 
   /* There must be a peer at this point */
   peer = gst_pad_get_peer (self->sinkpad);
-  caps = gst_pad_get_negotiated_caps (peer);
+  caps = gst_pad_get_current_caps (peer);
   if (!caps)
-    caps = gst_pad_get_caps_reffed (peer);
+    caps = gst_pad_query_caps (peer, NULL);
   gst_object_unref (peer);
 
   raw = is_raw_caps (caps, self->audio);
@@ -247,38 +241,43 @@ pad_blocked_cb (GstPad * pad, gboolean blocked, GstPlaySinkConvertBin * self)
   gst_play_sink_convert_bin_set_targets (self, !raw);
 
 unblock:
-  gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
-      (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
-      (GDestroyNotify) gst_object_unref);
-
-done:
+  self->sink_proxypad_block_id = 0;
   GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
-  return;
+
+  return GST_PAD_PROBE_REMOVE;
 }
 
 static gboolean
-gst_play_sink_convert_bin_sink_event (GstPad * pad, GstEvent * event)
+gst_play_sink_convert_bin_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
-  GstPlaySinkConvertBin *self =
-      GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
+  GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN (parent);
   gboolean ret;
 
-  ret = gst_proxy_pad_event_default (pad, gst_event_ref (event));
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
-    gboolean update;
-    gdouble rate, applied_rate;
-    GstFormat format;
-    gint64 start, stop, position;
+      gst_event_parse_caps (event, &caps);
+      ret = gst_play_sink_convert_bin_sink_setcaps (self, caps);
+      break;
+    }
+    default:
+      break;
+  }
+
+  ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
+
+  if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
+    GstSegment seg;
 
     GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
-    gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-        &format, &start, &stop, &position);
+    gst_event_copy_segment (event, &seg);
 
     GST_DEBUG_OBJECT (self, "Segment before %" GST_SEGMENT_FORMAT,
         &self->segment);
-    gst_segment_set_newsegment_full (&self->segment, update, rate, applied_rate,
-        format, start, stop, position);
+    self->segment = seg;
     GST_DEBUG_OBJECT (self, "Segment after %" GST_SEGMENT_FORMAT,
         &self->segment);
     GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
@@ -290,23 +289,40 @@ gst_play_sink_convert_bin_sink_event (GstPad * pad, GstEvent * event)
   }
 
   gst_event_unref (event);
-  gst_object_unref (self);
 
   return ret;
 }
 
+static void
+block_proxypad (GstPlaySinkConvertBin * self)
+{
+  if (self->sink_proxypad_block_id == 0) {
+    self->sink_proxypad_block_id =
+        gst_pad_add_probe (self->sink_proxypad,
+        GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, pad_blocked_cb,
+        gst_object_ref (self), (GDestroyNotify) gst_object_unref);
+  }
+}
+
+static void
+unblock_proxypad (GstPlaySinkConvertBin * self)
+{
+  if (self->sink_proxypad_block_id != 0) {
+    gst_pad_remove_probe (self->sink_proxypad, self->sink_proxypad_block_id);
+    self->sink_proxypad_block_id = 0;
+  }
+}
+
 static gboolean
-gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin * self,
+    GstCaps * caps)
 {
-  GstPlaySinkConvertBin *self =
-      GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
-  gboolean ret;
   GstStructure *s;
   const gchar *name;
   gboolean reconfigure = FALSE;
   gboolean raw;
 
-  GST_DEBUG_OBJECT (pad, "setcaps: %" GST_PTR_FORMAT, caps);
+  GST_DEBUG_OBJECT (self, "setcaps");
   GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
   s = gst_caps_get_structure (caps, 0);
   name = gst_structure_get_name (s);
@@ -323,17 +339,13 @@ gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
     if (!self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
       GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
       reconfigure = TRUE;
-      gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
-          (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
-          (GDestroyNotify) gst_object_unref);
+      block_proxypad (self);
     }
   } else {
     if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
       GST_DEBUG_OBJECT (self, "Changing caps from raw to non-raw");
       reconfigure = TRUE;
-      gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
-          (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
-          (GDestroyNotify) gst_object_unref);
+      block_proxypad (self);
     }
   }
 
@@ -344,18 +356,14 @@ gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
   }
 
   GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
-  ret = gst_ghost_pad_setcaps_default (pad, caps);
 
-  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT ": %d", caps,
-      ret);
+  GST_DEBUG_OBJECT (self, "Setting sink caps %" GST_PTR_FORMAT, caps);
 
-  gst_object_unref (self);
-
-  return ret;
+  return TRUE;
 }
 
 static GstCaps *
-gst_play_sink_convert_bin_getcaps (GstPad * pad)
+gst_play_sink_convert_bin_getcaps (GstPad * pad, GstCaps * filter)
 {
   GstPlaySinkConvertBin *self =
       GST_PLAY_SINK_CONVERT_BIN (gst_pad_get_parent (pad));
@@ -375,7 +383,7 @@ gst_play_sink_convert_bin_getcaps (GstPad * pad)
   if (otherpad) {
     peer = gst_pad_get_peer (otherpad);
     if (peer) {
-      GstCaps *peer_caps = gst_pad_get_caps_reffed (peer);
+      GstCaps *peer_caps = gst_pad_query_caps (peer, filter);
       gst_object_unref (peer);
       if (self->converter_caps) {
         peer_caps = gst_caps_make_writable (peer_caps);
@@ -397,6 +405,31 @@ gst_play_sink_convert_bin_getcaps (GstPad * pad)
   return ret;
 }
 
+static gboolean
+gst_play_sink_convert_bin_query (GstPad * pad, GstObject * parent,
+    GstQuery * query)
+{
+  gboolean res = FALSE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter, *caps;
+
+      gst_query_parse_caps (query, &filter);
+      caps = gst_play_sink_convert_bin_getcaps (pad, filter);
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      res = TRUE;
+      break;
+    }
+    default:
+      res = gst_pad_query_default (pad, parent, query);
+      break;
+  }
+  return res;
+}
+
 void
 gst_play_sink_convert_bin_remove_elements (GstPlaySinkConvertBin * self)
 {
@@ -456,7 +489,7 @@ gst_play_sink_convert_bin_cache_converter_caps (GstPlaySinkConvertBin * self)
     return;
   }
 
-  self->converter_caps = gst_pad_get_caps_reffed (pad);
+  self->converter_caps = gst_pad_query_caps (pad, NULL);
   GST_INFO_OBJECT (self, "Converter caps: %" GST_PTR_FORMAT,
       self->converter_caps);
 
@@ -473,10 +506,7 @@ gst_play_sink_convert_bin_change_state (GstElement * element,
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
-      if (gst_pad_is_blocked (self->sink_proxypad))
-        gst_pad_set_blocked_async_full (self->sink_proxypad, FALSE,
-            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
-            (GDestroyNotify) gst_object_unref);
+      unblock_proxypad (self);
       GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
@@ -504,10 +534,7 @@ gst_play_sink_convert_bin_change_state (GstElement * element,
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
-      if (!gst_pad_is_blocked (self->sink_proxypad))
-        gst_pad_set_blocked_async_full (self->sink_proxypad, TRUE,
-            (GstPadBlockCallback) pad_blocked_cb, gst_object_ref (self),
-            (GDestroyNotify) gst_object_unref);
+      unblock_proxypad (self);
       GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
       break;
     default:
@@ -557,10 +584,8 @@ gst_play_sink_convert_bin_init (GstPlaySinkConvertBin * self)
   self->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", templ);
   gst_pad_set_event_function (self->sinkpad,
       GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_sink_event));
-  gst_pad_set_setcaps_function (self->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_sink_setcaps));
-  gst_pad_set_getcaps_function (self->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps));
+  gst_pad_set_query_function (self->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query));
 
   self->sink_proxypad =
       GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD (self->sinkpad)));
@@ -570,8 +595,8 @@ gst_play_sink_convert_bin_init (GstPlaySinkConvertBin * self)
 
   templ = gst_static_pad_template_get (&srctemplate);
   self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ);
-  gst_pad_set_getcaps_function (self->srcpad,
-      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps));
+  gst_pad_set_query_function (self->srcpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_query));
   gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad);
   gst_object_unref (templ);