diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2002-02-03 20:10:04 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2002-02-03 20:10:04 +0000 |
commit | 98ffdface2db429656b2f7b8f3cc5a301d498d75 (patch) | |
tree | c2fc0ab1a9ddb064f573cf57263ed10a4d52a334 /sys/oss/gstosssink.c | |
parent | 2679c67d40a8641798f27e0a02562f8869293962 (diff) |
Assorted fixes.
Original commit message from CVS:
Assorted fixes.
Use the new clocking stuff.
Diffstat (limited to 'sys/oss/gstosssink.c')
-rw-r--r-- | sys/oss/gstosssink.c | 166 |
1 files changed, 128 insertions, 38 deletions
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c index 86d07e28..8a6b7d39 100644 --- a/sys/oss/gstosssink.c +++ b/sys/oss/gstosssink.c @@ -49,6 +49,8 @@ static gboolean gst_osssink_open_audio (GstOssSink *sink); 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 GstPadConnectReturn gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps); static void gst_osssink_set_property (GObject *object, guint prop_id, const GValue *value, @@ -159,11 +161,11 @@ gst_osssink_get_bufferpool (GstPad *pad) static void gst_osssink_finalize (GObject *object) { - GstOssSink *osssink = (GstOssSink *) object; + GstOssSink *osssink = (GstOssSink *) object; - g_free (osssink->device); + g_free (osssink->device); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } static void @@ -227,7 +229,6 @@ gst_osssink_init (GstOssSink *osssink) osssink->device = g_strdup ("/dev/dsp"); osssink->fd = -1; - osssink->clock = gst_clock_get_system(); osssink->channels = 1; osssink->frequency = 11025; osssink->fragment = 6; @@ -237,10 +238,16 @@ gst_osssink_init (GstOssSink *osssink) #else osssink->format = AFMT_S16_LE; #endif /* WORDS_BIGENDIAN */ - gst_clock_register (osssink->clock, GST_OBJECT (osssink)); + //gst_clock_register (osssink->clock, GST_OBJECT (osssink)); osssink->bufsize = 4096; + osssink->offset = 0LL; /* 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_ELEMENT (osssink))); + + GST_ELEMENT (osssink)->setclockfunc = gst_osssink_set_clock; + GST_ELEMENT (osssink)->getclockfunc = gst_osssink_get_clock; GST_FLAG_SET (osssink, GST_ELEMENT_THREAD_SUGGESTED); } @@ -262,6 +269,8 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) if (width != depth) return GST_PAD_CONNECT_REFUSED; + osssink->bps = 0; + law = gst_caps_get_int (caps, "law"); endianness = gst_caps_get_int (caps, "endianness"); sign = gst_caps_get_boolean (caps, "signed"); @@ -280,6 +289,7 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) else if (endianness == G_BIG_ENDIAN) format = AFMT_U16_BE; } + osssink->bps = 2; } else if (width == 8) { if (sign == TRUE) { @@ -288,6 +298,7 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) else { format = AFMT_U8; } + osssink->bps = 1; } } @@ -298,6 +309,9 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps) osssink->channels = gst_caps_get_int (caps, "channels"); osssink->frequency = gst_caps_get_int (caps, "rate"); + osssink->bps *= osssink->channels; + osssink->bps *= osssink->frequency; + if (!gst_osssink_sync_parms (osssink)) { return GST_PAD_CONNECT_REFUSED; } @@ -314,8 +328,8 @@ gst_osssink_sync_parms (GstOssSink *osssink) gint target_channels; gint target_frequency; - g_return_if_fail (osssink != NULL); - g_return_if_fail (GST_IS_OSSSINK (osssink)); + g_return_val_if_fail (osssink != NULL, FALSE); + g_return_val_if_fail (GST_IS_OSSSINK (osssink), FALSE); if (osssink->fd == -1) return FALSE; @@ -341,12 +355,12 @@ gst_osssink_sync_parms (GstOssSink *osssink) ioctl (osssink->fd, SNDCTL_DSP_CHANNELS, &osssink->channels); ioctl (osssink->fd, SNDCTL_DSP_SPEED, &osssink->frequency); - ioctl (osssink->fd, SNDCTL_DSP_GETBLKSIZE, &frag); + ioctl (osssink->fd, SNDCTL_DSP_GETBLKSIZE, &osssink->fragment); ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); GST_INFO (GST_CAT_PLUGIN_INFO, "osssink: set sound card to %dHz %d bit %s (%d bytes buffer, %08x fragment)", osssink->frequency, osssink->format, - (osssink->channels == 2) ? "stereo" : "mono", ospace.bytes, frag); + (osssink->channels == 2) ? "stereo" : "mono", ospace.bytes, osssink->fragment); gst_element_send_event (GST_ELEMENT (osssink), gst_event_new_info ("samplerate", GST_PROPS_INT (osssink->frequency), NULL)); @@ -355,6 +369,9 @@ gst_osssink_sync_parms (GstOssSink *osssink) gst_element_send_event (GST_ELEMENT (osssink), gst_event_new_info ("bits", GST_PROPS_INT (osssink->format), NULL)); + osssink->fragment_time = (1000000 * osssink->fragment) / osssink->bps; + GST_INFO (GST_CAT_PLUGIN_INFO, "fragment time %lu %llu\n", osssink->bps, osssink->fragment_time); + if (target_format != osssink->format || target_channels != osssink->channels || target_frequency != osssink->frequency) @@ -366,43 +383,90 @@ gst_osssink_sync_parms (GstOssSink *osssink) return TRUE; } +static void +gst_osssink_set_clock (GstElement *element, GstClock *clock) +{ + GstOssSink *osssink; + + osssink = GST_OSSSINK (element); + + osssink->clock = clock; +} + +static GstClock* +gst_osssink_get_clock (GstElement *element) +{ + GstOssSink *osssink; + + osssink = GST_OSSSINK (element); + + return osssink->provided_clock; +} + static void gst_osssink_chain (GstPad *pad, GstBuffer *buf) { GstOssSink *osssink; - gboolean in_flush; - audio_buf_info ospace; + GstClockTime buftime; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - /* this has to be an audio buffer */ osssink = GST_OSSSINK (gst_pad_get_parent (pad)); -// g_return_if_fail(GST_FLAG_IS_SET(osssink,GST_STATE_RUNNING)); - if (GST_IS_EVENT (buf)) { - gst_pad_event_default (pad, GST_EVENT (buf)); - return; - } + buftime = GST_BUFFER_TIMESTAMP (buf); + + if (osssink->fd >= 0) { + if (!osssink->mute) { + guchar *data = GST_BUFFER_DATA (buf); + gint size = GST_BUFFER_SIZE (buf); + + if (osssink->clock) { + if (osssink->clock == osssink->provided_clock) { + guint64 time; + gint granularity, granularity_time; + count_info optr; + audio_buf_info ospace; + gint queued; + + /* FIXME, NEW_MEDIA/DISCONT?. Try to get our start point */ + if (osssink->offset == 0LL && buftime != -1LL) { + //gst_oss_clock_set_base (GST_OSS_CLOCK (osssink->clock), buftime); + osssink->offset = buftime; + } + + ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); + ioctl (osssink->fd, SNDCTL_DSP_GETOPTR, &optr); + + queued = (ospace.fragstotal * ospace.fragsize) - ospace.bytes; + time = osssink->offset + (optr.bytes) * 1000000LL / osssink->bps; + + GST_DEBUG (GST_PLUGIN_INFO, "sync %llu %llu %d\n", buftime, time, queued); + + granularity = ospace.fragsize; + //granularity = size; + granularity_time = granularity * osssink->fragment_time / ospace.fragsize; + + while (size > 0) { + write (osssink->fd, data, MIN (size, granularity)); + data += granularity; + size -= granularity; + time += granularity_time; + gst_clock_set_time (osssink->provided_clock, time); + } + } + else { + gst_element_clock_wait (GST_ELEMENT (osssink), osssink->clock, buftime); + + write (osssink->fd, data, size); + } + } + else { + audio_buf_info ospace; - g_signal_emit (G_OBJECT (osssink), gst_osssink_signals[SIGNAL_HANDOFF], 0, - osssink); - - if (GST_BUFFER_DATA (buf) != NULL) { -#ifndef GST_DISABLE_TRACE - gst_trace_add_entry(NULL, 0, buf, "osssink: writing to soundcard"); -#endif // GST_DISABLE_TRACE - //g_print("osssink: writing to soundcard\n"); - if (osssink->fd >= 0) { - if (!osssink->mute) { - gst_clock_wait (osssink->clock, GST_BUFFER_TIMESTAMP (buf), GST_OBJECT (osssink)); ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); - GST_DEBUG (GST_CAT_PLUGIN_INFO,"osssink: (%d bytes buffer) %d %p %d\n", ospace.bytes, - osssink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - write (osssink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - //write(STDOUT_FILENO,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)); + + if (ospace.bytes >= size) { + write (osssink->fd, data, size); + } } } } @@ -588,12 +652,38 @@ gst_osssink_change_state (GstElement *element) case GST_STATE_READY_TO_PAUSED: break; case GST_STATE_PAUSED_TO_PLAYING: + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), TRUE); break; case GST_STATE_PLAYING_TO_PAUSED: - if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) - ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + { + if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) { + if (osssink->bps) { + GstClockTime time; + audio_buf_info ospace; + count_info optr; + gint queued; + + ioctl (osssink->fd, SNDCTL_DSP_GETOSPACE, &ospace); + ioctl (osssink->fd, SNDCTL_DSP_GETOPTR, &optr); + + queued = (ospace.fragstotal * ospace.fragsize) - ospace.bytes; + time = (optr.bytes + queued) * 1000000LL / osssink->bps; + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), FALSE); + gst_clock_set_time (osssink->provided_clock, time); + } + else { + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); + gst_oss_clock_set_update (GST_OSS_CLOCK (osssink->provided_clock), FALSE); + } + } + break; + } case GST_STATE_PAUSED_TO_READY: + if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) + ioctl (osssink->fd, SNDCTL_DSP_RESET, 0); break; case GST_STATE_READY_TO_NULL: if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) |