oggdemux: Better handling of sparse streams by sending segment updates

Fixes bug #397419.
This commit is contained in:
Tim-Philipp Müller 2009-09-10 10:00:16 +02:00 committed by Sebastian Dröge
parent 7a3797f332
commit 3a38a0958e
2 changed files with 54 additions and 1 deletions

View file

@ -127,6 +127,7 @@ static GstClockTime gst_annodex_granule_to_time (gint64 granulepos,
static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg, static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg,
GstOggPad * pad, GstFlowReturn ret); GstOggPad * pad, GstFlowReturn ret);
static void gst_ogg_demux_sync_streams (GstOggDemux * ogg);
G_DEFINE_TYPE (GstOggPad, gst_ogg_pad, GST_TYPE_PAD); G_DEFINE_TYPE (GstOggPad, gst_ogg_pad, GST_TYPE_PAD);
@ -161,6 +162,8 @@ gst_ogg_pad_init (GstOggPad * pad)
pad->start_time = GST_CLOCK_TIME_NONE; pad->start_time = GST_CLOCK_TIME_NONE;
pad->first_time = GST_CLOCK_TIME_NONE; pad->first_time = GST_CLOCK_TIME_NONE;
pad->last_stop = GST_CLOCK_TIME_NONE;
pad->have_type = FALSE; pad->have_type = FALSE;
pad->continued = NULL; pad->continued = NULL;
pad->headers = NULL; pad->headers = NULL;
@ -415,6 +418,7 @@ gst_ogg_pad_reset (GstOggPad * pad)
pad->continued = NULL; pad->continued = NULL;
pad->last_ret = GST_FLOW_OK; pad->last_ret = GST_FLOW_OK;
pad->last_stop = GST_CLOCK_TIME_NONE;
} }
/* the filter function for selecting the elements we can use in /* the filter function for selecting the elements we can use in
@ -874,6 +878,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet)
pad->discont = FALSE; pad->discont = FALSE;
} }
pad->last_stop = ogg->segment.last_stop;
ret = gst_pad_push (GST_PAD_CAST (pad), buf); ret = gst_pad_push (GST_PAD_CAST (pad), buf);
/* combine flows */ /* combine flows */
@ -1812,6 +1818,10 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
pad->discont = TRUE; pad->discont = TRUE;
pad->last_ret = GST_FLOW_OK; pad->last_ret = GST_FLOW_OK;
pad->is_sparse =
gst_structure_has_name (gst_caps_get_structure (GST_PAD_CAPS (pad),
0), "application/x-ogm-text");
/* activate first */ /* activate first */
gst_pad_set_active (GST_PAD_CAST (pad), TRUE); gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
@ -2918,7 +2928,7 @@ static GstFlowReturn
gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer) gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
{ {
GstOggDemux *ogg; GstOggDemux *ogg;
gint ret; gint ret = 0;
GstFlowReturn result = GST_FLOW_OK; GstFlowReturn result = GST_FLOW_OK;
ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad)); ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
@ -2940,6 +2950,9 @@ gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
result = gst_ogg_demux_handle_page (ogg, &page); result = gst_ogg_demux_handle_page (ogg, &page);
} }
} }
if (ret == 0 || result == GST_FLOW_OK) {
gst_ogg_demux_sync_streams (ogg);
}
return result; return result;
} }
@ -3090,6 +3103,41 @@ done:
return ret; return ret;
} }
static void
gst_ogg_demux_sync_streams (GstOggDemux * ogg)
{
GstClockTime cur;
GstOggChain *chain;
guint i;
chain = ogg->current_chain;
cur = ogg->segment.last_stop;
if (chain == NULL || cur == -1)
return;
for (i = 0; i < chain->streams->len; i++) {
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i);
/* Theoretically, we should be doing this for all streams, but we're only
* doing it for known-to-be-sparse streams at the moment in order not to
* break things for wrongly-muxed streams (like we used to produce once) */
if (stream->is_sparse && stream->last_stop != GST_CLOCK_TIME_NONE) {
/* Does this stream lag? Random threshold of 2 seconds */
if (GST_CLOCK_DIFF (stream->last_stop, cur) > (2 * GST_SECOND)) {
GST_DEBUG_OBJECT (stream, "synchronizing stream with others by "
"advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
GST_TIME_ARGS (stream->last_stop), GST_TIME_ARGS (cur));
stream->last_stop = cur;
/* advance stream time (FIXME: is this right, esp. time_pos?) */
gst_pad_push_event (GST_PAD_CAST (stream),
gst_event_new_new_segment (TRUE, ogg->segment.rate,
GST_FORMAT_TIME, stream->last_stop, -1, stream->last_stop));
}
}
}
}
/* random access code /* random access code
* *
* - first find all the chains and streams by scanning the file. * - first find all the chains and streams by scanning the file.
@ -3140,6 +3188,7 @@ gst_ogg_demux_loop (GstOggPad * pad)
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
goto pause; goto pause;
gst_ogg_demux_sync_streams (ogg);
return; return;
/* ERRORS */ /* ERRORS */

View file

@ -112,6 +112,10 @@ struct _GstOggPad
gint64 first_granule; /* the granulepos of first page == first sample in next page */ gint64 first_granule; /* the granulepos of first page == first sample in next page */
GstClockTime first_time; /* the timestamp of the second page or granuletime of first page */ GstClockTime first_time; /* the timestamp of the second page or granuletime of first page */
gboolean is_sparse; /* TRUE if this is a subtitle pad or some other sparse stream */
GstClockTime last_stop; /* last_stop when last push occured; used to detect when we
* need to send a newsegment update event for sparse streams */
ogg_stream_state stream; ogg_stream_state stream;
GList *continued; GList *continued;