mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
pulse: Port to the new multichannel caps
This commit is contained in:
parent
d239f10888
commit
dc049d1f1f
3 changed files with 116 additions and 111 deletions
|
@ -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;" \
|
||||
|
|
|
@ -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);
|
||||
caps = spec.caps;
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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] =
|
||||
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_RIGHT_OF_CENTER + 1] =
|
||||
PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (j != spec->info.channels) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue