diff options
-rw-r--r-- | ext/pulse/pulsesink.h | 6 | ||||
-rw-r--r-- | ext/pulse/pulsesrc.c | 68 | ||||
-rw-r--r-- | ext/pulse/pulseutil.c | 151 |
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; } |