diff options
author | Edward Hervey <edward@collabora.com> | 2013-07-20 12:02:22 +0200 |
---|---|---|
committer | Edward Hervey <edward@collabora.com> | 2013-07-30 08:28:07 +0200 |
commit | c16b9f45302d34529fde4dd73e92de2a09a5c781 (patch) | |
tree | 2781629b41667ac5334406f18a18d9fd647c94d1 | |
parent | 3e3667f9165729ddf0399bdf15174ec1609b2aee (diff) |
!!WIP mpegtsdemux: DTS/PCR offset calculationsmpegts-wip
-rw-r--r-- | gst/mpegtsdemux/mpegtsbase.c | 2 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtsbase.h | 2 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtspacketizer.c | 104 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtspacketizer.h | 44 | ||||
-rw-r--r-- | gst/mpegtsdemux/tsdemux.c | 41 |
5 files changed, 130 insertions, 63 deletions
diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index b4cd02376..f936b7b7b 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -653,6 +653,7 @@ mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program, program->pmt = pmt; program->pmt_pid = pmt_pid; program->pcr_pid = pmt->pcr_pid; + program->pcrtable = get_pcr_table (base->packetizer, pmt->pcr_pid); /* extract top-level registration_id if present */ program->registration_id = @@ -1289,6 +1290,7 @@ mpegts_base_scan (MpegTSBase * base) beach: mpegts_packetizer_clear (base->packetizer); + mpegts_packetizer_flush (base->packetizer, FALSE); return ret; no_initial_pcr: diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h index 4ed8ba11b..0ad2ec636 100644 --- a/gst/mpegtsdemux/mpegtsbase.h +++ b/gst/mpegtsdemux/mpegtsbase.h @@ -72,6 +72,8 @@ struct _MpegTSBaseProgram guint16 pmt_pid; guint16 pcr_pid; + MpegTSPCR *pcrtable; + /* Content of the registration descriptor (if present) */ guint32 registration_id; diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 8ed14c05f..1128cc2da 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -39,8 +39,8 @@ GST_DEBUG_CATEGORY_STATIC (mpegts_packetizer_debug); #define GST_CAT_DEFAULT mpegts_packetizer_debug -#define MPEGTS_PACKETIZER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_MPEGTS_PACKETIZER, MpegTSPacketizerPrivate)) +#define MPEGTS_PACKETIZER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_MPEGTS_PACKETIZER, MpegTSPacketizerPrivate)) static void _init_local (void); G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0, @@ -50,39 +50,6 @@ G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0, * 256 should be sufficient for most multiplexes */ #define MAX_PCR_OBS_CHANNELS 256 -typedef struct _MpegTSPCR -{ - guint16 pid; - - /* Following variables are only active/used when - * calculate_skew is TRUE */ - GstClockTime base_time; - GstClockTime base_pcrtime; - GstClockTime prev_out_time; - GstClockTime prev_in_time; - GstClockTime last_pcrtime; - gint64 window[MAX_WINDOW]; - guint window_pos; - guint window_size; - gboolean window_filling; - gint64 window_min; - gint64 skew; - gint64 prev_send_diff; - - /* Offset to apply to PCR to handle wraparounds */ - guint64 pcroffset; - - /* Used for bitrate calculation */ - /* FIXME : Replace this later on with a balanced tree or sequence */ - guint64 first_offset; - guint64 first_pcr; - GstClockTime first_pcr_ts; - guint64 last_offset; - guint64 last_pcr; - GstClockTime last_pcr_ts; - -} MpegTSPCR; - struct _MpegTSPacketizerPrivate { /* Shortcuts for adapter usage */ @@ -117,7 +84,7 @@ static void record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable, #define TABLE_ID_UNSET 0xFF #define PACKET_SYNC_BYTE 0x47 -static inline MpegTSPCR * +MpegTSPCR * get_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid) { MpegTSPacketizerPrivate *priv = packetizer->priv; @@ -153,23 +120,51 @@ get_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid) res->prev_send_diff = GST_CLOCK_TIME_NONE; res->prev_out_time = GST_CLOCK_TIME_NONE; res->pcroffset = 0; + + res->current_pcr = GST_CLOCK_TIME_NONE; } return res; } +static inline MpegTSPCR * +_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid) +{ + MpegTSPCR *res = + packetizer->priv->observations[packetizer->priv->pcrtablelut[pid]]; + if (G_LIKELY (res)) + return res; + return get_pcr_table (packetizer, pid); +} + static void -flush_observations (MpegTSPacketizer2 * packetizer) +flush_observations (MpegTSPacketizer2 * packetizer, gboolean hard) { MpegTSPacketizerPrivate *priv = packetizer->priv; gint i; for (i = 0; i < priv->lastobsid; i++) { - g_free (priv->observations[i]); - priv->observations[i] = NULL; + MpegTSPCR *pcrtable = priv->observations[i]; + if (hard) { + pcrtable->first_offset = -1; + pcrtable->first_pcr = -1; + pcrtable->first_pcr_ts = GST_CLOCK_TIME_NONE; + pcrtable->last_offset = -1; + pcrtable->last_pcr = -1; + pcrtable->last_pcr_ts = GST_CLOCK_TIME_NONE; + pcrtable->base_time = GST_CLOCK_TIME_NONE; + pcrtable->base_pcrtime = GST_CLOCK_TIME_NONE; + pcrtable->last_pcrtime = GST_CLOCK_TIME_NONE; + pcrtable->window_pos = 0; + pcrtable->window_filling = TRUE; + pcrtable->window_min = 0; + pcrtable->skew = 0; + pcrtable->prev_send_diff = GST_CLOCK_TIME_NONE; + pcrtable->prev_out_time = GST_CLOCK_TIME_NONE; + pcrtable->pcroffset = 0; + } + pcrtable->current_pcr = GST_CLOCK_TIME_NONE; } - memset (priv->pcrtablelut, 0xff, 0x200); - priv->lastobsid = 0; } static inline MpegTSPacketizerStreamSubtable * @@ -319,6 +314,7 @@ static void mpegts_packetizer_dispose (GObject * object) { MpegTSPacketizer2 *packetizer = GST_MPEGTS_PACKETIZER (object); + gint i; if (!packetizer->disposed) { if (packetizer->packet_size) @@ -338,7 +334,10 @@ mpegts_packetizer_dispose (GObject * object) packetizer->offset = 0; packetizer->empty = TRUE; - flush_observations (packetizer); + for (i = 0; i < packetizer->priv->lastobsid; i++) + g_free (packetizer->priv->observations[i]); + memset (packetizer->priv->pcrtablelut, 0xff, 0x200); + packetizer->priv->lastobsid = 0; } if (G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose) @@ -420,6 +419,7 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 * if (afcflags & MPEGTS_AFC_PCR_FLAG) { MpegTSPCR *pcrtable = NULL; packet->pcr = mpegts_packetizer_compute_pcr (data); + pcrtable->current_pcr = PCRTIME_TO_GSTTIME (pcr); data += 6; GST_DEBUG ("pcr 0x%04x %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT ") offset:%" G_GUINT64_FORMAT, packet->pid, packet->pcr, @@ -627,10 +627,8 @@ mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer, gboolean hard) packetizer->priv->offset = 0; packetizer->priv->mapped_size = 0; packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE; - if (hard) { - /* For pull mode seeks in tsdemux the observation must be preserved */ - flush_observations (packetizer); - } + /* For pull mode seeks in tsdemux the observation must be preserved */ + flush_observations (packetizer, hard); } void @@ -1526,10 +1524,9 @@ mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 * packetizer) GstClockTime mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, - guint64 offset, guint16 pid) + guint64 offset, MpegTSPCR * pcrtable) { MpegTSPacketizerPrivate *priv = packetizer->priv; - MpegTSPCR *pcrtable; GstClockTime res; if (G_UNLIKELY (!packetizer->calculate_offset)) @@ -1541,8 +1538,6 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, if (G_UNLIKELY (offset < priv->refoffset)) return GST_CLOCK_TIME_NONE; - pcrtable = get_pcr_table (packetizer, pid); - if (G_UNLIKELY (pcrtable->last_offset <= pcrtable->first_offset)) return GST_CLOCK_TIME_NONE; @@ -1558,10 +1553,9 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, GstClockTime mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, - GstClockTime pts, guint16 pcr_pid) + GstClockTime pts, MpegTSPCR * pcrtable) { GstClockTime res = GST_CLOCK_TIME_NONE; - MpegTSPCR *pcrtable = get_pcr_table (packetizer, pcr_pid); /* Use clock skew if present */ if (packetizer->calculate_skew @@ -1584,22 +1578,20 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for pts %" GST_TIME_FORMAT " pcr_pid:0x%04x", GST_TIME_ARGS (res), - GST_TIME_ARGS (pts), pcr_pid); + GST_TIME_ARGS (pts), pcrtable->pid); return res; } guint64 mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, - GstClockTime ts, guint16 pcr_pid) + GstClockTime ts, MpegTSPCR * pcrtable) { MpegTSPacketizerPrivate *priv = packetizer->priv; - MpegTSPCR *pcrtable; guint64 res; if (!packetizer->calculate_offset) return -1; - pcrtable = get_pcr_table (packetizer, pcr_pid); if (pcrtable->first_pcr == -1) return -1; diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h index cb1edfdc9..50eeef6dd 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -67,6 +67,42 @@ typedef struct _MpegTSPacketizer2 MpegTSPacketizer2; typedef struct _MpegTSPacketizer2Class MpegTSPacketizer2Class; typedef struct _MpegTSPacketizerPrivate MpegTSPacketizerPrivate; + +typedef struct _MpegTSPCR +{ + guint16 pid; + + /* Following variables are only active/used when + * calculate_skew is TRUE */ + GstClockTime base_time; + GstClockTime base_pcrtime; + GstClockTime prev_out_time; + GstClockTime prev_in_time; + GstClockTime last_pcrtime; + gint64 window[MAX_WINDOW]; + guint window_pos; + guint window_size; + gboolean window_filling; + gint64 window_min; + gint64 skew; + gint64 prev_send_diff; + + GstClockTime current_pcr; + + /* Offset to apply to PCR to handle wraparounds */ + guint64 pcroffset; + + /* Used for bitrate calculation */ + /* FIXME : Replace this later on with a balanced tree or sequence */ + guint64 first_offset; + guint64 first_pcr; + GstClockTime first_pcr_ts; + guint64 last_offset; + guint64 last_pcr; + GstClockTime last_pcr_ts; + +} MpegTSPCR; + typedef struct { guint16 pid; @@ -165,6 +201,8 @@ typedef enum { PACKET_NEED_MORE } MpegTSPacketizerPacketReturn; +G_GNUC_INTERNAL MpegTSPCR *get_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid); + G_GNUC_INTERNAL GType mpegts_packetizer_get_type(void); G_GNUC_INTERNAL MpegTSPacketizer2 *mpegts_packetizer_new (void); @@ -189,13 +227,13 @@ G_GNUC_INTERNAL guint mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 *packeti G_GNUC_INTERNAL GstClockTime mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, - guint64 offset, guint16 pcr_pid); + guint64 offset, MpegTSPCR *pcrtable); G_GNUC_INTERNAL guint64 mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, - GstClockTime ts, guint16 pcr_pid); + GstClockTime ts, MpegTSPCR *pcrtable); G_GNUC_INTERNAL GstClockTime mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, - GstClockTime pts, guint16 pcr_pid); + GstClockTime pts, MpegTSPCR *pcrtable); G_GNUC_INTERNAL void mpegts_packetizer_set_reference_offset (MpegTSPacketizer2 * packetizer, guint64 refoffset); diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 851a049bc..028e4c9ac 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -123,6 +123,11 @@ struct _TSDemuxStream guint current_size; guint allocated_size; + /* TEMPORARY HACK/DEBUG offset between first dts ever seen and PCR + * at that time */ + GstClockTime first_dts_offset; + guint64 last_compared_pcr; + /* Current PTS/DTS for this stream */ GstClockTime pts; GstClockTime dts; @@ -404,7 +409,7 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query) else { GstClockTime dur = mpegts_packetizer_offset_to_ts (base->packetizer, val, - demux->program->pcr_pid); + demux->program->pcrtable); if (GST_CLOCK_TIME_IS_VALID (dur)) gst_query_set_duration (query, GST_FORMAT_TIME, dur); else @@ -536,7 +541,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event) /* Convert start/stop to offset */ start_offset = mpegts_packetizer_ts_to_offset (base->packetizer, MAX (0, - start - SEEK_TIMESTAMP_OFFSET), demux->program->pcr_pid); + start - SEEK_TIMESTAMP_OFFSET), demux->program->pcrtable); if (G_UNLIKELY (start_offset == -1)) { GST_WARNING ("Couldn't convert start position to an offset"); @@ -1059,6 +1064,7 @@ gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * bstream, stream->pts = GST_CLOCK_TIME_NONE; stream->dts = GST_CLOCK_TIME_NONE; stream->continuity_counter = CONTINUITY_UNSET; + stream->first_dts_offset = GST_CLOCK_TIME_NONE; } stream->flow_return = GST_FLOW_OK; } @@ -1138,6 +1144,7 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream) stream->flow_return = GST_FLOW_OK; } stream->continuity_counter = CONTINUITY_UNSET; + stream->first_dts_offset = GST_CLOCK_TIME_NONE; } static void @@ -1201,7 +1208,7 @@ gst_ts_demux_record_pts (GstTSDemux * demux, TSDemuxStream * stream, /* Compute PTS in GstClockTime */ stream->pts = mpegts_packetizer_pts_to_ts (MPEG_TS_BASE_PACKETIZER (demux), - MPEGTIME_TO_GSTTIME (pts), demux->program->pcr_pid); + MPEGTIME_TO_GSTTIME (pts), demux->program->pcrtable); GST_LOG ("pid 0x%04x Stored PTS %" G_GUINT64_FORMAT, bs->pid, stream->pts); @@ -1234,7 +1241,7 @@ gst_ts_demux_record_dts (GstTSDemux * demux, TSDemuxStream * stream, /* Compute DTS in GstClockTime */ stream->dts = mpegts_packetizer_pts_to_ts (MPEG_TS_BASE_PACKETIZER (demux), - MPEGTIME_TO_GSTTIME (dts), demux->program->pcr_pid); + MPEGTIME_TO_GSTTIME (dts), demux->program->pcrtable); GST_LOG ("pid 0x%04x Stored DTS %" G_GUINT64_FORMAT, bs->pid, stream->dts); @@ -1269,6 +1276,32 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream, goto discont; } + /* TEMPORARY HACK/DEBUG */ + if (demux->program->pcrtable->current_pcr != GST_CLOCK_TIME_NONE && + demux->program->pcrtable->current_pcr != stream->last_compared_pcr) { + if (header.DTS != -1) { + stream->first_dts_offset = + MPEGTIME_TO_GSTTIME (header.DTS) - + demux->program->pcrtable->current_pcr; + stream->last_compared_pcr = demux->program->pcrtable->current_pcr; + GST_WARNING_OBJECT (stream->pad, + "DTS:%" GST_TIME_FORMAT " current_pcr:%" GST_TIME_FORMAT " offset:%" + GST_TIME_FORMAT, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (header.DTS)), + GST_TIME_ARGS (demux->program->pcrtable->current_pcr), + GST_TIME_ARGS (stream->first_dts_offset)); + } else if (header.PTS != -1) { + stream->first_dts_offset = + MPEGTIME_TO_GSTTIME (header.PTS) - + demux->program->pcrtable->current_pcr; + stream->last_compared_pcr = demux->program->pcrtable->current_pcr; + GST_WARNING_OBJECT (stream->pad, + "PTS:%" GST_TIME_FORMAT " current_pcr:%" GST_TIME_FORMAT " offset:%" + GST_TIME_FORMAT, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (header.PTS)), + GST_TIME_ARGS (demux->program->pcrtable->current_pcr), + GST_TIME_ARGS (stream->first_dts_offset)); + } + } + gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset); gst_ts_demux_record_pts (demux, stream, header.PTS, bufferoffset); |