summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <edward@collabora.com>2013-07-20 12:02:22 +0200
committerEdward Hervey <edward@collabora.com>2013-07-30 08:28:07 +0200
commitc16b9f45302d34529fde4dd73e92de2a09a5c781 (patch)
tree2781629b41667ac5334406f18a18d9fd647c94d1
parent3e3667f9165729ddf0399bdf15174ec1609b2aee (diff)
!!WIP mpegtsdemux: DTS/PCR offset calculationsmpegts-wip
-rw-r--r--gst/mpegtsdemux/mpegtsbase.c2
-rw-r--r--gst/mpegtsdemux/mpegtsbase.h2
-rw-r--r--gst/mpegtsdemux/mpegtspacketizer.c104
-rw-r--r--gst/mpegtsdemux/mpegtspacketizer.h44
-rw-r--r--gst/mpegtsdemux/tsdemux.c41
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);