summaryrefslogtreecommitdiff
path: root/gst/mpegdemux
diff options
context:
space:
mode:
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>2011-08-30 14:50:52 +0100
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>2011-11-28 13:57:29 +0000
commit7960280afbb2fdc436d8e1fcf89a414b37f6e135 (patch)
treeb4af6f0809a4e9482c087fa990d183419aa1739f /gst/mpegdemux
parent7521b597f4dc49d8d168f368f0e7ebaf98a72156 (diff)
downloadgstreamer-plugins-bad-7960280afbb2fdc436d8e1fcf89a414b37f6e135.tar.gz
mpegdemux: catch smaller PTS dicontinuities
In a test stream, I get one buffer with a PTS of about 15 seconds in the future compared to the previous one, and next buffers with timestamps continuing where the original ones left off. This caused the sink to wait 15 seconds to display the frame while more frames queued up, and then dump all the subsequent frames as they "arrived too late". Maybe that threshold should be made configurable, but for now, make it more smaller to catch more of these. https://bugzilla.gnome.org/show_bug.cgi?id=655804 Non AV streams keep using the larger threshold (10 minutes), as subtitles may arrive only every so often.
Diffstat (limited to 'gst/mpegdemux')
-rw-r--r--gst/mpegdemux/gstmpegtsdemux.c40
-rw-r--r--gst/mpegdemux/gstmpegtsdemux.h3
2 files changed, 35 insertions, 8 deletions
diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c
index b3b8249e6..f720c0774 100644
--- a/gst/mpegdemux/gstmpegtsdemux.c
+++ b/gst/mpegdemux/gstmpegtsdemux.c
@@ -88,6 +88,10 @@ enum
/* latency in mseconds */
#define TS_LATENCY 700
+/* threshold at which we deem PTS difference to be a discontinuity */
+#define DISCONT_THRESHOLD_AV (GST_SECOND * 2) /* 2 seconds */
+#define DISCONT_THRESHOLD_OTHER (GST_SECOND * 60 * 10) /* 10 minutes */
+
enum
{
PROP_0,
@@ -539,6 +543,20 @@ gst_mpegts_stream_is_video (GstMpegTSStream * stream)
return FALSE;
}
+static FORCE_INLINE gboolean
+gst_mpegts_stream_is_audio (GstMpegTSStream * stream)
+{
+ switch (stream->stream_type) {
+ case ST_AUDIO_MPEG1:
+ case ST_AUDIO_MPEG2:
+ case ST_AUDIO_AAC_ADTS:
+ case ST_AUDIO_AAC_LOAS:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gboolean
gst_mpegts_demux_is_reserved_PID (GstMpegTSDemux * demux, guint16 PID)
{
@@ -1040,16 +1058,21 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
demux = stream->demux;
srcpad = stream->pad;
- GST_DEBUG_OBJECT (demux, "got data on PID 0x%04x", stream->PID);
+ GST_DEBUG_OBJECT (demux, "got data on PID 0x%04x (flags %x)", stream->PID,
+ stream->flags);
if (first && filter->pts != -1) {
+ gint64 discont_threshold =
+ ((stream->flags & (MPEGTS_STREAM_FLAG_IS_AUDIO |
+ MPEGTS_STREAM_FLAG_IS_VIDEO))) ? DISCONT_THRESHOLD_AV :
+ DISCONT_THRESHOLD_OTHER;
pts = filter->pts;
time = MPEGTIME_TO_GSTTIME (pts) + stream->base_time;
if ((stream->last_time > 0 && stream->last_time < time &&
- time - stream->last_time > GST_SECOND * 60 * 10)
+ time - stream->last_time > discont_threshold)
|| (stream->last_time > time
- && stream->last_time - time > GST_SECOND * 60 * 10)) {
+ && stream->last_time - time > discont_threshold)) {
/* check first to see if we're in middle of detecting a discont in PCR.
* if we are we're not sure what timestamp the buffer should have, best
* to drop. */
@@ -1065,8 +1088,7 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
stream->last_time - time > MPEGTIME_TO_GSTTIME (G_MAXUINT32)) {
/* wrap around occurred */
if (stream->base_time + MPEGTIME_TO_GSTTIME ((guint64) (1) << 33) +
- MPEGTIME_TO_GSTTIME (pts) >
- stream->last_time + GST_SECOND * 60 * 10) {
+ MPEGTIME_TO_GSTTIME (pts) > stream->last_time + discont_threshold) {
GST_DEBUG_OBJECT (demux,
"looks like we have a corrupt packet because its pts is a lot lower than"
" the previous pts but not a wraparound");
@@ -1100,7 +1122,7 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
stream->base_time > 0) {
/* had a previous wrap around */
if (time - MPEGTIME_TO_GSTTIME ((guint64) (1) << 33) +
- GST_SECOND * 60 * 10 < stream->last_time) {
+ discont_threshold < stream->last_time) {
GST_DEBUG_OBJECT (demux,
"looks like we have a corrupt packet because its pts is a lot higher than"
" the previous pts but not because of a wraparound or pcr discont");
@@ -1202,7 +1224,8 @@ gst_mpegts_demux_data_cb (GstPESFilter * filter, gboolean first,
gst_mpegts_demux_send_tags_for_stream (demux, stream);
}
- GST_DEBUG_OBJECT (srcpad, "pushing buffer");
+ GST_DEBUG_OBJECT (srcpad, "pushing buffer ts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
gst_buffer_set_caps (buffer, GST_PAD_CAPS (srcpad));
if (stream->discont) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
@@ -1479,6 +1502,9 @@ gst_mpegts_stream_parse_pmt (GstMpegTSStream * stream,
/* Recognise video streams based on stream_type */
if (gst_mpegts_stream_is_video (ES_stream))
ES_stream->flags |= MPEGTS_STREAM_FLAG_IS_VIDEO;
+ /* likewise for audio */
+ if (gst_mpegts_stream_is_audio (ES_stream))
+ ES_stream->flags |= MPEGTS_STREAM_FLAG_IS_AUDIO;
/* set adaptor */
GST_LOG ("Initializing PES filter for PID %u", ES_stream->PID);
diff --git a/gst/mpegdemux/gstmpegtsdemux.h b/gst/mpegdemux/gstmpegtsdemux.h
index c3732ba1f..2dddfe01e 100644
--- a/gst/mpegdemux/gstmpegtsdemux.h
+++ b/gst/mpegdemux/gstmpegtsdemux.h
@@ -121,7 +121,8 @@ struct _GstMpegTSPAT {
typedef enum _MpegTsStreamFlags {
MPEGTS_STREAM_FLAG_STREAM_TYPE_UNKNOWN = 0x01,
MPEGTS_STREAM_FLAG_PMT_VALID = 0x02,
- MPEGTS_STREAM_FLAG_IS_VIDEO = 0x04
+ MPEGTS_STREAM_FLAG_IS_VIDEO = 0x04,
+ MPEGTS_STREAM_FLAG_IS_AUDIO = 0x08
} MpegTsStreamFlags;
/* Information associated to a single MPEG stream. */