mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-18 13:25:56 +00:00
- Keep track of pending clock waits so we can unlock them
Original commit message from CVS: - Keep track of pending clock waits so we can unlock them - don't wait when diff bigger than configurable max to avoid clock lockups
This commit is contained in:
parent
fb9970d85a
commit
290a082d53
4 changed files with 59 additions and 13 deletions
|
@ -29,9 +29,12 @@
|
||||||
#include "gstlog.h"
|
#include "gstlog.h"
|
||||||
#include "gstmemchunk.h"
|
#include "gstmemchunk.h"
|
||||||
|
|
||||||
|
#define DEFAULT_MAX_DIFF (2 * GST_SECOND)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ARG_0,
|
ARG_0,
|
||||||
ARG_STATS,
|
ARG_STATS,
|
||||||
|
ARG_MAX_DIFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstMemChunk *_gst_clock_entries_chunk;
|
static GstMemChunk *_gst_clock_entries_chunk;
|
||||||
|
@ -157,21 +160,28 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
|
||||||
requested = GST_CLOCK_ENTRY_TIME (entry);
|
requested = GST_CLOCK_ENTRY_TIME (entry);
|
||||||
|
|
||||||
if (requested == GST_CLOCK_TIME_NONE) {
|
if (requested == GST_CLOCK_TIME_NONE) {
|
||||||
res = GST_CLOCK_TIMEOUT;
|
return GST_CLOCK_TIMEOUT;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clock = GST_CLOCK_ENTRY_CLOCK (entry);
|
clock = GST_CLOCK_ENTRY_CLOCK (entry);
|
||||||
cclass = GST_CLOCK_GET_CLASS (clock);
|
cclass = GST_CLOCK_GET_CLASS (clock);
|
||||||
|
|
||||||
if (cclass->wait) {
|
if (cclass->wait) {
|
||||||
GstClockTime now;
|
GstClockTime now;
|
||||||
|
|
||||||
|
GST_LOCK (clock);
|
||||||
|
clock->entries = g_list_prepend (clock->entries, entry);
|
||||||
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = cclass->wait (clock, entry);
|
res = cclass->wait (clock, entry);
|
||||||
}
|
}
|
||||||
while (res == GST_CLOCK_ENTRY_RESTART);
|
while (res == GST_CLOCK_ENTRY_RESTART);
|
||||||
|
|
||||||
|
GST_LOCK (clock);
|
||||||
|
clock->entries = g_list_remove (clock->entries, entry);
|
||||||
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
if (jitter) {
|
if (jitter) {
|
||||||
now = gst_clock_get_time (clock);
|
now = gst_clock_get_time (clock);
|
||||||
*jitter = now - requested;
|
*jitter = now - requested;
|
||||||
|
@ -182,11 +192,6 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
if (entry->type == GST_CLOCK_ENTRY_SINGLE) {
|
|
||||||
gst_clock_id_free (id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +238,14 @@ gst_clock_id_wait_async (GstClockID id,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_clock_reschedule_func (GstClockEntry *entry)
|
||||||
|
{
|
||||||
|
entry->status = GST_CLOCK_ENTRY_OK;
|
||||||
|
|
||||||
|
gst_clock_id_unlock ((GstClockID)entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_clock_id_unschedule:
|
* gst_clock_id_unschedule:
|
||||||
* @id: The id to unschedule
|
* @id: The id to unschedule
|
||||||
|
@ -350,11 +363,16 @@ gst_clock_class_init (GstClockClass *klass)
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
|
||||||
g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
|
g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
|
||||||
FALSE, G_PARAM_READWRITE));
|
FALSE, G_PARAM_READWRITE));
|
||||||
|
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_DIFF,
|
||||||
|
g_param_spec_int64 ("max-diff", "Max diff", "The maximum amount of time to wait in nanoseconds",
|
||||||
|
0, G_MAXINT64, DEFAULT_MAX_DIFF, G_PARAM_READWRITE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_clock_init (GstClock *clock)
|
gst_clock_init (GstClock *clock)
|
||||||
{
|
{
|
||||||
|
clock->max_diff = DEFAULT_MAX_DIFF;
|
||||||
|
|
||||||
clock->speed = 1.0;
|
clock->speed = 1.0;
|
||||||
clock->active = FALSE;
|
clock->active = FALSE;
|
||||||
clock->start_time = 0;
|
clock->start_time = 0;
|
||||||
|
@ -489,6 +507,7 @@ gst_clock_set_active (GstClock *clock, gboolean active)
|
||||||
clock->last_time = time - clock->start_time;
|
clock->last_time = time - clock->start_time;
|
||||||
clock->accept_discont = FALSE;
|
clock->accept_discont = FALSE;
|
||||||
}
|
}
|
||||||
|
g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
|
||||||
GST_UNLOCK (clock);
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
g_mutex_lock (clock->active_mutex);
|
g_mutex_lock (clock->active_mutex);
|
||||||
|
@ -536,6 +555,7 @@ gst_clock_reset (GstClock *clock)
|
||||||
clock->active = FALSE;
|
clock->active = FALSE;
|
||||||
clock->start_time = time;
|
clock->start_time = time;
|
||||||
clock->last_time = 0LL;
|
clock->last_time = 0LL;
|
||||||
|
g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
|
||||||
GST_UNLOCK (clock);
|
GST_UNLOCK (clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,6 +603,7 @@ gst_clock_handle_discont (GstClock *clock, guint64 time)
|
||||||
clock->start_time = itime - time;
|
clock->start_time = itime - time;
|
||||||
clock->last_time = time;
|
clock->last_time = time;
|
||||||
clock->accept_discont = FALSE;
|
clock->accept_discont = FALSE;
|
||||||
|
g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
|
||||||
GST_UNLOCK (clock);
|
GST_UNLOCK (clock);
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_CLOCK, "new time %" G_GUINT64_FORMAT,
|
GST_DEBUG (GST_CAT_CLOCK, "new time %" G_GUINT64_FORMAT,
|
||||||
|
@ -675,6 +696,9 @@ gst_clock_set_property (GObject *object, guint prop_id,
|
||||||
case ARG_STATS:
|
case ARG_STATS:
|
||||||
clock->stats = g_value_get_boolean (value);
|
clock->stats = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case ARG_MAX_DIFF:
|
||||||
|
clock->max_diff = g_value_get_int64 (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -693,6 +717,9 @@ gst_clock_get_property (GObject *object, guint prop_id,
|
||||||
case ARG_STATS:
|
case ARG_STATS:
|
||||||
g_value_set_boolean (value, clock->stats);
|
g_value_set_boolean (value, clock->stats);
|
||||||
break;
|
break;
|
||||||
|
case ARG_MAX_DIFF:
|
||||||
|
g_value_set_int64 (value, clock->max_diff);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -122,6 +122,7 @@ struct _GstClock {
|
||||||
/* --- protected --- */
|
/* --- protected --- */
|
||||||
GstClockTime start_time;
|
GstClockTime start_time;
|
||||||
GstClockTime last_time;
|
GstClockTime last_time;
|
||||||
|
gint64 max_diff;
|
||||||
|
|
||||||
/* --- private --- */
|
/* --- private --- */
|
||||||
gboolean accept_discont;
|
gboolean accept_discont;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
/* #define GST_DEBUG_ENABLED */
|
/* #define GST_DEBUG_ENABLED */
|
||||||
#include "gst_private.h"
|
#include "gst_private.h"
|
||||||
|
#include "gstlog.h"
|
||||||
|
|
||||||
#include "gstsystemclock.h"
|
#include "gstsystemclock.h"
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ static void gst_system_clock_init (GstSystemClock *clock);
|
||||||
static GstClockTime gst_system_clock_get_internal_time (GstClock *clock);
|
static GstClockTime gst_system_clock_get_internal_time (GstClock *clock);
|
||||||
static guint64 gst_system_clock_get_resolution (GstClock *clock);
|
static guint64 gst_system_clock_get_resolution (GstClock *clock);
|
||||||
static GstClockEntryStatus gst_system_clock_wait (GstClock *clock, GstClockEntry *entry);
|
static GstClockEntryStatus gst_system_clock_wait (GstClock *clock, GstClockEntry *entry);
|
||||||
|
static void gst_system_clock_unlock (GstClock *clock, GstClockEntry *entry);
|
||||||
|
|
||||||
static GCond *_gst_sysclock_cond = NULL;
|
static GCond *_gst_sysclock_cond = NULL;
|
||||||
static GMutex *_gst_sysclock_mutex = NULL;
|
static GMutex *_gst_sysclock_mutex = NULL;
|
||||||
|
@ -82,6 +84,7 @@ gst_system_clock_class_init (GstSystemClockClass *klass)
|
||||||
gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
|
gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
|
||||||
gstclock_class->get_resolution = gst_system_clock_get_resolution;
|
gstclock_class->get_resolution = gst_system_clock_get_resolution;
|
||||||
gstclock_class->wait = gst_system_clock_wait;
|
gstclock_class->wait = gst_system_clock_wait;
|
||||||
|
gstclock_class->unlock = gst_system_clock_unlock;
|
||||||
|
|
||||||
_gst_sysclock_cond = g_cond_new ();
|
_gst_sysclock_cond = g_cond_new ();
|
||||||
_gst_sysclock_mutex = g_mutex_new ();
|
_gst_sysclock_mutex = g_mutex_new ();
|
||||||
|
@ -129,12 +132,19 @@ gst_system_clock_get_resolution (GstClock *clock)
|
||||||
static GstClockEntryStatus
|
static GstClockEntryStatus
|
||||||
gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
|
gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
|
||||||
{
|
{
|
||||||
GstClockEntryStatus res = GST_CLOCK_ENTRY_OK;
|
GstClockEntryStatus res;
|
||||||
GstClockTime current, target;
|
GstClockTime current, target;
|
||||||
|
gint64 diff;
|
||||||
|
|
||||||
current = gst_clock_get_time (clock);
|
current = gst_clock_get_time (clock);
|
||||||
target = gst_system_clock_get_internal_time (clock) +
|
diff = GST_CLOCK_ENTRY_TIME (entry) - current;
|
||||||
GST_CLOCK_ENTRY_TIME (entry) - current;
|
|
||||||
|
if (ABS (diff) > clock->max_diff) {
|
||||||
|
g_warning ("abnormal clock request diff: %lld > %lld", diff, clock->max_diff);
|
||||||
|
return GST_CLOCK_ENTRY_EARLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = gst_system_clock_get_internal_time (clock) + diff;
|
||||||
|
|
||||||
GST_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT
|
GST_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT
|
||||||
" target %" G_GUINT64_FORMAT
|
" target %" G_GUINT64_FORMAT
|
||||||
|
@ -148,6 +158,7 @@ gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
|
||||||
g_mutex_lock (_gst_sysclock_mutex);
|
g_mutex_lock (_gst_sysclock_mutex);
|
||||||
g_cond_timed_wait (_gst_sysclock_cond, _gst_sysclock_mutex, &tv);
|
g_cond_timed_wait (_gst_sysclock_cond, _gst_sysclock_mutex, &tv);
|
||||||
g_mutex_unlock (_gst_sysclock_mutex);
|
g_mutex_unlock (_gst_sysclock_mutex);
|
||||||
|
res = entry->status;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = GST_CLOCK_ENTRY_EARLY;
|
res = GST_CLOCK_ENTRY_EARLY;
|
||||||
|
@ -155,3 +166,10 @@ gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_system_clock_unlock (GstClock *clock, GstClockEntry *entry)
|
||||||
|
{
|
||||||
|
g_mutex_lock (_gst_sysclock_mutex);
|
||||||
|
g_cond_broadcast (_gst_sysclock_cond);
|
||||||
|
g_mutex_unlock (_gst_sysclock_mutex);
|
||||||
|
}
|
||||||
|
|
|
@ -40,11 +40,11 @@ typedef struct _GstSystemClock GstSystemClock;
|
||||||
typedef struct _GstSystemClockClass GstSystemClockClass;
|
typedef struct _GstSystemClockClass GstSystemClockClass;
|
||||||
|
|
||||||
struct _GstSystemClock {
|
struct _GstSystemClock {
|
||||||
GstClock clock;
|
GstClock clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstSystemClockClass {
|
struct _GstSystemClockClass {
|
||||||
GstClockClass parent_class;
|
GstClockClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_system_clock_get_type (void);
|
GType gst_system_clock_get_type (void);
|
||||||
|
|
Loading…
Reference in a new issue