pulse: Port to the new multichannel caps

This commit is contained in:
Sebastian Dröge 2012-01-04 10:27:09 +01:00
parent d239f10888
commit dc049d1f1f
3 changed files with 116 additions and 111 deletions

View file

@ -101,13 +101,17 @@ GType gst_pulsesink_get_type (void);
#define _PULSE_SINK_CAPS_COMMON \
"audio/x-raw, " \
"format = (string) " FORMATS ", " \
"layout = (string) interleaved, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, 32 ];" \
"audio/x-alaw, " \
"layout = (string) interleaved, " \
"rate = (int) [ 1, MAX], " \
"channels = (int) [ 1, 32 ];" \
"audio/x-mulaw, " \
"rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
"layout = (string) interleaved, " \
"rate = (int) [ 1, MAX], " \
"channels = (int) [ 1, 32 ];"
#define _PULSE_SINK_CAPS_1_0 \
"audio/x-ac3, framed = (boolean) true;" \

View file

@ -116,6 +116,7 @@ static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw, "
"format = (string) " FORMATS ", "
"layout = (string) interleaved, "
"rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, 32 ];"
"audio/x-alaw, "
@ -1136,22 +1137,48 @@ server_dead:
}
static gboolean
gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps)
{
pa_channel_map channel_map;
const pa_channel_map *m;
GstStructure *s;
gboolean need_channel_layout = FALSE;
GstAudioRingBufferSpec spec;
const gchar *name;
s = gst_caps_get_structure (*caps, 0);
gst_structure_get_int (s, "channels", &spec.info.channels);
if (!gst_structure_has_field (s, "channel-mask")) {
if (spec.info.channels == 1) {
pa_channel_map_init_mono (&channel_map);
} else if (spec.info.channels == 2) {
gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT), NULL);
pa_channel_map_init_stereo (&channel_map);
} else {
need_channel_layout = TRUE;
gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
G_GUINT64_CONSTANT (0), NULL);
}
}
memset (&spec, 0, sizeof (GstAudioRingBufferSpec));
spec.latency_time = GST_SECOND;
if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
if (!gst_audio_ring_buffer_parse_caps (&spec, *caps))
goto invalid_caps;
/* Keep the refcount of the caps at 1 to make them writable */
gst_caps_unref (spec.caps);
if (!need_channel_layout
&& !gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
need_channel_layout = TRUE;
gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
G_GUINT64_CONSTANT (0), NULL);
memset (spec.info.position, 0xff, sizeof (spec.info.position));
}
if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec))
goto invalid_spec;
@ -1160,17 +1187,6 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
if (!pulsesrc->context)
goto bad_context;
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_has_field (s, "channel-layout") ||
!gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
if (spec.info.channels == 1)
pa_channel_map_init_mono (&channel_map);
else if (spec.info.channels == 2)
pa_channel_map_init_stereo (&channel_map);
else
need_channel_layout = TRUE;
}
name = "Record Stream";
if (pulsesrc->proplist) {
if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
@ -1184,14 +1200,14 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
(need_channel_layout) ? NULL : &channel_map)))
goto create_failed;
if (need_channel_layout) {
const pa_channel_map *m = pa_stream_get_channel_map (pulsesrc->stream);
m = pa_stream_get_channel_map (pulsesrc->stream);
gst_pulse_channel_map_to_gst (m, &spec);
gst_audio_channel_positions_to_valid_order (spec.info.position,
spec.info.channels);
gst_caps_unref (*caps);
*caps = gst_audio_info_to_caps (&spec.info);
gst_pulse_channel_map_to_gst (m, &spec);
caps = spec.caps;
}
GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, caps);
GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
pulsesrc);
@ -1292,7 +1308,7 @@ gst_pulsesrc_negotiate (GstBaseSrc * basesrc)
result = TRUE;
} else if (gst_caps_is_fixed (caps)) {
/* yay, fixed caps, use those then */
result = gst_pulsesrc_create_stream (pulsesrc, caps);
result = gst_pulsesrc_create_stream (pulsesrc, &caps);
if (result)
result = gst_base_src_set_caps (basesrc, caps);
}
@ -1321,6 +1337,16 @@ gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
pa_threaded_mainloop_lock (pulsesrc->mainloop);
{
GstAudioRingBufferSpec s = *spec;
const pa_channel_map *m;
m = pa_stream_get_channel_map (pulsesrc->stream);
gst_pulse_channel_map_to_gst (m, &s);
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
(pulsesrc)->ringbuffer, s.info.position);
}
/* enable event notifications */
GST_LOG_OBJECT (pulsesrc, "subscribing to context events");
if (!(o = pa_context_subscribe (pulsesrc->context,

View file

@ -24,7 +24,6 @@
#endif
#include "pulseutil.h"
#include <gst/audio/multichannel.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* getpid on UNIX */
@ -33,60 +32,39 @@
# include <process.h> /* getpid on win32 */
#endif
static const pa_channel_position_t gst_pos_to_pa[GST_AUDIO_CHANNEL_POSITION_NUM]
= {
[GST_AUDIO_CHANNEL_POSITION_FRONT_MONO] = PA_CHANNEL_POSITION_MONO,
[GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT] = PA_CHANNEL_POSITION_FRONT_LEFT,
[GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT] = PA_CHANNEL_POSITION_FRONT_RIGHT,
[GST_AUDIO_CHANNEL_POSITION_REAR_CENTER] = PA_CHANNEL_POSITION_REAR_CENTER,
[GST_AUDIO_CHANNEL_POSITION_REAR_LEFT] = PA_CHANNEL_POSITION_REAR_LEFT,
[GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT] = PA_CHANNEL_POSITION_REAR_RIGHT,
[GST_AUDIO_CHANNEL_POSITION_LFE] = PA_CHANNEL_POSITION_LFE,
[GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER] = PA_CHANNEL_POSITION_FRONT_CENTER,
[GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] =
PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
[GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] =
PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
[GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT] = PA_CHANNEL_POSITION_SIDE_LEFT,
[GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT] = PA_CHANNEL_POSITION_SIDE_RIGHT,
[GST_AUDIO_CHANNEL_POSITION_TOP_CENTER] = PA_CHANNEL_POSITION_TOP_CENTER,
[GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT] =
PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
[GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT] =
PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
[GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER] =
PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
[GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT] =
PA_CHANNEL_POSITION_TOP_REAR_LEFT,
[GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT] =
PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
[GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER] =
PA_CHANNEL_POSITION_TOP_REAR_CENTER,
[GST_AUDIO_CHANNEL_POSITION_NONE] = PA_CHANNEL_POSITION_INVALID
};
/* All index are increased by one because PA_CHANNEL_POSITION_INVALID == -1 */
static const GstAudioChannelPosition
pa_to_gst_pos[GST_AUDIO_CHANNEL_POSITION_NUM]
= {
[PA_CHANNEL_POSITION_MONO + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
[PA_CHANNEL_POSITION_FRONT_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
[PA_CHANNEL_POSITION_FRONT_RIGHT + 1] =
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
[PA_CHANNEL_POSITION_REAR_CENTER + 1] =
GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
[PA_CHANNEL_POSITION_REAR_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
[PA_CHANNEL_POSITION_REAR_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
[PA_CHANNEL_POSITION_LFE + 1] = GST_AUDIO_CHANNEL_POSITION_LFE,
[PA_CHANNEL_POSITION_FRONT_CENTER + 1] =
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
[PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER + 1] =
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
[PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER + 1] =
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
[PA_CHANNEL_POSITION_SIDE_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
[PA_CHANNEL_POSITION_SIDE_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
[PA_CHANNEL_POSITION_INVALID + 1] = GST_AUDIO_CHANNEL_POSITION_NONE,
static const struct
{
GstAudioChannelPosition gst_pos;
pa_channel_position_t pa_pos;
} gst_pa_pos_table[] = {
{
GST_AUDIO_CHANNEL_POSITION_MONO, PA_CHANNEL_POSITION_MONO}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, PA_CHANNEL_POSITION_REAR_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_LEFT}, {
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_REAR_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_LFE1, PA_CHANNEL_POSITION_LFE}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_FRONT_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_LEFT}, {
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, PA_CHANNEL_POSITION_SIDE_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, PA_CHANNEL_POSITION_TOP_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
PA_CHANNEL_POSITION_TOP_FRONT_LEFT}, {
GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
PA_CHANNEL_POSITION_TOP_FRONT_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
PA_CHANNEL_POSITION_TOP_FRONT_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, PA_CHANNEL_POSITION_TOP_REAR_LEFT}, {
GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
PA_CHANNEL_POSITION_TOP_REAR_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
PA_CHANNEL_POSITION_TOP_REAR_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_NONE, PA_CHANNEL_POSITION_INVALID}
};
static gboolean
@ -235,29 +213,30 @@ pa_channel_map *
gst_pulse_gst_to_channel_map (pa_channel_map * map,
const GstAudioRingBufferSpec * spec)
{
int i;
GstAudioChannelPosition *pos;
gint i, j;
gint channels;
const GstAudioChannelPosition *pos;
pa_channel_map_init (map);
if (!(pos =
gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps,
0)))) {
channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
pos = spec->info.position;
for (j = 0; j < channels; j++) {
for (i = 0; i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
if (pos[j] == gst_pa_pos_table[i].gst_pos) {
map->map[j] = gst_pa_pos_table[i].pa_pos;
break;
}
}
if (i == G_N_ELEMENTS (gst_pa_pos_table))
return NULL;
}
if (j != spec->info.channels) {
return NULL;
}
for (i = 0; i < spec->info.channels; i++) {
if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) {
/* no valid mappings for these channels */
g_free (pos);
return NULL;
} else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM)
map->map[i] = gst_pos_to_pa[pos[i]];
else
map->map[i] = PA_CHANNEL_POSITION_INVALID;
}
g_free (pos);
map->channels = spec->info.channels;
if (!pa_channel_map_valid (map)) {
@ -271,30 +250,30 @@ GstAudioRingBufferSpec *
gst_pulse_channel_map_to_gst (const pa_channel_map * map,
GstAudioRingBufferSpec * spec)
{
int i;
GstAudioChannelPosition *pos;
gint i, j;
gboolean invalid = FALSE;
gint channels;
GstAudioChannelPosition *pos;
channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
g_return_val_if_fail (map->channels == channels, NULL);
pos = g_new0 (GstAudioChannelPosition, channels + 1);
pos = spec->info.position;
for (i = 0; i < channels; i++) {
if (map->map[i] == PA_CHANNEL_POSITION_INVALID) {
invalid = TRUE;
break;
} else if ((int) map->map[i] < (int) GST_AUDIO_CHANNEL_POSITION_NUM) {
pos[i] = pa_to_gst_pos[map->map[i] + 1];
} else {
invalid = TRUE;
break;
for (j = 0; j < channels; j++) {
for (i = 0; j < channels && i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
if (map->map[j] == gst_pa_pos_table[i].pa_pos) {
pos[j] = gst_pa_pos_table[i].gst_pos;
break;
}
}
if (i == G_N_ELEMENTS (gst_pa_pos_table))
return NULL;
}
if (!invalid && !gst_audio_check_channel_positions (pos, channels))
if (!invalid
&& !gst_audio_check_valid_channel_positions (pos, channels, FALSE))
invalid = TRUE;
if (invalid) {
@ -302,10 +281,6 @@ gst_pulse_channel_map_to_gst (const pa_channel_map * map,
pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
}
gst_audio_set_channel_positions (gst_caps_get_structure (spec->caps, 0), pos);
g_free (pos);
return spec;
}