mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 19:20:35 +00:00
Resurect ossclock with a simple algorithm
Original commit message from CVS: Resurect ossclock with a simple algorithm
This commit is contained in:
parent
dac1353696
commit
40b3b23ce1
4 changed files with 108 additions and 34 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -65,6 +65,7 @@ struct _GstOssSink {
|
|||
GstClock *clock;
|
||||
gboolean resync;
|
||||
gboolean sync;
|
||||
guint64 handled;
|
||||
|
||||
/* device */
|
||||
gchar *device;
|
||||
|
|
Loading…
Reference in a new issue