mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
oggdemux: implement seek in push mode
Refactor start time collection code. When we receive a flush_stop, resync to the new start time and push out a new segment event.
This commit is contained in:
parent
9be4e53001
commit
f96caa17b3
2 changed files with 102 additions and 38 deletions
|
@ -712,6 +712,29 @@ no_buffer:
|
|||
}
|
||||
}
|
||||
|
||||
static guint64
|
||||
gst_ogg_demux_collect_start_time (GstOggDemux * ogg, GstOggChain * chain)
|
||||
{
|
||||
gint i;
|
||||
guint64 start_time = G_MAXUINT64;
|
||||
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
||||
if (pad->map.is_skeleton)
|
||||
continue;
|
||||
|
||||
/* can do this if the pad start time is not defined */
|
||||
if (pad->start_time == GST_CLOCK_TIME_NONE) {
|
||||
start_time = G_MAXUINT64;
|
||||
break;
|
||||
} else {
|
||||
start_time = MIN (start_time, pad->start_time);
|
||||
}
|
||||
}
|
||||
return start_time;
|
||||
}
|
||||
|
||||
/* submit a packet to the oggpad, this function will run the
|
||||
* typefind code for the pad if this is the first packet for this
|
||||
* stream
|
||||
|
@ -820,23 +843,55 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||
|
||||
/* check if complete chain has start time */
|
||||
if (chain == ogg->building_chain) {
|
||||
GstEvent *event = NULL;
|
||||
|
||||
/* see if we have enough info to activate the chain, we have enough info
|
||||
* when all streams have a valid start time. */
|
||||
if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
|
||||
GstEvent *event;
|
||||
if (ogg->resync) {
|
||||
guint64 start_time;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_start));
|
||||
GST_DEBUG_OBJECT (ogg, "segment_stop: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_stop));
|
||||
GST_DEBUG_OBJECT (ogg, "segment_time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->begin_time));
|
||||
GST_DEBUG_OBJECT (ogg, "need to resync");
|
||||
|
||||
/* create the newsegment event we are going to send out */
|
||||
event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
|
||||
GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
|
||||
chain->begin_time);
|
||||
/* when we need to resync after a seek, we wait until we have received
|
||||
* timestamps on all streams */
|
||||
start_time = gst_ogg_demux_collect_start_time (ogg, chain);
|
||||
|
||||
if (start_time != G_MAXUINT64) {
|
||||
gint64 segment_time;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "start_time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (start_time));
|
||||
|
||||
if (chain->segment_start < start_time)
|
||||
segment_time =
|
||||
(start_time - chain->segment_start) + chain->begin_time;
|
||||
else
|
||||
segment_time = chain->begin_time;
|
||||
|
||||
/* create the newsegment event we are going to send out */
|
||||
event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
|
||||
GST_FORMAT_TIME, start_time, chain->segment_stop, segment_time);
|
||||
|
||||
ogg->resync = FALSE;
|
||||
}
|
||||
} else {
|
||||
/* see if we have enough info to activate the chain, we have enough info
|
||||
* when all streams have a valid start time. */
|
||||
if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_start));
|
||||
GST_DEBUG_OBJECT (ogg, "segment_stop: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->segment_stop));
|
||||
GST_DEBUG_OBJECT (ogg, "segment_time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (chain->begin_time));
|
||||
|
||||
/* create the newsegment event we are going to send out */
|
||||
event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
|
||||
GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
|
||||
chain->begin_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (event) {
|
||||
gst_event_set_seqnum (event, ogg->seqnum);
|
||||
|
||||
gst_ogg_demux_activate_chain (ogg, chain, event);
|
||||
|
@ -1149,8 +1204,6 @@ gst_ogg_chain_has_stream (GstOggChain * chain, glong serialno)
|
|||
return gst_ogg_chain_get_stream (chain, serialno) != NULL;
|
||||
}
|
||||
|
||||
#define CURRENT_CHAIN(ogg) (&g_array_index ((ogg)->chains, GstOggChain, (ogg)->current_chain))
|
||||
|
||||
/* signals and args */
|
||||
enum
|
||||
{
|
||||
|
@ -1268,6 +1321,27 @@ gst_ogg_demux_finalize (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_demux_reset_streams (GstOggDemux * ogg)
|
||||
{
|
||||
GstOggChain *chain;
|
||||
guint i;
|
||||
|
||||
chain = ogg->current_chain;
|
||||
if (chain == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
||||
stream->start_time = -1;
|
||||
stream->map.accumulated_granule = 0;
|
||||
}
|
||||
ogg->building_chain = chain;
|
||||
ogg->current_chain = NULL;
|
||||
ogg->resync = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
|
@ -1284,6 +1358,7 @@ gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
|
|||
GST_DEBUG_OBJECT (ogg, "got a flush stop event");
|
||||
ogg_sync_reset (&ogg->sync);
|
||||
res = gst_ogg_demux_send_event (ogg, event);
|
||||
gst_ogg_demux_reset_streams (ogg);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
GST_DEBUG_OBJECT (ogg, "got a new segment event");
|
||||
|
@ -1645,16 +1720,15 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
|
|||
|
||||
bitrate += pad->map.bitrate;
|
||||
|
||||
/* mark discont */
|
||||
gst_ogg_pad_mark_discont (pad);
|
||||
pad->last_ret = GST_FLOW_OK;
|
||||
|
||||
if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL)
|
||||
continue;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
|
||||
|
||||
/* mark discont */
|
||||
gst_ogg_pad_mark_discont (pad);
|
||||
pad->last_ret = GST_FLOW_OK;
|
||||
pad->added = TRUE;
|
||||
|
||||
structure = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
|
||||
pad->is_sparse =
|
||||
gst_structure_has_name (structure, "application/x-ogm-text") ||
|
||||
|
@ -1666,6 +1740,7 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
|
|||
gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
|
||||
pad->added = TRUE;
|
||||
}
|
||||
ogg->bitrate = bitrate;
|
||||
}
|
||||
|
@ -2674,29 +2749,16 @@ gst_ogg_demux_find_chain (GstOggDemux * ogg, glong serialno)
|
|||
static gboolean
|
||||
gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
|
||||
{
|
||||
gint i;
|
||||
gboolean res = TRUE;
|
||||
|
||||
chain->total_time = GST_CLOCK_TIME_NONE;
|
||||
chain->segment_start = G_MAXUINT64;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "trying to collect chain info");
|
||||
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
chain->segment_start = gst_ogg_demux_collect_start_time (ogg, chain);
|
||||
|
||||
if (pad->map.is_skeleton)
|
||||
continue;
|
||||
|
||||
/* can do this if the pad start time is not defined */
|
||||
if (pad->start_time == GST_CLOCK_TIME_NONE)
|
||||
res = FALSE;
|
||||
else
|
||||
chain->segment_start = MIN (chain->segment_start, pad->start_time);
|
||||
}
|
||||
|
||||
if (chain->segment_stop != GST_CLOCK_TIME_NONE
|
||||
&& chain->segment_start != G_MAXUINT64)
|
||||
if (chain->segment_start == G_MAXUINT64)
|
||||
res = FALSE;
|
||||
else if (chain->segment_stop != GST_CLOCK_TIME_NONE)
|
||||
chain->total_time = chain->segment_stop - chain->segment_start;
|
||||
|
||||
GST_DEBUG ("total time %" G_GUINT64_FORMAT, chain->total_time);
|
||||
|
@ -3316,6 +3378,7 @@ gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
|
|||
ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
|
||||
|
||||
ogg->pullmode = FALSE;
|
||||
ogg->resync = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ struct _GstOggDemux
|
|||
gboolean running;
|
||||
|
||||
gboolean need_chains;
|
||||
gboolean resync;
|
||||
|
||||
/* state */
|
||||
GMutex *chain_lock; /* we need the lock to protect the chains */
|
||||
|
|
Loading…
Reference in a new issue