tee: First deactivate the pad and then remove it when releasing pads
[platform/upstream/gstreamer.git] / plugins / elements / gsttee.c
index ce5449a..0ff7527 100644 (file)
@@ -460,12 +460,8 @@ gst_tee_release_pad (GstElement * element, GstPad * pad)
   }
   GST_OBJECT_UNLOCK (tee);
 
-  gst_object_ref (pad);
-  gst_element_remove_pad (GST_ELEMENT_CAST (tee), pad);
-
   gst_pad_set_active (pad, FALSE);
-
-  gst_object_unref (pad);
+  gst_element_remove_pad (GST_ELEMENT_CAST (tee), pad);
 
   if (changed) {
     gst_tee_notify_alloc_pad (tee);
@@ -573,6 +569,7 @@ struct AllocQueryCtx
   guint size;
   guint min_buffers;
   gboolean first_query;
+  guint num_pads;
 };
 
 /* This function will aggregate some of the allocation query information with
@@ -623,7 +620,7 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data)
   gst_object_unref (peer_pad);
 
   /* Allocation Params:
-   * store the maximum alignment, prefix and pading, but ignore the
+   * store the maximum alignment, prefix and padding, but ignore the
    * allocators and the flags which are tied to downstream allocation */
   count = gst_query_get_n_allocation_params (query);
   for (i = 0; i < count; i++) {
@@ -715,6 +712,7 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data)
   }
 
   ctx->first_query = FALSE;
+  ctx->num_pads++;
   gst_query_unref (query);
 
   return TRUE;
@@ -758,6 +756,7 @@ gst_tee_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
         gst_allocation_params_init (&ctx.params);
         ctx.size = 0;
         ctx.min_buffers = 0;
+        ctx.num_pads = 0;
         gst_tee_clear_query_allocation_meta (query);
       }
 
@@ -789,9 +788,21 @@ gst_tee_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
         }
 #endif
 
-        gst_query_add_allocation_param (ctx.query, NULL, &ctx.params);
-        gst_query_add_allocation_pool (ctx.query, NULL, ctx.size,
-            ctx.min_buffers, 0);
+        /* Allocate one more buffers when multiplexing so we don't starve the
+         * downstream threads. */
+        if (ctx.num_pads > 1)
+          ctx.min_buffers++;
+
+        /* Check that we actually have parameters besides the defaults. */
+        if (ctx.params.align || ctx.params.prefix || ctx.params.padding) {
+          gst_query_add_allocation_param (ctx.query, NULL, &ctx.params);
+        }
+        /* When size == 0, buffers created from this pool would have no memory
+         * allocated. */
+        if (ctx.size) {
+          gst_query_add_allocation_pool (ctx.query, NULL, ctx.size,
+              ctx.min_buffers, 0);
+        }
       } else {
         gst_tee_clear_query_allocation_meta (query);
       }
@@ -884,12 +895,14 @@ gst_tee_handle_data (GstTee * tee, gpointer data, gboolean is_list)
       ret = gst_pad_push (pad, GST_BUFFER_CAST (data));
     }
 
+    GST_OBJECT_LOCK (tee);
     if (GST_TEE_PAD_CAST (pad)->removed)
       ret = GST_FLOW_NOT_LINKED;
 
     if (ret == GST_FLOW_NOT_LINKED && tee->allow_not_linked) {
       ret = GST_FLOW_OK;
     }
+    GST_OBJECT_UNLOCK (tee);
 
     gst_object_unref (pad);
 
@@ -928,6 +941,8 @@ restart:
 
       GST_OBJECT_LOCK (tee);
       /* keep track of which pad we pushed and the result value */
+      if (GST_TEE_PAD_CAST (pad)->removed)
+        ret = GST_FLOW_NOT_LINKED;
       GST_TEE_PAD_CAST (pad)->pushed = TRUE;
       GST_TEE_PAD_CAST (pad)->result = ret;
       gst_object_unref (pad);