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.
This commit is contained in:
Thiago Santos 2013-12-12 10:50:27 -03:00
parent 9dd6e22ba9
commit a82f3418fd

View file

@ -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,