Commit 4d67d1bd authored by Arun Raghavan's avatar Arun Raghavan Committed by Arun Raghavan

pulsesrc: Move to extended stream API

This is needed as a precursor to allowing capture of IEC61937
formats. We now also need to include the channel map while converting
format info to caps so that a correct channel mask is generated for
pulsesrc's caps.
parent 8f8de410
Pipeline #14523 passed with stages
in 62 minutes and 47 seconds
...@@ -898,7 +898,7 @@ gst_pulseringbuffer_acquire (GstAudioRingBuffer * buf, ...@@ -898,7 +898,7 @@ gst_pulseringbuffer_acquire (GstAudioRingBuffer * 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 */
if (!gst_pulse_fill_format_info (spec, &pbuf->format, &pbuf->channels)) if (!gst_pulse_fill_format_info (spec, &pbuf->format, NULL, &pbuf->channels))
goto invalid_spec; goto invalid_spec;
pbuf->is_pcm = pa_format_info_is_pcm (pbuf->format); pbuf->is_pcm = pa_format_info_is_pcm (pbuf->format);
...@@ -2273,7 +2273,7 @@ gst_pulsesink_query_acceptcaps (GstPulseSink * psink, GstCaps * caps) ...@@ -2273,7 +2273,7 @@ gst_pulsesink_query_acceptcaps (GstPulseSink * psink, GstCaps * caps)
if (!gst_audio_ring_buffer_parse_caps (&spec, caps)) if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
goto out; goto out;
if (!gst_pulse_fill_format_info (&spec, &format, &channels)) if (!gst_pulse_fill_format_info (&spec, &format, NULL, &channels))
goto out; goto out;
/* Make sure input is framed (one frame per buffer) and can be payloaded */ /* Make sure input is framed (one frame per buffer) and can be payloaded */
......
...@@ -261,7 +261,7 @@ gst_pulsesrc_init (GstPulseSrc * pulsesrc) ...@@ -261,7 +261,7 @@ gst_pulsesrc_init (GstPulseSrc * pulsesrc)
pulsesrc->read_buffer = NULL; pulsesrc->read_buffer = NULL;
pulsesrc->read_buffer_length = 0; pulsesrc->read_buffer_length = 0;
pa_sample_spec_init (&pulsesrc->sample_spec); pulsesrc->format = NULL;
pulsesrc->operation_success = FALSE; pulsesrc->operation_success = FALSE;
pulsesrc->paused = TRUE; pulsesrc->paused = TRUE;
...@@ -340,6 +340,8 @@ gst_pulsesrc_finalize (GObject * object) ...@@ -340,6 +340,8 @@ gst_pulsesrc_finalize (GObject * object)
gst_structure_free (pulsesrc->properties); gst_structure_free (pulsesrc->properties);
if (pulsesrc->proplist) if (pulsesrc->proplist)
pa_proplist_free (pulsesrc->proplist); pa_proplist_free (pulsesrc->proplist);
if (pulsesrc->format)
pa_format_info_free (pulsesrc->format);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
...@@ -628,7 +630,7 @@ gst_pulsesrc_set_stream_volume (GstPulseSrc * pulsesrc, gdouble volume) ...@@ -628,7 +630,7 @@ gst_pulsesrc_set_stream_volume (GstPulseSrc * pulsesrc, gdouble volume)
GST_DEBUG_OBJECT (pulsesrc, "setting volume to %f", volume); GST_DEBUG_OBJECT (pulsesrc, "setting volume to %f", volume);
gst_pulse_cvolume_from_linear (&v, pulsesrc->sample_spec.channels, volume); gst_pulse_cvolume_from_linear (&v, pulsesrc->channels, volume);
if (!(o = pa_context_set_source_output_volume (pulsesrc->context, if (!(o = pa_context_set_source_output_volume (pulsesrc->context,
pulsesrc->source_output_idx, &v, NULL, NULL))) pulsesrc->source_output_idx, &v, NULL, NULL)))
...@@ -1220,7 +1222,7 @@ gst_pulsesrc_delay (GstAudioSrc * asrc) ...@@ -1220,7 +1222,7 @@ gst_pulsesrc_delay (GstAudioSrc * asrc)
if (negative) if (negative)
result = 0; result = 0;
else else
result = (guint) ((t * pulsesrc->sample_spec.rate) / 1000000LL); result = (guint) ((t * pulsesrc->rate) / 1000000LL);
} }
return result; return result;
...@@ -1238,7 +1240,7 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps, ...@@ -1238,7 +1240,7 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps,
GstAudioRingBufferSpec * rspec) GstAudioRingBufferSpec * rspec)
{ {
pa_channel_map channel_map; pa_channel_map channel_map;
const pa_channel_map *m; pa_format_info *formats[1];
GstStructure *s; GstStructure *s;
gboolean need_channel_layout = FALSE; gboolean need_channel_layout = FALSE;
GstAudioRingBufferSpec new_spec, *spec = NULL; GstAudioRingBufferSpec new_spec, *spec = NULL;
...@@ -1298,34 +1300,36 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps, ...@@ -1298,34 +1300,36 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps,
g_assert_not_reached (); g_assert_not_reached ();
} }
if (!gst_pulse_fill_sample_spec (spec, &pulsesrc->sample_spec)) if (!gst_pulse_fill_format_info (spec, &pulsesrc->format, &pulsesrc->rate,
&pulsesrc->channels))
goto invalid_spec; goto invalid_spec;
if (need_channel_layout) {
pa_channel_map_init_auto (&channel_map, pulsesrc->channels,
PA_CHANNEL_MAP_DEFAULT);
}
pa_format_info_set_channel_map (pulsesrc->format, &channel_map);
pa_threaded_mainloop_lock (pulsesrc->mainloop); pa_threaded_mainloop_lock (pulsesrc->mainloop);
if (!pulsesrc->context) if (!pulsesrc->context)
goto bad_context; goto bad_context;
name = "Record Stream"; name = "Record Stream";
if (pulsesrc->proplist) {
if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context, formats[0] = pulsesrc->format;
name, &pulsesrc->sample_spec,
(need_channel_layout) ? NULL : &channel_map, if (!(pulsesrc->stream = pa_stream_new_extended (pulsesrc->context,
pulsesrc->proplist))) name, formats, 1, pulsesrc->proplist)))
goto create_failed;
} else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
name, &pulsesrc->sample_spec,
(need_channel_layout) ? NULL : &channel_map)))
goto create_failed; goto create_failed;
if (caps) { if (caps) {
m = pa_stream_get_channel_map (pulsesrc->stream); gst_pulse_channel_map_to_gst (&channel_map, &new_spec);
gst_pulse_channel_map_to_gst (m, &new_spec);
gst_audio_channel_positions_to_valid_order (new_spec.info.position, gst_audio_channel_positions_to_valid_order (new_spec.info.position,
new_spec.info.channels); new_spec.info.channels);
gst_caps_unref (*caps); gst_caps_unref (*caps);
*caps = gst_audio_info_to_caps (&new_spec.info); *caps = gst_pulse_format_info_to_caps (pulsesrc->format);
GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps); GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
} }
...@@ -1479,10 +1483,15 @@ gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec) ...@@ -1479,10 +1483,15 @@ gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
{ {
GstAudioRingBufferSpec s = *spec; GstAudioRingBufferSpec s = *spec;
const pa_channel_map *m; pa_channel_map m;
if (gst_pulse_format_info_get_channel_map (pulsesrc->format, &m) < 0) {
GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
("Could not get channel map for stream"), (NULL));
goto unlock_and_fail;
}
m = pa_stream_get_channel_map (pulsesrc->stream); gst_pulse_channel_map_to_gst (&m, &s);
gst_pulse_channel_map_to_gst (m, &s);
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
(pulsesrc)->ringbuffer, s.info.position); (pulsesrc)->ringbuffer, s.info.position);
} }
......
...@@ -60,7 +60,9 @@ struct _GstPulseSrc ...@@ -60,7 +60,9 @@ struct _GstPulseSrc
pa_stream *stream; pa_stream *stream;
guint32 source_output_idx; guint32 source_output_idx;
pa_sample_spec sample_spec; pa_format_info *format;
guint rate;
guint channels;
const void *read_buffer; const void *read_buffer;
size_t read_buffer_length; size_t read_buffer_length;
......
...@@ -138,7 +138,7 @@ gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec, pa_sample_spec * ss) ...@@ -138,7 +138,7 @@ gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec, pa_sample_spec * ss)
gboolean gboolean
gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f, gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f,
guint * channels) guint * rate, guint * channels)
{ {
pa_format_info *format; pa_format_info *format;
pa_sample_format_t sf = PA_SAMPLE_INVALID; pa_sample_format_t sf = PA_SAMPLE_INVALID;
...@@ -186,7 +186,10 @@ gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f, ...@@ -186,7 +186,10 @@ gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, pa_format_info ** f,
goto fail; goto fail;
*f = format; *f = format;
*channels = GST_AUDIO_INFO_CHANNELS (ainfo); if (rate)
*rate = GST_AUDIO_INFO_RATE (ainfo);
if (channels)
*channels = GST_AUDIO_INFO_CHANNELS (ainfo);
return TRUE; return TRUE;
...@@ -434,12 +437,34 @@ gst_pulse_format_info_int_prop_to_value (pa_format_info * format, ...@@ -434,12 +437,34 @@ gst_pulse_format_info_int_prop_to_value (pa_format_info * format,
return TRUE; return TRUE;
} }
/* FIXME: switch to PA API when it is available */
int
gst_pulse_format_info_get_channel_map (pa_format_info * f, pa_channel_map * map)
{
int r;
char *map_str;
r = pa_format_info_get_prop_string (f, PA_PROP_FORMAT_CHANNEL_MAP, &map_str);
if (r < 0)
return r;
map = pa_channel_map_parse (map, map_str);
pa_xfree (map_str);
if (!map)
return -PA_ERR_INVALID;
return 0;
}
GstCaps * GstCaps *
gst_pulse_format_info_to_caps (pa_format_info * format) gst_pulse_format_info_to_caps (pa_format_info * format)
{ {
GstCaps *ret = NULL; GstCaps *ret = NULL;
GValue v = { 0, }; GValue v = { 0, };
pa_sample_spec ss; pa_sample_spec ss;
pa_channel_map map;
int channels = 0;
switch (format->encoding) { switch (format->encoding) {
case PA_ENCODING_PCM:{ case PA_ENCODING_PCM:{
...@@ -504,6 +529,25 @@ gst_pulse_format_info_to_caps (pa_format_info * format) ...@@ -504,6 +529,25 @@ gst_pulse_format_info_to_caps (pa_format_info * format)
&v)) &v))
gst_caps_set_value (ret, "channels", &v); gst_caps_set_value (ret, "channels", &v);
if (pa_format_info_get_prop_int (format, PA_PROP_FORMAT_CHANNELS,
&channels) == 0
&& gst_pulse_format_info_get_channel_map (format, &map) == 0) {
guint64 channel_mask;
GstAudioRingBufferSpec spec;
GST_AUDIO_INFO_CHANNELS (&spec.info) = channels;
if (gst_pulse_channel_map_to_gst (&map, &spec) &&
!(GST_AUDIO_INFO_IS_UNPOSITIONED (&spec.info)) &&
gst_audio_channel_positions_to_mask (&GST_AUDIO_INFO_POSITION
(&spec.info, 0), channels, FALSE, &channel_mask)) {
gst_caps_set_simple (ret, "channel-mask", GST_TYPE_BITMASK,
channel_mask, NULL);
} else {
GST_WARNING ("Could not convert channel map to channel mask");
}
}
out: out:
return ret; return ret;
} }
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
gboolean gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec, gboolean gst_pulse_fill_sample_spec (GstAudioRingBufferSpec * spec,
pa_sample_spec * ss); pa_sample_spec * ss);
gboolean gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec, gboolean gst_pulse_fill_format_info (GstAudioRingBufferSpec * spec,
pa_format_info ** f, guint * channels); pa_format_info ** f, guint * rate, guint * channels);
const char * gst_pulse_sample_format_to_caps_format (pa_sample_format_t sf); const char * gst_pulse_sample_format_to_caps_format (pa_sample_format_t sf);
gchar *gst_pulse_client_name (void); gchar *gst_pulse_client_name (void);
...@@ -91,6 +91,8 @@ void gst_pulse_cvolume_from_linear (pa_cvolume *v, unsigned channels, gdouble vo ...@@ -91,6 +91,8 @@ void gst_pulse_cvolume_from_linear (pa_cvolume *v, unsigned channels, gdouble vo
pa_proplist *gst_pulse_make_proplist (const GstStructure *properties); pa_proplist *gst_pulse_make_proplist (const GstStructure *properties);
GstStructure *gst_pulse_make_structure (pa_proplist *properties); GstStructure *gst_pulse_make_structure (pa_proplist *properties);
int gst_pulse_format_info_get_channel_map (pa_format_info * format,
pa_channel_map *map);
GstCaps * gst_pulse_format_info_to_caps (pa_format_info * format); GstCaps * gst_pulse_format_info_to_caps (pa_format_info * format);
GstCaps * gst_pulse_fix_pcm_caps (GstCaps * incaps); GstCaps * gst_pulse_fix_pcm_caps (GstCaps * incaps);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment