alsa: Port to the new multichannel caps

This commit is contained in:
Sebastian Dröge 2011-12-20 11:44:27 +01:00
parent d7c1b90a50
commit 2fc75efdce
4 changed files with 104 additions and 34 deletions

View file

@ -204,26 +204,23 @@ get_channel_free_structure (const GstStructure * in_structure)
return s;
}
#define ONE_64 G_GUINT64_CONSTANT (1)
#define CHANNEL_MASK_STEREO ((ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT))
#define CHANNEL_MASK_2_1 (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
#define CHANNEL_MASK_4_0 (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT))
#define CHANNEL_MASK_5_1 (CHANNEL_MASK_4_0 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
#define CHANNEL_MASK_7_1 (CHANNEL_MASK_5_1 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT))
static void
caps_add_channel_configuration (GstCaps * caps,
const GstStructure * in_structure, gint min_chans, gint max_chans)
{
GstAudioChannelPosition pos[8] = {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE,
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
};
GstStructure *s = NULL;
gint c;
if (min_chans == max_chans && max_chans <= 2) {
if (min_chans == max_chans && max_chans == 1) {
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
gst_caps_append_structure (caps, s);
return;
}
@ -233,11 +230,16 @@ caps_add_channel_configuration (GstCaps * caps,
/* mono and stereo don't need channel configurations */
if (min_chans == 2) {
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
gst_caps_append_structure (caps, s);
} else if (min_chans == 1 && max_chans >= 2) {
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
gst_caps_append_structure (caps, s);
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
gst_caps_append_structure (caps, s);
}
@ -245,41 +247,44 @@ caps_add_channel_configuration (GstCaps * caps,
* alsa might work around that/fix it somehow. Can we tell alsa
* what our channel layout is like? */
if (max_chans >= 3 && min_chans <= 3) {
GstAudioChannelPosition pos_21[3] = {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_LFE
};
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
gst_audio_set_channel_positions (s, pos_21);
gst_structure_set (s, "channels", G_TYPE_INT, 3, "channel-mask",
GST_TYPE_BITMASK, CHANNEL_MASK_2_1, NULL);
gst_caps_append_structure (caps, s);
}
/* everything else (4, 6, 8 channels) needs a channel layout */
for (c = MAX (4, min_chans); c <= 8; c += 2) {
if (max_chans >= c) {
guint64 channel_mask;
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
gst_audio_set_channel_positions (s, pos);
switch (c) {
case 4:
channel_mask = CHANNEL_MASK_4_0;
break;
case 6:
channel_mask = CHANNEL_MASK_5_1;
break;
case 8:
channel_mask = CHANNEL_MASK_7_1;
break;
default:
g_assert_not_reached ();
break;
}
gst_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
GST_TYPE_BITMASK, channel_mask, NULL);
gst_caps_append_structure (caps, s);
}
}
/* NONE layouts for everything else */
for (c = MAX (9, min_chans); c <= max_chans; ++c) {
GstAudioChannelPosition *ch_layout;
guint i;
ch_layout = g_new (GstAudioChannelPosition, c);
for (i = 0; i < c; ++i) {
ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
}
s = get_channel_free_structure (in_structure);
gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
gst_audio_set_channel_positions (s, ch_layout);
gst_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
gst_caps_append_structure (caps, s);
g_free (ch_layout);
}
}
@ -599,3 +604,55 @@ gst_alsa_find_device_name (GstObject * obj, const gchar * device,
return ret;
}
/* ALSA channel positions */
const GstAudioChannelPosition alsa_position[][8] = {
{
GST_AUDIO_CHANNEL_POSITION_MONO},
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_LFE1},
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
{
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID},
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE1},
{
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID,
GST_AUDIO_CHANNEL_POSITION_INVALID},
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE1,
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
};

View file

@ -31,6 +31,7 @@
#include <alsa/control.h>
#include <alsa/error.h>
#include <gst/gst.h>
#include <gst/audio/audio.h>
#define GST_CHECK_ALSA_VERSION(major,minor,micro) \
(SND_LIB_MAJOR > (major) || \
@ -56,5 +57,9 @@ gchar * gst_alsa_find_card_name (GstObject * obj,
const gchar * devcard,
snd_pcm_stream_t stream);
void gst_alsa_add_channel_reorder_map (GstObject * obj,
GstCaps * caps);
extern const GstAudioChannelPosition alsa_position[][8];
#endif /* __GST_ALSA_H__ */

View file

@ -713,6 +713,10 @@ alsasink_parse_spec (GstAlsaSink * alsa, GstAudioRingBufferSpec * spec)
alsa->period_time = spec->latency_time;
alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK
(alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
return TRUE;
/* ERRORS */

View file

@ -642,6 +642,10 @@ alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
alsa->period_time = spec->latency_time;
alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
(alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
return TRUE;
/* ERRORS */