summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2002-05-28 22:52:52 +0000
committerWim Taymans <wim.taymans@gmail.com>2002-05-28 22:52:52 +0000
commit40b3b23ce1fef9a5bba0175f518d94107097c591 (patch)
tree920a8d329ac1f0fc06425134dee47950fa7e8f82 /sys
parentdac1353696dca0f0fdc17cb76066b0f5da96b207 (diff)
Resurect ossclock with a simple algorithm
Original commit message from CVS: Resurect ossclock with a simple algorithm
Diffstat (limited to 'sys')
-rw-r--r--sys/oss/gstossclock.c58
-rw-r--r--sys/oss/gstossclock.h3
-rw-r--r--sys/oss/gstosssink.c80
-rw-r--r--sys/oss/gstosssink.h1
4 files changed, 108 insertions, 34 deletions
diff --git a/sys/oss/gstossclock.c b/sys/oss/gstossclock.c
index bd1bf8e7..5171c086 100644
--- a/sys/oss/gstossclock.c
+++ b/sys/oss/gstossclock.c
@@ -92,34 +92,48 @@ gst_oss_clock_new (gchar *name, GstOssClockGetTimeFunc func, gpointer user_data)
return oss_clock;
}
-static GstClockTime
-gst_oss_clock_get_internal_time (GstClock *clock)
+void
+gst_oss_clock_set_active (GstClock *clock, gboolean active)
{
- GTimeVal timeval;
- GstClockTime time1;
- GstClockTime time2;
- GstClockTimeDiff diff1, diff2;
GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
-
+ GTimeVal timeval;
+ GstClockTime time;
+ GstClockTime osstime;
+
g_get_current_time (&timeval);
- time1 = oss_clock->func (clock, oss_clock->user_data);
- time2 = GST_TIMEVAL_TO_TIME (timeval);
- if (!oss_clock->prev1) {
- oss_clock->prev1 = time1;
+ time = GST_TIMEVAL_TO_TIME (timeval);
+ osstime = oss_clock->func (clock, oss_clock->user_data);
+
+ if (active) {
+ oss_clock->adjust = time - osstime;
+ }
+ else {
+ oss_clock->adjust = osstime - time;
}
- diff1 = time1 - oss_clock->prev1;
- diff2 = time2 - oss_clock->prev2;
- oss_clock->prev1 = time1;
- oss_clock->prev2 = time2;
+ oss_clock->active = active;
+}
+
+static GstClockTime
+gst_oss_clock_get_internal_time (GstClock *clock)
+{
+ GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+ if (oss_clock->active) {
+ GstClockTime osstime;
+
+ osstime = oss_clock->func (clock, oss_clock->user_data) + oss_clock->adjust;
- if (diff1) {
- oss_clock->adjust -= diff2 - diff1;
+ return osstime;
+ }
+ else {
+ GstClockTime time;
+ GTimeVal timeval;
+
+ g_get_current_time (&timeval);
+ time = GST_TIMEVAL_TO_TIME (timeval);
+
+ return time;
}
- /*
- g_print ("diff %lld %lld %lld %lld %lld %lld\n",
- diff1, diff2, time1, time2, diff2 - diff1, oss_clock->adjust);
- */
- return time2 + oss_clock->adjust;
}
diff --git a/sys/oss/gstossclock.h b/sys/oss/gstossclock.h
index e3f28325..00f2f763 100644
--- a/sys/oss/gstossclock.h
+++ b/sys/oss/gstossclock.h
@@ -56,6 +56,8 @@ struct _GstOssClock {
GstClockTime prev1, prev2;
GstClockTimeDiff adjust;
+
+ gboolean active;
};
struct _GstOssClockClass {
@@ -65,6 +67,7 @@ struct _GstOssClockClass {
GType gst_oss_clock_get_type (void);
GstOssClock* gst_oss_clock_new (gchar *name, GstOssClockGetTimeFunc func,
gpointer user_data);
+void gst_oss_clock_set_active (GstClock *clock, gboolean active);
#ifdef __cplusplus
}
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c
index 88d05616..e71bed73 100644
--- a/sys/oss/gstosssink.c
+++ b/sys/oss/gstosssink.c
@@ -50,7 +50,8 @@ static void gst_osssink_close_audio (GstOssSink *sink);
static gboolean gst_osssink_sync_parms (GstOssSink *osssink);
static GstElementStateReturn gst_osssink_change_state (GstElement *element);
static void gst_osssink_set_clock (GstElement *element, GstClock *clock);
-//static GstClock* gst_osssink_get_clock (GstElement *element);
+static GstClock* gst_osssink_get_clock (GstElement *element);
+static GstClockTime gst_osssink_get_time (GstClock *clock, gpointer data);
static GstPadConnectReturn gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps);
@@ -249,13 +250,17 @@ gst_osssink_init (GstOssSink *osssink)
osssink->sync = TRUE;
/* 6 buffers per chunk by default */
osssink->sinkpool = gst_buffer_pool_get_default (osssink->bufsize, 6);
+ osssink->provided_clock = GST_CLOCK (gst_oss_clock_new ("ossclock", gst_osssink_get_time, osssink));
+ osssink->handled = 0;
GST_ELEMENT (osssink)->setclockfunc = gst_osssink_set_clock;
+ GST_ELEMENT (osssink)->getclockfunc = gst_osssink_get_clock;
GST_FLAG_SET (osssink, GST_ELEMENT_THREAD_SUGGESTED);
GST_FLAG_SET (osssink, GST_ELEMENT_EVENT_AWARE);
}
+
static GstPadConnectReturn
gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps)
{
@@ -397,6 +402,59 @@ gst_osssink_sync_parms (GstOssSink *osssink)
return TRUE;
}
+static inline gint64
+gst_osssink_get_delay (GstOssSink *osssink)
+{
+ gint delay = 0;
+
+ if (ioctl (osssink->fd, SNDCTL_DSP_GETODELAY, &delay) < 0) {
+ audio_buf_info info;
+ if (ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+ delay = 0;
+ }
+ else {
+ delay = (info.fragstotal * info.fragsize) - info.bytes;
+ }
+ }
+ return delay;
+}
+
+static GstClockTime
+gst_osssink_get_time (GstClock *clock, gpointer data)
+{
+ GstOssSink *osssink = GST_OSSSINK (data);
+ gint delay;
+ GstClockTime res;
+
+ if (!osssink->bps)
+ return 0;
+
+ delay = gst_osssink_get_delay (osssink);
+
+ /* sometimes delay is bigger than the number of bytes sent to the device, which screws
+ * up this calculation, we assume that everything is still in the device then */
+ if (((guint64)delay) > osssink->handled) {
+ delay = osssink->handled;
+ }
+ res = (osssink->handled - delay) * GST_SECOND / osssink->bps;
+
+ /*
+ g_print ("from osssink: %lld %d %lld %d\n", res, delay, osssink->handled, osssink->bps);
+ */
+
+ return res;
+}
+
+static GstClock*
+gst_osssink_get_clock (GstElement *element)
+{
+ GstOssSink *osssink;
+
+ osssink = GST_OSSSINK (element);
+
+ return GST_CLOCK (osssink->provided_clock);
+}
+
static void
gst_osssink_set_clock (GstElement *element, GstClock *clock)
{
@@ -418,11 +476,11 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
if (GST_IS_EVENT (buf)) {
GstEvent *event = GST_EVENT (buf);
- //gint64 offset;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
ioctl (osssink->fd, SNDCTL_DSP_SYNC);
+ gst_oss_clock_set_active (osssink->clock, FALSE);
gst_pad_event_default (pad, event);
return;
case GST_EVENT_NEW_MEDIA:
@@ -434,7 +492,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
ioctl (osssink->fd, SNDCTL_DSP_RESET);
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
- gst_clock_handle_discont (osssink->clock, value);
+ osssink->handled = 0;
}
osssink->resync = TRUE;
return;
@@ -464,15 +522,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
gint64 queued;
GstClockTimeDiff jitter;
- if (ioctl (osssink->fd, SNDCTL_DSP_GETODELAY, &delay) < 0) {
- audio_buf_info info;
- if (ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
- delay = 0;
- }
- else {
- delay = (info.fragstotal * info.fragsize) - info.bytes;
- }
- }
+ delay = gst_osssink_get_delay (osssink);
queued = delay * GST_SECOND / osssink->bps;
if (osssink->resync && osssink->sync) {
@@ -480,12 +530,16 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
buftime - queued, &jitter);
if (jitter > 0) {
+ gst_clock_handle_discont (osssink->clock, buftime - queued + jitter);
write (osssink->fd, data, size);
+ gst_oss_clock_set_active (osssink->provided_clock, TRUE);
osssink->resync = FALSE;
+ osssink->handled += size;
}
}
else {
write (osssink->fd, data, size);
+ osssink->handled += size;
}
}
/* no clock, try to be as fast as possible */
@@ -703,6 +757,8 @@ gst_osssink_change_state (GstElement *element)
{
if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN))
ioctl (osssink->fd, SNDCTL_DSP_RESET, 0);
+ gst_oss_clock_set_active (osssink->provided_clock, FALSE);
+ osssink->resync = TRUE;
break;
}
case GST_STATE_PAUSED_TO_READY:
diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h
index 66bbfd78..ed5a3af3 100644
--- a/sys/oss/gstosssink.h
+++ b/sys/oss/gstosssink.h
@@ -65,6 +65,7 @@ struct _GstOssSink {
GstClock *clock;
gboolean resync;
gboolean sync;
+ guint64 handled;
/* device */
gchar *device;