mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 04:56:24 +00:00
tsdemux: Calculate pcr/time/offset separately per program
Avoids quite a few issues with multi-program streams
This commit is contained in:
parent
a8d1e88bda
commit
4f55cc12ae
3 changed files with 240 additions and 196 deletions
|
@ -84,19 +84,29 @@ static void _init_local (void);
|
||||||
G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0,
|
G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0,
|
||||||
_init_local ());
|
_init_local ());
|
||||||
|
|
||||||
typedef struct
|
/* Maximum number of MpegTSPcr
|
||||||
{
|
* 256 should be sufficient for most multiplexes */
|
||||||
guint64 offset; /* offset in upstream */
|
#define MAX_PCR_OBS_CHANNELS 256
|
||||||
guint64 pcr; /* pcr (wraparound not fixed) */
|
|
||||||
} MpegTSPacketizerOffset;
|
|
||||||
|
|
||||||
struct _MpegTSPacketizerPrivate
|
typedef struct _MpegTSPCR
|
||||||
{
|
{
|
||||||
/* Shortcuts for adapter usage */
|
guint16 pid;
|
||||||
guint available;
|
|
||||||
guint8 *mapped;
|
/* Following variables are only active/used when
|
||||||
guint offset;
|
* calculate_skew is TRUE */
|
||||||
guint mapped_size;
|
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;
|
||||||
|
gint wrap_count;
|
||||||
|
|
||||||
/* Used for bitrate calculation */
|
/* Used for bitrate calculation */
|
||||||
/* FIXME : Replace this later on with a balanced tree or sequence */
|
/* FIXME : Replace this later on with a balanced tree or sequence */
|
||||||
|
@ -107,6 +117,16 @@ struct _MpegTSPacketizerPrivate
|
||||||
guint64 last_pcr;
|
guint64 last_pcr;
|
||||||
GstClockTime last_pcr_ts;
|
GstClockTime last_pcr_ts;
|
||||||
|
|
||||||
|
} MpegTSPCR;
|
||||||
|
|
||||||
|
struct _MpegTSPacketizerPrivate
|
||||||
|
{
|
||||||
|
/* Shortcuts for adapter usage */
|
||||||
|
guint available;
|
||||||
|
guint8 *mapped;
|
||||||
|
guint offset;
|
||||||
|
guint mapped_size;
|
||||||
|
|
||||||
/* Reference offset */
|
/* Reference offset */
|
||||||
guint64 refoffset;
|
guint64 refoffset;
|
||||||
|
|
||||||
|
@ -114,6 +134,11 @@ struct _MpegTSPacketizerPrivate
|
||||||
|
|
||||||
/* Last inputted timestamp */
|
/* Last inputted timestamp */
|
||||||
GstClockTime last_in_time;
|
GstClockTime last_in_time;
|
||||||
|
|
||||||
|
/* offset to observations table */
|
||||||
|
guint8 pcrtablelut[0x2000];
|
||||||
|
MpegTSPCR *observations[MAX_PCR_OBS_CHANNELS];
|
||||||
|
guint8 lastobsid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mpegts_packetizer_dispose (GObject * object);
|
static void mpegts_packetizer_dispose (GObject * object);
|
||||||
|
@ -123,11 +148,10 @@ static gchar *convert_to_utf8 (const gchar * text, gint length, guint start,
|
||||||
static gchar *get_encoding (const gchar * text, guint * start_text,
|
static gchar *get_encoding (const gchar * text, guint * start_text,
|
||||||
gboolean * is_multibyte);
|
gboolean * is_multibyte);
|
||||||
static gchar *get_encoding_and_convert (const gchar * text, guint length);
|
static gchar *get_encoding_and_convert (const gchar * text, guint length);
|
||||||
static GstClockTime calculate_skew (MpegTSPacketizer2 * packetizer,
|
static GstClockTime calculate_skew (MpegTSPCR * pcr,
|
||||||
guint64 pcrtime, GstClockTime time);
|
guint64 pcrtime, GstClockTime time);
|
||||||
static void record_pcr (MpegTSPacketizer2 * packetizer, guint64 pcr,
|
static void record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable,
|
||||||
guint64 offset);
|
guint64 pcr, guint64 offset);
|
||||||
static void mpegts_packetizer_reset_skew (MpegTSPacketizer2 * packetizer);
|
|
||||||
|
|
||||||
#define CONTINUITY_UNSET 255
|
#define CONTINUITY_UNSET 255
|
||||||
#define MAX_CONTINUITY 15
|
#define MAX_CONTINUITY 15
|
||||||
|
@ -135,6 +159,47 @@ static void mpegts_packetizer_reset_skew (MpegTSPacketizer2 * packetizer);
|
||||||
#define TABLE_ID_UNSET 0xFF
|
#define TABLE_ID_UNSET 0xFF
|
||||||
#define PACKET_SYNC_BYTE 0x47
|
#define PACKET_SYNC_BYTE 0x47
|
||||||
|
|
||||||
|
static MpegTSPCR *
|
||||||
|
get_pcr_table (MpegTSPacketizer2 * packetizer, guint16 pid)
|
||||||
|
{
|
||||||
|
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
||||||
|
MpegTSPCR *res;
|
||||||
|
|
||||||
|
res = priv->observations[priv->pcrtablelut[pid]];
|
||||||
|
|
||||||
|
if (G_UNLIKELY (res == NULL)) {
|
||||||
|
/* If we don't have a PCR table for the requested PID, create one .. */
|
||||||
|
res = g_new0 (MpegTSPCR, 1);
|
||||||
|
/* Add it to the last table position */
|
||||||
|
priv->observations[priv->lastobsid] = res;
|
||||||
|
/* Update the pcrtablelut */
|
||||||
|
priv->pcrtablelut[pid] = priv->lastobsid;
|
||||||
|
/* And increment the last know slot */
|
||||||
|
priv->lastobsid++;
|
||||||
|
|
||||||
|
/* Finally set the default values */
|
||||||
|
res->pid = pid;
|
||||||
|
res->first_offset = -1;
|
||||||
|
res->first_pcr = -1;
|
||||||
|
res->first_pcr_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
res->last_offset = -1;
|
||||||
|
res->last_pcr = -1;
|
||||||
|
res->last_pcr_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
res->base_time = GST_CLOCK_TIME_NONE;
|
||||||
|
res->base_pcrtime = GST_CLOCK_TIME_NONE;
|
||||||
|
res->last_pcrtime = GST_CLOCK_TIME_NONE;
|
||||||
|
res->window_pos = 0;
|
||||||
|
res->window_filling = TRUE;
|
||||||
|
res->window_min = 0;
|
||||||
|
res->skew = 0;
|
||||||
|
res->prev_send_diff = GST_CLOCK_TIME_NONE;
|
||||||
|
res->prev_out_time = GST_CLOCK_TIME_NONE;
|
||||||
|
res->wrap_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
mpegts_packetizer_stream_subtable_compare (gconstpointer a, gconstpointer b)
|
mpegts_packetizer_stream_subtable_compare (gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
|
@ -211,7 +276,9 @@ mpegts_packetizer_class_init (MpegTSPacketizer2Class * klass)
|
||||||
static void
|
static void
|
||||||
mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
|
mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
|
||||||
{
|
{
|
||||||
packetizer->priv = MPEGTS_PACKETIZER_GET_PRIVATE (packetizer);
|
MpegTSPacketizerPrivate *priv;
|
||||||
|
|
||||||
|
priv = packetizer->priv = MPEGTS_PACKETIZER_GET_PRIVATE (packetizer);
|
||||||
packetizer->adapter = gst_adapter_new ();
|
packetizer->adapter = gst_adapter_new ();
|
||||||
packetizer->offset = 0;
|
packetizer->offset = 0;
|
||||||
packetizer->empty = TRUE;
|
packetizer->empty = TRUE;
|
||||||
|
@ -219,22 +286,19 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
|
||||||
packetizer->know_packet_size = FALSE;
|
packetizer->know_packet_size = FALSE;
|
||||||
packetizer->calculate_skew = FALSE;
|
packetizer->calculate_skew = FALSE;
|
||||||
packetizer->calculate_offset = FALSE;
|
packetizer->calculate_offset = FALSE;
|
||||||
mpegts_packetizer_reset_skew (packetizer);
|
|
||||||
|
|
||||||
packetizer->priv->available = 0;
|
priv->available = 0;
|
||||||
packetizer->priv->mapped = NULL;
|
priv->mapped = NULL;
|
||||||
packetizer->priv->mapped_size = 0;
|
priv->mapped_size = 0;
|
||||||
packetizer->priv->offset = 0;
|
priv->offset = 0;
|
||||||
|
|
||||||
packetizer->priv->first_offset = -1;
|
memset (priv->pcrtablelut, 0xff, 0x200);
|
||||||
packetizer->priv->first_pcr = -1;
|
memset (priv->observations, 0x0, sizeof (priv->observations));
|
||||||
packetizer->priv->first_pcr_ts = GST_CLOCK_TIME_NONE;
|
priv->lastobsid = 0;
|
||||||
packetizer->priv->last_offset = -1;
|
|
||||||
packetizer->priv->last_pcr = -1;
|
priv->nb_seen_offsets = 0;
|
||||||
packetizer->priv->last_pcr_ts = GST_CLOCK_TIME_NONE;
|
priv->refoffset = -1;
|
||||||
packetizer->priv->nb_seen_offsets = 0;
|
priv->last_in_time = GST_CLOCK_TIME_NONE;
|
||||||
packetizer->priv->refoffset = -1;
|
|
||||||
packetizer->priv->last_in_time = GST_CLOCK_TIME_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -331,15 +395,22 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
|
||||||
|
|
||||||
/* PCR */
|
/* PCR */
|
||||||
if (afcflags & MPEGTS_AFC_PCR_FLAG) {
|
if (afcflags & MPEGTS_AFC_PCR_FLAG) {
|
||||||
|
MpegTSPCR *pcrtable = NULL;
|
||||||
packet->pcr = mpegts_packetizer_compute_pcr (data);
|
packet->pcr = mpegts_packetizer_compute_pcr (data);
|
||||||
*data += 6;
|
data += 6;
|
||||||
GST_DEBUG ("pcr %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT ")",
|
GST_DEBUG ("pcr 0x%04x %" G_GUINT64_FORMAT " (%" GST_TIME_FORMAT
|
||||||
packet->pcr, GST_TIME_ARGS (PCRTIME_TO_GSTTIME (packet->pcr)));
|
") offset:%" G_GUINT64_FORMAT, packet->pid, packet->pcr,
|
||||||
|
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (packet->pcr)), packet->offset);
|
||||||
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (packet->origts) && packetizer->calculate_skew)
|
if (GST_CLOCK_TIME_IS_VALID (packet->origts) && packetizer->calculate_skew) {
|
||||||
packet->origts = calculate_skew (packetizer, packet->pcr, packet->origts);
|
pcrtable = get_pcr_table (packetizer, packet->pid);
|
||||||
if (packetizer->calculate_offset)
|
packet->origts = calculate_skew (pcrtable, packet->pcr, packet->origts);
|
||||||
record_pcr (packetizer, packet->pcr, packet->offset);
|
}
|
||||||
|
if (packetizer->calculate_offset) {
|
||||||
|
if (!pcrtable)
|
||||||
|
pcrtable = get_pcr_table (packetizer, packet->pid);
|
||||||
|
record_pcr (packetizer, pcrtable, packet->pcr, packet->offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OPCR */
|
/* OPCR */
|
||||||
|
@ -3006,44 +3077,20 @@ failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mpegts_packetizer_reset_skew:
|
|
||||||
* @packetizer: an #MpegTSPacketizer2
|
|
||||||
*
|
|
||||||
* Reset the skew calculations in @packetizer.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
mpegts_packetizer_reset_skew (MpegTSPacketizer2 * packetizer)
|
mpegts_packetizer_resync (MpegTSPCR * pcr, GstClockTime time,
|
||||||
{
|
|
||||||
/* FIXME : These variables should be *per* PCR PID */
|
|
||||||
packetizer->base_time = GST_CLOCK_TIME_NONE;
|
|
||||||
packetizer->base_pcrtime = GST_CLOCK_TIME_NONE;
|
|
||||||
packetizer->last_pcrtime = GST_CLOCK_TIME_NONE;
|
|
||||||
packetizer->window_pos = 0;
|
|
||||||
packetizer->window_filling = TRUE;
|
|
||||||
packetizer->window_min = 0;
|
|
||||||
packetizer->skew = 0;
|
|
||||||
packetizer->prev_send_diff = GST_CLOCK_TIME_NONE;
|
|
||||||
packetizer->prev_out_time = GST_CLOCK_TIME_NONE;
|
|
||||||
packetizer->wrap_count = 0;
|
|
||||||
GST_DEBUG ("reset skew correction");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mpegts_packetizer_resync (MpegTSPacketizer2 * packetizer, GstClockTime time,
|
|
||||||
GstClockTime gstpcrtime, gboolean reset_skew)
|
GstClockTime gstpcrtime, gboolean reset_skew)
|
||||||
{
|
{
|
||||||
/* FIXME : These variables should be *per* PCR PID */
|
pcr->base_time = time;
|
||||||
packetizer->base_time = time;
|
pcr->base_pcrtime = gstpcrtime;
|
||||||
packetizer->base_pcrtime = gstpcrtime;
|
pcr->prev_out_time = GST_CLOCK_TIME_NONE;
|
||||||
packetizer->prev_out_time = GST_CLOCK_TIME_NONE;
|
pcr->prev_send_diff = GST_CLOCK_TIME_NONE;
|
||||||
packetizer->prev_send_diff = GST_CLOCK_TIME_NONE;
|
|
||||||
if (reset_skew) {
|
if (reset_skew) {
|
||||||
packetizer->window_filling = TRUE;
|
pcr->window_filling = TRUE;
|
||||||
packetizer->window_pos = 0;
|
pcr->window_pos = 0;
|
||||||
packetizer->window_min = 0;
|
pcr->window_min = 0;
|
||||||
packetizer->window_size = 0;
|
pcr->window_size = 0;
|
||||||
packetizer->skew = 0;
|
pcr->skew = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3113,8 +3160,7 @@ mpegts_packetizer_resync (MpegTSPacketizer2 * packetizer, GstClockTime time,
|
||||||
* Returns: @time adjusted with the clock skew.
|
* Returns: @time adjusted with the clock skew.
|
||||||
*/
|
*/
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
|
calculate_skew (MpegTSPCR * pcr, guint64 pcrtime, GstClockTime time)
|
||||||
GstClockTime time)
|
|
||||||
{
|
{
|
||||||
guint64 send_diff, recv_diff;
|
guint64 send_diff, recv_diff;
|
||||||
gint64 delta;
|
gint64 delta;
|
||||||
|
@ -3124,60 +3170,59 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
|
||||||
guint64 slope;
|
guint64 slope;
|
||||||
|
|
||||||
gstpcrtime =
|
gstpcrtime =
|
||||||
PCRTIME_TO_GSTTIME (pcrtime) + packetizer->wrap_count * PCR_GST_MAX_VALUE;
|
PCRTIME_TO_GSTTIME (pcrtime) + pcr->wrap_count * PCR_GST_MAX_VALUE;
|
||||||
|
|
||||||
/* first time, lock on to time and gstpcrtime */
|
/* first time, lock on to time and gstpcrtime */
|
||||||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (packetizer->base_time))) {
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pcr->base_time))) {
|
||||||
packetizer->base_time = time;
|
pcr->base_time = time;
|
||||||
packetizer->prev_out_time = GST_CLOCK_TIME_NONE;
|
pcr->prev_out_time = GST_CLOCK_TIME_NONE;
|
||||||
GST_DEBUG ("Taking new base time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
|
GST_DEBUG ("Taking new base time %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (packetizer->base_pcrtime))) {
|
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pcr->base_pcrtime))) {
|
||||||
packetizer->base_pcrtime = gstpcrtime;
|
pcr->base_pcrtime = gstpcrtime;
|
||||||
packetizer->prev_send_diff = -1;
|
pcr->prev_send_diff = -1;
|
||||||
GST_DEBUG ("Taking new base pcrtime %" GST_TIME_FORMAT,
|
GST_DEBUG ("Taking new base pcrtime %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (gstpcrtime));
|
GST_TIME_ARGS (gstpcrtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_LIKELY (gstpcrtime >= packetizer->base_pcrtime))
|
if (G_LIKELY (gstpcrtime >= pcr->base_pcrtime))
|
||||||
send_diff = gstpcrtime - packetizer->base_pcrtime;
|
send_diff = gstpcrtime - pcr->base_pcrtime;
|
||||||
else if (GST_CLOCK_TIME_IS_VALID (time)
|
else if (GST_CLOCK_TIME_IS_VALID (time)
|
||||||
&& (packetizer->last_pcrtime - gstpcrtime > PCR_GST_MAX_VALUE / 2)) {
|
&& (pcr->last_pcrtime - gstpcrtime > PCR_GST_MAX_VALUE / 2)) {
|
||||||
/* Detect wraparounds */
|
/* Detect wraparounds */
|
||||||
GST_DEBUG ("PCR wrap");
|
GST_DEBUG ("PCR wrap");
|
||||||
packetizer->wrap_count++;
|
pcr->wrap_count++;
|
||||||
gstpcrtime =
|
gstpcrtime =
|
||||||
PCRTIME_TO_GSTTIME (pcrtime) +
|
PCRTIME_TO_GSTTIME (pcrtime) + pcr->wrap_count * PCR_GST_MAX_VALUE;
|
||||||
packetizer->wrap_count * PCR_GST_MAX_VALUE;
|
send_diff = gstpcrtime - pcr->base_pcrtime;
|
||||||
send_diff = gstpcrtime - packetizer->base_pcrtime;
|
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("backward timestamps at server but no timestamps");
|
GST_WARNING ("backward timestamps at server but no timestamps");
|
||||||
send_diff = 0;
|
send_diff = 0;
|
||||||
/* at least try to get a new timestamp.. */
|
/* at least try to get a new timestamp.. */
|
||||||
packetizer->base_time = GST_CLOCK_TIME_NONE;
|
pcr->base_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("gstpcr %" GST_TIME_FORMAT ", buftime %" GST_TIME_FORMAT ", base %"
|
GST_DEBUG ("gstpcr %" GST_TIME_FORMAT ", buftime %" GST_TIME_FORMAT ", base %"
|
||||||
GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT,
|
GST_TIME_FORMAT ", send_diff %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (gstpcrtime), GST_TIME_ARGS (time),
|
GST_TIME_ARGS (gstpcrtime), GST_TIME_ARGS (time),
|
||||||
GST_TIME_ARGS (packetizer->base_pcrtime), GST_TIME_ARGS (send_diff));
|
GST_TIME_ARGS (pcr->base_pcrtime), GST_TIME_ARGS (send_diff));
|
||||||
|
|
||||||
/* keep track of the last extended pcrtime */
|
/* keep track of the last extended pcrtime */
|
||||||
packetizer->last_pcrtime = gstpcrtime;
|
pcr->last_pcrtime = gstpcrtime;
|
||||||
|
|
||||||
/* we don't have an arrival timestamp so we can't do skew detection. we
|
/* we don't have an arrival timestamp so we can't do skew detection. we
|
||||||
* should still apply a timestamp based on RTP timestamp and base_time */
|
* should still apply a timestamp based on RTP timestamp and base_time */
|
||||||
if (!GST_CLOCK_TIME_IS_VALID (time)
|
if (!GST_CLOCK_TIME_IS_VALID (time)
|
||||||
|| !GST_CLOCK_TIME_IS_VALID (packetizer->base_time))
|
|| !GST_CLOCK_TIME_IS_VALID (pcr->base_time))
|
||||||
goto no_skew;
|
goto no_skew;
|
||||||
|
|
||||||
/* elapsed time at receiver, includes the jitter */
|
/* elapsed time at receiver, includes the jitter */
|
||||||
recv_diff = time - packetizer->base_time;
|
recv_diff = time - pcr->base_time;
|
||||||
|
|
||||||
/* Ignore packets received at 100% the same time (i.e. from the same input buffer) */
|
/* Ignore packets received at 100% the same time (i.e. from the same input buffer) */
|
||||||
if (G_UNLIKELY (time == packetizer->prev_in_time
|
if (G_UNLIKELY (time == pcr->prev_in_time
|
||||||
&& GST_CLOCK_TIME_IS_VALID (packetizer->prev_in_time)))
|
&& GST_CLOCK_TIME_IS_VALID (pcr->prev_in_time)))
|
||||||
goto no_skew;
|
goto no_skew;
|
||||||
|
|
||||||
/* measure the diff */
|
/* measure the diff */
|
||||||
|
@ -3190,38 +3235,38 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
|
||||||
|
|
||||||
GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
|
GST_DEBUG ("time %" GST_TIME_FORMAT ", base %" GST_TIME_FORMAT ", recv_diff %"
|
||||||
GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
|
GST_TIME_FORMAT ", slope %" G_GUINT64_FORMAT, GST_TIME_ARGS (time),
|
||||||
GST_TIME_ARGS (packetizer->base_time), GST_TIME_ARGS (recv_diff), slope);
|
GST_TIME_ARGS (pcr->base_time), GST_TIME_ARGS (recv_diff), slope);
|
||||||
|
|
||||||
/* if the difference between the sender timeline and the receiver timeline
|
/* if the difference between the sender timeline and the receiver timeline
|
||||||
* changed too quickly we have to resync because the server likely restarted
|
* changed too quickly we have to resync because the server likely restarted
|
||||||
* its timestamps. */
|
* its timestamps. */
|
||||||
if (ABS (delta - packetizer->skew) > GST_SECOND) {
|
if (ABS (delta - pcr->skew) > GST_SECOND) {
|
||||||
GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew",
|
GST_WARNING ("delta - skew: %" GST_TIME_FORMAT " too big, reset skew",
|
||||||
GST_TIME_ARGS (delta - packetizer->skew));
|
GST_TIME_ARGS (delta - pcr->skew));
|
||||||
mpegts_packetizer_resync (packetizer, time, gstpcrtime, TRUE);
|
mpegts_packetizer_resync (pcr, time, gstpcrtime, TRUE);
|
||||||
send_diff = 0;
|
send_diff = 0;
|
||||||
delta = 0;
|
delta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = packetizer->window_pos;
|
pos = pcr->window_pos;
|
||||||
|
|
||||||
if (G_UNLIKELY (packetizer->window_filling)) {
|
if (G_UNLIKELY (pcr->window_filling)) {
|
||||||
/* we are filling the window */
|
/* we are filling the window */
|
||||||
GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta);
|
GST_DEBUG ("filling %d, delta %" G_GINT64_FORMAT, pos, delta);
|
||||||
packetizer->window[pos++] = delta;
|
pcr->window[pos++] = delta;
|
||||||
/* calc the min delta we observed */
|
/* calc the min delta we observed */
|
||||||
if (G_UNLIKELY (pos == 1 || delta < packetizer->window_min))
|
if (G_UNLIKELY (pos == 1 || delta < pcr->window_min))
|
||||||
packetizer->window_min = delta;
|
pcr->window_min = delta;
|
||||||
|
|
||||||
if (G_UNLIKELY (send_diff >= MAX_TIME || pos >= MAX_WINDOW)) {
|
if (G_UNLIKELY (send_diff >= MAX_TIME || pos >= MAX_WINDOW)) {
|
||||||
packetizer->window_size = pos;
|
pcr->window_size = pos;
|
||||||
|
|
||||||
/* window filled */
|
/* window filled */
|
||||||
GST_DEBUG ("min %" G_GINT64_FORMAT, packetizer->window_min);
|
GST_DEBUG ("min %" G_GINT64_FORMAT, pcr->window_min);
|
||||||
|
|
||||||
/* the skew is now the min */
|
/* the skew is now the min */
|
||||||
packetizer->skew = packetizer->window_min;
|
pcr->skew = pcr->window_min;
|
||||||
packetizer->window_filling = FALSE;
|
pcr->window_filling = FALSE;
|
||||||
} else {
|
} else {
|
||||||
gint perc_time, perc_window, perc;
|
gint perc_time, perc_window, perc;
|
||||||
|
|
||||||
|
@ -3237,73 +3282,70 @@ calculate_skew (MpegTSPacketizer2 * packetizer, guint64 pcrtime,
|
||||||
|
|
||||||
/* quickly go to the min value when we are filling up, slowly when we are
|
/* quickly go to the min value when we are filling up, slowly when we are
|
||||||
* just starting because we're not sure it's a good value yet. */
|
* just starting because we're not sure it's a good value yet. */
|
||||||
packetizer->skew =
|
pcr->skew =
|
||||||
(perc * packetizer->window_min + ((10000 -
|
(perc * pcr->window_min + ((10000 - perc) * pcr->skew)) / 10000;
|
||||||
perc) * packetizer->skew)) / 10000;
|
pcr->window_size = pos + 1;
|
||||||
packetizer->window_size = pos + 1;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* pick old value and store new value. We keep the previous value in order
|
/* pick old value and store new value. We keep the previous value in order
|
||||||
* to quickly check if the min of the window changed */
|
* to quickly check if the min of the window changed */
|
||||||
old = packetizer->window[pos];
|
old = pcr->window[pos];
|
||||||
packetizer->window[pos++] = delta;
|
pcr->window[pos++] = delta;
|
||||||
|
|
||||||
if (G_UNLIKELY (delta <= packetizer->window_min)) {
|
if (G_UNLIKELY (delta <= pcr->window_min)) {
|
||||||
/* if the new value we inserted is smaller or equal to the current min,
|
/* if the new value we inserted is smaller or equal to the current min,
|
||||||
* it becomes the new min */
|
* it becomes the new min */
|
||||||
packetizer->window_min = delta;
|
pcr->window_min = delta;
|
||||||
} else if (G_UNLIKELY (old == packetizer->window_min)) {
|
} else if (G_UNLIKELY (old == pcr->window_min)) {
|
||||||
gint64 min = G_MAXINT64;
|
gint64 min = G_MAXINT64;
|
||||||
|
|
||||||
/* if we removed the old min, we have to find a new min */
|
/* if we removed the old min, we have to find a new min */
|
||||||
for (i = 0; i < packetizer->window_size; i++) {
|
for (i = 0; i < pcr->window_size; i++) {
|
||||||
/* we found another value equal to the old min, we can stop searching now */
|
/* we found another value equal to the old min, we can stop searching now */
|
||||||
if (packetizer->window[i] == old) {
|
if (pcr->window[i] == old) {
|
||||||
min = old;
|
min = old;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (packetizer->window[i] < min)
|
if (pcr->window[i] < min)
|
||||||
min = packetizer->window[i];
|
min = pcr->window[i];
|
||||||
}
|
}
|
||||||
packetizer->window_min = min;
|
pcr->window_min = min;
|
||||||
}
|
}
|
||||||
/* average the min values */
|
/* average the min values */
|
||||||
packetizer->skew =
|
pcr->skew = (pcr->window_min + (124 * pcr->skew)) / 125;
|
||||||
(packetizer->window_min + (124 * packetizer->skew)) / 125;
|
|
||||||
GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT, delta,
|
GST_DEBUG ("delta %" G_GINT64_FORMAT ", new min: %" G_GINT64_FORMAT, delta,
|
||||||
packetizer->window_min);
|
pcr->window_min);
|
||||||
}
|
}
|
||||||
/* wrap around in the window */
|
/* wrap around in the window */
|
||||||
if (G_UNLIKELY (pos >= packetizer->window_size))
|
if (G_UNLIKELY (pos >= pcr->window_size))
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
packetizer->window_pos = pos;
|
pcr->window_pos = pos;
|
||||||
|
|
||||||
no_skew:
|
no_skew:
|
||||||
/* the output time is defined as the base timestamp plus the PCR time
|
/* the output time is defined as the base timestamp plus the PCR time
|
||||||
* adjusted for the clock skew .*/
|
* adjusted for the clock skew .*/
|
||||||
if (packetizer->base_time != -1) {
|
if (pcr->base_time != -1) {
|
||||||
out_time = packetizer->base_time + send_diff;
|
out_time = pcr->base_time + send_diff;
|
||||||
/* skew can be negative and we don't want to make invalid timestamps */
|
/* skew can be negative and we don't want to make invalid timestamps */
|
||||||
if (packetizer->skew < 0 && out_time < -packetizer->skew) {
|
if (pcr->skew < 0 && out_time < -pcr->skew) {
|
||||||
out_time = 0;
|
out_time = 0;
|
||||||
} else {
|
} else {
|
||||||
out_time += packetizer->skew;
|
out_time += pcr->skew;
|
||||||
}
|
}
|
||||||
/* check if timestamps are not going backwards, we can only check this if we
|
/* check if timestamps are not going backwards, we can only check this if we
|
||||||
* have a previous out time and a previous send_diff */
|
* have a previous out time and a previous send_diff */
|
||||||
if (G_LIKELY (packetizer->prev_out_time != -1
|
if (G_LIKELY (pcr->prev_out_time != -1 && pcr->prev_send_diff != -1)) {
|
||||||
&& packetizer->prev_send_diff != -1)) {
|
|
||||||
/* now check for backwards timestamps */
|
/* now check for backwards timestamps */
|
||||||
if (G_UNLIKELY (
|
if (G_UNLIKELY (
|
||||||
/* if the server timestamps went up and the out_time backwards */
|
/* if the server timestamps went up and the out_time backwards */
|
||||||
(send_diff > packetizer->prev_send_diff
|
(send_diff > pcr->prev_send_diff
|
||||||
&& out_time < packetizer->prev_out_time) ||
|
&& out_time < pcr->prev_out_time) ||
|
||||||
/* if the server timestamps went backwards and the out_time forwards */
|
/* if the server timestamps went backwards and the out_time forwards */
|
||||||
(send_diff < packetizer->prev_send_diff
|
(send_diff < pcr->prev_send_diff
|
||||||
&& out_time > packetizer->prev_out_time) ||
|
&& out_time > pcr->prev_out_time) ||
|
||||||
/* if the server timestamps did not change */
|
/* if the server timestamps did not change */
|
||||||
send_diff == packetizer->prev_send_diff)) {
|
send_diff == pcr->prev_send_diff)) {
|
||||||
GST_DEBUG ("backwards timestamps, using previous time");
|
GST_DEBUG ("backwards timestamps, using previous time");
|
||||||
out_time = GSTTIME_TO_MPEGTIME (out_time);
|
out_time = GSTTIME_TO_MPEGTIME (out_time);
|
||||||
}
|
}
|
||||||
|
@ -3313,41 +3355,42 @@ no_skew:
|
||||||
out_time = time;
|
out_time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
packetizer->prev_out_time = out_time;
|
pcr->prev_out_time = out_time;
|
||||||
packetizer->prev_in_time = time;
|
pcr->prev_in_time = time;
|
||||||
packetizer->prev_send_diff = send_diff;
|
pcr->prev_send_diff = send_diff;
|
||||||
|
|
||||||
GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
|
GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
|
||||||
packetizer->skew, GST_TIME_ARGS (out_time));
|
pcr->skew, GST_TIME_ARGS (out_time));
|
||||||
|
|
||||||
return out_time;
|
return out_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
record_pcr (MpegTSPacketizer2 * packetizer, guint64 pcr, guint64 offset)
|
record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable, guint64 pcr,
|
||||||
|
guint64 offset)
|
||||||
{
|
{
|
||||||
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
||||||
|
|
||||||
/* Check against first PCR */
|
/* Check against first PCR */
|
||||||
if (priv->first_pcr == -1 || priv->first_offset > offset) {
|
if (pcrtable->first_pcr == -1 || pcrtable->first_offset > offset) {
|
||||||
GST_DEBUG ("Recording first value. PCR:%" G_GUINT64_FORMAT " offset:%"
|
GST_DEBUG ("Recording first value. PCR:%" G_GUINT64_FORMAT " offset:%"
|
||||||
G_GUINT64_FORMAT, pcr, offset);
|
G_GUINT64_FORMAT " pcr_pid:0x%04x", pcr, offset, pcrtable->pid);
|
||||||
priv->first_pcr = pcr;
|
pcrtable->first_pcr = pcr;
|
||||||
priv->first_pcr_ts = PCRTIME_TO_GSTTIME (pcr);
|
pcrtable->first_pcr_ts = PCRTIME_TO_GSTTIME (pcr);
|
||||||
priv->first_offset = offset;
|
pcrtable->first_offset = offset;
|
||||||
priv->nb_seen_offsets++;
|
priv->nb_seen_offsets++;
|
||||||
} else
|
} else
|
||||||
/* If we didn't update the first PCR, let's check against last PCR */
|
/* If we didn't update the first PCR, let's check against last PCR */
|
||||||
if (priv->last_pcr == -1 || priv->last_offset < offset) {
|
if (pcrtable->last_pcr == -1 || pcrtable->last_offset < offset) {
|
||||||
GST_DEBUG ("Recording last value. PCR:%" G_GUINT64_FORMAT " offset:%"
|
GST_DEBUG ("Recording last value. PCR:%" G_GUINT64_FORMAT " offset:%"
|
||||||
G_GUINT64_FORMAT, pcr, offset);
|
G_GUINT64_FORMAT " pcr_pid:0x%04x", pcr, offset, pcrtable->pid);
|
||||||
if (G_UNLIKELY (priv->first_pcr != -1 && pcr < priv->first_pcr)) {
|
if (G_UNLIKELY (pcrtable->first_pcr != -1 && pcr < pcrtable->first_pcr)) {
|
||||||
GST_DEBUG ("rollover detected");
|
GST_DEBUG ("rollover detected");
|
||||||
pcr += PCR_MAX_VALUE;
|
pcr += PCR_MAX_VALUE;
|
||||||
}
|
}
|
||||||
priv->last_pcr = pcr;
|
pcrtable->last_pcr = pcr;
|
||||||
priv->last_pcr_ts = PCRTIME_TO_GSTTIME (pcr);
|
pcrtable->last_pcr_ts = PCRTIME_TO_GSTTIME (pcr);
|
||||||
priv->last_offset = offset;
|
pcrtable->last_offset = offset;
|
||||||
priv->nb_seen_offsets++;
|
priv->nb_seen_offsets++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3359,9 +3402,11 @@ mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 * packetizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
GstClockTime
|
GstClockTime
|
||||||
mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset)
|
mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset,
|
||||||
|
guint16 pid)
|
||||||
{
|
{
|
||||||
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
||||||
|
MpegTSPCR *pcrtable;
|
||||||
GstClockTime res;
|
GstClockTime res;
|
||||||
|
|
||||||
if (G_UNLIKELY (!packetizer->calculate_offset))
|
if (G_UNLIKELY (!packetizer->calculate_offset))
|
||||||
|
@ -3373,10 +3418,12 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset)
|
||||||
if (G_UNLIKELY (offset < priv->refoffset))
|
if (G_UNLIKELY (offset < priv->refoffset))
|
||||||
return GST_CLOCK_TIME_NONE;
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
pcrtable = get_pcr_table (packetizer, pid);
|
||||||
|
|
||||||
/* Convert byte difference into time difference */
|
/* Convert byte difference into time difference */
|
||||||
res = PCRTIME_TO_GSTTIME (gst_util_uint64_scale (offset - priv->refoffset,
|
res = PCRTIME_TO_GSTTIME (gst_util_uint64_scale (offset - priv->refoffset,
|
||||||
priv->last_pcr - priv->first_pcr,
|
pcrtable->last_pcr - pcrtable->first_pcr,
|
||||||
priv->last_offset - priv->first_offset));
|
pcrtable->last_offset - pcrtable->first_offset));
|
||||||
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for offset %"
|
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for offset %"
|
||||||
G_GUINT64_FORMAT, GST_TIME_ARGS (res), offset);
|
G_GUINT64_FORMAT, GST_TIME_ARGS (res), offset);
|
||||||
|
|
||||||
|
@ -3384,48 +3431,57 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer, guint64 offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
GstClockTime
|
GstClockTime
|
||||||
mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, GstClockTime pts)
|
mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer, GstClockTime pts,
|
||||||
|
guint16 pcr_pid)
|
||||||
{
|
{
|
||||||
GstClockTime res = GST_CLOCK_TIME_NONE;
|
GstClockTime res = GST_CLOCK_TIME_NONE;
|
||||||
|
MpegTSPCR *pcrtable = get_pcr_table (packetizer, pcr_pid);
|
||||||
|
|
||||||
/* Use clock skew if present */
|
/* Use clock skew if present */
|
||||||
if (packetizer->calculate_skew
|
if (packetizer->calculate_skew
|
||||||
&& GST_CLOCK_TIME_IS_VALID (packetizer->base_time)) {
|
&& GST_CLOCK_TIME_IS_VALID (pcrtable->base_time)) {
|
||||||
GST_DEBUG ("pts %" G_GUINT64_FORMAT " base_pcrtime:%" G_GUINT64_FORMAT
|
GST_DEBUG ("pts %" G_GUINT64_FORMAT " base_pcrtime:%" G_GUINT64_FORMAT
|
||||||
" base_time:%" GST_TIME_FORMAT, pts, packetizer->base_pcrtime,
|
" base_time:%" GST_TIME_FORMAT, pts, pcrtable->base_pcrtime,
|
||||||
GST_TIME_ARGS (packetizer->base_time));
|
GST_TIME_ARGS (pcrtable->base_time));
|
||||||
res = pts - packetizer->base_pcrtime + packetizer->base_time +
|
res = pts - pcrtable->base_pcrtime + pcrtable->base_time + pcrtable->skew;
|
||||||
packetizer->skew;
|
|
||||||
} else
|
} else
|
||||||
/* If not, use pcr observations */
|
/* If not, use pcr observations */
|
||||||
if (packetizer->calculate_offset && packetizer->priv->first_pcr != -1) {
|
if (packetizer->calculate_offset && pcrtable->first_pcr != -1) {
|
||||||
/* Rollover */
|
/* Rollover */
|
||||||
if (G_UNLIKELY (pts < packetizer->priv->first_pcr_ts))
|
if (G_UNLIKELY (pts < pcrtable->first_pcr_ts))
|
||||||
pts += MPEGTIME_TO_GSTTIME (PTS_DTS_MAX_VALUE);
|
pts += MPEGTIME_TO_GSTTIME (PTS_DTS_MAX_VALUE);
|
||||||
res = pts - packetizer->priv->first_pcr_ts;
|
res = pts - pcrtable->first_pcr_ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for pts %"
|
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for pts %"
|
||||||
GST_TIME_FORMAT, GST_TIME_ARGS (res), GST_TIME_ARGS (pts));
|
GST_TIME_FORMAT " pcr_pid:0x%04x", GST_TIME_ARGS (res),
|
||||||
|
GST_TIME_ARGS (pts), pcr_pid);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint64
|
guint64
|
||||||
mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, GstClockTime ts)
|
mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer, GstClockTime ts,
|
||||||
|
guint16 pcr_pid)
|
||||||
{
|
{
|
||||||
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
MpegTSPacketizerPrivate *priv = packetizer->priv;
|
||||||
|
MpegTSPCR *pcrtable;
|
||||||
guint64 res;
|
guint64 res;
|
||||||
|
|
||||||
if (!packetizer->calculate_offset || packetizer->priv->first_pcr == -1)
|
if (!packetizer->calculate_offset)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pcrtable = get_pcr_table (packetizer, pcr_pid);
|
||||||
|
if (pcrtable->first_pcr == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
GST_DEBUG ("ts(pcr) %" G_GUINT64_FORMAT " first_pcr:%" G_GUINT64_FORMAT,
|
GST_DEBUG ("ts(pcr) %" G_GUINT64_FORMAT " first_pcr:%" G_GUINT64_FORMAT,
|
||||||
GSTTIME_TO_MPEGTIME (ts), priv->first_pcr);
|
GSTTIME_TO_MPEGTIME (ts), pcrtable->first_pcr);
|
||||||
|
|
||||||
/* Convert ts to PCRTIME */
|
/* Convert ts to PCRTIME */
|
||||||
res = gst_util_uint64_scale (GSTTIME_TO_PCRTIME (ts),
|
res = gst_util_uint64_scale (GSTTIME_TO_PCRTIME (ts),
|
||||||
priv->last_offset - priv->first_offset, priv->last_pcr - priv->first_pcr);
|
pcrtable->last_offset - pcrtable->first_offset,
|
||||||
res += priv->first_offset + priv->refoffset;
|
pcrtable->last_pcr - pcrtable->first_pcr);
|
||||||
|
res += pcrtable->first_offset + priv->refoffset;
|
||||||
|
|
||||||
GST_DEBUG ("Returning offset %" G_GUINT64_FORMAT " for ts %" GST_TIME_FORMAT,
|
GST_DEBUG ("Returning offset %" G_GUINT64_FORMAT " for ts %" GST_TIME_FORMAT,
|
||||||
res, GST_TIME_ARGS (ts));
|
res, GST_TIME_ARGS (ts));
|
||||||
|
|
|
@ -100,23 +100,6 @@ struct _MpegTSPacketizer2 {
|
||||||
/* clock skew calculation */
|
/* clock skew calculation */
|
||||||
gboolean calculate_skew;
|
gboolean calculate_skew;
|
||||||
|
|
||||||
/* Following variables are only active/used when
|
|
||||||
* calculate_skew is TRUE */
|
|
||||||
/* FIXME : These variables should be *per* PCR PID */
|
|
||||||
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;
|
|
||||||
gint wrap_count;
|
|
||||||
|
|
||||||
/* offset/bitrate calculator */
|
/* offset/bitrate calculator */
|
||||||
gboolean calculate_offset;
|
gboolean calculate_offset;
|
||||||
|
|
||||||
|
@ -220,13 +203,13 @@ guint mpegts_packetizer_get_seen_pcr (MpegTSPacketizer2 *packetizer);
|
||||||
|
|
||||||
GstClockTime
|
GstClockTime
|
||||||
mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
|
mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
guint64 offset);
|
guint64 offset, guint16 pcr_pid);
|
||||||
guint64
|
guint64
|
||||||
mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer,
|
mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer,
|
||||||
GstClockTime ts);
|
GstClockTime ts, guint16 pcr_pid);
|
||||||
GstClockTime
|
GstClockTime
|
||||||
mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
|
mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
GstClockTime pts);
|
GstClockTime pts, guint16 pcr_pid);
|
||||||
void
|
void
|
||||||
mpegts_packetizer_set_reference_offset (MpegTSPacketizer2 * packetizer,
|
mpegts_packetizer_set_reference_offset (MpegTSPacketizer2 * packetizer,
|
||||||
guint64 refoffset);
|
guint64 refoffset);
|
||||||
|
|
|
@ -405,7 +405,8 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
else {
|
else {
|
||||||
GstClockTime dur =
|
GstClockTime dur =
|
||||||
mpegts_packetizer_offset_to_ts (base->packetizer, val);
|
mpegts_packetizer_offset_to_ts (base->packetizer, val,
|
||||||
|
demux->program->pcr_pid);
|
||||||
if (GST_CLOCK_TIME_IS_VALID (dur))
|
if (GST_CLOCK_TIME_IS_VALID (dur))
|
||||||
gst_query_set_duration (query, GST_FORMAT_TIME, dur);
|
gst_query_set_duration (query, GST_FORMAT_TIME, dur);
|
||||||
else
|
else
|
||||||
|
@ -523,7 +524,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event)
|
||||||
/* Convert start/stop to offset */
|
/* Convert start/stop to offset */
|
||||||
start_offset =
|
start_offset =
|
||||||
mpegts_packetizer_ts_to_offset (base->packetizer, MAX (0,
|
mpegts_packetizer_ts_to_offset (base->packetizer, MAX (0,
|
||||||
start - SEEK_TIMESTAMP_OFFSET));
|
start - SEEK_TIMESTAMP_OFFSET), demux->program->pcr_pid);
|
||||||
|
|
||||||
if (G_UNLIKELY (start_offset == -1)) {
|
if (G_UNLIKELY (start_offset == -1)) {
|
||||||
GST_WARNING ("Couldn't convert start position to an offset");
|
GST_WARNING ("Couldn't convert start position to an offset");
|
||||||
|
@ -1434,7 +1435,9 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GST_CLOCK_TIME_IS_VALID (lowest_pts))
|
if (GST_CLOCK_TIME_IS_VALID (lowest_pts))
|
||||||
firstts = mpegts_packetizer_pts_to_ts (base->packetizer, lowest_pts);
|
firstts =
|
||||||
|
mpegts_packetizer_pts_to_ts (base->packetizer, lowest_pts,
|
||||||
|
demux->program->pcr_pid);
|
||||||
GST_DEBUG ("lowest_pts %" G_GUINT64_FORMAT " => clocktime %" GST_TIME_FORMAT,
|
GST_DEBUG ("lowest_pts %" G_GUINT64_FORMAT " => clocktime %" GST_TIME_FORMAT,
|
||||||
lowest_pts, GST_TIME_ARGS (firstts));
|
lowest_pts, GST_TIME_ARGS (firstts));
|
||||||
|
|
||||||
|
@ -1536,10 +1539,12 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
GST_TIME_ARGS (stream->pts));
|
GST_TIME_ARGS (stream->pts));
|
||||||
if (GST_CLOCK_TIME_IS_VALID (stream->pts))
|
if (GST_CLOCK_TIME_IS_VALID (stream->pts))
|
||||||
GST_BUFFER_PTS (buffer) =
|
GST_BUFFER_PTS (buffer) =
|
||||||
mpegts_packetizer_pts_to_ts (packetizer, stream->pts);
|
mpegts_packetizer_pts_to_ts (packetizer, stream->pts,
|
||||||
|
demux->program->pcr_pid);
|
||||||
if (GST_CLOCK_TIME_IS_VALID (stream->dts))
|
if (GST_CLOCK_TIME_IS_VALID (stream->dts))
|
||||||
GST_BUFFER_DTS (buffer) =
|
GST_BUFFER_DTS (buffer) =
|
||||||
mpegts_packetizer_pts_to_ts (packetizer, stream->dts);
|
mpegts_packetizer_pts_to_ts (packetizer, stream->dts,
|
||||||
|
demux->program->pcr_pid);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (stream->pad,
|
GST_DEBUG_OBJECT (stream->pad,
|
||||||
"Pushing buffer with timestamp: %" GST_TIME_FORMAT,
|
"Pushing buffer with timestamp: %" GST_TIME_FORMAT,
|
||||||
|
|
Loading…
Reference in a new issue