decodebin3/urisourcebin: Switch to actual EOS events internally

Use the intended sequence for re-using elements:
* EOS
* STREAM_START if element is to be re-used

This avoids having elements (such as queue/multiqueue/queue2) not
properly resetting themselves.

When delaying EOS propagation (because we want to wait until all
streams of a group are done for example), we re-trigger them by
first sending the cached STREAM_START and then EOS (which will
cause elements to re-set themselves if needed and accept new
buffers/events).

https://bugzilla.gnome.org/show_bug.cgi?id=785951
This commit is contained in:
Edward Hervey 2017-08-09 16:23:03 +02:00 committed by Sebastian Dröge
parent 94d2e4c223
commit ce65017d03
3 changed files with 60 additions and 44 deletions

View file

@ -268,8 +268,11 @@ parse_chain_output_probe (GstPad * pad, GstPadProbeInfo * info,
GST_DEBUG_OBJECT (pad,
"Got EOS end of input stream, post custom-eos");
s = gst_structure_new_empty ("decodebin3-custom-eos");
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
event = gst_event_new_eos ();
gst_event_set_seqnum (event, gst_event_get_seqnum (ev));
s = gst_event_writable_structure (event);
gst_structure_set (s, "decodebin3-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
gst_pad_send_event (peer, event);
gst_object_unref (peer);
} else {

View file

@ -1506,7 +1506,7 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
continue;
if (slot->is_drained) {
GST_DEBUG_OBJECT (slot->sink_pad, "slot %p is draned", slot);
GST_LOG_OBJECT (slot->sink_pad, "slot %p is drained", slot);
continue;
}
@ -1538,11 +1538,17 @@ check_all_slot_for_eos (GstDecodebin3 * dbin)
DecodebinInputStream *input = (DecodebinInputStream *) iter->data;
GstPad *peer = gst_pad_get_peer (input->srcpad);
/* Send EOS and then remove elements */
/* Send EOS to all slots */
if (peer) {
GstEvent *stream_start =
gst_pad_get_sticky_event (input->srcpad, GST_EVENT_STREAM_START, 0);
/* First forward the STREAM_START event to reset the EOS status (if any) */
if (stream_start)
gst_pad_send_event (peer, stream_start);
gst_pad_send_event (peer, gst_event_new_eos ());
gst_object_unref (peer);
}
} else
GST_DEBUG_OBJECT (dbin, "no output");
}
}
}
@ -1627,10 +1633,36 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
}
break;
case GST_EVENT_EOS:
/* FIXME : Figure out */
{
const GstStructure *s = gst_event_get_structure (ev);
slot->is_drained = TRUE;
/* Custom EOS handling first */
if (s && gst_structure_has_field (s, "decodebin3-custom-eos")) {
ret = GST_PAD_PROBE_DROP;
SELECTION_LOCK (dbin);
if (slot->input == NULL) {
GST_DEBUG_OBJECT (pad,
"Got custom-eos from null input stream, remove output stream");
/* Remove the output */
if (slot->output) {
DecodebinOutputStream *output = slot->output;
dbin->output_streams =
g_list_remove (dbin->output_streams, output);
free_output_stream (dbin, output);
}
slot->probe_id = 0;
dbin->slots = g_list_remove (dbin->slots, slot);
free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE;
} else {
check_all_slot_for_eos (dbin);
}
SELECTION_UNLOCK (dbin);
break;
}
GST_FIXME_OBJECT (pad, "EOS on multiqueue source pad. input:%p",
slot->input);
slot->is_drained = TRUE;
if (slot->input == NULL) {
GstPad *peer;
GST_DEBUG_OBJECT (pad,
@ -1657,32 +1689,13 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE;
}
break;
case GST_EVENT_CUSTOM_DOWNSTREAM:
if (gst_event_has_name (ev, "decodebin3-custom-eos")) {
slot->is_drained = TRUE;
ret = GST_PAD_PROBE_DROP;
} else {
GST_DEBUG_OBJECT (pad, "What happens with event ?");
SELECTION_LOCK (dbin);
if (slot->input == NULL) {
GST_DEBUG_OBJECT (pad,
"Got custom-eos from null input stream, remove output stream");
/* Remove the output */
if (slot->output) {
DecodebinOutputStream *output = slot->output;
dbin->output_streams =
g_list_remove (dbin->output_streams, output);
free_output_stream (dbin, output);
}
slot->probe_id = 0;
dbin->slots = g_list_remove (dbin->slots, slot);
free_multiqueue_slot_async (dbin, slot);
ret = GST_PAD_PROBE_REMOVE;
} else {
check_all_slot_for_eos (dbin);
}
check_all_slot_for_eos (dbin);
SELECTION_UNLOCK (dbin);
}
}
break;
default:
break;

View file

@ -1109,19 +1109,15 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
switch (GST_EVENT_TYPE (ev)) {
case GST_EVENT_EOS:
{
GstEvent *event;
GstStructure *s;
guint32 seqnum = gst_event_get_seqnum (ev);
GST_LOG_OBJECT (urisrc, "EOS on pad %" GST_PTR_FORMAT, pad);
/* never forward actual EOS to slot */
ret = GST_PAD_PROBE_DROP;
if ((urisrc->pending_pads &&
link_pending_pad_to_output (urisrc, child_info->output_slot))) {
/* Found a new source pad to give this slot data - no need to send EOS */
GST_URI_SOURCE_BIN_UNLOCK (urisrc);
ret = GST_PAD_PROBE_DROP;
goto done;
}
@ -1134,11 +1130,12 @@ demux_pad_events (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
remove_buffering_msgs (urisrc,
GST_OBJECT_CAST (child_info->output_slot->queue));
/* Actually feed a custom EOS event to avoid marking pads as EOSed */
s = gst_structure_new_empty ("urisourcebin-custom-eos");
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
gst_event_set_seqnum (event, seqnum);
gst_pad_send_event (child_info->output_slot->sinkpad, event);
/* Mark this custom EOS */
ev = gst_event_make_writable (ev);
GST_PAD_PROBE_INFO_DATA (info) = ev;
s = gst_event_writable_structure (ev);
gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
}
break;
case GST_EVENT_CAPS:
@ -1301,8 +1298,9 @@ source_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
GST_LOG_OBJECT (pad, "%s, urisrc %p", GST_EVENT_TYPE_NAME (event), event);
if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM &&
gst_event_has_name (event, "urisourcebin-custom-eos")) {
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS && gst_event_get_structure (event)
&& gst_structure_has_field (gst_event_get_structure (event),
"urisourcebin-custom-eos")) {
OutputSlotInfo *slot;
GST_DEBUG_OBJECT (pad, "we received EOS");
@ -1442,8 +1440,10 @@ pad_removed_cb (GstElement * element, GstPad * pad, GstURISourceBin * urisrc)
GST_LOG_OBJECT (element,
"Pad %" GST_PTR_FORMAT " was removed without EOS. Sending.", pad);
s = gst_structure_new_empty ("urisourcebin-custom-eos");
event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
event = gst_event_new_eos ();
s = gst_event_writable_structure (event);
gst_structure_set (s, "urisourcebin-custom-eos", G_TYPE_BOOLEAN, TRUE,
NULL);
gst_pad_send_event (slot->sinkpad, event);
} else {
GST_LOG_OBJECT (urisrc, "Removed pad has no output slot");