mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-25 07:26:29 +00:00
tsdemux: Add locking around mpegtspacketiser groups.
Otherwise occasionally DURATION queries can crash, if they happen at the wrong moment.
This commit is contained in:
parent
6e51790a11
commit
c103f7134b
2 changed files with 40 additions and 3 deletions
|
@ -45,6 +45,9 @@ G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0,
|
||||||
|
|
||||||
#define ABSDIFF(a,b) ((a) < (b) ? (b) - (a) : (a) - (b))
|
#define ABSDIFF(a,b) ((a) < (b) ? (b) - (a) : (a) - (b))
|
||||||
|
|
||||||
|
#define PACKETIZER_GROUP_LOCK(p) g_mutex_lock(&((p)->group_lock))
|
||||||
|
#define PACKETIZER_GROUP_UNLOCK(p) g_mutex_unlock(&((p)->group_lock))
|
||||||
|
|
||||||
static void mpegts_packetizer_dispose (GObject * object);
|
static void mpegts_packetizer_dispose (GObject * object);
|
||||||
static void mpegts_packetizer_finalize (GObject * object);
|
static void mpegts_packetizer_finalize (GObject * object);
|
||||||
static GstClockTime calculate_skew (MpegTSPCR * pcr, guint64 pcrtime,
|
static GstClockTime calculate_skew (MpegTSPCR * pcr, guint64 pcrtime,
|
||||||
|
@ -234,6 +237,8 @@ mpegts_packetizer_class_init (MpegTSPacketizer2Class * klass)
|
||||||
static void
|
static void
|
||||||
mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
|
mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
|
||||||
{
|
{
|
||||||
|
g_mutex_init (&packetizer->group_lock);
|
||||||
|
|
||||||
packetizer->adapter = gst_adapter_new ();
|
packetizer->adapter = gst_adapter_new ();
|
||||||
packetizer->offset = 0;
|
packetizer->offset = 0;
|
||||||
packetizer->empty = TRUE;
|
packetizer->empty = TRUE;
|
||||||
|
@ -374,6 +379,7 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
|
||||||
") offset:%" G_GUINT64_FORMAT, packet->pid, packet->pcr,
|
") offset:%" G_GUINT64_FORMAT, packet->pid, packet->pcr,
|
||||||
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (packet->pcr)), packet->offset);
|
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (packet->pcr)), packet->offset);
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
if (packetizer->calculate_skew
|
if (packetizer->calculate_skew
|
||||||
&& GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) {
|
&& GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) {
|
||||||
pcrtable = get_pcr_table (packetizer, packet->pid);
|
pcrtable = get_pcr_table (packetizer, packet->pid);
|
||||||
|
@ -384,6 +390,7 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
|
||||||
pcrtable = get_pcr_table (packetizer, packet->pid);
|
pcrtable = get_pcr_table (packetizer, packet->pid);
|
||||||
record_pcr (packetizer, pcrtable, packet->pcr, packet->offset);
|
record_pcr (packetizer, pcrtable, packet->pcr, packet->offset);
|
||||||
}
|
}
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
}
|
}
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
/* OPCR */
|
/* OPCR */
|
||||||
|
@ -560,12 +567,15 @@ mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer)
|
||||||
packetizer->last_in_time = GST_CLOCK_TIME_NONE;
|
packetizer->last_in_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
/* Close current PCR group */
|
/* Close current PCR group */
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
|
|
||||||
for (i = 0; i < MAX_PCR_OBS_CHANNELS; i++) {
|
for (i = 0; i < MAX_PCR_OBS_CHANNELS; i++) {
|
||||||
if (packetizer->observations[i])
|
if (packetizer->observations[i])
|
||||||
_close_current_group (packetizer->observations[i]);
|
_close_current_group (packetizer->observations[i]);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -592,12 +602,14 @@ mpegts_packetizer_flush (MpegTSPacketizer2 * packetizer, gboolean hard)
|
||||||
packetizer->last_in_time = GST_CLOCK_TIME_NONE;
|
packetizer->last_in_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
/* Close current PCR group */
|
/* Close current PCR group */
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
for (i = 0; i < MAX_PCR_OBS_CHANNELS; i++) {
|
for (i = 0; i < MAX_PCR_OBS_CHANNELS; i++) {
|
||||||
if (packetizer->observations[i])
|
if (packetizer->observations[i])
|
||||||
_close_current_group (packetizer->observations[i]);
|
_close_current_group (packetizer->observations[i]);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
|
|
||||||
if (hard) {
|
if (hard) {
|
||||||
/* For pull mode seeks in tsdemux the observation must be preserved */
|
/* For pull mode seeks in tsdemux the observation must be preserved */
|
||||||
|
@ -2078,9 +2090,12 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
if (G_UNLIKELY (offset < packetizer->refoffset))
|
if (G_UNLIKELY (offset < packetizer->refoffset))
|
||||||
return GST_CLOCK_TIME_NONE;
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
|
|
||||||
pcrtable = get_pcr_table (packetizer, pid);
|
pcrtable = get_pcr_table (packetizer, pid);
|
||||||
|
|
||||||
if (g_list_length (pcrtable->groups) < 1) {
|
if (g_list_length (pcrtable->groups) < 1) {
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
GST_WARNING ("Not enough observations to return a duration estimate");
|
GST_WARNING ("Not enough observations to return a duration estimate");
|
||||||
return GST_CLOCK_TIME_NONE;
|
return GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
|
@ -2117,6 +2132,9 @@ mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
res =
|
res =
|
||||||
PCRTIME_TO_GSTTIME (gst_util_uint64_scale (offset - packetizer->refoffset,
|
PCRTIME_TO_GSTTIME (gst_util_uint64_scale (offset - packetizer->refoffset,
|
||||||
lastpcr, lastoffset));
|
lastpcr, lastoffset));
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -2130,7 +2148,10 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
GstClockTime pts, guint16 pcr_pid)
|
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);
|
MpegTSPCR *pcrtable;
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
|
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
|
||||||
|
@ -2232,6 +2253,8 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
|
||||||
} else
|
} else
|
||||||
GST_WARNING ("Not enough information to calculate proper timestamp");
|
GST_WARNING ("Not enough information to calculate proper timestamp");
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
|
|
||||||
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for pts %"
|
GST_DEBUG ("Returning timestamp %" GST_TIME_FORMAT " for pts %"
|
||||||
GST_TIME_FORMAT " pcr_pid:0x%04x", GST_TIME_ARGS (res),
|
GST_TIME_FORMAT " pcr_pid:0x%04x", GST_TIME_ARGS (res),
|
||||||
GST_TIME_ARGS (pts), pcr_pid);
|
GST_TIME_ARGS (pts), pcr_pid);
|
||||||
|
@ -2253,10 +2276,13 @@ mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer,
|
||||||
if (!packetizer->calculate_offset)
|
if (!packetizer->calculate_offset)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
pcrtable = get_pcr_table (packetizer, pcr_pid);
|
pcrtable = get_pcr_table (packetizer, pcr_pid);
|
||||||
|
|
||||||
if (pcrtable->groups == NULL)
|
if (pcrtable->groups == NULL) {
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
querypcr = GSTTIME_TO_PCRTIME (ts);
|
querypcr = GSTTIME_TO_PCRTIME (ts);
|
||||||
|
|
||||||
|
@ -2333,6 +2359,8 @@ calculate_points:
|
||||||
prevgroup->values[prevgroup->last_value].pcr + prevgroup->pcr_offset;
|
prevgroup->values[prevgroup->last_value].pcr + prevgroup->pcr_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
|
|
||||||
GST_DEBUG ("Using prev PCR %" G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT,
|
GST_DEBUG ("Using prev PCR %" G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT,
|
||||||
firstpcr, firstoffset);
|
firstpcr, firstoffset);
|
||||||
GST_DEBUG ("Using last PCR %" G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT,
|
GST_DEBUG ("Using last PCR %" G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT,
|
||||||
|
@ -2355,7 +2383,9 @@ mpegts_packetizer_set_reference_offset (MpegTSPacketizer2 * packetizer,
|
||||||
{
|
{
|
||||||
GST_DEBUG ("Setting reference offset to %" G_GUINT64_FORMAT, refoffset);
|
GST_DEBUG ("Setting reference offset to %" G_GUINT64_FORMAT, refoffset);
|
||||||
|
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
packetizer->refoffset = refoffset;
|
packetizer->refoffset = refoffset;
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2370,10 +2400,13 @@ mpegts_packetizer_set_current_pcr_offset (MpegTSPacketizer2 * packetizer,
|
||||||
gboolean apply = FALSE;
|
gboolean apply = FALSE;
|
||||||
|
|
||||||
/* fast path */
|
/* fast path */
|
||||||
|
PACKETIZER_GROUP_LOCK (packetizer);
|
||||||
pcrtable = get_pcr_table (packetizer, pcr_pid);
|
pcrtable = get_pcr_table (packetizer, pcr_pid);
|
||||||
|
|
||||||
if (pcrtable == NULL || pcrtable->current->group == NULL)
|
if (pcrtable == NULL || pcrtable->current->group == NULL) {
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pcr_offset = GSTTIME_TO_PCRTIME (offset);
|
pcr_offset = GSTTIME_TO_PCRTIME (offset);
|
||||||
|
|
||||||
|
@ -2393,6 +2426,7 @@ mpegts_packetizer_set_current_pcr_offset (MpegTSPacketizer2 * packetizer,
|
||||||
delta = pcr_offset - group->pcr_offset;
|
delta = pcr_offset - group->pcr_offset;
|
||||||
if (delta == 0) {
|
if (delta == 0) {
|
||||||
GST_DEBUG ("No shift to apply");
|
GST_DEBUG ("No shift to apply");
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GST_DEBUG ("Shifting groups by %" GST_TIME_FORMAT
|
GST_DEBUG ("Shifting groups by %" GST_TIME_FORMAT
|
||||||
|
@ -2417,4 +2451,5 @@ mpegts_packetizer_set_current_pcr_offset (MpegTSPacketizer2 * packetizer,
|
||||||
tgroup->first_offset,
|
tgroup->first_offset,
|
||||||
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (tgroup->pcr_offset)));
|
GST_TIME_ARGS (PCRTIME_TO_GSTTIME (tgroup->pcr_offset)));
|
||||||
}
|
}
|
||||||
|
PACKETIZER_GROUP_UNLOCK (packetizer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,8 @@ typedef struct _MpegTSPCR
|
||||||
struct _MpegTSPacketizer2 {
|
struct _MpegTSPacketizer2 {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
|
GMutex group_lock;
|
||||||
|
|
||||||
GstAdapter *adapter;
|
GstAdapter *adapter;
|
||||||
/* streams hashed by pid */
|
/* streams hashed by pid */
|
||||||
/* FIXME : be more memory efficient (see how it's done in mpegtsbase) */
|
/* FIXME : be more memory efficient (see how it's done in mpegtsbase) */
|
||||||
|
|
Loading…
Reference in a new issue