pulsesink: Use the extended stream API if available

This uses the new extended API for creating streams. This will allow us
to support compressed formats natively in pulsesink as well.
This commit is contained in:
Arun Raghavan 2011-03-01 15:34:46 +05:30
parent 379049809c
commit a67b536741
4 changed files with 131 additions and 0 deletions

View file

@ -839,6 +839,10 @@ AG_GST_CHECK_FEATURE(PULSE, [pulseaudio plug-in], pulseaudio, [
if test x$HAVE_PULSE_0_9_20 = xyes; then if test x$HAVE_PULSE_0_9_20 = xyes; then
AC_DEFINE(HAVE_PULSE_0_9_20, 1, [defined if pulseaudio >= 0.9.20 is available]) AC_DEFINE(HAVE_PULSE_0_9_20, 1, [defined if pulseaudio >= 0.9.20 is available])
fi fi
AG_GST_PKG_CHECK_MODULES(PULSE_1_0, libpulse >= 0.98)
if test x$HAVE_PULSE_1_0 = xyes; then
AC_DEFINE(HAVE_PULSE_1_0, 1, [defined if pulseaudio >= 1.0 is available])
fi
]) ])
dnl *** dv1394 *** dnl *** dv1394 ***

View file

@ -138,7 +138,12 @@ struct _GstPulseRingBuffer
pa_context *context; pa_context *context;
pa_stream *stream; pa_stream *stream;
#if HAVE_PULSE_1_0
pa_format_info *format;
guint channels;
#else
pa_sample_spec sample_spec; pa_sample_spec sample_spec;
#endif
void *m_data; void *m_data;
size_t m_towrite; size_t m_towrite;
@ -222,7 +227,12 @@ gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf)
pbuf->context = NULL; pbuf->context = NULL;
pbuf->stream = NULL; pbuf->stream = NULL;
#ifdef HAVE_PULSE_1_0
pbuf->format = NULL;
pbuf->channels = 0;
#else
pa_sample_spec_init (&pbuf->sample_spec); pa_sample_spec_init (&pbuf->sample_spec);
#endif
pbuf->m_data = NULL; pbuf->m_data = NULL;
pbuf->m_towrite = 0; pbuf->m_towrite = 0;
@ -251,6 +261,13 @@ gst_pulsering_destroy_stream (GstPulseRingBuffer * pbuf)
pbuf->m_offset = 0; pbuf->m_offset = 0;
pbuf->m_lastoffset = 0; pbuf->m_lastoffset = 0;
} }
#ifdef HAVE_PULSE_1_0
if (pbuf->format) {
pa_format_info_free (pbuf->format);
pbuf->format = NULL;
pbuf->channels = 0;
}
#endif
pa_stream_disconnect (pbuf->stream); pa_stream_disconnect (pbuf->stream);
@ -718,14 +735,22 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
pa_stream_flags_t flags; pa_stream_flags_t flags;
const gchar *name; const gchar *name;
GstAudioClock *clock; GstAudioClock *clock;
#ifdef HAVE_PULSE_1_0
pa_format_info *formats[1];
#endif
psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf)); psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
pbuf = GST_PULSERING_BUFFER_CAST (buf); pbuf = GST_PULSERING_BUFFER_CAST (buf);
GST_LOG_OBJECT (psink, "creating sample spec"); GST_LOG_OBJECT (psink, "creating sample spec");
/* convert the gstreamer sample spec to the pulseaudio format */ /* convert the gstreamer sample spec to the pulseaudio format */
#ifdef HAVE_PULSE_1_0
if (!gst_pulse_fill_format_info (spec, &pbuf->format, &pbuf->channels))
goto invalid_spec;
#else
if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec)) if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec))
goto invalid_spec; goto invalid_spec;
#endif
pa_threaded_mainloop_lock (mainloop); pa_threaded_mainloop_lock (mainloop);
@ -742,7 +767,13 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
pa_operation_unref (o); pa_operation_unref (o);
/* initialize the channel map */ /* initialize the channel map */
#ifdef HAVE_PULSE_1_0
if (pa_format_info_is_pcm (pbuf->format) &&
gst_pulse_gst_to_channel_map (&channel_map, spec))
pa_format_info_set_channel_map (pbuf->format, &channel_map);
#else
gst_pulse_gst_to_channel_map (&channel_map, spec); gst_pulse_gst_to_channel_map (&channel_map, spec);
#endif
/* find a good name for the stream */ /* find a good name for the stream */
if (psink->stream_name) if (psink->stream_name)
@ -751,10 +782,17 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
name = "Playback Stream"; name = "Playback Stream";
/* create a stream */ /* create a stream */
#ifdef HAVE_PULSE_1_0
formats[0] = pbuf->format;
if (!(pbuf->stream = pa_stream_new_extended (pbuf->context, name, formats, 1,
psink->proplist)))
goto stream_failed;
#else
GST_LOG_OBJECT (psink, "creating stream with name %s", name); GST_LOG_OBJECT (psink, "creating stream with name %s", name);
if (!(pbuf->stream = pa_stream_new_with_proplist (pbuf->context, name, if (!(pbuf->stream = pa_stream_new_with_proplist (pbuf->context, name,
&pbuf->sample_spec, &channel_map, psink->proplist))) &pbuf->sample_spec, &channel_map, psink->proplist)))
goto stream_failed; goto stream_failed;
#endif
/* install essential callbacks */ /* install essential callbacks */
pa_stream_set_state_callback (pbuf->stream, pa_stream_set_state_callback (pbuf->stream,
@ -792,8 +830,13 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
if (psink->volume_set) { if (psink->volume_set) {
GST_LOG_OBJECT (psink, "have volume of %f", psink->volume); GST_LOG_OBJECT (psink, "have volume of %f", psink->volume);
pv = &v; pv = &v;
#ifdef HAVE_PULSE_1_0
if (pa_format_info_is_pcm (pbuf->format))
gst_pulse_cvolume_from_linear (pv, pbuf->channels, psink->volume);
#else
gst_pulse_cvolume_from_linear (pv, pbuf->sample_spec.channels, gst_pulse_cvolume_from_linear (pv, pbuf->sample_spec.channels,
psink->volume); psink->volume);
#endif
} else { } else {
pv = NULL; pv = NULL;
} }
@ -1923,7 +1966,12 @@ gst_pulsesink_set_volume (GstPulseSink * psink, gdouble volume)
if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX) if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
goto no_index; goto no_index;
#ifdef HAVE_PULSE_1_0
if (pa_format_info_is_pcm (pbuf->format))
gst_pulse_cvolume_from_linear (&v, pbuf->channels, volume);
#else
gst_pulse_cvolume_from_linear (&v, pbuf->sample_spec.channels, volume); gst_pulse_cvolume_from_linear (&v, pbuf->sample_spec.channels, volume);
#endif
if (!(o = pa_context_set_sink_input_volume (pbuf->context, idx, if (!(o = pa_context_set_sink_input_volume (pbuf->context, idx,
&v, NULL, NULL))) &v, NULL, NULL)))

View file

@ -118,6 +118,81 @@ gst_pulse_fill_sample_spec (GstRingBufferSpec * spec, pa_sample_spec * ss)
return TRUE; return TRUE;
} }
#ifdef HAVE_PULSE_1_0
gboolean
gst_pulse_fill_format_info (GstRingBufferSpec * spec, pa_format_info ** f,
guint * channels)
{
pa_format_info *format;
pa_sample_format_t sf = PA_SAMPLE_INVALID;
format = pa_format_info_new ();
if (spec->format == GST_MU_LAW && spec->width == 8) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_ULAW;
} else if (spec->format == GST_A_LAW && spec->width == 8) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_ALAW;
} else if (spec->format == GST_U8 && spec->width == 8) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_U8;
} else if (spec->format == GST_S16_LE && spec->width == 16) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S16LE;
} else if (spec->format == GST_S16_BE && spec->width == 16) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S16BE;
} else if (spec->format == GST_FLOAT32_LE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_FLOAT32LE;
} else if (spec->format == GST_FLOAT32_BE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_FLOAT32BE;
} else if (spec->format == GST_S32_LE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S32LE;
} else if (spec->format == GST_S32_BE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S32BE;
} else if (spec->format == GST_S24_3LE && spec->width == 24) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S24LE;
} else if (spec->format == GST_S24_3BE && spec->width == 24) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S24BE;
} else if (spec->format == GST_S24_LE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S24_32LE;
} else if (spec->format == GST_S24_BE && spec->width == 32) {
format->encoding = PA_ENCODING_PCM;
sf = PA_SAMPLE_S24_32BE;
} else {
goto fail;
}
if (format->encoding == PA_ENCODING_PCM) {
pa_format_info_set_sample_format (format, sf);
pa_format_info_set_channels (format, spec->channels);
}
pa_format_info_set_rate (format, spec->rate);
if (!pa_format_info_valid (format))
goto fail;
*f = format;
*channels = spec->channels;
return TRUE;
fail:
if (format)
pa_format_info_free (format);
return FALSE;
}
#endif
/* PATH_MAX is not defined everywhere, e.g. on GNU Hurd */ /* PATH_MAX is not defined everywhere, e.g. on GNU Hurd */
#ifndef PATH_MAX #ifndef PATH_MAX
#define PATH_MAX 4096 #define PATH_MAX 4096

View file

@ -28,6 +28,10 @@
gboolean gst_pulse_fill_sample_spec (GstRingBufferSpec * spec, gboolean gst_pulse_fill_sample_spec (GstRingBufferSpec * spec,
pa_sample_spec * ss); pa_sample_spec * ss);
#ifdef HAVE_PULSE_1_0
gboolean gst_pulse_fill_format_info (GstRingBufferSpec * spec,
pa_format_info ** f, guint * channels);
#endif
gchar *gst_pulse_client_name (void); gchar *gst_pulse_client_name (void);