diff --git a/ChangeLog b/ChangeLog index 00fd4073b2..7ddcb5f5a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2006-03-23 Wim Taymans + + Patch by: Michal Benes + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_init), + (gst_mpeg_demux_parse_packet), (gst_mpeg_demux_parse_pes), + (gst_mpeg_demux_send_subbuffer), (gst_mpeg_demux_reset): + * gst/mpegstream/gstmpegdemux.h: + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_parse_packhead): + Timestamps in mpeg stream are 32-bit numbers. Therefore, with a + clock_freq of 90kHz this timestamp overflows every ~13 hours. This + situation really happens when grabbing DVB streams. Current + mpegdemuxer can not handle this situation correctly and it + restarts counting gstreamer timestamps from zero. + Fixes #326598. + 2006-03-15 Michael Smith * ext/a52dec/gsta52dec.c: (gst_a52dec_sink_event), diff --git a/common b/common index 9200457d08..252846b570 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 9200457d08a57f0d7eaeb56915804fa8faf14418 +Subproject commit 252846b570144570a0aee25b5adefbfac3f5d4eb diff --git a/gst/mpegstream/gstmpegdemux.c b/gst/mpegstream/gstmpegdemux.c index 042a4eb523..d10ff55223 100644 --- a/gst/mpegstream/gstmpegdemux.c +++ b/gst/mpegstream/gstmpegdemux.c @@ -225,6 +225,8 @@ gst_mpeg_demux_init (GstMPEGDemux * mpeg_demux, GstMPEGDemuxClass * klass) mpeg_demux->max_gap = GST_CLOCK_TIME_NONE; mpeg_demux->max_gap_tolerance = GST_CLOCK_TIME_NONE; + + mpeg_demux->last_pts = -1; } static GstFlowReturn @@ -682,6 +684,15 @@ done: headerlen, datalen); if (pts != -1) { + /* Check for pts overflow */ + if (mpeg_demux->last_pts != -1) { + gint32 diff = pts - mpeg_demux->last_pts; + + if (diff > -4 * CLOCK_FREQ && diff < 4 * CLOCK_FREQ) + pts = mpeg_demux->last_pts + diff; + } + mpeg_demux->last_pts = pts; + timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse, MPEGTIME_TO_GSTTIME (pts)); @@ -780,6 +791,15 @@ gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer) pts |= ((guint64) * buf++) << 7; pts |= ((guint64) (*buf++ & 0xFE)) >> 1; + /* Check for pts overflow */ + if (mpeg_demux->last_pts != -1) { + gint32 diff = pts - mpeg_demux->last_pts; + + if (diff > -4 * CLOCK_FREQ && diff < 4 * CLOCK_FREQ) + pts = mpeg_demux->last_pts + diff; + } + mpeg_demux->last_pts = pts; + timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse, MPEGTIME_TO_GSTTIME (pts)); @@ -904,6 +924,7 @@ gst_mpeg_demux_send_subbuffer (GstMPEGDemux * mpeg_demux, GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + offset; + GST_BUFFER_CAPS (outbuf) = gst_caps_ref (outstream->caps); ret = gst_pad_push (outstream->pad, outbuf); if (GST_CLOCK_TIME_IS_VALID (mpeg_demux->max_gap) && @@ -1197,6 +1218,7 @@ gst_mpeg_demux_reset (GstMPEGDemux * mpeg_demux) mpeg_demux->total_size_bound = 0LL; mpeg_demux->index = NULL; + mpeg_demux->last_pts = -1; /* * Don't adjust things that are only for subclass use diff --git a/gst/mpegstream/gstmpegdemux.h b/gst/mpegstream/gstmpegdemux.h index 2174af284d..b8d3ac9f7d 100644 --- a/gst/mpegstream/gstmpegdemux.h +++ b/gst/mpegstream/gstmpegdemux.h @@ -123,6 +123,7 @@ struct _GstMPEGDemux { gboolean packet_rate_restriction; gint64 total_size_bound; + gint64 last_pts; GstIndex *index; /* stream output */ diff --git a/gst/mpegstream/gstmpegparse.c b/gst/mpegstream/gstmpegparse.c index f5ec6ca568..5ad896f63c 100644 --- a/gst/mpegstream/gstmpegparse.c +++ b/gst/mpegstream/gstmpegparse.c @@ -526,6 +526,16 @@ gst_mpeg_parse_parse_packhead (GstMPEGParse * mpeg_parse, GstBuffer * buffer) } new_rate *= MP_MUX_RATE_MULT; + /* Deal with SCR overflow */ + if (mpeg_parse->current_scr != MP_INVALID_SCR) { + guint32 diff; + + diff = scr - mpeg_parse->current_scr; + if (diff < 4 * CLOCK_FREQ) + scr = mpeg_parse->current_scr + diff; + } + + prev_scr = mpeg_parse->current_scr; mpeg_parse->current_scr = scr;