summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/pulse/pulsesink.h6
-rw-r--r--ext/pulse/pulsesrc.c68
-rw-r--r--ext/pulse/pulseutil.c151
3 files changed, 115 insertions, 110 deletions
diff --git a/ext/pulse/pulsesink.h b/ext/pulse/pulsesink.h
index 067f684bb..9f5ae2211 100644
--- a/ext/pulse/pulsesink.h
+++ b/ext/pulse/pulsesink.h
@@ -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;" \
diff --git a/ext/pulse/pulsesrc.c b/ext/pulse/pulsesrc.c
index 09acced08..e8e91b24a 100644
--- a/ext/pulse/pulsesrc.c
+++ b/ext/pulse/pulsesrc.c
@@ -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);
-
- gst_pulse_channel_map_to_gst (m, &spec);
- caps = spec.caps;
- }
+ 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_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,
diff --git a/ext/pulse/pulseutil.c b/ext/pulse/pulseutil.c
index e29e7e970..607fdd436 100644
--- a/ext/pulse/pulseutil.c
+++ b/ext/pulse/pulseutil.c
@@ -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)))) {
- return NULL;
+ 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;
}
- 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;
+ if (j != spec->info.channels) {
+ return NULL;
}
- 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;
}