From cf3f3f14da6561223bf9f5d6bf1ff230526d40eb Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 3 Oct 2011 17:50:43 +0100 Subject: [PATCH] flvdemux: detect large pts gaps and resync Should work on multiple gaps, but tested on only one. https://bugzilla.gnome.org/show_bug.cgi?id=631430 --- gst/flv/gstflvdemux.c | 34 ++++++++++++++++++++++++++++++++-- gst/flv/gstflvdemux.h | 4 ++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c index 8aa352e53b..7d3c992fe1 100644 --- a/gst/flv/gstflvdemux.c +++ b/gst/flv/gstflvdemux.c @@ -84,6 +84,9 @@ GST_BOILERPLATE (GstFlvDemux, gst_flv_demux, GstElement, GST_TYPE_ELEMENT); /* 1 byte of tag type + 3 bytes of tag data size */ #define FLV_TAG_TYPE_SIZE 4 +/* two seconds - consider pts are resynced to another base if this different */ +#define RESYNC_THRESHOLD 2000 + static gboolean flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event); static gboolean gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, @@ -759,6 +762,23 @@ gst_flv_demux_push_tags (GstFlvDemux * demux) } } +static void +gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 pts, guint32 * last, + GstClockTime * offset) +{ + if (ABS (pts - *last) >= RESYNC_THRESHOLD) { + /* Theoretically, we should use substract the duration of the last buffer, + but this demuxer sends no durations on buffers, not sure if it cannot + know, or just does not care to calculate. */ + gint32 dpts = pts - *last; + *offset -= dpts * GST_MSECOND; + GST_WARNING_OBJECT (demux, + "Large pts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %" + GST_TIME_FORMAT "", dpts, GST_TIME_ARGS (*offset)); + } + *last = pts; +} + static GstFlowReturn gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) { @@ -945,8 +965,12 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer) } } + /* detect (and deem to be resyncs) large pts gaps */ + gst_flv_demux_update_resync (demux, pts, &demux->last_audio_pts, + &demux->audio_time_offset); + /* Fill buffer with data */ - GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND; + GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->audio_time_offset; GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++; GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset; @@ -1313,8 +1337,12 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer) } } + /* detect (and deem to be resyncs) large pts gaps */ + gst_flv_demux_update_resync (demux, pts, &demux->last_video_pts, + &demux->video_time_offset); + /* Fill buffer with data */ - GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND; + GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->video_time_offset; GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (outbuf) = demux->video_offset++; GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset; @@ -1627,6 +1655,8 @@ gst_flv_demux_cleanup (GstFlvDemux * demux) demux->index_max_time = 0; demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE; + demux->last_audio_pts = demux->last_video_pts = 0; + demux->audio_time_offset = demux->video_time_offset = 0; demux->no_more_pads = FALSE; diff --git a/gst/flv/gstflvdemux.h b/gst/flv/gstflvdemux.h index 60083e8675..07559a5201 100644 --- a/gst/flv/gstflvdemux.h +++ b/gst/flv/gstflvdemux.h @@ -95,6 +95,8 @@ struct _GstFlvDemux gboolean audio_linked; GstBuffer * audio_codec_data; GstClockTime audio_start; + guint32 last_audio_pts; + GstClockTime audio_time_offset; /* Video infos */ guint32 w; @@ -109,6 +111,8 @@ struct _GstFlvDemux gboolean got_par; GstBuffer * video_codec_data; GstClockTime video_start; + guint32 last_video_pts; + GstClockTime video_time_offset; gdouble framerate; gboolean random_access;