/**
* SECTION:element-input-selector
+ * @title: input-selector
* @see_also: #GstOutputSelector
*
* Direct one out of N input streams to the output pad.
* The input pads are from a GstPad subclass and have additional
* properties, which users may find useful, namely:
*
- * <itemizedlist>
- * <listitem>
- * "running-time": Running time of stream on pad (#gint64)
- * </listitem>
- * <listitem>
- * "tags": The currently active tags on the pad (#GstTagList, boxed type)
- * </listitem>
- * <listitem>
- * "active": If the pad is currently active (#gboolean)
- * </listitem>
- * <listitem>
- * "always-ok" : Make an inactive pads return #GST_FLOW_OK instead of
+ * * "running-time": Running time of stream on pad (#gint64)
+ * * "tags": The currently active tags on the pad (#GstTagList, boxed type)
+ * * "active": If the pad is currently active (#gboolean)
+ * * "always-ok" : Make an inactive pads return #GST_FLOW_OK instead of
* #GST_FLOW_NOT_LINKED
- * </listitem>
- * </itemizedlist>
+ *
*/
#ifdef HAVE_CONFIG_H
GstPad parent;
gboolean pushed; /* when buffer was pushed downstream since activation */
+ guint group_id; /* Group ID from the last stream-start */
+ gboolean group_done; /* when Stream Group Done has been
+ received */
gboolean eos; /* when EOS has been received */
gboolean eos_sent; /* when EOS was sent downstream */
gboolean discont; /* after switching we create a discont */
{
GST_OBJECT_LOCK (pad);
pad->pushed = FALSE;
+ pad->group_done = FALSE;
pad->eos = FALSE;
pad->eos_sent = FALSE;
pad->events_pending = FALSE;
if (selpad->segment.format != GST_FORMAT_TIME) {
GST_DEBUG_OBJECT (selpad, "Buffer %p with segment not in time format, "
"not caching", buffer);
+ gst_buffer_unref (buffer);
return;
}
gst_pad_push_event (self->srcpad, gst_event_ref (eos_event));
GST_INPUT_SELECTOR_LOCK (self);
+ /* Wake up other pads so they can continue when syncing to
+ * running time, as this pad just switched to EOS and
+ * may enable others to progress */
+ GST_INPUT_SELECTOR_BROADCAST (self);
pad->eos_sent = TRUE;
} else {
/* we can be unlocked here when we are shutting down (flushing) or when we
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_STREAM_START:{
- guint group_id;
-
- if (!gst_event_parse_group_id (event, &group_id))
+ if (!gst_event_parse_group_id (event, &selpad->group_id)) {
sel->have_group_id = FALSE;
+ selpad->group_id = 0;
+ }
break;
}
case GST_EVENT_FLUSH_START:
/* Unblock the pad if it's waiting */
selpad->flushing = TRUE;
sel->eos = FALSE;
+ selpad->group_done = FALSE;
GST_INPUT_SELECTOR_BROADCAST (sel);
break;
case GST_EVENT_FLUSH_STOP:
}
break;
+ case GST_EVENT_STREAM_GROUP_DONE:{
+ GST_DEBUG_OBJECT (sel, "Stream group-done in inputselector pad %s",
+ GST_OBJECT_NAME (selpad));
+ gst_event_parse_stream_group_done (event, &selpad->group_id);
+ selpad->group_done = TRUE;
+ if (sel->sync_streams && active_sinkpad == pad)
+ GST_INPUT_SELECTOR_BROADCAST (sel);
+ break;
+ }
default:
break;
}
GST_INPUT_SELECTOR_UNLOCK (sel);
if (new_tags)
g_object_notify (G_OBJECT (selpad), "tags");
- if (event) {
- if (forward) {
- GST_DEBUG_OBJECT (pad, "forwarding event");
- res = gst_pad_push_event (sel->srcpad, event);
- } else {
- /* If we aren't forwarding the event because the pad is not the
- * active_sinkpad, then set the flag on the pad
- * that says a segment needs sending if/when that pad is activated.
- * For all other cases, we send the event immediately, which makes
- * sparse streams and other segment updates work correctly downstream.
- */
- if (GST_EVENT_IS_STICKY (event))
- selpad->events_pending = TRUE;
- gst_event_unref (event);
- }
+ if (forward) {
+ GST_DEBUG_OBJECT (pad, "forwarding event");
+ res = gst_pad_push_event (sel->srcpad, event);
+ } else {
+ /* If we aren't forwarding the event because the pad is not the
+ * active_sinkpad, then set the flag on the pad
+ * that says a segment needs sending if/when that pad is activated.
+ * For all other cases, we send the event immediately, which makes
+ * sparse streams and other segment updates work correctly downstream.
+ */
+ if (GST_EVENT_IS_STICKY (event))
+ selpad->events_pending = TRUE;
+ gst_event_unref (event);
}
return res;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
- /* always proxy caps query, regardless of active pad or not */
+ case GST_QUERY_POSITION:
+ case GST_QUERY_DURATION:
+ /* always proxy caps/position/duration query, regardless of active pad or not
+ * See https://bugzilla.gnome.org/show_bug.cgi?id=775445 */
res = gst_pad_peer_query (self->srcpad, query);
break;
case GST_QUERY_ALLOCATION:{
GST_FORMAT_TIME, active_seg->position);
}
+ /* Don't wait if the group is finished on the active pad,
+ * as the running time won't progress now */
+ if (selpad != active_selpad && active_selpad->group_done &&
+ selpad->group_id == active_selpad->group_id) {
+ GST_DEBUG_OBJECT (selpad, "Active pad received group-done. Unblocking");
+ GST_INPUT_SELECTOR_UNLOCK (sel);
+ break;
+ }
+
if (selpad != active_selpad && !sel->eos && !sel->flushing
&& !selpad->flushing && (cur_running_time == GST_CLOCK_TIME_NONE
|| running_time >= cur_running_time)) {
"Julien Moutte <julien@moutte.net>, "
"Jan Schmidt <thaytan@mad.scientist.com>, "
"Wim Taymans <wim.taymans@gmail.com>");
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_input_selector_sink_factory));
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&gst_input_selector_src_factory));
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &gst_input_selector_sink_factory);
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &gst_input_selector_src_factory);
gstelement_class->request_new_pad = gst_input_selector_request_new_pad;
gstelement_class->release_pad = gst_input_selector_release_pad;