Commit eaefb24d authored by HoonHee Lee's avatar HoonHee Lee

decodebin3: add a fallback function when seeking with flushing

When try to flush seek to playbin3 pipeline, source and multiqueue pre is
working in upstream changes and auto plugggig of parsebin maybe on progress.

Sometimes seek event can't be delivered to source part(e.g. urisourcebin)
because one of pads of parsebin is not linked yet during auto plugging.

And flush-start/stop event can't be traveled to decoder to sink elements by
pad not linked.

To avoid this symptom, intercept seek event and push directly source part
and force to push flush-start/stop from multiqueue to sink.
parent 5b5fd903
Pipeline #27318 passed with stages
in 71 minutes and 50 seconds
......@@ -353,6 +353,9 @@ struct _DecodebinOutputStream
/* keyframe dropping probe */
gulong drop_probe_id;
gboolean got_flush_start;
gboolean got_flush_stop;
};
/* Pending pads from parsebin */
......@@ -2650,6 +2653,166 @@ handle_stream_switch (GstDecodebin3 * dbin, GList * select_streams,
return ret;
}
static void
check_all_output_for_flush (GstDecodebin3 * dbin)
{
GList *tmp;
for (tmp = dbin->output_streams; tmp; tmp = tmp->next) {
DecodebinOutputStream *output = (DecodebinOutputStream *) tmp->data;
MultiQueueSlot *slot;
GstEvent *flush_event;
GstPad *sinkpad;
GstPad *peer;
slot = output->slot;
sinkpad = slot->sink_pad;
peer = gst_pad_get_peer (output->src_pad);
GST_DEBUG_OBJECT (output->src_pad, "peerpad(%s:%s)",
GST_DEBUG_PAD_NAME (peer));
if (!output->got_flush_start) {
flush_event = gst_event_new_flush_start ();
GST_DEBUG_OBJECT (sinkpad, "Sending: %" GST_PTR_FORMAT, flush_event);
gst_pad_send_event (sinkpad, flush_event);
if (!GST_PAD_IS_FLUSHING (peer)) {
flush_event = gst_event_new_flush_start ();
GST_DEBUG_OBJECT (peer, "Forced to pushing: %" GST_PTR_FORMAT,
flush_event);
gst_pad_send_event (peer, flush_event);
}
output->got_flush_start = FALSE;
}
if (!output->got_flush_stop) {
flush_event = gst_event_new_flush_stop (TRUE);
GST_DEBUG_OBJECT (sinkpad, "Sending: %" GST_PTR_FORMAT, flush_event);
gst_pad_send_event (sinkpad, flush_event);
if (GST_PAD_IS_FLUSHING (peer)) {
flush_event = gst_event_new_flush_stop (TRUE);
GST_DEBUG_OBJECT (peer, "Forced to pushing: %" GST_PTR_FORMAT,
flush_event);
gst_pad_send_event (peer, flush_event);
}
}
output->got_flush_stop = FALSE;
gst_object_unref (peer);
}
}
static void
mark_all_output_flush (GstDecodebin3 * dbin, gboolean mark)
{
GList *tmp;
for (tmp = dbin->output_streams; tmp; tmp = tmp->next) {
DecodebinOutputStream *output = (DecodebinOutputStream *) tmp->data;
output->got_flush_start = mark;
output->got_flush_stop = mark;
}
}
static gboolean
output_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstDecodebin3 *dbin = (GstDecodebin3 *) parent;
DecodebinOutputStream *output;
GList *tmp;
gboolean ret = TRUE;
for (tmp = dbin->output_streams; tmp; tmp = tmp->next) {
DecodebinOutputStream *out = (DecodebinOutputStream *) tmp->data;
if (out->src_pad == pad) {
output = out;
break;
}
}
GST_LOG_OBJECT (pad, "Got event %p %s", event, GST_EVENT_TYPE_NAME (event));
if (!output)
goto no_output;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
{
GstEvent *copy;
DecodebinInput *input = dbin->main_input;
GST_DEBUG_OBJECT (pad, "Seeing Seek:%" GST_PTR_FORMAT, event);
copy = gst_event_copy (event);
mark_all_output_flush (dbin, FALSE);
GST_DEBUG_OBJECT (pad, "Pushing Seek event: %p", event);
ret = gst_pad_event_default (pad, parent, event);
GST_DEBUG_OBJECT (pad, "Pushed Seek event: ret: %d", ret);
if (ret) {
gst_event_unref (copy);
check_all_output_for_flush (dbin);
} else {
GST_DEBUG_OBJECT (pad, "Seek failure. try again to(%s:%s): %p",
GST_DEBUG_PAD_NAME (input->parsebin_sink), copy);
if ((ret = gst_pad_push_event (input->parsebin_sink, copy)) == FALSE)
GST_DEBUG_OBJECT (pad, "Seek Failed to pad(%s:%s)",
GST_DEBUG_PAD_NAME (input->parsebin_sink));
else {
GST_DEBUG_OBJECT (pad, "Seek success to pad(%s:%s)",
GST_DEBUG_PAD_NAME (input->parsebin_sink));
check_all_output_for_flush (dbin);
}
}
return ret;
}
break;
default:
break;
}
forward:
GST_DEBUG_OBJECT (pad, "Pushing event: %" GST_PTR_FORMAT, event);
ret = gst_pad_event_default (pad, parent, event);
GST_DEBUG_OBJECT (pad, "Pushed event: %d", ret);
return ret;
no_output:
GST_DEBUG_OBJECT (pad, "No corresponding output");
goto forward;
}
static GstPadProbeReturn
output_srcpad_flush_probe (GstPad * pad, GstPadProbeInfo * info,
DecodebinOutputStream * output)
{
GstPadProbeReturn ret = GST_PAD_PROBE_OK;
GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
{
GST_DEBUG_OBJECT (pad, "Got FLUSH-START: %" GST_PTR_FORMAT, event);
output->got_flush_start = TRUE;
}
break;
case GST_EVENT_FLUSH_STOP:
{
GST_DEBUG_OBJECT (pad, "Got FLUSH-STOP: %" GST_PTR_FORMAT, event);
output->got_flush_stop = TRUE;
}
break;
default:
break;
}
return ret;
}
static GstPadProbeReturn
ghost_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
DecodebinOutputStream * output)
......@@ -2831,6 +2994,9 @@ create_output_stream (GstDecodebin3 * dbin, GstStreamType type)
(GstPad *) gst_proxy_pad_get_internal ((GstProxyPad *) res->src_pad);
gst_pad_add_probe (internal_pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
(GstPadProbeCallback) ghost_pad_event_probe, res, NULL);
gst_pad_add_probe (res->src_pad, GST_PAD_PROBE_TYPE_EVENT_FLUSH,
(GstPadProbeCallback) output_srcpad_flush_probe, res, NULL);
gst_pad_set_event_function (res->src_pad, output_srcpad_event);
gst_object_unref (internal_pad);
dbin->output_streams = g_list_append (dbin->output_streams, res);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment