From 28a2902a7b6601785c9237dfb6218a68f1845083 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 24 May 2013 10:59:59 +0200 Subject: [PATCH] tsdemux: fixes seeking in pull mode Preserve the current segment and observations in pull mode seeks with flushing. https://bugzilla.gnome.org/show_bug.cgi?id=698050 --- gst/mpegtsdemux/mpegtsbase.c | 15 ++++++++------- gst/mpegtsdemux/mpegtsbase.h | 6 ++++-- gst/mpegtsdemux/mpegtspacketizer.c | 7 +++++-- gst/mpegtsdemux/mpegtspacketizer.h | 2 +- gst/mpegtsdemux/tsdemux.c | 9 ++++++--- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 02fa53bae4..8914e4fef2 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -1291,7 +1291,7 @@ gst_mpegts_base_handle_eos (MpegTSBase * base) } static inline void -mpegts_base_flush (MpegTSBase * base) +mpegts_base_flush (MpegTSBase * base, gboolean hard) { MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); @@ -1299,7 +1299,7 @@ mpegts_base_flush (MpegTSBase * base) if (G_UNLIKELY (klass->flush == NULL)) GST_WARNING_OBJECT (base, "Class doesn't have a 'flush' implementation !"); else - klass->flush (base); + klass->flush (base, hard); } static gboolean @@ -1337,8 +1337,8 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); - mpegts_packetizer_flush (base->packetizer); - mpegts_base_flush (base); + mpegts_packetizer_flush (base->packetizer, TRUE); + mpegts_base_flush (base, TRUE); gst_segment_init (&base->segment, GST_FORMAT_UNDEFINED); base->seen_pat = FALSE; break; @@ -1684,9 +1684,10 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad, /* send a FLUSH_STOP for the sinkpad, since we need data for seeking */ GST_DEBUG_OBJECT (base, "sending flush stop"); gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop (TRUE)); - /* And actually flush our pending data */ - mpegts_base_flush (base); - mpegts_packetizer_flush (base->packetizer); + /* And actually flush our pending data but allow to preserve some info + * to perform the seek */ + mpegts_base_flush (base, FALSE); + mpegts_packetizer_flush (base->packetizer, FALSE); } if (flags & (GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_SKIP)) { diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h index e872330362..83c0c94a86 100644 --- a/gst/mpegtsdemux/mpegtsbase.h +++ b/gst/mpegtsdemux/mpegtsbase.h @@ -165,8 +165,10 @@ struct _MpegTSBaseClass { /* seek is called to wait for seeking */ GstFlowReturn (*seek) (MpegTSBase * base, GstEvent * event); - /* flush all streams */ - void (*flush) (MpegTSBase * base); + /* flush all streams + * The hard inicator is used to flush completelly on FLUSH_STOP events + * or partially in pull mode seeks of tsdemux */ + void (*flush) (MpegTSBase * base, gboolean hard); /* Notifies subclasses input buffer has been handled */ GstFlowReturn (*input_done) (MpegTSBase *base, GstBuffer *buffer); diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index d28bda5db4..a19c3909c3 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -2480,7 +2480,7 @@ mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer) } void -mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer) +mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer, gboolean hard) { GST_DEBUG ("Flushing"); @@ -2501,7 +2501,10 @@ mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer) packetizer->priv->offset = 0; packetizer->priv->mapped_size = 0; packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE; - flush_observations (packetizer); + if (hard) { + /* For pull mode seeks in tsdemux the observation must be preserved */ + flush_observations (packetizer); + } } void diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h index e51b2cae05..78a4008912 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -167,7 +167,7 @@ G_GNUC_INTERNAL GType mpegts_packetizer_get_type(void); G_GNUC_INTERNAL MpegTSPacketizer2 *mpegts_packetizer_new (void); G_GNUC_INTERNAL void mpegts_packetizer_clear (MpegTSPacketizer2 *packetizer); -G_GNUC_INTERNAL void mpegts_packetizer_flush (MpegTSPacketizer2 *packetizer); +G_GNUC_INTERNAL void mpegts_packetizer_flush (MpegTSPacketizer2 *packetizer, gboolean hard); G_GNUC_INTERNAL void mpegts_packetizer_push (MpegTSPacketizer2 *packetizer, GstBuffer *buffer); G_GNUC_INTERNAL gboolean mpegts_packetizer_has_packets (MpegTSPacketizer2 *packetizer); G_GNUC_INTERNAL MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *packetizer, diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 20b08e3046..475f9ceccf 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -228,7 +228,7 @@ static void gst_ts_demux_reset (MpegTSBase * base); static GstFlowReturn gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, MpegTSPacketizerSection * section); -static void gst_ts_demux_flush (MpegTSBase * base); +static void gst_ts_demux_flush (MpegTSBase * base, gboolean hard); static void gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * stream, MpegTSBaseProgram * program); @@ -1579,7 +1579,7 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream, } static void -gst_ts_demux_flush (MpegTSBase * base) +gst_ts_demux_flush (MpegTSBase * base, gboolean hard) { GstTSDemux *demux = GST_TS_DEMUX_CAST (base); @@ -1590,7 +1590,10 @@ gst_ts_demux_flush (MpegTSBase * base) demux->segment_event = NULL; } demux->calculate_update_segment = FALSE; - gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED); + if (hard) { + /* For pull mode seeks the current segment needs to be preserved */ + gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED); + } } static GstFlowReturn