Commit 0f5b9aca authored by hoonhee.lee's avatar hoonhee.lee

decodebin3: add a fallback function when upstream changes and flush seek

When we try to flush seek to playbin3 pipeline, multiqueue pre is ongoing
upstream changes with auto-plugging.

In this scenario, below symptoms are observed.
  * Seek event can't be delivered to from multiqueue pre to source part.
    Because a pad of this part is not linked during auto plugging.
  * flush-start/stop event could not be delivered to decoder and sink
    elements by pad not linked.

To avoid this symptom, we try to seek event to parsebin sink and make sure
flush-start and flush-stop are delivered to decoder and sink elements.
parent 779704b8
Pipeline #38635 canceled with stages
in 104 minutes and 15 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,159 @@ handle_stream_switch (GstDecodebin3 * dbin, GList * select_streams,
return ret;
}
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 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);
}
}
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);
}
}
gst_object_unref (peer);
}
}
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:
{
GstFlowReturn flow_ret;
GstEvent *copy;
DecodebinInput *input = dbin->main_input;
GST_DEBUG_OBJECT (pad, "Seeing Seek:%" GST_PTR_FORMAT, event);
GST_DEBUG_OBJECT (pad, "parsebin_sink(%s:%s)",
GST_DEBUG_PAD_NAME (input->parsebin_sink));
copy = gst_event_copy (event);
mark_all_output_flush (dbin, FALSE);
GST_DEBUG_OBJECT (pad, "Pushing Seek event: %p", event);
ret = gst_pad_push_event (input->parsebin_sink, event);
flow_ret = GST_PAD_LAST_FLOW_RETURN (input->parsebin_sink);
GST_DEBUG_OBJECT (pad, "Pushed Seek event: ret: %d, pad_flow_return: %s",
ret, gst_flow_get_name (flow_ret));
if (ret) {
gst_event_unref (copy);
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);
GST_LOG_OBJECT (pad, "Got event %p %s", event, GST_EVENT_TYPE_NAME (event));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
{
GST_DEBUG_OBJECT (pad, "Got FLUSH-START");
output->got_flush_start = TRUE;
}
break;
case GST_EVENT_FLUSH_STOP:
{
GST_DEBUG_OBJECT (pad, "Got FLUSH-STOP");
output->got_flush_stop = TRUE;
}
break;
default:
break;
}
return ret;
}
static GstPadProbeReturn
ghost_pad_event_probe (GstPad * pad, GstPadProbeInfo * info,
DecodebinOutputStream * output)
......@@ -2831,6 +2987,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