| /* GStreamer |
| * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> |
| * 2000 Wim Taymans <wtay@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 "gstelement.h" |
| #include "gstclock.h" |
| |
| |
| 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) |
| { |
| GstClock *clock = (GstClock *) g_malloc(sizeof(GstClock)); |
| |
| 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; |
| } |
| |
| GstClock* |
| gst_clock_get_system(void) |
| { |
| if (the_system_clock == NULL) { |
| the_system_clock = gst_clock_new ("system_clock"); |
| gst_clock_reset (the_system_clock); |
| } |
| return the_system_clock; |
| } |
| |
| void |
| gst_clock_register (GstClock *clock, GstObject *obj) |
| { |
| if ((GST_ELEMENT(obj))->numsrcpads == 0) { |
| GST_DEBUG (0,"gst_clock: setting registered sink object 0x%p\n", obj); |
| clock->sinkobjects = g_list_append (clock->sinkobjects, obj); |
| clock->num++; |
| } |
| } |
| |
| 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 (0,"gst_clock: setting clock to %llu %llu %llu\n", time, now, clock->start_time); |
| } |
| |
| 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); |
| } |
| |
| void |
| gst_clock_reset (GstClock *clock) |
| { |
| struct timeval tfnow; |
| |
| 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 (0,"gst_clock: setting start clock %llu\n", clock->start_time); |
| g_mutex_unlock (clock->lock); |
| } |
| |
| void |
| gst_clock_wait (GstClock *clock, GstClockTime time, GstObject *obj) |
| { |
| struct timeval tfnow; |
| GstClockTime now; |
| GstClockTimeDiff diff; |
| |
| |
| gettimeofday (&tfnow, (struct timezone *)NULL); |
| g_mutex_lock (clock->lock); |
| now = tfnow.tv_sec*1000000LL+tfnow.tv_usec - clock->start_time; |
| |
| diff = GST_CLOCK_DIFF (time, now); |
| // if we are not behind wait a bit |
| GST_DEBUG (0,"gst_clock: %s waiting for time %08llu %08llu %08lld\n", GST_OBJECT_NAME (obj), time, now, diff); |
| |
| 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 (0,"gst_clock: %s waiting %u %llu %llu %llu seconds\n", GST_OBJECT_NAME (obj), |
| (int)tfnow.tv_sec, now, diff, time); |
| } |
| GST_DEBUG (0,"gst_clock: %s waiting for time %08llu %08llu %08lld done \n", GST_OBJECT_NAME (obj), time, now, diff); |
| } |