alsa: Add channel map API support

The initial support for the new ALSA chmap API.
Just translate the current chmap to GstAudioChannelPosition during the
setup.  No function to specify the channel map manually yet, so still
impossible to assign any non-standard positions or to configure in a
different order even if the hardware allows.

https://bugzilla.gnome.org/show_bug.cgi?id=709755
This commit is contained in:
Takashi Iwai 2013-10-08 17:07:02 +02:00 committed by Sebastian Dröge
parent 6d659e3c6f
commit 76d807893c
4 changed files with 80 additions and 0 deletions

View file

@ -707,3 +707,55 @@ const GstAudioChannelPosition alsa_position[][8] = {
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT} GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
}; };
#ifdef SND_CHMAP_API_VERSION
/* +1 is to make zero as holes */
#define ITEM(x, y) \
[SND_CHMAP_ ## x] = GST_AUDIO_CHANNEL_POSITION_ ## y + 1
static GstAudioChannelPosition gst_pos[SND_CHMAP_LAST + 1] = {
ITEM(MONO, MONO),
ITEM(FL, FRONT_LEFT),
ITEM(FR, FRONT_RIGHT),
ITEM(FC, FRONT_CENTER),
ITEM(RL, REAR_LEFT),
ITEM(RR, REAR_RIGHT),
ITEM(RC, REAR_CENTER),
ITEM(LFE, LFE1),
ITEM(SL, SIDE_LEFT),
ITEM(SR, SIDE_RIGHT),
ITEM(FLC, FRONT_LEFT_OF_CENTER),
ITEM(FRC, FRONT_RIGHT_OF_CENTER),
ITEM(FLW, WIDE_LEFT),
ITEM(FRW, WIDE_RIGHT),
ITEM(TC, TOP_CENTER),
ITEM(TFL, TOP_FRONT_LEFT),
ITEM(TFR, TOP_FRONT_RIGHT),
ITEM(TFC, TOP_FRONT_CENTER),
ITEM(TRL, TOP_REAR_LEFT),
ITEM(TRR, TOP_REAR_RIGHT),
ITEM(TRC, TOP_REAR_CENTER),
ITEM(LLFE, LFE1),
ITEM(RLFE, LFE2),
ITEM(BC, BOTTOM_FRONT_CENTER),
ITEM(BLC, BOTTOM_FRONT_LEFT),
ITEM(BRC, BOTTOM_FRONT_LEFT),
};
#undef ITEM
gboolean alsa_chmap_to_channel_positions (const snd_pcm_chmap_t *chmap,
GstAudioChannelPosition *pos)
{
int c;
for (c = 0; c < chmap->channels; c++) {
if (chmap->pos[c] > SND_CHMAP_LAST)
return FALSE;
pos[c] = gst_pos[chmap->pos[c]];
if (!pos[c])
return FALSE;
pos[c]--;
}
return TRUE;
}
#endif /* SND_CHMAP_API_VERSION */

View file

@ -71,5 +71,9 @@ void gst_alsa_add_channel_reorder_map (GstObject * obj,
GstCaps * caps); GstCaps * caps);
extern const GstAudioChannelPosition alsa_position[][8]; extern const GstAudioChannelPosition alsa_position[][8];
#ifdef SND_CHMAP_API_VERSION
gboolean alsa_chmap_to_channel_positions (const snd_pcm_chmap_t *chmap,
GstAudioChannelPosition *pos);
#endif
#endif /* __GST_ALSA_H__ */ #endif /* __GST_ALSA_H__ */

View file

@ -896,6 +896,18 @@ gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
snd_output_close (out_buf); snd_output_close (out_buf);
} }
#ifdef SND_CHMAP_API_VERSION
if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) {
snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle);
if (chmap && chmap->channels == alsa->channels) {
GstAudioChannelPosition pos[8];
if (alsa_chmap_to_channel_positions (chmap, pos))
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK (alsa)->ringbuffer, pos);
}
free (chmap);
}
#endif /* SND_CHMAP_API_VERSION */
return TRUE; return TRUE;
/* ERRORS */ /* ERRORS */

View file

@ -783,6 +783,18 @@ gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
snd_output_close (out_buf); snd_output_close (out_buf);
} }
#ifdef SND_CHMAP_API_VERSION
if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) {
snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle);
if (chmap && chmap->channels == alsa->channels) {
GstAudioChannelPosition pos[8];
if (alsa_chmap_to_channel_positions (chmap, pos))
gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC (alsa)->ringbuffer, pos);
}
free (chmap);
}
#endif /* SND_CHMAP_API_VERSION */
return TRUE; return TRUE;
/* ERRORS */ /* ERRORS */