mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 01:31:03 +00:00
Added a first stab at a better clocking system.
Original commit message from CVS: Added a first stab at a better clocking system. It still needs more infrastructure for async notification and custom clock implementors. This thing can still deadlock the pipeline.
This commit is contained in:
parent
6b2df345f7
commit
53b6bb6242
15 changed files with 695 additions and 191 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "common"]
|
||||
path = common
|
||||
url = git://anongit.freedesktop.org/gstreamer/common
|
1
common
Submodule
1
common
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d81417a103945ab1c393e74557983b1163e9e353
|
|
@ -79,6 +79,7 @@ libgst_la_SOURCES = \
|
|||
gstprops.c \
|
||||
gstqueue.c \
|
||||
gstscheduler.c \
|
||||
gstsystemclock.c \
|
||||
gstthread.c \
|
||||
$(GST_TRACE_SRC) \
|
||||
gsttype.c \
|
||||
|
@ -187,6 +188,7 @@ libgstinclude_HEADERS = \
|
|||
gstprops.h \
|
||||
gstqueue.h \
|
||||
gstscheduler.h \
|
||||
gstsystemclock.h \
|
||||
gstthread.h \
|
||||
gsttrace.h \
|
||||
gsttype.h \
|
||||
|
|
|
@ -137,6 +137,8 @@ int main(int argc,char *argv[])
|
|||
exit (-4);
|
||||
}
|
||||
|
||||
gst_bin_use_clock (GST_BIN (bin), gst_system_clock_obtain ());
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(bin, GST_STATE_PLAYING);
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ gst_disksink_handle_event (GstPad *pad, GstEvent *event)
|
|||
gst_disksink_getcurrentfilename(disksink), sys_errlist[errno]);
|
||||
break;
|
||||
default:
|
||||
g_warning("Unhandled event %d\n", type);
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <gst/gstpad.h>
|
||||
#include <gst/gstbuffer.h>
|
||||
#include <gst/gstcpu.h>
|
||||
#include <gst/gstclock.h>
|
||||
#include <gst/gstsystemclock.h>
|
||||
#include <gst/gstelement.h>
|
||||
#include <gst/gstbin.h>
|
||||
#include <gst/gstpipeline.h>
|
||||
|
|
128
gst/gstbin.c
128
gst/gstbin.c
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "gstevent.h"
|
||||
#include "gstbin.h"
|
||||
#include "gstxml.h"
|
||||
#include "gstsystemclock.h"
|
||||
|
||||
#include "gstscheduler.h"
|
||||
|
||||
|
@ -160,6 +162,93 @@ gst_bin_reset_element_sched (GstElement * element, GstScheduler * sched)
|
|||
gst_element_set_sched (element, sched);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_bin_get_clock_elements (GstBin *bin, GList **needing, GList **providing)
|
||||
{
|
||||
GList *children = gst_bin_get_list (bin);
|
||||
|
||||
while (children) {
|
||||
GstElement *child = GST_ELEMENT (children->data);
|
||||
|
||||
if (GST_IS_BIN (child)) {
|
||||
gst_bin_get_clock_elements (GST_BIN (child), needing, providing);
|
||||
}
|
||||
if (child->getclockfunc) {
|
||||
*providing = g_list_prepend (*providing, child);
|
||||
}
|
||||
if (child->setclockfunc) {
|
||||
*needing = g_list_prepend (*needing, child);
|
||||
}
|
||||
|
||||
children = g_list_next (children);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_distribute_clock (GstBin *bin, GList *needing, GstClock *clock)
|
||||
{
|
||||
while (needing) {
|
||||
GST_DEBUG (GST_CAT_CLOCK, "setting clock on %s\n", GST_ELEMENT_NAME (needing->data));
|
||||
gst_element_set_clock (GST_ELEMENT (needing->data), clock);
|
||||
|
||||
needing = g_list_next (needing);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_distribute_clocks (GstBin *bin)
|
||||
{
|
||||
GList *needing = NULL, *providing = NULL;
|
||||
GstElement *provider;
|
||||
GstClock *clock;
|
||||
|
||||
gst_bin_get_clock_elements (bin, &needing, &providing);
|
||||
|
||||
if (GST_FLAG_IS_SET (bin, GST_BIN_FLAG_FIXED_CLOCK)) {
|
||||
clock = bin->clock;
|
||||
}
|
||||
else if (providing) {
|
||||
clock = gst_element_get_clock (GST_ELEMENT (providing->data));
|
||||
}
|
||||
else {
|
||||
GST_DEBUG (GST_CAT_CLOCK, "no clock provided, using default clock\n");
|
||||
clock = gst_system_clock_obtain ();
|
||||
}
|
||||
|
||||
GST_BIN_CLOCK (bin) = clock;
|
||||
gst_bin_distribute_clock (bin, needing, clock);
|
||||
}
|
||||
|
||||
GstClock*
|
||||
gst_bin_get_clock (GstBin *bin)
|
||||
{
|
||||
g_return_val_if_fail (bin != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
||||
|
||||
return GST_BIN_CLOCK (bin);
|
||||
}
|
||||
|
||||
void
|
||||
gst_bin_use_clock (GstBin *bin, GstClock *clock)
|
||||
{
|
||||
g_return_if_fail (bin != NULL);
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
GST_FLAG_SET (bin, GST_BIN_FLAG_FIXED_CLOCK);
|
||||
GST_BIN_CLOCK (bin) = clock;
|
||||
}
|
||||
|
||||
void
|
||||
gst_bin_auto_clock (GstBin *bin)
|
||||
{
|
||||
g_return_if_fail (bin != NULL);
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
GST_FLAG_UNSET (bin, GST_BIN_FLAG_FIXED_CLOCK);
|
||||
GST_BIN_CLOCK (bin) = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
|
||||
{
|
||||
|
@ -412,14 +501,9 @@ gst_bin_child_state_change (GstBin *bin, GstElementState oldstate, GstElementSta
|
|||
void
|
||||
gst_bin_child_error (GstBin *bin, GstElement *child)
|
||||
{
|
||||
g_return_if_fail (GST_IS_BIN (bin));
|
||||
|
||||
if (GST_STATE (bin) != GST_STATE_NULL) {
|
||||
/*
|
||||
GST_STATE_PENDING (bin) = ((GST_STATE (bin) >> 1));
|
||||
if (gst_element_set_state (bin, GST_STATE (bin)>>1) != GST_STATE_SUCCESS) {
|
||||
gst_element_error (GST_ELEMENT (bin), "bin \"%s\" couldn't change state on error from child \"%s\"",
|
||||
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (child));
|
||||
}
|
||||
*/
|
||||
gst_element_info (GST_ELEMENT (bin), "bin \"%s\" stopped because child \"%s\" signalled an error",
|
||||
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (child));
|
||||
}
|
||||
|
@ -443,6 +527,7 @@ gst_bin_change_state (GstElement * element)
|
|||
GstElement *child;
|
||||
GstElementStateReturn ret;
|
||||
GstElementState old_state, pending;
|
||||
gint transition;
|
||||
gboolean have_async = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
|
||||
|
@ -451,6 +536,7 @@ gst_bin_change_state (GstElement * element)
|
|||
|
||||
old_state = GST_STATE (element);
|
||||
pending = GST_STATE_PENDING (element);
|
||||
transition = GST_STATE_TRANSITION (element);
|
||||
|
||||
GST_INFO_ELEMENT (GST_CAT_STATES, element, "changing childrens' state from %s to %s",
|
||||
gst_element_statename (old_state), gst_element_statename (pending));
|
||||
|
@ -482,6 +568,28 @@ gst_bin_change_state (GstElement * element)
|
|||
}
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_SCHED (bin) != NULL && GST_ELEMENT_PARENT (bin) == NULL) {
|
||||
switch (transition) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
gst_bin_distribute_clocks (bin);
|
||||
break;
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (GST_BIN_CLOCK (bin))
|
||||
gst_clock_reset (GST_BIN_CLOCK (bin));
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_PLAYING:
|
||||
gst_bin_distribute_clocks (bin);
|
||||
if (GST_BIN_CLOCK (bin))
|
||||
gst_clock_activate (GST_BIN_CLOCK (bin), TRUE);
|
||||
break;
|
||||
case GST_STATE_PLAYING_TO_PAUSED:
|
||||
if (GST_BIN_CLOCK (bin))
|
||||
gst_clock_activate (GST_BIN_CLOCK (bin), FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s, now in %s",
|
||||
gst_element_statename (old_state),
|
||||
gst_element_statename (pending),
|
||||
|
@ -499,9 +607,13 @@ gst_bin_change_state (GstElement * element)
|
|||
static GstElementStateReturn
|
||||
gst_bin_change_state_norecurse (GstBin * bin)
|
||||
{
|
||||
GstElementStateReturn ret;
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state) {
|
||||
GST_DEBUG_ELEMENT (GST_CAT_STATES, bin, "setting bin's own state\n");
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT (bin));
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT (bin));
|
||||
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return GST_STATE_FAILURE;
|
||||
|
|
15
gst/gstbin.h
15
gst/gstbin.h
|
@ -48,6 +48,10 @@ extern GType _gst_bin_type;
|
|||
# define GST_BIN_CLASS GST_BIN_CLASS_CAST
|
||||
#endif
|
||||
|
||||
#define GST_BIN_CLOCK_PROVIDERS(bin) (GST_BIN(bin)->clock_providers)
|
||||
#define GST_BIN_CLOCK_RECEIVERS(bin) (GST_BIN(bin)->clock_receivers)
|
||||
#define GST_BIN_CLOCK(bin) (GST_BIN(bin)->clock)
|
||||
|
||||
typedef enum {
|
||||
/* this bin is a manager of child elements, i.e. a pipeline or thread */
|
||||
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
|
||||
|
@ -57,6 +61,8 @@ typedef enum {
|
|||
/* we prefer to have cothreads when its an option, over chain-based */
|
||||
GST_BIN_FLAG_PREFER_COTHREADS,
|
||||
|
||||
GST_BIN_FLAG_FIXED_CLOCK,
|
||||
|
||||
/* padding */
|
||||
GST_BIN_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 4,
|
||||
} GstBinFlags;
|
||||
|
@ -73,6 +79,8 @@ struct _GstBin {
|
|||
|
||||
GstElementState child_states[GST_NUM_STATES];
|
||||
|
||||
GstClock *clock;
|
||||
|
||||
gpointer sched_private;
|
||||
};
|
||||
|
||||
|
@ -108,11 +116,18 @@ gboolean gst_bin_set_state_type (GstBin *bin, GstElementState state, GType type
|
|||
|
||||
gboolean gst_bin_iterate (GstBin *bin);
|
||||
|
||||
void gst_bin_use_clock (GstBin *bin, GstClock *clock);
|
||||
GstClock* gst_bin_get_clock (GstBin *bin);
|
||||
void gst_bin_auto_clock (GstBin *bin);
|
||||
|
||||
/* internal */
|
||||
/* one of our childs signaled a state change */
|
||||
void gst_bin_child_state_change (GstBin *bin, GstElementState oldstate,
|
||||
GstElementState newstate, GstElement *child);
|
||||
/* one of our childs signaled an error */
|
||||
void gst_bin_child_error (GstBin *bin, GstElement *child);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
265
gst/gstclock.c
265
gst/gstclock.c
|
@ -25,176 +25,153 @@
|
|||
/* #define GST_DEBUG_ENABLED */
|
||||
#include "gst_private.h"
|
||||
|
||||
#include "gstelement.h"
|
||||
#include "gstclock.h"
|
||||
|
||||
#define CLASS(clock) GST_CLOCK_CLASS (G_OBJECT_GET_CLASS (clock))
|
||||
|
||||
static GstClock *the_system_clock = NULL;
|
||||
|
||||
/**
|
||||
* gst_clock_new:
|
||||
* @name: the name of the new clock
|
||||
*
|
||||
* create a new clock element
|
||||
*
|
||||
* Returns: the new clock element
|
||||
*/
|
||||
GstClock*
|
||||
gst_clock_new (gchar *name)
|
||||
static void gst_clock_class_init (GstClockClass *klass);
|
||||
static void gst_clock_init (GstClock *clock);
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
/* static guint gst_clock_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
gst_clock_get_type (void)
|
||||
{
|
||||
GstClock *clock = (GstClock *) g_malloc(sizeof(GstClock));
|
||||
static GType clock_type = 0;
|
||||
|
||||
clock->name = g_strdup (name);
|
||||
clock->sinkobjects = NULL;
|
||||
clock->sinkmutex = g_mutex_new ();
|
||||
clock->lock = g_mutex_new ();
|
||||
g_mutex_lock (clock->sinkmutex);
|
||||
|
||||
clock->num = 0;
|
||||
clock->num_locked = 0;
|
||||
clock->locking = FALSE;
|
||||
|
||||
return clock;
|
||||
if (!clock_type) {
|
||||
static const GTypeInfo clock_info = {
|
||||
sizeof (GstObjectClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_clock_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstObject),
|
||||
4,
|
||||
(GInstanceInitFunc) gst_clock_init,
|
||||
NULL
|
||||
};
|
||||
clock_type = g_type_register_static (GST_TYPE_OBJECT, "GstClock",
|
||||
&clock_info, G_TYPE_FLAG_ABSTRACT);
|
||||
}
|
||||
return clock_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_get_system:
|
||||
*
|
||||
* Get the global system clock
|
||||
*
|
||||
* Returns: the global clock
|
||||
*/
|
||||
GstClock*
|
||||
gst_clock_get_system(void)
|
||||
static void
|
||||
gst_clock_class_init (GstClockClass *klass)
|
||||
{
|
||||
if (the_system_clock == NULL) {
|
||||
the_system_clock = gst_clock_new ("system_clock");
|
||||
gst_clock_reset (the_system_clock);
|
||||
}
|
||||
return the_system_clock;
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstobject_class = (GstObjectClass*) klass;
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_register:
|
||||
* @clock: the name of the clock to register to
|
||||
* @obj: the object registering to the clock
|
||||
*
|
||||
* State that an object is interested in listening to the
|
||||
* given clock
|
||||
*/
|
||||
void
|
||||
gst_clock_register (GstClock *clock, GstObject *obj)
|
||||
static void
|
||||
gst_clock_init (GstClock *clock)
|
||||
{
|
||||
if ((GST_ELEMENT(obj))->numsrcpads == 0) {
|
||||
GST_DEBUG (GST_CAT_CLOCK,"gst_clock: setting registered sink object 0x%p\n", obj);
|
||||
clock->sinkobjects = g_list_append (clock->sinkobjects, obj);
|
||||
clock->num++;
|
||||
}
|
||||
clock->speed = 1.0;
|
||||
clock->active = FALSE;
|
||||
clock->start_time = 0;
|
||||
|
||||
clock->active_mutex = g_mutex_new ();
|
||||
clock->active_cond = g_cond_new ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_set:
|
||||
* @clock: The clock to set
|
||||
* @time: the time to set
|
||||
*
|
||||
* Set the time of the given clock to time.
|
||||
*/
|
||||
void
|
||||
gst_clock_set (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
struct timeval tfnow;
|
||||
GstClockTime now;
|
||||
|
||||
gettimeofday (&tfnow, (struct timezone *)NULL);
|
||||
now = tfnow.tv_sec*1000000LL+tfnow.tv_usec;
|
||||
g_mutex_lock (clock->lock);
|
||||
clock->start_time = now - time;
|
||||
g_mutex_unlock (clock->lock);
|
||||
GST_DEBUG (GST_CAT_CLOCK,"gst_clock: setting clock to %llu %llu %llu\n",
|
||||
time, now, clock->start_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_current_diff:
|
||||
* @clock: the clock to calculate the diff against
|
||||
* @time: the time
|
||||
*
|
||||
* Calculate the difference between the given clock and the
|
||||
* given time
|
||||
*
|
||||
* Returns: the clock difference
|
||||
*/
|
||||
GstClockTimeDiff
|
||||
gst_clock_current_diff (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
struct timeval tfnow;
|
||||
GstClockTime now;
|
||||
|
||||
gettimeofday (&tfnow, (struct timezone *)NULL);
|
||||
g_mutex_lock (clock->lock);
|
||||
now = ((guint64)tfnow.tv_sec*1000000LL+tfnow.tv_usec) - (guint64)clock->start_time;
|
||||
g_mutex_unlock (clock->lock);
|
||||
|
||||
return GST_CLOCK_DIFF (time, now);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_reset:
|
||||
* @clock: the clock to reset
|
||||
*
|
||||
* Reset the given clock. The of the clock will be adjusted back
|
||||
* to 0.
|
||||
*/
|
||||
void
|
||||
gst_clock_reset (GstClock *clock)
|
||||
{
|
||||
struct timeval tfnow;
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
gettimeofday (&tfnow, (struct timezone *)NULL);
|
||||
g_mutex_lock (clock->lock);
|
||||
clock->start_time = ((guint64)tfnow.tv_sec)*1000000LL+tfnow.tv_usec;
|
||||
clock->current_time = clock->start_time;
|
||||
clock->adjust = 0LL;
|
||||
GST_DEBUG (GST_CAT_CLOCK,"gst_clock: setting start clock %llu\n", clock->start_time);
|
||||
g_mutex_unlock (clock->lock);
|
||||
clock->start_time = 0;
|
||||
clock->active = FALSE;
|
||||
|
||||
if (CLASS (clock)->reset)
|
||||
CLASS (clock)->reset (clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clock_wait:
|
||||
* @clock: the clock to wait on
|
||||
* @time: the time to wait for
|
||||
* @obj: the object performing the wait
|
||||
*
|
||||
* Wait for a specific clock tick on the given clock.
|
||||
*/
|
||||
void
|
||||
gst_clock_wait (GstClock *clock, GstClockTime time, GstObject *obj)
|
||||
gst_clock_activate (GstClock *clock, gboolean active)
|
||||
{
|
||||
struct timeval tfnow;
|
||||
GstClockTime now;
|
||||
GstClockTimeDiff diff;
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
clock->active = active;
|
||||
|
||||
gettimeofday (&tfnow, (struct timezone *)NULL);
|
||||
g_mutex_lock (clock->lock);
|
||||
now = tfnow.tv_sec*1000000LL+tfnow.tv_usec - clock->start_time;
|
||||
if (CLASS (clock)->activate)
|
||||
CLASS (clock)->activate (clock, active);
|
||||
|
||||
diff = GST_CLOCK_DIFF (time, now);
|
||||
/* if we are not behind wait a bit */
|
||||
GST_DEBUG (GST_CAT_CLOCK,"gst_clock: %s waiting for time %08llu %08llu %08lld\n",
|
||||
GST_OBJECT_NAME (obj), time, now, diff);
|
||||
g_mutex_lock (clock->active_mutex);
|
||||
g_cond_signal (clock->active_cond);
|
||||
g_mutex_unlock (clock->active_mutex);
|
||||
|
||||
g_mutex_unlock (clock->lock);
|
||||
if (diff > 10000 ) {
|
||||
tfnow.tv_usec = (diff % 1000000);
|
||||
tfnow.tv_sec = diff / 1000000;
|
||||
/* FIXME, this piece of code does not work with egcs optimisations on, had to use the following line */
|
||||
if (!tfnow.tv_sec) {
|
||||
select(0, NULL, NULL, NULL, &tfnow);
|
||||
}
|
||||
else GST_DEBUG (GST_CAT_CLOCK,"gst_clock: %s waiting %u %llu %llu %llu seconds\n",
|
||||
GST_OBJECT_NAME (obj), (int)tfnow.tv_sec, now, diff, time);
|
||||
|
||||
gboolean
|
||||
gst_clock_is_active (GstClock *clock)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
||||
|
||||
return clock->active;
|
||||
}
|
||||
GST_DEBUG (GST_CAT_CLOCK,"gst_clock: %s waiting for time %08llu %08llu %08lld done \n",
|
||||
GST_OBJECT_NAME (obj), time, now, diff);
|
||||
|
||||
void
|
||||
gst_clock_set_time (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
if (CLASS (clock)->set_time)
|
||||
CLASS (clock)->set_time (clock, time);
|
||||
}
|
||||
|
||||
GstClockTime
|
||||
gst_clock_get_time (GstClock *clock)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
|
||||
|
||||
if (CLASS (clock)->get_time)
|
||||
return CLASS (clock)->get_time (clock);
|
||||
|
||||
return 0LL;
|
||||
}
|
||||
|
||||
GstClockReturn
|
||||
gst_clock_wait (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_STOPPED);
|
||||
|
||||
if (!clock->active) {
|
||||
g_mutex_lock (clock->active_mutex);
|
||||
g_cond_wait (clock->active_cond, clock->active_mutex);
|
||||
g_mutex_unlock (clock->active_mutex);
|
||||
}
|
||||
if (CLASS (clock)->wait)
|
||||
return CLASS (clock)->wait (clock, time);
|
||||
|
||||
return GST_CLOCK_TIMEOUT;
|
||||
}
|
||||
|
||||
void
|
||||
gst_clock_set_resolution (GstClock *clock, guint64 resolution)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||
|
||||
if (CLASS (clock)->set_resolution)
|
||||
CLASS (clock)->set_resolution (clock, resolution);
|
||||
}
|
||||
|
||||
guint64
|
||||
gst_clock_get_resolution (GstClock *clock)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
|
||||
|
||||
if (CLASS (clock)->get_resolution)
|
||||
return CLASS (clock)->get_resolution (clock);
|
||||
|
||||
return 0LL;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,45 +24,103 @@
|
|||
#ifndef __GST_CLOCK_H__
|
||||
#define __GST_CLOCK_H__
|
||||
|
||||
#include <gst/gstobject.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <gst/gstobject.h>
|
||||
|
||||
#define GST_TYPE_CLOCK \
|
||||
(gst_clock_get_type())
|
||||
#define GST_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CLOCK,GstClock))
|
||||
#define GST_CLOCK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CLOCK,GstClockClass))
|
||||
#define GST_IS_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CLOCK))
|
||||
#define GST_IS_CLOCK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLOCK))
|
||||
|
||||
typedef guint64 GstClockTime;
|
||||
typedef gint64 GstClockTimeDiff;
|
||||
typedef gpointer GstClockID;
|
||||
|
||||
#define GST_CLOCK_DIFF(s, e) (GstClockTimeDiff)((s)-(e))
|
||||
#define GST_TIMEVAL_TO_TIME(tv) ((tv).tv_sec * (guint64) G_USEC_PER_SEC + (tv).tv_usec)
|
||||
|
||||
typedef struct _GstClock GstClock;
|
||||
typedef struct _GstClockClass GstClockClass;
|
||||
|
||||
typedef void (*GstClockCallback) (GstClock *clock, GstClockTime time, GstClockID id, gpointer user_data);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_CLOCK_STOPPED = 0,
|
||||
GST_CLOCK_TIMEOUT = 1,
|
||||
GST_CLOCK_EARLY = 2,
|
||||
GST_CLOCK_ERROR = 3,
|
||||
} GstClockReturn;
|
||||
|
||||
struct _GstClock {
|
||||
gchar *name;
|
||||
GstObject object;
|
||||
|
||||
GstClockTime start_time;
|
||||
GstClockTime current_time;
|
||||
GstClockTimeDiff adjust;
|
||||
gboolean locking;
|
||||
GList *sinkobjects;
|
||||
gint num, num_locked;
|
||||
GMutex *sinkmutex;
|
||||
GMutex *lock;
|
||||
gdouble speed;
|
||||
gboolean active;
|
||||
|
||||
GMutex *active_mutex;
|
||||
GCond *active_cond;
|
||||
};
|
||||
|
||||
GstClock* gst_clock_new (gchar *name);
|
||||
GstClock* gst_clock_get_system (void);
|
||||
struct _GstClockClass {
|
||||
GstObjectClass parent_class;
|
||||
|
||||
void gst_clock_register (GstClock *clock, GstObject *obj);
|
||||
void gst_clock_set (GstClock *clock, GstClockTime time);
|
||||
/* vtable */
|
||||
void (*activate) (GstClock *clock, gboolean active);
|
||||
void (*reset) (GstClock *clock);
|
||||
|
||||
void (*set_time) (GstClock *clock, GstClockTime time);
|
||||
GstClockTime (*get_time) (GstClock *clock);
|
||||
|
||||
GstClockReturn (*wait) (GstClock *clock, GstClockTime time);
|
||||
GstClockID (*wait_async) (GstClock *clock, GstClockTime time,
|
||||
GstClockCallback func, gpointer user_data);
|
||||
void (*cancel_wait_async) (GstClock *clock, GstClockID id);
|
||||
GstClockID (*notify_async) (GstClock *clock, GstClockTime interval,
|
||||
GstClockCallback func, gpointer user_data);
|
||||
void (*remove_notify_async) (GstClock *clock, GstClockID id);
|
||||
|
||||
void (*set_resolution) (GstClock *clock, guint64 resolution);
|
||||
guint64 (*get_resolution) (GstClock *clock);
|
||||
|
||||
/* signals */
|
||||
};
|
||||
|
||||
GType gst_clock_get_type (void);
|
||||
|
||||
void gst_clock_set_speed (GstClock *clock, gdouble speed);
|
||||
void gst_clock_get_speed (GstClock *clock, gdouble speed);
|
||||
|
||||
void gst_clock_activate (GstClock *clock, gboolean active);
|
||||
gboolean gst_clock_is_active (GstClock *clock);
|
||||
void gst_clock_reset (GstClock *clock);
|
||||
void gst_clock_wait (GstClock *clock, GstClockTime time, GstObject *obj);
|
||||
GstClockTimeDiff gst_clock_current_diff (GstClock *clock, GstClockTime time);
|
||||
|
||||
void gst_clock_set_time (GstClock *clock, GstClockTime time);
|
||||
GstClockTime gst_clock_get_time (GstClock *clock);
|
||||
|
||||
GstClockReturn gst_clock_wait (GstClock *clock, GstClockTime time);
|
||||
GstClockID gst_clock_wait_async (GstClock *clock, GstClockTime time,
|
||||
GstClockCallback func, gpointer user_data);
|
||||
void gst_clock_cancel_wait_async (GstClock *clock, GstClockID id);
|
||||
GstClockID gst_clock_notify_async (GstClock *clock, GstClockTime interval,
|
||||
GstClockCallback func, gpointer user_data);
|
||||
void gst_clock_remove_notify_async (GstClock *clock, GstClockID id);
|
||||
|
||||
void gst_clock_set_resolution (GstClock *clock, guint64 resolution);
|
||||
guint64 gst_clock_get_resolution (GstClock *clock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __GST_CLOCK_H__ */
|
||||
|
|
|
@ -273,6 +273,61 @@ gst_element_get_parent (GstElement *element)
|
|||
return GST_OBJECT_PARENT (element);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_set_clock:
|
||||
* @element: GstElement to set the clock to
|
||||
* @clock: the clock to set for the element
|
||||
*
|
||||
* Set the clock for the element
|
||||
*/
|
||||
void
|
||||
gst_element_set_clock (GstElement *element, GstClock *clock)
|
||||
{
|
||||
GstElementClass *oclass;
|
||||
|
||||
g_return_if_fail (element != NULL);
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
|
||||
if (element->setclockfunc)
|
||||
element->setclockfunc (element, clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_get_clock:
|
||||
* @element: GstElement to get the clock of
|
||||
*
|
||||
* Get the clock of the element
|
||||
*/
|
||||
GstClock*
|
||||
gst_element_get_clock (GstElement *element)
|
||||
{
|
||||
g_return_val_if_fail (element != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
||||
|
||||
if (element->getclockfunc)
|
||||
return element->getclockfunc (element);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_clock_wait:
|
||||
* @element: GstElement to wait for the clock
|
||||
* @clock: the clock to wait for
|
||||
* @time: the time to wait for
|
||||
*
|
||||
* Wait for a specific time on the clock
|
||||
*/
|
||||
GstClockReturn
|
||||
gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time)
|
||||
{
|
||||
g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
|
||||
|
||||
/* FIXME inform the scheduler */
|
||||
return gst_clock_wait (clock, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_add_pad:
|
||||
* @element: element to add pad to
|
||||
|
@ -328,11 +383,11 @@ gst_element_remove_pad (GstElement *element, GstPad *pad)
|
|||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
||||
g_return_if_fail (GST_PAD_PARENT (pad) == element);
|
||||
|
||||
/* check to see if the pad is still connected */
|
||||
/* FIXME: what if someone calls _remove_pad instead of
|
||||
_remove_ghost_pad? */
|
||||
if (GST_IS_REAL_PAD (pad))
|
||||
{
|
||||
if (GST_IS_REAL_PAD (pad)) {
|
||||
g_return_if_fail (GST_RPAD_PEER (pad) == NULL);
|
||||
}
|
||||
|
||||
|
@ -1364,12 +1419,14 @@ gst_element_dispose (GObject *object)
|
|||
orig = pads = g_list_copy (element->pads);
|
||||
while (pads) {
|
||||
pad = GST_PAD (pads->data);
|
||||
if (GST_PAD_PEER (pad))
|
||||
{
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
|
||||
|
||||
if (GST_PAD_PEER (pad)) {
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "disconnecting pad '%s'\n",
|
||||
GST_OBJECT_NAME (GST_OBJECT (GST_PAD (GST_PAD_PEER (pad)))));
|
||||
gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
|
||||
}
|
||||
gst_element_remove_pad (element, pad);
|
||||
|
||||
pads = g_list_next (pads);
|
||||
}
|
||||
g_list_free (orig);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <gst/gsttypes.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstpad.h>
|
||||
#include <gst/gstclock.h>
|
||||
#include <gst/gstpluginfeature.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -108,6 +109,7 @@ typedef enum {
|
|||
#define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj))
|
||||
#define GST_ELEMENT_MANAGER(obj) (((GstElement*)(obj))->manager)
|
||||
#define GST_ELEMENT_SCHED(obj) (((GstElement*)(obj))->sched)
|
||||
#define GST_ELEMENT_CLOCK(obj) (((GstElement*)(obj))->clock)
|
||||
#define GST_ELEMENT_PADS(obj) ((obj)->pads)
|
||||
|
||||
/*typedef struct _GstElement GstElement;*/
|
||||
|
@ -116,6 +118,8 @@ typedef struct _GstElementFactory GstElementFactory;
|
|||
typedef struct _GstElementFactoryClass GstElementFactoryClass;
|
||||
|
||||
typedef void (*GstElementLoopFunction) (GstElement *element);
|
||||
typedef void (*GstElementSetClockFunction) (GstElement *element, GstClock *clock);
|
||||
typedef GstClock* (*GstElementGetClockFunction) (GstElement *element);
|
||||
|
||||
struct _GstElement {
|
||||
GstObject object;
|
||||
|
@ -128,6 +132,8 @@ struct _GstElement {
|
|||
|
||||
GstScheduler *sched;
|
||||
gpointer sched_private;
|
||||
GstElementSetClockFunction setclockfunc;
|
||||
GstElementGetClockFunction getclockfunc;
|
||||
|
||||
/* element pads */
|
||||
guint16 numpads;
|
||||
|
@ -183,6 +189,10 @@ const gchar* gst_element_get_name (GstElement *element);
|
|||
void gst_element_set_parent (GstElement *element, GstObject *parent);
|
||||
GstObject* gst_element_get_parent (GstElement *element);
|
||||
|
||||
GstClock* gst_element_get_clock (GstElement *element);
|
||||
void gst_element_set_clock (GstElement *element, GstClock *clock);
|
||||
GstClockReturn gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time);
|
||||
|
||||
void gst_element_yield (GstElement *element);
|
||||
gboolean gst_element_interrupt (GstElement *element);
|
||||
void gst_element_set_sched (GstElement *element, GstScheduler *sched);
|
||||
|
|
199
gst/gstsystemclock.c
Normal file
199
gst/gstsystemclock.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000 Wim Taymans <wim.taymans@chello.be>
|
||||
*
|
||||
* gstclock.c: Clock subsystem for maintaining time sync
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
/* #define GST_DEBUG_ENABLED */
|
||||
#include "gst_private.h"
|
||||
|
||||
#include "gstsystemclock.h"
|
||||
|
||||
#define CLASS(clock) GST_SYSTEM_CLOCK_CLASS (G_OBJECT_GET_CLASS (clock))
|
||||
|
||||
static GstClock *_the_system_clock = NULL;
|
||||
|
||||
static void gst_system_clock_class_init (GstSystemClockClass *klass);
|
||||
static void gst_system_clock_init (GstSystemClock *clock);
|
||||
|
||||
static void gst_system_clock_activate (GstClock *clock, gboolean active);
|
||||
static void gst_system_clock_reset (GstClock *clock);
|
||||
static void gst_system_clock_set_time (GstClock *clock, GstClockTime time);
|
||||
static GstClockTime gst_system_clock_get_time (GstClock *clock);
|
||||
static GstClockReturn gst_system_clock_wait (GstClock *clock, GstClockTime time);
|
||||
static guint64 gst_system_clock_get_resolution (GstClock *clock);
|
||||
|
||||
|
||||
static GstClockClass *parent_class = NULL;
|
||||
/* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
|
||||
|
||||
GType
|
||||
gst_system_clock_get_type (void)
|
||||
{
|
||||
static GType clock_type = 0;
|
||||
|
||||
if (!clock_type) {
|
||||
static const GTypeInfo clock_info = {
|
||||
sizeof (GstSystemClockClass),
|
||||
NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_system_clock_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstSystemClock),
|
||||
4,
|
||||
(GInstanceInitFunc) gst_system_clock_init,
|
||||
NULL
|
||||
};
|
||||
clock_type = g_type_register_static (GST_TYPE_CLOCK, "GstSystemClock",
|
||||
&clock_info, 0);
|
||||
}
|
||||
return clock_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_system_clock_class_init (GstSystemClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstObjectClass *gstobject_class;
|
||||
GstClockClass *gstclock_class;
|
||||
|
||||
gobject_class = (GObjectClass*) klass;
|
||||
gstobject_class = (GstObjectClass*) klass;
|
||||
gstclock_class = (GstClockClass*) klass;
|
||||
|
||||
parent_class = g_type_class_ref (GST_TYPE_CLOCK);
|
||||
|
||||
gstclock_class->activate = gst_system_clock_activate;
|
||||
gstclock_class->reset = gst_system_clock_reset;
|
||||
gstclock_class->set_time = gst_system_clock_set_time;
|
||||
gstclock_class->get_time = gst_system_clock_get_time;
|
||||
gstclock_class->wait = gst_system_clock_wait;
|
||||
gstclock_class->get_resolution = gst_system_clock_get_resolution;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_system_clock_init (GstSystemClock *clock)
|
||||
{
|
||||
}
|
||||
|
||||
GstClock*
|
||||
gst_system_clock_obtain (void)
|
||||
{
|
||||
if (_the_system_clock == NULL) {
|
||||
_the_system_clock = GST_CLOCK (g_object_new (GST_TYPE_SYSTEM_CLOCK, NULL));
|
||||
gst_object_set_name (GST_OBJECT (_the_system_clock), "GstSystemClock");
|
||||
}
|
||||
return _the_system_clock;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_system_clock_activate (GstClock *clock, gboolean active)
|
||||
{
|
||||
GTimeVal timeval;
|
||||
GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
|
||||
|
||||
g_get_current_time (&timeval);
|
||||
GST_LOCK (clock);
|
||||
if (active) {
|
||||
sys_clock->absolute_start = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->current_time;;
|
||||
}
|
||||
else {
|
||||
sys_clock->current_time = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->absolute_start;
|
||||
}
|
||||
GST_UNLOCK (clock);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_system_clock_set_time (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
GTimeVal timeval;
|
||||
GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
|
||||
|
||||
g_get_current_time (&timeval);
|
||||
|
||||
GST_LOCK (clock);
|
||||
sys_clock->absolute_start = GST_TIMEVAL_TO_TIME (timeval) - time;
|
||||
sys_clock->current_time = time;
|
||||
GST_UNLOCK (clock);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_system_clock_reset (GstClock *clock)
|
||||
{
|
||||
gst_system_clock_set_time (clock, 0LL);
|
||||
}
|
||||
|
||||
static GstClockTime
|
||||
gst_system_clock_get_time (GstClock *clock)
|
||||
{
|
||||
GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
|
||||
GstClockTime res;
|
||||
|
||||
if (!clock->active) {
|
||||
GST_LOCK (clock);
|
||||
res = sys_clock->current_time;
|
||||
}
|
||||
else {
|
||||
GTimeVal timeval;
|
||||
|
||||
g_get_current_time (&timeval);
|
||||
|
||||
GST_LOCK (clock);
|
||||
res = GST_TIMEVAL_TO_TIME (timeval) - sys_clock->absolute_start;
|
||||
}
|
||||
GST_UNLOCK (clock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstClockReturn
|
||||
gst_system_clock_wait (GstClock *clock, GstClockTime time)
|
||||
{
|
||||
GstClockTime target;
|
||||
GTimeVal timeval;
|
||||
GCond *cond = g_cond_new ();
|
||||
GstSystemClock *sys_clock = GST_SYSTEM_CLOCK (clock);
|
||||
GstClockReturn ret;
|
||||
|
||||
GST_LOCK (clock);
|
||||
target = time + sys_clock->absolute_start;
|
||||
|
||||
timeval.tv_usec = target % 1000000;
|
||||
timeval.tv_sec = target / 1000000;
|
||||
|
||||
g_cond_timed_wait (cond, GST_GET_LOCK (clock), &timeval);
|
||||
GST_UNLOCK (clock);
|
||||
|
||||
ret = GST_CLOCK_TIMEOUT;
|
||||
|
||||
g_cond_free (cond);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static guint64
|
||||
gst_system_clock_get_resolution (GstClock *clock)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
68
gst/gstsystemclock.h
Normal file
68
gst/gstsystemclock.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000 Wim Taymans <wtay@chello.be>
|
||||
*
|
||||
* gstclock.h: Header for clock subsystem
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GST_SYSTEM_CLOCK_H__
|
||||
#define __GST_SYSTEM_CLOCK_H__
|
||||
|
||||
#include <gst/gstclock.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define GST_TYPE_SYSTEM_CLOCK \
|
||||
(gst_system_clock_get_type())
|
||||
#define GST_SYSTEM_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SYSTEM_CLOCK,GstSystemClock))
|
||||
#define GST_SYSTEM_CLOCK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SYSTEM_CLOCK,GstSystemClockClass))
|
||||
#define GST_IS_SYSTEM_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SYSTEM_CLOCK))
|
||||
#define GST_IS_SYSTEM_CLOCK_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SYSTEM_CLOCK))
|
||||
|
||||
|
||||
typedef struct _GstSystemClock GstSystemClock;
|
||||
typedef struct _GstSystemClockClass GstSystemClockClass;
|
||||
|
||||
struct _GstSystemClock {
|
||||
GstClock clock;
|
||||
|
||||
GstClockTime absolute_start;
|
||||
GstClockTime current_time;
|
||||
};
|
||||
|
||||
struct _GstSystemClockClass {
|
||||
GstClockClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_system_clock_get_type (void);
|
||||
|
||||
GstClock* gst_system_clock_obtain (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __GST_SYSTEM_CLOCK_H__ */
|
|
@ -304,7 +304,7 @@ gst_disksink_handle_event (GstPad *pad, GstEvent *event)
|
|||
gst_disksink_getcurrentfilename(disksink), sys_errlist[errno]);
|
||||
break;
|
||||
default:
|
||||
g_warning("Unhandled event %d\n", type);
|
||||
gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue