From a82f3418fdc1e7787828f0a2a946b12e6f00332f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 12 Dec 2013 10:50:27 -0300 Subject: [PATCH] qtdemux: drain the adapter before pushing EOS In a fragmented scenario, qtdemux is operating in push mode and it gets a fragmented buffer. While processing its data downstream gets unlinked (or a input-selector changes its active pad and returns not-linked). Qtdemux stops processing this fragment and returns not-linked upstream, leaving the remaining data in its adapter. When it gets an EOS it should make sure that all the data it had received is pushed before pushing EOS. --- gst/isomp4/qtdemux.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 72000a9507..70269f1825 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -440,6 +440,8 @@ static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent, static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps); static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream); +static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux, + gboolean force); static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length); @@ -1887,7 +1889,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent, GstEvent * event) { GstQTDemux *demux = GST_QTDEMUX (parent); - gboolean res; + gboolean res = TRUE; GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event)); @@ -2036,6 +2038,13 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent, } if (!has_valid_stream) gst_qtdemux_post_no_playable_stream_error (demux); + else { + GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u", + (guint) gst_adapter_available (demux->adapter)); + if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) { + res = FALSE; + } + } } break; case GST_EVENT_CAPS:{ @@ -2052,7 +2061,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent, break; } - res = gst_pad_event_default (demux->sinkpad, parent, event); + res = gst_pad_event_default (demux->sinkpad, parent, event) & res; drop: return res; @@ -4593,22 +4602,29 @@ static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf) { GstQTDemux *demux; - GstFlowReturn ret = GST_FLOW_OK; - demux = GST_QTDEMUX (parent); + demux = GST_QTDEMUX (parent); gst_adapter_push (demux->adapter, inbuf); + GST_DEBUG_OBJECT (demux, + "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf, + demux->neededbytes, gst_adapter_available (demux->adapter)); + + return gst_qtdemux_process_adapter (demux, FALSE); +} + +static GstFlowReturn +gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force) +{ + GstFlowReturn ret = GST_FLOW_OK; + /* we never really mean to buffer that much */ if (demux->neededbytes == -1) { goto eos; } - GST_DEBUG_OBJECT (demux, - "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf, - demux->neededbytes, gst_adapter_available (demux->adapter)); - while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) && - (ret == GST_FLOW_OK)) { + (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) { GST_DEBUG_OBJECT (demux, "state:%d , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT,