+ alsasrc compiles and runs in "alsasrc ! fakesink" and "alsasrc ! osssink" pipelines. seems to have a 100% cpu issue...

Original commit message from CVS:
+ alsasrc compiles and runs in "alsasrc ! fakesink" and "alsasrc ! osssink"
pipelines. seems to have a 100% cpu issue at the moment.
This commit is contained in:
Leif Johnson 2003-02-27 23:13:22 +00:00
parent 1516bb3f58
commit 20a9403fbf
2 changed files with 276 additions and 185 deletions

View file

@ -92,10 +92,15 @@ static GstPad *gst_alsa_request_new_pad (GstElement *element, GstPadTe
static GstPadLinkReturn gst_alsa_link (GstPad *pad, GstCaps *caps);
static GstCaps *gst_alsa_caps (snd_pcm_format_t format, gint rate, gint channels);
static GstBufferPool *gst_alsa_src_get_buffer_pool (GstPad *pad);
static GstElementStateReturn gst_alsa_change_state (GstElement *element);
/* audio processing functions */
static int gst_alsa_do_mmap (GstAlsa *this, guint numpads, snd_pcm_sframes_t *avail);
static void gst_alsa_sink_loop (GstElement *element);
static void gst_alsa_src_loop (GstElement *element);
static void gst_alsa_xrun_recovery (GstAlsa *this);
static gboolean gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr);
@ -241,16 +246,16 @@ gst_alsa_class_init (GstAlsaClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE,
g_param_spec_string ("device", "Device", "Alsa device, as defined in an asoundrc",
"default", G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/* The next 3 should only be settable on srcs, should it? */
/* the next 3 are only settable on srcs */
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FORMAT,
g_param_spec_enum ("format", "Format", "PCM audio format",
GST_TYPE_ALSA_FORMAT, -1, G_PARAM_READABLE));
GST_TYPE_ALSA_FORMAT, -1, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHANNELS,
g_param_spec_int ("channels", "Channels", "Number of channels",
1, GST_ALSA_MAX_CHANNELS, 2, G_PARAM_READABLE));
1, GST_ALSA_MAX_CHANNELS, 2, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_RATE,
g_param_spec_int ("rate", "Rate", "Sample rate, in Hz",
8000, 192000, 44100, G_PARAM_READABLE));
8000, 192000, 44100, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PERIODCOUNT,
g_param_spec_int ("period-count", "Period count", "Number of hardware buffers to use",
2, 64, 2, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
@ -281,7 +286,14 @@ gst_alsa_init (GstAlsa *this)
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC) {
this->stream = SND_PCM_STREAM_CAPTURE;
this->format = SND_PCM_FORMAT_S16; /* native endian */
this->pads[0].pad = gst_pad_new_from_template (gst_alsa_sink_pad_factory (), "src");
gst_element_set_loop_function (GST_ELEMENT (this), gst_alsa_src_loop);
this->pads[0].pad = gst_pad_new_from_template (gst_alsa_src_pad_factory (), "src");
gst_pad_set_bufferpool_function(this->pads[0].pad, gst_alsa_src_get_buffer_pool);
/* set the rate to a sensible value. we can't have gobject construct this
manually since it only really makes sense on src elements. the rate can
be changed later through the gobject set property function. */
this->rate = 44100;
} else if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SINK) {
this->stream = SND_PCM_STREAM_PLAYBACK;
this->format = SND_PCM_FORMAT_UNKNOWN; /* we don't know until caps are set */
@ -312,15 +324,21 @@ gst_alsa_set_property (GObject *object, guint prop_id, const GValue *value,
g_free (this->device);
this->device = g_strdup (g_value_get_string (value));
break;
/* case ARG_FORMAT:
case ARG_FORMAT:
/* setting this property only makes sense on sources */
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC)
this->format = g_value_get_enum (value);
break;
case ARG_CHANNELS:
/* setting this property only makes sense on sources */
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC)
this->channels = g_value_get_int (value);
break;
case ARG_RATE:
/* setting this property only makes sense on sources */
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC)
this->rate = g_value_get_int (value);
break;*/
break;
case ARG_PERIODCOUNT:
g_return_if_fail (!GST_FLAG_IS_SET (this, GST_ALSA_RUNNING));
this->period_count = g_value_get_int (value);
@ -363,7 +381,7 @@ gst_alsa_get_property (GObject *object, guint prop_id, GValue *value,
case ARG_DEVICE:
g_value_set_string (value, this->device);
break;
/* case ARG_FORMAT:
case ARG_FORMAT:
g_value_set_enum (value, this->format);
break;
case ARG_CHANNELS:
@ -372,7 +390,7 @@ gst_alsa_get_property (GObject *object, guint prop_id, GValue *value,
case ARG_RATE:
g_value_set_int (value, this->rate);
break;
*/ case ARG_PERIODCOUNT:
case ARG_PERIODCOUNT:
g_value_set_int (value, this->period_count);
break;
case ARG_PERIODSIZE:
@ -456,7 +474,7 @@ gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ,
g_return_val_if_fail (!GST_FLAG_IS_SET (element, GST_ALSA_RUNNING), NULL);
/* you can't request a pad if the non-request pad already has more than 1 channel */
g_return_val_if_fail (this->channels > GST_ELEMENT(this)->numpads, NULL);
g_return_val_if_fail (this->channels <= element->numpads, NULL);
if (name) {
/* locate the channel number in the requested pad name. to do so look at
@ -491,6 +509,8 @@ found_channel:
gst_element_add_pad (GST_ELEMENT (this), this->pads[channel].pad);
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SINK)
this->pads[channel].bs = gst_bytestream_new (this->pads[channel].pad);
else
gst_pad_set_bufferpool_function(this->pads[channel].pad, gst_alsa_src_get_buffer_pool);
return this->pads[channel].pad;
}
@ -500,15 +520,15 @@ static snd_pcm_format_t
gst_alsa_get_format (GstCaps *caps)
{
const gchar *format_name;
/**
* We have to differentiate between int and float, so lets find out which one we have.
* Somebody fix the float caps spec please.
*/
/* we have to differentiate between int and float formats */
if (!gst_caps_get_string (caps, "format", &format_name))
return SND_PCM_FORMAT_UNKNOWN;
if (strncmp (format_name, "int", 3) == 0) {
gboolean sign;
int width, depth, endianness, law;
gint width, depth, endianness, law;
/* extract the needed information from the caps */
if (!gst_caps_get (caps,
"width", &width,
@ -545,9 +565,11 @@ gst_alsa_get_format (GstCaps *caps)
}
default: return SND_PCM_FORMAT_UNKNOWN;
}
} else if (strncmp (format_name, "float", 5) == 0) {
gchar *layout;
gfloat intercept, slope;
/* get layout */
if (!gst_caps_get (caps, "layout", &layout,
"intercept", &intercept,
@ -559,8 +581,12 @@ gst_alsa_get_format (GstCaps *caps)
}
/* match layout to format wrt to endianness */
if (strncmp (layout, "gfloat", 6) == 0) {
if (G_BYTE_ORDER == G_LITTLE_ENDIAN) return SND_PCM_FORMAT_FLOAT_LE;
if (G_BYTE_ORDER == G_BIG_ENDIAN) return SND_PCM_FORMAT_FLOAT_BE;
return SND_PCM_FORMAT_FLOAT;
} else if (strncmp (layout, "gdouble", 7) == 0) {
if (G_BYTE_ORDER == G_LITTLE_ENDIAN) return SND_PCM_FORMAT_FLOAT64_LE;
if (G_BYTE_ORDER == G_BIG_ENDIAN) return SND_PCM_FORMAT_FLOAT64_BE;
return SND_PCM_FORMAT_FLOAT64;
} else {
return SND_PCM_FORMAT_UNKNOWN;
@ -569,6 +595,7 @@ gst_alsa_get_format (GstCaps *caps)
return SND_PCM_FORMAT_UNKNOWN;
}
/* get props for a spec */
static GstProps *
gst_alsa_get_props (snd_pcm_format_t format)
@ -637,6 +664,7 @@ static inline void add_channels (GstProps *props, gint rate, gint channels) {
gst_props_add_entry (props, gst_props_entry_new ("channels", GST_PROPS_INT (channels)));
}
}
/**
* Get all available caps.
* @format: SND_PCM_FORMAT_UNKNOWN for all formats, desired format else
@ -694,7 +722,6 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
format = gst_alsa_get_format (caps);
GST_DEBUG (GST_CAT_CAPS, "found format %s\n", snd_pcm_format_name (format));
/* FIXME: allow changing the format here, even by retrying caps on other pads */
if (format == SND_PCM_FORMAT_UNKNOWN || (this->format != SND_PCM_FORMAT_UNKNOWN && this->format != format))
return GST_PAD_LINK_REFUSED;
@ -728,6 +755,22 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
return GST_PAD_LINK_DELAYED;
}
static GstBufferPool *
gst_alsa_src_get_buffer_pool (GstPad *pad)
{
int width, bytes_per_frame;
GstAlsa *this = GST_ALSA (gst_pad_get_parent (pad));
width = snd_pcm_format_physical_width (this->format);
bytes_per_frame = ( width / 8 ) * (GST_ELEMENT (this)->numpads == 1 ? this->channels : 1);
/* FIXME : is this right ? constant size buffers are probably a good thing,
but what if the size changes (e.g. during xrun autorecovery) ? */
return gst_buffer_pool_get_default (this->period_size * bytes_per_frame,
this->period_count);
}
static GstElementStateReturn
gst_alsa_change_state (GstElement *element)
{
@ -772,10 +815,101 @@ gst_alsa_change_state (GstElement *element)
/*** AUDIO PROCESSING *********************************************************/
static int
gst_alsa_do_mmap (GstAlsa *this, guint numpads, snd_pcm_sframes_t *avail)
{
snd_pcm_uframes_t offset;
snd_pcm_channel_area_t *dst, *src, *areas;
int i, err, width = snd_pcm_format_physical_width (this->format);
/* areas points to the memory areas that belong to gstreamer. */
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC) {
areas = dst = calloc(this->channels, sizeof(snd_pcm_channel_area_t));
} else {
areas = src = calloc(this->channels, sizeof(snd_pcm_channel_area_t));
}
if (numpads == 1) {
/* interleaved */
for (i = 0; i < this->channels; i++) {
areas[i].addr = this->pads[0].data;
areas[i].first = i * width;
areas[i].step = this->channels * width;
}
} else {
/* noninterleaved */
for (i = 0; i < this->channels; i++) {
areas[i].addr = this->pads[i].data;
areas[i].first = 0;
areas[i].step = width;
}
}
/* might want to try to do some pointer sneakery in the first if block to get
rid of this second if block ... but right now i'm too sleepy */
if (G_OBJECT_TYPE (this) == GST_TYPE_ALSA_SRC) {
if ((err = snd_pcm_mmap_begin (this->handle, (const snd_pcm_channel_area_t **) &src, &offset, avail)) < 0) {
g_warning ("gstalsa: mmap failed: %s", snd_strerror (err));
return -1;
}
} else {
if ((err = snd_pcm_mmap_begin (this->handle, (const snd_pcm_channel_area_t **) &dst, &offset, avail)) < 0) {
g_warning ("gstalsa: mmap failed: %s", snd_strerror (err));
return -1;
}
}
if ((err = snd_pcm_areas_copy (dst, offset, src, 0, this->channels, *avail, this->format)) < 0) {
snd_pcm_mmap_commit (this->handle, offset, 0);
g_warning ("gstalsa: data copy failed: %s", snd_strerror (err));
return -1;
}
if ((err = snd_pcm_mmap_commit (this->handle, offset, *avail)) < 0) {
g_warning ("gstalsa: mmap commit failed: %s", snd_strerror (err));
return -1;
}
return err;
}
inline static snd_pcm_sframes_t
gst_alsa_update_avail (GstAlsa *this)
{
snd_pcm_sframes_t avail = snd_pcm_avail_update (this->handle);
if (avail < 0) {
if (avail == -EPIPE) {
gst_alsa_xrun_recovery (this);
return -EPIPE;
} else {
g_warning ("unknown ALSA avail_update return value (%d)", (int) avail);
return -1;
}
}
return avail;
}
inline static gint
gst_alsa_pcm_wait (GstAlsa *this)
{
if (snd_pcm_state (this->handle) == SND_PCM_STATE_RUNNING) {
if (snd_pcm_wait (this->handle, 1000) < 0) {
if (errno == EINTR) {
/* happens mostly when run under gdb, or when exiting due to a signal */
GST_DEBUG (GST_CAT_PLUGIN_INFO, "got interrupted while waiting");
if (gst_element_interrupt (GST_ELEMENT (this)))
return -1;
}
g_warning ("error waiting for alsa pcm: (%d: %s)", errno, strerror (errno));
return -1;
}
}
return 0;
}
static void
gst_alsa_sink_loop (GstElement *element)
{
snd_pcm_sframes_t avail;
snd_pcm_sframes_t avail, copied;
gint i;
gint bytes, num_bytes; /* per channel */
GstAlsa *this = GST_ALSA (element);
@ -798,79 +932,38 @@ gst_alsa_sink_loop (GstElement *element)
}
}
restart:
avail = snd_pcm_avail_update (this->handle);
if (avail < 0) {
if (avail == -EPIPE) {
gst_alsa_xrun_recovery (this);
goto restart;
} else {
g_warning ("unknown ALSA avail_update return value (%d)", (int) avail);
return;
}
}
sink_restart:
while (1) {
avail = gst_alsa_update_avail (this);
if (avail == -EPIPE) goto sink_restart;
if (avail == -1) break;
if (avail > 0) {
int width = snd_pcm_format_physical_width (this->format);
/* check how many bytes we still have in all our bytestreams */
bytes = avail * ( snd_pcm_format_physical_width (this->format) / 8 ) * (element->numpads == 1 ? this->channels : 1);
bytes = avail * ( width / 8 ) * (element->numpads == 1 ? this->channels : 1);
for (i = 0; i < element->numpads; i++) {
g_assert (this->pads[i].pad != NULL);
do {
num_bytes = gst_bytestream_peek_bytes (this->pads[i].bs, &this->pads[i].data, bytes);
} while (num_bytes == 0 && gst_alsa_sink_check_event (this, i));
if (num_bytes == 0)
return;
break;
bytes = MIN (bytes, num_bytes);
}
/* FIXME: lotsa stuff can have happened while fetching data. Do we need to check something? */
/* put this data into alsa */
{
snd_pcm_uframes_t offset;
snd_pcm_channel_area_t *dst;
int err;
int width = snd_pcm_format_physical_width (this->format);
snd_pcm_channel_area_t *src = calloc(this->channels, sizeof(snd_pcm_channel_area_t));
avail = bytes / (width / 8 ) / (element->numpads == 1 ? this->channels : 1);
if (element->numpads == 1) {
/* interleaved */
for (i = 0; i < this->channels; i++) {
src[i].addr = this->pads[0].data;
src[i].first = i * width;
src[i].step = this->channels * width;
}
} else {
/* noninterleaved */
for (i = 0; i < this->channels; i++) {
src[i].addr = this->pads[i].data;
src[i].first = 0;
src[i].step = width;
}
}
if ((err = snd_pcm_mmap_begin (this->handle, (const snd_pcm_channel_area_t **) &dst, &offset, &avail)) < 0) {
g_warning ("gstalsa: mmap failed: %s", snd_strerror (err));
return;
}
if ((err = snd_pcm_areas_copy (dst, offset, src, 0, this->channels, avail, this->format)) < 0) {
snd_pcm_mmap_commit (this->handle, offset, 0);
g_warning ("gstalsa: data copy failed: %s", snd_strerror (err));
return;
}
if ((err = snd_pcm_mmap_commit (this->handle, offset, avail)) < 0) {
g_warning ("gstalsa: mmap commit failed: %s", snd_strerror (err));
return;
}
if ((copied = gst_alsa_do_mmap (this, element->numpads, &avail)) < 0)
break;
/* flush the data */
bytes = err * ( width / 8 ) * (element->numpads == 1 ? this->channels : 1);
for (i = 0; i < element->numpads; i++) {
bytes = copied * ( width / 8 ) * (element->numpads == 1 ? this->channels : 1);
for (i = 0; i < element->numpads; i++)
gst_bytestream_flush (this->pads[i].bs, bytes);
}
}
/* BUG: we start the stream explicitly, autostart doesn't work correctly (alsa 0.9.0rc7) */
if (snd_pcm_state(this->handle) == SND_PCM_STATE_PREPARED && snd_pcm_avail_update (this->handle) == 0) {
@ -880,21 +973,89 @@ restart:
}
/* wait */
if (snd_pcm_state(this->handle) == SND_PCM_STATE_RUNNING) {
if (snd_pcm_wait (this->handle, 1000) < 0) {
if (errno == EINTR) {
/* this happens mostly when run
* under gdb, or when exiting due to a signal */
GST_DEBUG (GST_CAT_PLUGIN_INFO, "got interrupted while waiting");
if (gst_element_interrupt (element))
return;
else
goto restart;
if (gst_alsa_pcm_wait (this) < 0)
break;
}
g_warning ("error waiting for alsa pcm: (%d: %s)", errno, strerror (errno));
}
static void
gst_alsa_src_loop (GstElement *element)
{
snd_pcm_sframes_t avail, copied;
GstBufferPool *pool = NULL;
GstBuffer *buf;
GstCaps *caps;
gint i;
GstAlsaPad *pad;
GstAlsa *this = GST_ALSA (element);
g_return_if_fail (this != NULL);
static gboolean caps_set = FALSE;
/* set the caps on all pads */
if (!caps_set) {
GST_DEBUG (GST_CAT_NEGOTIATION, "starting caps negotiation");
caps = gst_alsa_caps (this->format, this->rate, this->channels);
for (i = 0; i < element->numpads; i++) {
if (gst_pad_try_set_caps (this->pads[i].pad, caps) <= 0) {
GST_DEBUG (GST_CAT_NEGOTIATION, "setting caps (%p) in alsasrc (%p) on pad %d failed", caps, this, i);
return;
}
}
caps_set = TRUE;
}
src_restart:
while (1) {
avail = gst_alsa_update_avail (this);
if (avail == -EPIPE) goto src_restart;
if (avail == -1) break;
if (avail > 0) {
int width = snd_pcm_format_physical_width (this->format);
int bytes_per_frame = ( width / 8 ) * (element->numpads == 1 ? this->channels : 1);
if ((copied = gst_alsa_do_mmap (this, element->numpads, &avail)) < 0)
break;
/* we get the buffer pool once per go round */
if (! pool) pool = gst_alsa_src_get_buffer_pool (this->pads[0].pad);
/* push the data to gstreamer if it's big enough to fill up a buffer. */
for (i = 0; i < element->numpads; i++) {
pad = &this->pads[i];
pad->offset += MIN (copied, this->period_size - pad->offset);
if (pad->offset >= this->period_size) {
g_assert (pad->offset <= this->period_size);
buf = gst_buffer_new_from_pool (pool, 0, 0);
GST_BUFFER_DATA (buf) = pad->data;
GST_BUFFER_SIZE (buf) = this->period_size * bytes_per_frame;
GST_BUFFER_MAXSIZE (buf) = this->period_size * bytes_per_frame;
gst_pad_push (pad->pad, buf);
pad->data = NULL;
pad->offset = 0;
}
}
pool = NULL;
/* BUG: we start the stream explicitly, autostart doesn't work correctly (alsa 0.9.0rc7) */
if (snd_pcm_state(this->handle) == SND_PCM_STATE_PREPARED && snd_pcm_avail_update (this->handle) == 0) {
GST_DEBUG (GST_CAT_PLUGIN_INFO, "Explicitly starting capture");
snd_pcm_start(this->handle);
}
}
/* wait */
if (gst_alsa_pcm_wait (this) < 0)
break;
}
}
static void
@ -916,10 +1077,11 @@ gst_alsa_xrun_recovery (GstAlsa *this)
timersub (&now, &tstamp, &diff);
g_warning ("alsa: xrun of at least %.3f msecs", diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
/* if we're allowed to recover, ... */
if (this->autorecover) {
/* increase the period size or buffer size / period count to prevent
further xruns (at the cost of increased latency and memory usage).
Only do this if it's allowed. */
/* ... then increase the period size or buffer size / period count to
prevent further xruns (at the cost of increased latency and memory
usage). */
if (this->period_count >= 4) {
this->period_size *= 2;
this->period_count /= 2;
@ -933,75 +1095,7 @@ gst_alsa_xrun_recovery (GstAlsa *this)
gst_element_error (GST_ELEMENT (this), "alsasink: Error restarting audio after xrun");
}
}
#if 0
/* FIXME: DO NOT RECORD WITH ALSA, IT DOESN'T WORK, IT ONLY COMPILES */
static gboolean
gst_alsa_src_process (GstAlsa *this, snd_pcm_uframes_t frames)
{
GstAlsaPad *pad = NULL;
GstBuffer *buf;
GstCaps *caps;
GList *l;
guint32 channel;
gint unit;
static gboolean caps_set = FALSE;
/* let's get on the caps-setting merry-go-round! */
if (!caps_set) {
caps = gst_alsa_caps (this->format, this->rate, this->channels);
l = this->pads;
while (l) {
if (gst_pad_try_set_caps (GST_ALSA_PAD (l)->pad, caps) <= 0) {
DEBUG (this, "setting caps (%p) in source (%p) failed\n", caps, this);
sleep (1);
return FALSE;
}
l = l->next;
}
caps_set = TRUE;
}
unit = this->sample_bytes * (this->data_interleaved ? this->channels : 1);
/* pull the same amount of data into each pad. create an outgoing buffer with
the data, and push the buffer. lather, rinse, repeat. */
while (frames) {
l = this->pads;
while (l) {
pad = GST_ALSA_PAD (l);
if (!pad->buf)
pad->buf = g_malloc (this->period_frames * unit);
channel = (pad->channel > 0) ? pad->channel - 1 : 0;
memcpy (pad->buf + pad->offset * unit, this->access_addr[channel],
MIN (frames, this->period_frames - pad->offset) * unit);
pad->offset += MIN (frames, this->period_frames - pad->offset);
if (pad->offset >= this->period_frames) {
g_assert (pad->offset <= this->period_frames);
buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = pad->buf;
GST_BUFFER_SIZE (buf) = this->period_frames * unit;
GST_BUFFER_MAXSIZE (buf) = this->period_frames * unit;
gst_pad_push (pad->pad, buf);
pad->buf = NULL;
pad->offset = 0;
}
l = l->next;
}
/* all pads should have the same amount of data, shouldn't matter which one
we use for updating output frames ... */
frames -= MIN (frames, this->period_frames - pad->offset);
}
return TRUE;
}
#endif
/* TRUE, if everything should continue */
static gboolean
gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr)
@ -1188,8 +1282,7 @@ gst_alsa_close_audio (GstAlsa *this)
g_return_val_if_fail (this != NULL, FALSE);
g_return_val_if_fail (this->handle != NULL, FALSE);
ERROR_CHECK (snd_pcm_close (this->handle),
"Error closing device: %s");
ERROR_CHECK (snd_pcm_close (this->handle), "Error closing device: %s");
this->handle = NULL;
GST_FLAG_UNSET (this, GST_ALSA_OPEN);
@ -1208,14 +1301,11 @@ plugin_init (GModule * module, GstPlugin * plugin)
if (!gst_library_load ("gstbytestream"))
return FALSE;
/* FIXME: doesn't work */
if (0) {
factory = gst_element_factory_new ("alsasrc", GST_TYPE_ALSA_SRC, &gst_alsa_src_details);
g_return_val_if_fail (factory != NULL, FALSE);
gst_element_factory_add_pad_template (factory, gst_alsa_src_pad_factory ());
gst_element_factory_add_pad_template (factory, gst_alsa_src_request_pad_factory ());
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
}
factory = gst_element_factory_new ("alsasink", GST_TYPE_ALSA_SINK, &gst_alsa_sink_details);
g_return_val_if_fail (factory != NULL, FALSE);

View file

@ -70,6 +70,7 @@ typedef struct {
GstPad *pad;
GstByteStream *bs;
guint8 *data;
guint8 offset;
} GstAlsaPad;
struct _GstAlsa {