diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 0f307785be..5c7cd0abeb 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -127,6 +127,7 @@ static GstClockTime gst_annodex_granule_to_time (gint64 granulepos, static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg, GstOggPad * pad, GstFlowReturn ret); +static void gst_ogg_demux_sync_streams (GstOggDemux * ogg); 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->first_time = GST_CLOCK_TIME_NONE; + pad->last_stop = GST_CLOCK_TIME_NONE; + pad->have_type = FALSE; pad->continued = NULL; pad->headers = NULL; @@ -415,6 +418,7 @@ gst_ogg_pad_reset (GstOggPad * pad) pad->continued = NULL; pad->last_ret = GST_FLOW_OK; + pad->last_stop = GST_CLOCK_TIME_NONE; } /* 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->last_stop = ogg->segment.last_stop; + ret = gst_pad_push (GST_PAD_CAST (pad), buf); /* combine flows */ @@ -1812,6 +1818,10 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, pad->discont = TRUE; 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 */ gst_pad_set_active (GST_PAD_CAST (pad), TRUE); @@ -2918,7 +2928,7 @@ static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer) { GstOggDemux *ogg; - gint ret; + gint ret = 0; GstFlowReturn result = GST_FLOW_OK; 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); } } + if (ret == 0 || result == GST_FLOW_OK) { + gst_ogg_demux_sync_streams (ogg); + } return result; } @@ -3090,6 +3103,41 @@ done: 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 * * - 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) goto pause; + gst_ogg_demux_sync_streams (ogg); return; /* ERRORS */ diff --git a/ext/ogg/gstoggdemux.h b/ext/ogg/gstoggdemux.h index 46f5460fec..6cc7fb9b78 100644 --- a/ext/ogg/gstoggdemux.h +++ b/ext/ogg/gstoggdemux.h @@ -112,6 +112,10 @@ struct _GstOggPad 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 */ + 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; GList *continued;