Resurect ossclock with a simple algorithm

Original commit message from CVS:
Resurect ossclock with a simple algorithm
This commit is contained in:
Wim Taymans 2002-05-28 22:52:52 +00:00
parent dac1353696
commit 40b3b23ce1
4 changed files with 108 additions and 34 deletions

View file

@ -92,34 +92,48 @@ gst_oss_clock_new (gchar *name, GstOssClockGetTimeFunc func, gpointer user_data)
return oss_clock;
}
void
gst_oss_clock_set_active (GstClock *clock, gboolean active)
{
GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
GTimeVal timeval;
GstClockTime time;
GstClockTime osstime;
g_get_current_time (&timeval);
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;
}
oss_clock->active = active;
}
static GstClockTime
gst_oss_clock_get_internal_time (GstClock *clock)
{
GTimeVal timeval;
GstClockTime time1;
GstClockTime time2;
GstClockTimeDiff diff1, diff2;
GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
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;
}
diff1 = time1 - oss_clock->prev1;
diff2 = time2 - oss_clock->prev2;
if (oss_clock->active) {
GstClockTime osstime;
osstime = oss_clock->func (clock, oss_clock->user_data) + oss_clock->adjust;
oss_clock->prev1 = time1;
oss_clock->prev2 = time2;
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;
}

View file

@ -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
}

View file

@ -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:

View file

@ -65,6 +65,7 @@ struct _GstOssSink {
GstClock *clock;
gboolean resync;
gboolean sync;
guint64 handled;
/* device */
gchar *device;