mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
rewrote the caps nego / state change stuff once again, new features:
Original commit message from CVS: rewrote the caps nego / state change stuff once again, new features: - bugfixes - get_caps function to report better caps when device is opened - better _link function
This commit is contained in:
parent
28530ecdbe
commit
f7995c6fd8
2 changed files with 188 additions and 108 deletions
|
@ -24,6 +24,12 @@
|
|||
#include "gstalsa.h"
|
||||
|
||||
/* error checking for standard alsa functions */
|
||||
#define SIMPLE_ERROR_CHECK(value) G_STMT_START{ \
|
||||
int err = (value); \
|
||||
if (err < 0) { \
|
||||
return FALSE; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
#ifdef G_HAVE_ISO_VARARGS
|
||||
#define ERROR_CHECK(value, ...) G_STMT_START{ \
|
||||
int err = (value); \
|
||||
|
@ -90,6 +96,7 @@ static GstPadTemplate *gst_alsa_sink_request_pad_factory ();
|
|||
|
||||
static GstPad *gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name);
|
||||
static GstPadLinkReturn gst_alsa_link (GstPad *pad, GstCaps *caps);
|
||||
static GstCaps *gst_alsa_get_caps (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);
|
||||
|
@ -106,11 +113,12 @@ static void gst_alsa_xrun_recovery (GstAlsa *this);
|
|||
static gboolean gst_alsa_sink_check_event (GstAlsa *this, gint pad_nr);
|
||||
|
||||
/* alsa setup / start / stop functions */
|
||||
static gboolean gst_alsa_set_hw_params (GstAlsa *this, GstAlsaFormat *format);
|
||||
static gboolean gst_alsa_probe_hw_params (GstAlsa *this, GstAlsaFormat *format);
|
||||
static gboolean gst_alsa_set_hw_params (GstAlsa *this);
|
||||
static gboolean gst_alsa_set_sw_params (GstAlsa *this);
|
||||
|
||||
static gboolean gst_alsa_open_audio (GstAlsa *this);
|
||||
static gboolean gst_alsa_start_audio (GstAlsa *this, GstAlsaFormat *format);
|
||||
static gboolean gst_alsa_start_audio (GstAlsa *this);
|
||||
static gboolean gst_alsa_drain_audio (GstAlsa *this);
|
||||
static gboolean gst_alsa_stop_audio (GstAlsa *this);
|
||||
static gboolean gst_alsa_close_audio (GstAlsa *this);
|
||||
|
@ -257,7 +265,7 @@ gst_alsa_class_init (GstAlsaClass *klass)
|
|||
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_READWRITE));
|
||||
GST_ALSA_MIN_RATE, GST_ALSA_MAX_RATE, 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));
|
||||
|
@ -311,6 +319,7 @@ gst_alsa_init (GstAlsa *this)
|
|||
}
|
||||
|
||||
gst_pad_set_link_function (this->pads[0].pad, gst_alsa_link);
|
||||
gst_pad_set_getcaps_function (this->pads[0].pad, gst_alsa_get_caps);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -384,7 +393,7 @@ gst_alsa_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
|
||||
if (GST_FLAG_IS_SET (this, GST_ALSA_RUNNING)) {
|
||||
gst_alsa_stop_audio (this);
|
||||
gst_alsa_start_audio (this, NULL);
|
||||
gst_alsa_start_audio (this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,6 +534,7 @@ gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ,
|
|||
found_channel:
|
||||
this->pads[channel].pad = gst_pad_new_from_template (templ, name);
|
||||
gst_pad_set_link_function (this->pads[channel].pad, gst_alsa_link);
|
||||
gst_pad_set_getcaps_function (this->pads[channel].pad, gst_alsa_get_caps);
|
||||
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);
|
||||
|
@ -707,16 +717,20 @@ gst_alsa_get_props (snd_pcm_format_t format)
|
|||
}
|
||||
|
||||
static inline void
|
||||
add_channels (GstProps *props, gint rate, gint channels) {
|
||||
if (rate < 0) {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("rate", GST_PROPS_INT_RANGE (8000, 192000)));
|
||||
add_channels (GstProps *props, gint min_rate, gint max_rate, gint min_channels, gint max_channels) {
|
||||
if (min_rate < 0) {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("rate", GST_PROPS_INT_RANGE (GST_ALSA_MIN_RATE, GST_ALSA_MAX_RATE)));
|
||||
} else if (max_rate < 0) {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("rate", GST_PROPS_INT (min_rate)));
|
||||
} else {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("rate", GST_PROPS_INT (rate)));
|
||||
gst_props_add_entry (props, gst_props_entry_new ("rate", GST_PROPS_INT_RANGE (min_rate, max_rate)));
|
||||
}
|
||||
if (channels < 0) {
|
||||
if (min_channels < 0) {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("channels", GST_PROPS_INT_RANGE (1, GST_ALSA_MAX_CHANNELS)));
|
||||
} else if (max_channels < 0) {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("channels", GST_PROPS_INT (min_channels)));
|
||||
} else {
|
||||
gst_props_add_entry (props, gst_props_entry_new ("channels", GST_PROPS_INT (channels)));
|
||||
gst_props_add_entry (props, gst_props_entry_new ("channels", GST_PROPS_INT_RANGE (min_channels, max_channels)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,8 +751,8 @@ gst_alsa_caps (snd_pcm_format_t format, gint rate, gint channels)
|
|||
/* we can never use a format we can't set caps for */
|
||||
g_assert (props != NULL);
|
||||
|
||||
add_channels (props, rate, channels);
|
||||
ret_caps = gst_caps_new ("alsacaps", "audio/raw", props);
|
||||
add_channels (props, rate, -1, channels, -1);
|
||||
ret_caps = gst_caps_new (g_strdup (snd_pcm_format_name (format)), "audio/raw", props);
|
||||
} else {
|
||||
int i;
|
||||
GstProps *props;
|
||||
|
@ -747,7 +761,7 @@ gst_alsa_caps (snd_pcm_format_t format, gint rate, gint channels)
|
|||
props = gst_alsa_get_props (i);
|
||||
/* can be NULL, because not all alsa formats can be specified as caps */
|
||||
if (props != NULL) {
|
||||
add_channels (props, rate, channels);
|
||||
add_channels (props, rate, -1, channels, -1);
|
||||
ret_caps = gst_caps_append (ret_caps, gst_caps_new (g_strdup (snd_pcm_format_name (i)),
|
||||
"audio/raw", props));
|
||||
}
|
||||
|
@ -757,12 +771,71 @@ gst_alsa_caps (snd_pcm_format_t format, gint rate, gint channels)
|
|||
return ret_caps;
|
||||
}
|
||||
|
||||
/* Return better caps when device is open */
|
||||
static GstCaps *
|
||||
gst_alsa_get_caps (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstAlsa *this;
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_format_mask_t *mask;
|
||||
int i;
|
||||
unsigned int min_rate, max_rate;
|
||||
gint min_channels, max_channels;
|
||||
GstCaps *ret = NULL;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
|
||||
this = GST_ALSA (gst_pad_get_parent (pad));
|
||||
|
||||
if (!GST_FLAG_IS_SET (this, GST_ALSA_OPEN))
|
||||
return gst_pad_get_pad_template_caps (pad);
|
||||
|
||||
snd_pcm_hw_params_alloca (&hw_params);
|
||||
ERROR_CHECK (snd_pcm_hw_params_any (this->handle, hw_params),
|
||||
"Broken configuration for this PCM: %s");
|
||||
|
||||
if (((GstElement *) this)->numpads > 1) {
|
||||
min_channels = 1;
|
||||
max_channels = -1;
|
||||
} else {
|
||||
ERROR_CHECK (snd_pcm_hw_params_get_channels_min (hw_params, &min_rate),
|
||||
"Coulödn't get minimum channel count for device %s: %s", this->device);
|
||||
ERROR_CHECK (snd_pcm_hw_params_get_channels_max (hw_params, &max_rate),
|
||||
"Coulödn't get maximum channel count for device %s: %s", this->device);
|
||||
min_channels = min_rate;
|
||||
max_channels = max_rate > GST_ALSA_MAX_CHANNELS ? GST_ALSA_MAX_CHANNELS : max_rate;
|
||||
}
|
||||
|
||||
ERROR_CHECK (snd_pcm_hw_params_get_rate_min (hw_params, &min_rate, &i),
|
||||
"Coulödn't get minimum rate for device %s: %s", this->device);
|
||||
min_rate = min_rate < GST_ALSA_MIN_RATE ? GST_ALSA_MIN_RATE : min_rate + i;
|
||||
ERROR_CHECK (snd_pcm_hw_params_get_rate_max (hw_params, &max_rate, &i),
|
||||
"Coulödn't get maximum rate for device %s: %s", this->device);
|
||||
max_rate = max_rate > GST_ALSA_MAX_RATE ? GST_ALSA_MAX_RATE : max_rate + i;
|
||||
|
||||
snd_pcm_format_mask_alloca (&mask);
|
||||
snd_pcm_hw_params_get_format_mask (hw_params, mask);
|
||||
for (i = 0; i <= SND_PCM_FORMAT_LAST; i++) {
|
||||
if (snd_pcm_format_mask_test (mask, i)) {
|
||||
GstProps *props = gst_alsa_get_props (i);
|
||||
/* we can never use a format we can't set caps for */
|
||||
if (props != NULL) {
|
||||
add_channels (props, min_rate, max_rate, min_channels, max_channels);
|
||||
ret = gst_caps_append (ret, gst_caps_new (g_strdup (snd_pcm_format_name (i)),
|
||||
"audio/raw", props));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* Negotiates the caps */
|
||||
GstPadLinkReturn
|
||||
gst_alsa_link (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstAlsa *this;
|
||||
GstAlsaFormat *format;
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
g_return_val_if_fail (caps != NULL, GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (pad != NULL, GST_PAD_LINK_REFUSED);
|
||||
|
@ -780,16 +853,21 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
|
|||
|
||||
GST_DEBUG (GST_CAT_CAPS, "found format %s\n", snd_pcm_format_name (format->format));
|
||||
|
||||
if (gst_alsa_formats_match (this->format, format)) {
|
||||
g_free (format);
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
||||
if (!GST_FLAG_IS_SET (this, GST_ALSA_CAPS_NEGO)) {
|
||||
gint i;
|
||||
|
||||
GST_FLAG_SET (this, GST_ALSA_CAPS_NEGO);
|
||||
|
||||
if (gst_alsa_formats_match (this->format, format)) {
|
||||
ret = GST_PAD_LINK_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!gst_alsa_probe_hw_params (this, format)) {
|
||||
ret = GST_PAD_LINK_REFUSED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ((GstElement *) this)->numpads; i++) {
|
||||
g_assert (this->pads[i].pad != NULL);
|
||||
if (this->pads[i].pad == pad)
|
||||
|
@ -806,10 +884,10 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
|
|||
}
|
||||
gst_caps_unref (old);
|
||||
} else {
|
||||
/* FIXME: unset caps somehow */
|
||||
/* FIXME: unset caps on pads somehow */
|
||||
}
|
||||
g_free (format);
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
ret = GST_PAD_LINK_REFUSED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,11 +895,10 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
|
|||
|
||||
/* sync the params */
|
||||
if (GST_FLAG_IS_SET (this, GST_ALSA_RUNNING)) gst_alsa_stop_audio (this);
|
||||
if (GST_FLAG_IS_SET (this, GST_ALSA_OPEN)) gst_alsa_close_audio (this);
|
||||
|
||||
if (!gst_alsa_open_audio (this)) return GST_PAD_LINK_REFUSED;
|
||||
if (!gst_alsa_start_audio (this, format)) {
|
||||
g_free (format);
|
||||
g_free (this->format);
|
||||
this->format = format;
|
||||
if (!gst_alsa_start_audio (this)) {
|
||||
gst_element_error (GST_ELEMENT (this), "Probed format doesn't work");
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
}
|
||||
|
@ -830,6 +907,11 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
|
|||
}
|
||||
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
|
||||
out:
|
||||
g_free (format);
|
||||
GST_FLAG_UNSET (this, GST_ALSA_CAPS_NEGO);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstBufferPool *
|
||||
|
@ -865,7 +947,7 @@ gst_alsa_change_state (GstElement *element)
|
|||
break;
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!GST_FLAG_IS_SET (element, GST_ALSA_RUNNING))
|
||||
if (!gst_alsa_start_audio (this, NULL))
|
||||
if (!gst_alsa_start_audio (this))
|
||||
return GST_STATE_FAILURE;
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_PLAYING:
|
||||
|
@ -1072,6 +1154,7 @@ gst_alsa_sink_loop (GstElement *element)
|
|||
}
|
||||
if (this->format == NULL) {
|
||||
gst_element_error (GST_ELEMENT (this), "alsasink: No caps available");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1111,10 +1194,7 @@ sink_restart:
|
|||
return;
|
||||
}
|
||||
|
||||
if (gst_element_get_state (element) != GST_STATE_PLAYING)
|
||||
return;
|
||||
/* FIXME: lotsa stuff can have happened while fetching data. Do we need to check something? */
|
||||
|
||||
|
||||
/* put this data into alsa */
|
||||
if ((copied = this->transmit (this, &avail)) < 0)
|
||||
|
@ -1247,7 +1327,7 @@ gst_alsa_xrun_recovery (GstAlsa *this)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(gst_alsa_stop_audio (this) && gst_alsa_start_audio (this, NULL))) {
|
||||
if (!(gst_alsa_stop_audio (this) && gst_alsa_start_audio (this))) {
|
||||
gst_element_error (GST_ELEMENT (this), "alsasink: Error restarting audio after xrun");
|
||||
}
|
||||
}
|
||||
|
@ -1303,70 +1383,24 @@ gst_alsa_open_audio (GstAlsa *this)
|
|||
GST_FLAG_SET (this, GST_ALSA_OPEN);
|
||||
return TRUE;
|
||||
}
|
||||
/* error checking for hw params functions (no warnings on probing ie during capsnego) */
|
||||
#ifdef G_HAVE_ISO_VARARGS
|
||||
#define MY_ERROR_CHECK(value, ...) G_STMT_START{ \
|
||||
int err = (value); \
|
||||
if (err < 0) { \
|
||||
if (! (format && oldformat)) \
|
||||
g_warning ( __VA_ARGS__, snd_strerror (err)); \
|
||||
return FALSE; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||
#define MY_ERROR_CHECK(value, args...) G_STMT_START{ \
|
||||
int err = (value); \
|
||||
if (err < 0) { \
|
||||
if (! (format && oldformat)) \
|
||||
g_warning ( ## args, snd_strerror (err)); \
|
||||
return FALSE; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
#else
|
||||
#define MY_ERROR_CHECK(value, args...) G_STMT_START{ \
|
||||
int err = (value); \
|
||||
if (err < 0) { \
|
||||
if (! (format && oldformat)) \
|
||||
g_warning (snd_strerror (err)); \
|
||||
return FALSE; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
#endif
|
||||
/**
|
||||
* You must set all hw parameters at once and can't use already set params and
|
||||
* change them.
|
||||
* Thx ALSA for not documenting this
|
||||
*/
|
||||
/* if someone finds an easy way to merge this with _set_hw_params, go ahead */
|
||||
static gboolean
|
||||
gst_alsa_set_hw_params (GstAlsa *this, GstAlsaFormat *format)
|
||||
gst_alsa_probe_hw_params (GstAlsa *this, GstAlsaFormat *format)
|
||||
{
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_access_mask_t *mask;
|
||||
GstAlsaFormat * oldformat;
|
||||
snd_pcm_uframes_t period_size;
|
||||
unsigned int period_count;
|
||||
|
||||
g_return_val_if_fail (this != NULL, FALSE);
|
||||
g_return_val_if_fail (this->handle != NULL, FALSE);
|
||||
|
||||
if (format == NULL || format == this->format) {
|
||||
format = this->format;
|
||||
oldformat = NULL;
|
||||
} else {
|
||||
oldformat = this->format;
|
||||
}
|
||||
|
||||
if (format && oldformat) {
|
||||
GST_INFO (GST_CAT_PLUGIN_INFO, "Probing format: %s %dHz, %d channels\n",
|
||||
snd_pcm_format_name (format->format), format->rate, format->channels);
|
||||
} else {
|
||||
GST_INFO (GST_CAT_PLUGIN_INFO, "Preparing format: %s %dHz, %d channels\n",
|
||||
snd_pcm_format_name (format->format), format->rate, format->channels);
|
||||
}
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
|
||||
GST_INFO (GST_CAT_PLUGIN_INFO, "Probing format: %s %dHz, %d channels\n",
|
||||
snd_pcm_format_name (format->format), format->rate, format->channels);
|
||||
|
||||
snd_pcm_hw_params_alloca (&hw_params);
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_any (this->handle, hw_params),
|
||||
"Broken configuration for this PCM: %s");
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_periods_integer (this->handle, hw_params),
|
||||
"cannot restrict period size to integral value: %s");
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_any (this->handle, hw_params));
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_periods_integer (this->handle, hw_params));
|
||||
|
||||
/* enable this for soundcard specific debugging */
|
||||
/* snd_pcm_hw_params_dump (hw_params, this->out); */
|
||||
|
@ -1378,25 +1412,71 @@ gst_alsa_set_hw_params (GstAlsa *this, GstAlsaFormat *format)
|
|||
} else {
|
||||
snd_pcm_access_mask_set (mask, this->mmap ? SND_PCM_ACCESS_MMAP_NONINTERLEAVED : SND_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
}
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_access_mask (this->handle, hw_params, mask),
|
||||
"The Gstreamer ALSA plugin does not support your hardware. Error: %s");
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_access_mask (this->handle, hw_params, mask));
|
||||
|
||||
if (format) {
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_format (this->handle, hw_params, format->format),
|
||||
"Sample format (%s) not available: %s", snd_pcm_format_name (format->format));
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_channels (this->handle, hw_params, format->channels),
|
||||
"Channels count (%d) not available: %s", format->channels);
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_rate (this->handle, hw_params, format->rate, 0),
|
||||
"error setting rate (%d): %s", format->rate);
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_format (this->handle, hw_params, format->format));
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_channels (this->handle, hw_params, format->channels));
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_rate (this->handle, hw_params, format->rate, 0));
|
||||
|
||||
period_count = this->period_count;
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_periods_near (this->handle, hw_params, &period_count, 0));
|
||||
period_size = this->period_size;
|
||||
SIMPLE_ERROR_CHECK (snd_pcm_hw_params_set_period_size_near (this->handle, hw_params, &period_size, 0));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/**
|
||||
* You must set all hw parameters at once and can't use already set params and
|
||||
* change them.
|
||||
* Thx ALSA for not documenting this
|
||||
*/
|
||||
static gboolean
|
||||
gst_alsa_set_hw_params (GstAlsa *this)
|
||||
{
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_access_mask_t *mask;
|
||||
|
||||
g_return_val_if_fail (this != NULL, FALSE);
|
||||
g_return_val_if_fail (this->handle != NULL, FALSE);
|
||||
|
||||
GST_INFO (GST_CAT_PLUGIN_INFO, "Preparing format: %s %dHz, %d channels\n",
|
||||
snd_pcm_format_name (this->format->format), this->format->rate, this->format->channels);
|
||||
|
||||
snd_pcm_hw_params_alloca (&hw_params);
|
||||
ERROR_CHECK (snd_pcm_hw_params_any (this->handle, hw_params),
|
||||
"Broken configuration for this PCM: %s");
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_periods_integer (this->handle, hw_params),
|
||||
"cannot restrict period size to integral value: %s");
|
||||
|
||||
/* enable this for soundcard specific debugging */
|
||||
/* snd_pcm_hw_params_dump (hw_params, this->out); */
|
||||
|
||||
mask = alloca (snd_pcm_access_mask_sizeof ());
|
||||
snd_pcm_access_mask_none (mask);
|
||||
if (GST_ELEMENT (this)->numpads == 1) {
|
||||
snd_pcm_access_mask_set (mask, this->mmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
} else {
|
||||
snd_pcm_access_mask_set (mask, this->mmap ? SND_PCM_ACCESS_MMAP_NONINTERLEAVED : SND_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||
}
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_access_mask (this->handle, hw_params, mask),
|
||||
"The Gstreamer ALSA plugin does not support your hardware. Error: %s");
|
||||
|
||||
if (this->format) {
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_format (this->handle, hw_params, this->format->format),
|
||||
"Sample format (%s) not available: %s", snd_pcm_format_name (this->format->format));
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_channels (this->handle, hw_params, this->format->channels),
|
||||
"Channels count (%d) not available: %s", this->format->channels);
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_rate (this->handle, hw_params, this->format->rate, 0),
|
||||
"error setting rate (%d): %s", this->format->rate);
|
||||
}
|
||||
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_periods_near (this->handle, hw_params, &this->period_count, 0),
|
||||
"error setting buffer size to %u: %s", (guint) this->period_count);
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params_set_period_size_near (this->handle, hw_params, &this->period_size, 0),
|
||||
"error setting period size to %u frames: %s", (guint) this->period_size);
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_periods_near (this->handle, hw_params, &this->period_count, 0),
|
||||
"error setting buffer size to %u: %s", (guint) this->period_count);
|
||||
ERROR_CHECK (snd_pcm_hw_params_set_period_size_near (this->handle, hw_params, &this->period_size, 0),
|
||||
"error setting period size to %u frames: %s", (guint) this->period_size);
|
||||
|
||||
MY_ERROR_CHECK (snd_pcm_hw_params (this->handle, hw_params),
|
||||
"Could not set hardware parameters: %s");
|
||||
ERROR_CHECK (snd_pcm_hw_params (this->handle, hw_params),
|
||||
"Could not set hardware parameters: %s");
|
||||
|
||||
/* now get the pcm caps */
|
||||
GST_ALSA_CAPS_SET (this, GST_ALSA_CAPS_PAUSE, snd_pcm_hw_params_can_pause (hw_params));
|
||||
|
@ -1409,12 +1489,8 @@ gst_alsa_set_hw_params (GstAlsa *this, GstAlsaFormat *format)
|
|||
this->transmit = gst_alsa_do_read_write;
|
||||
}
|
||||
|
||||
g_free (oldformat);
|
||||
this->format = format;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#undef MY_ERROR_CHECK
|
||||
static gboolean
|
||||
gst_alsa_set_sw_params (GstAlsa *this)
|
||||
{
|
||||
|
@ -1444,9 +1520,11 @@ gst_alsa_set_sw_params (GstAlsa *this)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_alsa_start_audio (GstAlsa *this, GstAlsaFormat *format)
|
||||
gst_alsa_start_audio (GstAlsa *this)
|
||||
{
|
||||
if (!gst_alsa_set_hw_params (this, format))
|
||||
g_assert (GST_FLAG_IS_SET (this, GST_ALSA_OPEN));
|
||||
|
||||
if (!gst_alsa_set_hw_params (this))
|
||||
return FALSE;
|
||||
if (!gst_alsa_set_sw_params (this))
|
||||
return FALSE;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <glib.h>
|
||||
|
||||
#define GST_ALSA_MAX_CHANNELS 64 /* we don't support more than 64 channels */
|
||||
#define GST_ALSA_MIN_RATE 8000
|
||||
#define GST_ALSA_MAX_RATE 192000
|
||||
|
||||
#define GST_ALSA(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA, GstAlsa)
|
||||
#define GST_ALSA_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_ALSA, GstAlsaClass)
|
||||
|
|
Loading…
Reference in a new issue