decodebin3: Remove FIXME and do remove_input_stream() only for the corresponding...
[platform/upstream/gst-plugins-base.git] / gst / playback / gstdecodebin3-parse.c
1 /* GStreamer
2  *
3  * Copyright (C) <2015> Centricular Ltd
4  *  @author: Edward Hervey <edward@centricular.com>
5  *  @author: Jan Schmidt <jan@centricular.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #if 0
24 /* Not needed for now - we're including gstdecodebin3-parse.c into gstdecodebin3.c */
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <glib.h>
30 #include <glib-object.h>
31 #include <glib/gprintf.h>
32 #include <gst/gst.h>
33 #include <gst/pbutils/pbutils.h>
34
35 #include "gstplayback.h"
36 #endif
37
38 /* Streams that come from demuxers (input/upstream) */
39 /* FIXME : All this is hardcoded. Switch to tree of chains */
40 struct _DecodebinInputStream
41 {
42   GstDecodebin3 *dbin;
43   GstStream *pending_stream;    /* Extra ref */
44   GstStream *active_stream;
45
46   DecodebinInput *input;
47
48   GstPad *srcpad;               /* From demuxer */
49
50   /* id of the pad event probe */
51   gulong output_event_probe_id;
52
53   /* id of the buffer blocking probe on the input (demuxer src) pad */
54   gulong input_buffer_probe_id;
55
56   /* Whether we saw an EOS on input. This should be treated accordingly
57    * when the stream is no longer used */
58   gboolean saw_eos;
59 };
60
61 static void parsebin_pad_added_cb (GstElement * demux, GstPad * pad,
62     DecodebinInput * input);
63 static void parsebin_pad_removed_cb (GstElement * demux, GstPad * pad,
64     DecodebinInput * input);
65
66 /* WITH SELECTION_LOCK TAKEN! */
67 static gboolean
68 pending_pads_are_eos (DecodebinInput * input)
69 {
70   GList *tmp;
71
72   for (tmp = input->pending_pads; tmp; tmp = tmp->next) {
73     PendingPad *ppad = (PendingPad *) tmp->data;
74     if (ppad->saw_eos == FALSE)
75       return FALSE;
76   }
77
78   return TRUE;
79 }
80
81 /* WITH SELECTION_LOCK TAKEN! */
82 static gboolean
83 all_inputs_are_eos (GstDecodebin3 * dbin)
84 {
85   GList *tmp;
86   /* First check input streams */
87   for (tmp = dbin->input_streams; tmp; tmp = tmp->next) {
88     DecodebinInputStream *input = (DecodebinInputStream *) tmp->data;
89     if (input->saw_eos == FALSE)
90       return FALSE;
91   }
92
93   /* Check pending pads */
94   if (!pending_pads_are_eos (dbin->main_input))
95     return FALSE;
96   for (tmp = dbin->other_inputs; tmp; tmp = tmp->next)
97     if (!pending_pads_are_eos ((DecodebinInput *) tmp->data))
98       return FALSE;
99
100   GST_DEBUG_OBJECT (dbin, "All streams are EOS");
101   return TRUE;
102 }
103
104 /* WITH SELECTION_LOCK TAKEN! */
105 static void
106 check_all_streams_for_eos (GstDecodebin3 * dbin)
107 {
108   GList *tmp;
109
110   if (!all_inputs_are_eos (dbin))
111     return;
112
113   /* We know all streams are EOS, properly clean up everything */
114   for (tmp = dbin->input_streams; tmp; tmp = tmp->next) {
115     DecodebinInputStream *input = (DecodebinInputStream *) tmp->data;
116     GstPad *peer = gst_pad_get_peer (input->srcpad);
117
118     /* Send EOS and then remove elements */
119     if (peer) {
120       gst_pad_send_event (peer, gst_event_new_eos ());
121       gst_object_unref (peer);
122     }
123     GST_FIXME_OBJECT (input->srcpad, "Remove input stream");
124   }
125 }
126
127 /* Get the intersection of parser caps and available (sorted) decoders */
128 static GstCaps *
129 get_parser_caps_filter (GstDecodebin3 * dbin, GstCaps * caps)
130 {
131   GList *tmp;
132   GstCaps *filter_caps = gst_caps_new_empty ();
133
134   g_mutex_lock (&dbin->factories_lock);
135   gst_decode_bin_update_factories_list (dbin);
136   for (tmp = dbin->decoder_factories; tmp; tmp = tmp->next) {
137     GstElementFactory *factory = (GstElementFactory *) tmp->data;
138     GstCaps *tcaps, *intersection;
139     const GList *tmps;
140
141     GST_LOG ("Trying factory %s",
142         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
143     for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
144         tmps = tmps->next) {
145       GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
146       if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
147         continue;
148       tcaps = gst_static_pad_template_get_caps (st);
149       intersection =
150           gst_caps_intersect_full (tcaps, caps, GST_CAPS_INTERSECT_FIRST);
151       filter_caps = gst_caps_merge (filter_caps, intersection);
152       gst_caps_unref (tcaps);
153     }
154   }
155   g_mutex_unlock (&dbin->factories_lock);
156   GST_DEBUG_OBJECT (dbin, "Got filter caps %" GST_PTR_FORMAT, filter_caps);
157   return filter_caps;
158 }
159
160 static gboolean
161 check_parser_caps_filter (GstDecodebin3 * dbin, GstCaps * caps)
162 {
163   GList *tmp;
164   gboolean res = FALSE;
165
166   g_mutex_lock (&dbin->factories_lock);
167   gst_decode_bin_update_factories_list (dbin);
168   for (tmp = dbin->decoder_factories; tmp; tmp = tmp->next) {
169     GstElementFactory *factory = (GstElementFactory *) tmp->data;
170     GstCaps *tcaps;
171     const GList *tmps;
172
173     GST_LOG ("Trying factory %s",
174         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
175     for (tmps = gst_element_factory_get_static_pad_templates (factory); tmps;
176         tmps = tmps->next) {
177       GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
178       if (st->direction != GST_PAD_SINK || st->presence != GST_PAD_ALWAYS)
179         continue;
180       tcaps = gst_static_pad_template_get_caps (st);
181       if (gst_caps_can_intersect (tcaps, caps)) {
182         res = TRUE;
183         gst_caps_unref (tcaps);
184         goto beach;
185       }
186       gst_caps_unref (tcaps);
187     }
188   }
189 beach:
190   g_mutex_unlock (&dbin->factories_lock);
191   GST_DEBUG_OBJECT (dbin, "Can intersect : %d", res);
192   return res;
193 }
194
195 /* Probe on the output of a parser chain (the last
196  * src pad) */
197 static GstPadProbeReturn
198 parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info,
199     DecodebinInputStream * input)
200 {
201   GstPadProbeReturn ret = GST_PAD_PROBE_OK;
202
203   if (GST_IS_EVENT (GST_PAD_PROBE_INFO_DATA (info))) {
204     GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info);
205
206     GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (ev));
207     switch (GST_EVENT_TYPE (ev)) {
208       case GST_EVENT_STREAM_START:
209       {
210         GstStream *stream = NULL;
211         guint group_id = G_MAXUINT32;
212
213         if (!gst_event_parse_group_id (ev, &group_id)) {
214           GST_FIXME_OBJECT (pad,
215               "Consider implementing group-id handling on stream-start event");
216           group_id = gst_util_group_id_next ();
217         }
218
219         GST_DEBUG_OBJECT (pad, "Got stream-start, group_id:%d, input %p",
220             group_id, input->input);
221         if (set_input_group_id (input->input, &group_id)) {
222           ev = gst_event_make_writable (ev);
223           gst_event_set_group_id (ev, group_id);
224           GST_PAD_PROBE_INFO_DATA (info) = ev;
225         }
226         input->saw_eos = FALSE;
227
228         gst_event_parse_stream (ev, &stream);
229         /* FIXME : Would we ever end up with a stream already set on the input ?? */
230         if (stream) {
231           if (input->active_stream != stream) {
232             MultiQueueSlot *slot;
233             if (input->active_stream)
234               gst_object_unref (input->active_stream);
235             input->active_stream = stream;
236             /* We have the beginning of a stream, get a multiqueue slot and link to it */
237             SELECTION_LOCK (input->dbin);
238             slot = get_slot_for_input (input->dbin, input);
239             link_input_to_slot (input, slot);
240             SELECTION_UNLOCK (input->dbin);
241           } else
242             gst_object_unref (stream);
243         }
244       }
245         break;
246       case GST_EVENT_CAPS:
247       {
248         GstCaps *caps = NULL;
249         gst_event_parse_caps (ev, &caps);
250         GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps);
251         if (caps && input->active_stream)
252           gst_stream_set_caps (input->active_stream, caps);
253       }
254         break;
255       case GST_EVENT_EOS:
256         input->saw_eos = TRUE;
257         if (all_inputs_are_eos (input->dbin)) {
258           GST_DEBUG_OBJECT (pad, "real input pad, marking as EOS");
259           SELECTION_LOCK (input->dbin);
260           check_all_streams_for_eos (input->dbin);
261           SELECTION_UNLOCK (input->dbin);
262         } else {
263           GstPad *peer = gst_pad_get_peer (input->srcpad);
264           if (peer) {
265             /* Send custom-eos event to multiqueue slot */
266             GstStructure *s;
267             GstEvent *event;
268
269             GST_DEBUG_OBJECT (pad,
270                 "Got EOS end of input stream, post custom-eos");
271             s = gst_structure_new_empty ("decodebin3-custom-eos");
272             event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
273             gst_pad_send_event (peer, event);
274             gst_object_unref (peer);
275           } else {
276             GST_FIXME_OBJECT (pad, "No peer, what should we do ?");
277           }
278         }
279         ret = GST_PAD_PROBE_DROP;
280         break;
281       case GST_EVENT_FLUSH_STOP:
282         GST_DEBUG_OBJECT (pad, "Clear saw_eos flag");
283         input->saw_eos = FALSE;
284       default:
285         break;
286     }
287   } else if (GST_IS_QUERY (GST_PAD_PROBE_INFO_DATA (info))) {
288     GstQuery *q = GST_PAD_PROBE_INFO_QUERY (info);
289     GST_DEBUG_OBJECT (pad, "Seeing query %s", GST_QUERY_TYPE_NAME (q));
290     /* If we have a parser, we want to reply to the caps query */
291     /* FIXME: Set a flag when the input stream is created for
292      * streams where we shouldn't reply to these queries */
293     if (GST_QUERY_TYPE (q) == GST_QUERY_CAPS
294         && (info->type & GST_PAD_PROBE_TYPE_PULL)) {
295       GstCaps *filter = NULL;
296       GstCaps *allowed;
297       gst_query_parse_caps (q, &filter);
298       allowed = get_parser_caps_filter (input->dbin, filter);
299       GST_DEBUG_OBJECT (pad,
300           "Intercepting caps query, setting %" GST_PTR_FORMAT, allowed);
301       gst_query_set_caps_result (q, allowed);
302       gst_caps_unref (allowed);
303       ret = GST_PAD_PROBE_HANDLED;
304     } else if (GST_QUERY_TYPE (q) == GST_QUERY_ACCEPT_CAPS) {
305       GstCaps *prop = NULL;
306       gst_query_parse_accept_caps (q, &prop);
307       /* Fast check against target caps */
308       if (gst_caps_can_intersect (prop, input->dbin->caps))
309         gst_query_set_accept_caps_result (q, TRUE);
310       else {
311         gboolean accepted = check_parser_caps_filter (input->dbin, prop);
312         /* check against caps filter */
313         gst_query_set_accept_caps_result (q, accepted);
314         GST_DEBUG_OBJECT (pad, "ACCEPT_CAPS query, returning %d", accepted);
315       }
316       ret = GST_PAD_PROBE_HANDLED;
317     }
318   }
319
320   return ret;
321 }
322
323 static DecodebinInputStream *
324 create_input_stream (GstDecodebin3 * dbin, GstStream * stream, GstPad * pad,
325     DecodebinInput * input)
326 {
327   DecodebinInputStream *res = g_new0 (DecodebinInputStream, 1);
328
329   GST_DEBUG_OBJECT (pad, "Creating input stream for stream %p %s (input:%p)",
330       stream, gst_stream_get_stream_id (stream), input);
331
332   res->dbin = dbin;
333   res->input = input;
334   res->pending_stream = gst_object_ref (stream);
335   res->srcpad = pad;
336
337   /* Put probe on output source pad (for detecting EOS/STREAM_START/FLUSH) */
338   res->output_event_probe_id =
339       gst_pad_add_probe (pad,
340       GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM
341       | GST_PAD_PROBE_TYPE_EVENT_FLUSH,
342       (GstPadProbeCallback) parse_chain_output_probe, res, NULL);
343
344   /* Add to list of current input streams */
345   SELECTION_LOCK (dbin);
346   dbin->input_streams = g_list_append (dbin->input_streams, res);
347   SELECTION_UNLOCK (dbin);
348   GST_DEBUG_OBJECT (pad, "Done creating input stream");
349
350   return res;
351 }
352
353 /* WITH SELECTION_LOCK TAKEN! */
354 static void
355 remove_input_stream (GstDecodebin3 * dbin, DecodebinInputStream * stream)
356 {
357   MultiQueueSlot *slot;
358
359   GST_DEBUG_OBJECT (dbin, "Removing input stream %p (%s)", stream,
360       stream->active_stream ? gst_stream_get_stream_id (stream->active_stream) :
361       "<NONE>");
362
363   /* Unlink from slot */
364   if (stream->srcpad) {
365     GstPad *peer;
366     peer = gst_pad_get_peer (stream->srcpad);
367     if (peer) {
368       gst_pad_unlink (stream->srcpad, peer);
369       gst_object_unref (peer);
370     }
371   }
372
373   slot = get_slot_for_input (dbin, stream);
374   if (slot) {
375     slot->pending_stream = NULL;
376     slot->input = NULL;
377     GST_DEBUG_OBJECT (dbin, "slot %p cleared", slot);
378   }
379
380   if (stream->active_stream)
381     gst_object_unref (stream->active_stream);
382   if (stream->pending_stream)
383     gst_object_unref (stream->pending_stream);
384
385   dbin->input_streams = g_list_remove (dbin->input_streams, stream);
386
387   g_free (stream);
388 }
389
390
391 /* FIXME : HACK, REMOVE, USE INPUT CHAINS */
392 static GstPadProbeReturn
393 parsebin_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
394     DecodebinInput * input)
395 {
396   GstDecodebin3 *dbin = input->dbin;
397   GList *tmp, *unused_slot = NULL;
398
399   GST_DEBUG_OBJECT (pad, "Got a buffer ! UNBLOCK !");
400
401   /* Any data out the demuxer means it's not creating pads
402    * any more right now */
403
404   /* 1. Re-use existing streams if/when possible */
405   GST_FIXME_OBJECT (dbin, "Re-use existing input streams if/when possible");
406
407   /* 2. Remove unused streams (push EOS) */
408   GST_DEBUG_OBJECT (dbin, "Removing unused streams");
409   SELECTION_LOCK (dbin);
410   tmp = dbin->input_streams;
411   while (tmp != NULL) {
412     DecodebinInputStream *input_stream = (DecodebinInputStream *) tmp->data;
413     GList *next = tmp->next;
414
415     if (input_stream->input != input) {
416       tmp = next;
417       continue;
418     }
419
420     GST_DEBUG_OBJECT (dbin, "Checking input stream %p", input_stream);
421     if (input_stream->input_buffer_probe_id) {
422       GST_DEBUG_OBJECT (dbin,
423           "Removing pad block on input %p pad %" GST_PTR_FORMAT, input_stream,
424           input_stream->srcpad);
425       gst_pad_remove_probe (input_stream->srcpad,
426           input_stream->input_buffer_probe_id);
427     }
428     input_stream->input_buffer_probe_id = 0;
429
430     if (input_stream->saw_eos) {
431       remove_input_stream (dbin, input_stream);
432       tmp = dbin->input_streams;
433     } else
434       tmp = next;
435   }
436   SELECTION_UNLOCK (dbin);
437
438   GST_DEBUG_OBJECT (dbin, "Creating new streams (if needed)");
439   /* 3. Create new streams */
440   for (tmp = input->pending_pads; tmp; tmp = tmp->next) {
441     GstStream *stream;
442     PendingPad *ppad = (PendingPad *) tmp->data;
443
444     stream = gst_pad_get_stream (ppad->pad);
445     if (stream == NULL) {
446       GST_ERROR_OBJECT (dbin, "No stream for pad ????");
447     } else {
448       MultiQueueSlot *slot;
449       DecodebinInputStream *input_stream;
450       /* The remaining pads in pending_pads are the ones that require a new
451        * input stream */
452       input_stream = create_input_stream (dbin, stream, ppad->pad, ppad->input);
453       /* See if we can link it straight away */
454       input_stream->active_stream = stream;
455
456       SELECTION_LOCK (dbin);
457       slot = get_slot_for_input (dbin, input_stream);
458       link_input_to_slot (input_stream, slot);
459       SELECTION_UNLOCK (dbin);
460
461       /* Remove the buffer and event probe */
462       gst_pad_remove_probe (ppad->pad, ppad->buffer_probe);
463       gst_pad_remove_probe (ppad->pad, ppad->event_probe);
464       g_free (ppad);
465     }
466   }
467
468   g_list_free (input->pending_pads);
469   input->pending_pads = NULL;
470
471   /* Weed out unused multiqueue slots */
472   SELECTION_LOCK (dbin);
473   for (tmp = dbin->slots; tmp; tmp = tmp->next) {
474     MultiQueueSlot *slot = (MultiQueueSlot *) tmp->data;
475     GST_LOG_OBJECT (dbin, "Slot %d input:%p", slot->id, slot->input);
476     if (slot->input == NULL) {
477       unused_slot =
478           g_list_append (unused_slot, gst_object_ref (slot->sink_pad));
479     }
480   }
481   SELECTION_UNLOCK (dbin);
482
483   for (tmp = unused_slot; tmp; tmp = tmp->next) {
484     GstPad *sink_pad = (GstPad *) tmp->data;
485     GST_DEBUG_OBJECT (sink_pad, "Sending EOS to unused slot");
486     gst_pad_send_event (sink_pad, gst_event_new_eos ());
487   }
488
489   if (unused_slot)
490     g_list_free_full (unused_slot, (GDestroyNotify) gst_object_unref);
491
492   return GST_PAD_PROBE_OK;
493 }
494
495 static GstPadProbeReturn
496 parsebin_pending_event_probe (GstPad * pad, GstPadProbeInfo * info,
497     PendingPad * ppad)
498 {
499   GstDecodebin3 *dbin = ppad->dbin;
500   /* We drop all events by default */
501   GstPadProbeReturn ret = GST_PAD_PROBE_DROP;
502   GstEvent *ev = GST_PAD_PROBE_INFO_EVENT (info);
503
504   GST_DEBUG_OBJECT (pad, "Got event %p %s", ev, GST_EVENT_TYPE_NAME (ev));
505   switch (GST_EVENT_TYPE (ev)) {
506     case GST_EVENT_EOS:
507     {
508       GST_DEBUG_OBJECT (pad, "Pending pad marked as EOS, removing");
509       ppad->input->pending_pads =
510           g_list_remove (ppad->input->pending_pads, ppad);
511       gst_pad_remove_probe (ppad->pad, ppad->buffer_probe);
512       gst_pad_remove_probe (ppad->pad, ppad->event_probe);
513       g_free (ppad);
514
515       check_all_streams_for_eos (dbin);
516     }
517       break;
518     default:
519       break;
520   }
521
522   return ret;
523 }
524
525 static void
526 parsebin_pad_added_cb (GstElement * demux, GstPad * pad, DecodebinInput * input)
527 {
528   GstDecodebin3 *dbin = input->dbin;
529   PendingPad *ppad;
530   GList *tmp;
531
532   GST_DEBUG_OBJECT (dbin, "New pad %s:%s (input:%p)", GST_DEBUG_PAD_NAME (pad),
533       input);
534
535   ppad = g_new0 (PendingPad, 1);
536   ppad->dbin = dbin;
537   ppad->input = input;
538   ppad->pad = pad;
539
540   ppad->event_probe =
541       gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
542       (GstPadProbeCallback) parsebin_pending_event_probe, ppad, NULL);
543   ppad->buffer_probe =
544       gst_pad_add_probe (pad,
545       GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER,
546       (GstPadProbeCallback) parsebin_buffer_probe, input, NULL);
547
548   input->pending_pads = g_list_append (input->pending_pads, ppad);
549
550   /* Check if all existing input streams have a buffer probe set */
551   for (tmp = dbin->input_streams; tmp; tmp = tmp->next) {
552     DecodebinInputStream *input_stream = (DecodebinInputStream *) tmp->data;
553     if (input_stream->input == input &&
554         input_stream->input_buffer_probe_id == 0) {
555       GST_DEBUG_OBJECT (input_stream->srcpad, "Adding blocking buffer probe");
556       input_stream->input_buffer_probe_id =
557           gst_pad_add_probe (input_stream->srcpad,
558           GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER,
559           (GstPadProbeCallback) parsebin_buffer_probe, input_stream->input,
560           NULL);
561     }
562   }
563 }
564
565 static void
566 parsebin_pad_removed_cb (GstElement * demux, GstPad * pad, DecodebinInput * inp)
567 {
568   GstDecodebin3 *dbin = inp->dbin;
569   DecodebinInputStream *input = NULL;
570   GList *tmp;
571   GST_DEBUG_OBJECT (pad, "removed");
572
573   for (tmp = dbin->input_streams; tmp; tmp = tmp->next) {
574     DecodebinInputStream *cand = (DecodebinInputStream *) tmp->data;
575     if (cand->srcpad == pad)
576       input = cand;
577   }
578   /* If there are no pending pads, this means we will definitely not need this
579    * stream anymore */
580   if (input) {
581     GST_DEBUG_OBJECT (pad, "stream %p", input);
582     if (inp->pending_pads == NULL) {
583       MultiQueueSlot *slot;
584
585       GST_DEBUG_OBJECT (pad, "Remove input stream %p", input);
586
587       SELECTION_LOCK (dbin);
588       slot = get_slot_for_input (dbin, input);
589
590       remove_input_stream (dbin, input);
591       if (slot && g_list_find (dbin->slots, slot) && slot->is_drained) {
592         /* if slot is still there and already drained, remove it in here */
593         if (slot->output) {
594           DecodebinOutputStream *output = slot->output;
595           GST_DEBUG_OBJECT (pad,
596               "Multiqueue was drained, Remove output stream");
597
598           dbin->output_streams = g_list_remove (dbin->output_streams, output);
599           free_output_stream (dbin, output);
600         }
601         GST_DEBUG_OBJECT (pad, "No pending pad, Remove multiqueue slot");
602         if (slot->probe_id)
603           gst_pad_remove_probe (slot->src_pad, slot->probe_id);
604         slot->probe_id = 0;
605         dbin->slots = g_list_remove (dbin->slots, slot);
606         free_multiqueue_slot_async (dbin, slot);
607       }
608       SELECTION_UNLOCK (dbin);
609     } else {
610       input->srcpad = NULL;
611       if (input->input_buffer_probe_id)
612         gst_pad_remove_probe (pad, input->input_buffer_probe_id);
613       input->input_buffer_probe_id = 0;
614     }
615   }
616 }