From 031de644f9a7970896b1f143a66951cf50668d67 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 27 May 2002 04:48:57 +0000 Subject: [PATCH] fixups in the prop view/controller compilation fixes in the player add gst-editor to gst-all fixes to adder to comply... Original commit message from CVS: * fixups in the prop view/controller * compilation fixes in the player * add gst-editor to gst-all * fixes to adder to comply with new osssink sync issues * alsa fixes, although still 100% cpu is used, yum * reenable locking of threaded elements, seems to work fine here * fix a makefile in examples/plugins --- ext/alsa/gstalsa.c | 54 +++++++++++++++++++++++++++++++++++++++++++--------- gst/adder/gstadder.c | 23 ++++++++++++++++++---- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/ext/alsa/gstalsa.c b/ext/alsa/gstalsa.c index afe057e..a05869a 100644 --- a/ext/alsa/gstalsa.c +++ b/ext/alsa/gstalsa.c @@ -20,6 +20,7 @@ */ #include +#include #include "gstalsa.h" static GstElementDetails gst_alsa_sink_details = { @@ -69,6 +70,7 @@ static void gst_alsa_close_audio(GstAlsa *this); static gboolean gst_alsa_set_params(GstAlsa *this); static void gst_alsa_loop (GstElement *element); +static void gst_alsa_xrun_recovery (GstAlsa *this); static gboolean gst_alsa_sink_process (GstAlsa *this, snd_pcm_uframes_t frames); static gboolean gst_alsa_src_process (GstAlsa *this, snd_pcm_uframes_t frames); @@ -80,6 +82,13 @@ static void memset_interleave (char *dst, char val, unsigned int bytes, unsigned int unit_bytes, unsigned int skip_bytes); +/* #define _DEBUG */ +#ifdef _DEBUG +#define DEBUG(text, args...) g_message(text, ##args) +#else +#define DEBUG(text, args...) +#endif + enum { ARG_0, @@ -785,7 +794,7 @@ gst_alsa_connect(GstPad *pad, GstCaps *caps) return GST_PAD_CONNECT_DELAYED; } -/* shamelessly stolen from pbd's audioengine. thanks, paul! */ +/* shamelessly stolen from pbd's audioengine and jack alsa_driver. thanks, paul! */ static void gst_alsa_loop (GstElement *element) { @@ -833,11 +842,12 @@ gst_alsa_loop (GstElement *element) xrun_detected = FALSE; this->avail = snd_pcm_avail_update (this->handle); -// g_print ("snd_pcm_avail_update() = %d\n", (int)this->avail); + DEBUG ("snd_pcm_avail_update() = %d", (int)this->avail); if (this->avail < 0) { if (this->avail == -EPIPE) { - xrun_detected = TRUE; + gst_alsa_xrun_recovery (this); + this->avail = 0; } else { g_warning("unknown ALSA avail_update return value (%d)", (int)this->avail); @@ -848,12 +858,8 @@ gst_alsa_loop (GstElement *element) /* round down to nearest period_frames avail */ this->avail -= this->avail % this->period_frames; -// g_print ("snd_pcm_avail_update(), rounded down = %d\n", (int)this->avail); + DEBUG ("snd_pcm_avail_update(), rounded down = %d", (int)this->avail); - /* pretty sophisticated eh? */ - if (xrun_detected) - g_warning ("xrun detected"); - /* we need to loop here because the available bytes might not be * contiguous */ while (this->avail) { @@ -1025,6 +1031,36 @@ gst_alsa_sink_process (GstAlsa *this, snd_pcm_uframes_t frames) return TRUE; } +static void +gst_alsa_xrun_recovery (GstAlsa *this) +{ + snd_pcm_status_t *status; + int res; + + snd_pcm_status_alloca(&status); + + if (this->stream == SND_PCM_STREAM_CAPTURE) { + if ((res = snd_pcm_status(this->handle, status)) < 0) { + g_warning ("status error: %s", snd_strerror(res)); + } + } else { + if ((res = snd_pcm_status(this->handle, status)) < 0) { + g_warning ("status error: %s", snd_strerror(res)); + } + } + + if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) { + struct timeval now, diff, tstamp; + gettimeofday(&now, 0); + snd_pcm_status_get_trigger_tstamp(status, &tstamp); + timersub(&now, &tstamp, &diff); + g_warning("alsa: xrun of at least %.3f msecs", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); + } + + gst_alsa_stop_audio (this); + gst_alsa_start_audio (this); +} + /* taken more or less from pbd's audioengine code */ static gboolean gst_alsa_set_params (GstAlsa *this) @@ -1144,7 +1180,7 @@ gst_alsa_set_params (GstAlsa *this) return FALSE; } - ret = snd_pcm_sw_params_set_stop_threshold (this->handle, sw_param, ~0U); + ret = snd_pcm_sw_params_set_stop_threshold (this->handle, sw_param, this->buffer_frames); if (ret < 0) { g_warning("could not set stop mode: %s", snd_strerror(ret)); return FALSE; diff --git a/gst/adder/gstadder.c b/gst/adder/gstadder.c index 2ecb6d7..fd31e0b 100644 --- a/gst/adder/gstadder.c +++ b/gst/adder/gstadder.c @@ -157,37 +157,43 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps) gst_caps_get_int (caps, "endianness", &adder->endianness); gst_caps_get_boolean (caps, "signed", &adder->is_signed); gst_caps_get_int (caps, "channels", &adder->channels); + gst_caps_get_int (caps, "rate", &adder->rate); } else if (strcmp (format, "float") == 0) { adder->format = GST_ADDER_FORMAT_FLOAT; gst_caps_get_string (caps, "layout", &adder->layout); gst_caps_get_float (caps, "intercept", &adder->intercept); gst_caps_get_float (caps, "slope", &adder->slope); gst_caps_get_int (caps, "channels", &adder->channels); + gst_caps_get_int (caps, "rate", &adder->rate); } } else { /* otherwise, a previously-connected pad has set all the values. we should barf if some of the attempted new values don't match. */ if (strcmp (format, "int") == 0) { - gint width, channels; + gint width, channels, rate; gboolean is_signed; gst_caps_get_int (caps, "width", &width); gst_caps_get_int (caps, "channels", &channels); gst_caps_get_boolean (caps, "signed", &is_signed); + gst_caps_get_int (caps, "rate", &rate); if ((adder->format != GST_ADDER_FORMAT_INT) || (adder->width != width) || (adder->channels != channels) || - (adder->is_signed != is_signed)) { + (adder->is_signed != is_signed) || + (adder->rate != rate)) { return FALSE; } } else if (strcmp (format, "float") == 0) { - gint channels; + gint channels, rate; gst_caps_get_int (caps, "channels", &channels); + gst_caps_get_int (caps, "rate", &rate); if ((adder->format != GST_ADDER_FORMAT_FLOAT) || - (adder->channels != channels)) { + (adder->channels != channels) || + (adder->rate != rate)) { return FALSE; } } else { @@ -377,6 +383,8 @@ gst_adder_loop (GstElement *element) guint8 *raw_in; guint32 waiting; guint32 got_bytes; + gint64 timestamp = 0; + gint64 offset = 0; register guint i; g_return_if_fail (element != NULL); @@ -474,6 +482,13 @@ gst_adder_loop (GstElement *element) inputs = g_slist_next (inputs); } + GST_BUFFER_TIMESTAMP (buf_out) = timestamp; + if (adder->format == GST_ADDER_FORMAT_FLOAT) + offset += GST_BUFFER_SIZE (buf_out) / sizeof (gfloat) / adder->channels; + else + offset += GST_BUFFER_SIZE (buf_out) * 8 / adder->width / adder->channels; + timestamp = offset * GST_SECOND / adder->rate; + /* send it out */ GST_DEBUG (0, "pushing buf_out"); -- 2.7.4