[MPlayer-dev-eng] [PATCH] Additional AC3 passthrough support for alsa9
Andy Lo-A-Foe
andy at alsaplayer.org
Sun May 26 11:04:38 CEST 2002
Hi,
Attached is a patch that adds additional AC3 passthrough support to the
alsa9 audio driver. It sets the correct SPDIF control bits. I've tested
it on my DTT2500 with a Trident 4DWave NX card using ALSA CVS.
This patch also fixes a crashing bug in the alsa9 driver.
Please apply.. (patch is against the v0.90pre4 tree)
Thanks,
Andy @ alsaplayer.org
-------------- next part --------------
--- libao2/ao_alsa9.c Sat Apr 27 10:38:33 2002
+++ /usr/src/MPLAYER/MPlayer-0.90pre4/libao2/ao_alsa9.c Sun May 26 10:57:32 2002
@@ -2,9 +2,10 @@
ao_alsa9 - ALSA-0.9.x output plugin for MPlayer
(C) Alex Beregszaszi <alex at naxine.org>
-
+
modified for better alsa-0.9.0beta8a-support by Joy Winter <joy at pingfm.org>
-
+ additional AC3 passthrough support by Andy Lo A Foe <andy at alsaplayer.org>
+
This driver is still at alpha stage.
If you want stable sound-support use the OSS emulation instead.
@@ -53,6 +54,124 @@
static int chunk_size = -1;
static int start_delay = 1;
+snd_pcm_t *
+spdif_init(int acard, int adevice)
+{
+ //char *pcm_name = "hw:0,2"; /* first card second device */
+ char pcm_name[255];
+ static snd_aes_iec958_t spdif;
+ snd_pcm_info_t *info;
+ snd_pcm_t *handler;
+ snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
+ unsigned int channels = 2;
+ unsigned int rate = 48000;
+ int err, c;
+
+ if (err = snprintf(&pcm_name[0], 11, "hw:%1d,%1d", acard, adevice) <= 0)
+ {
+ return NULL;
+ }
+
+ if ((err = snd_pcm_open(&handler, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
+ {
+ fprintf(stderr, "open: %s\n", snd_strerror(err));
+ return NULL;
+ }
+
+ snd_pcm_info_alloca(&info);
+
+ if ((err = snd_pcm_info(handler, info)) < 0) {
+ fprintf(stderr, "info: %s\n", snd_strerror(err));
+ snd_pcm_close(handler);
+ return NULL;
+ }
+ printf("device: %d, subdevice: %d\n", snd_pcm_info_get_device(info),
+ snd_pcm_info_get_subdevice(info));
+ {
+ snd_ctl_elem_value_t *ctl;
+ snd_ctl_t *ctl_handler;
+ char ctl_name[12];
+ int ctl_card;
+
+ spdif.status[0] = IEC958_AES0_NONAUDIO |
+ IEC958_AES0_CON_EMPHASIS_NONE;
+ spdif.status[1] = IEC958_AES1_CON_ORIGINAL |
+ IEC958_AES1_CON_PCM_CODER;
+ spdif.status[2] = 0;
+ spdif.status[3] = IEC958_AES3_CON_FS_48000;
+
+ snd_ctl_elem_value_alloca(&ctl);
+ snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM);
+ snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info));
+ snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info));
+ snd_ctl_elem_value_set_name(ctl, SND_CTL_NAME_IEC958("", PLAYBACK,PCM_STREAM));
+ snd_ctl_elem_value_set_iec958(ctl, &spdif);
+ ctl_card = snd_pcm_info_get_card(info);
+ if (ctl_card < 0) {
+ fprintf(stderr, "Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card");
+ goto __diga_end;
+ }
+ sprintf(ctl_name, "hw:%d", ctl_card);
+ printf("hw:%d\n", ctl_card);
+ if ((err = snd_ctl_open(&ctl_handler, ctl_name, 0)) < 0) {
+ fprintf(stderr, "Unable to open the control interface '%s': %s", ctl_name, snd_strerror(err));
+ goto __diga_end;
+ }
+ if ((err = snd_ctl_elem_write(ctl_handler, ctl)) < 0) {
+ fprintf(stderr, "Unable to update the IEC958 control: %s", snd_strerror(err));
+ goto __diga_end;
+ }
+ snd_ctl_close(ctl_handler);
+ __diga_end:
+
+ }
+
+ {
+ snd_pcm_hw_params_t *params;
+ snd_pcm_sw_params_t *swparams;
+
+ snd_pcm_hw_params_alloca(¶ms);
+ snd_pcm_sw_params_alloca(&swparams);
+
+ err = snd_pcm_hw_params_any(handler, params);
+ if (err < 0) {
+ fprintf(stderr, "Broken configuration for this PCM: no configurations available");
+ return NULL;
+ }
+ err = snd_pcm_hw_params_set_access(handler, params,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) {
+ fprintf(stderr, "Access tyep not available");
+ return NULL;
+ }
+ err = snd_pcm_hw_params_set_format(handler, params, format);
+
+ if (err < 0) {
+ fprintf(stderr, "Sample format non available");
+ return NULL;
+ }
+
+ err = snd_pcm_hw_params_set_channels(handler, params, channels);
+
+ if (err < 0) {
+ fprintf(stderr, "Channels count non avaible");
+ return NULL;
+ }
+
+ err = snd_pcm_hw_params_set_rate_near(handler, params, rate, 0); assert(err >= 0);
+
+ err = snd_pcm_hw_params(handler, params);
+
+ if (err < 0) {
+ fprintf(stderr, "Cannot set buffer size\n");
+ return NULL;
+ }
+ snd_pcm_sw_params_current(handler, swparams);
+ }
+ return handler;
+}
+
+
/* to set/get/query special features/parameters */
static int control(int cmd, int arg)
{
@@ -190,15 +309,21 @@
printf("alsa-init: %d soundcard%s found, using: %s\n", cards+1,
(cards >= 0) ? "" : "s", alsa_device);
- if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK,
- 0)) < 0)
- {
- printf("alsa-init: playback open error: %s\n", snd_strerror(err));
- return(0);
- }
+ if (format == AFMT_AC3) {
+ // Try to initialize the SPDIF interface
+ alsa_handler = spdif_init(0, 2);
+ }
+
+ if (!alsa_handler) {
+ if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK,
+ 0)) < 0)
+ {
+ printf("alsa-init: playback open error: %s\n", snd_strerror(err));
+ return(0);
+ }
+ }
snd_pcm_hw_params_malloc(&alsa_hwparams);
- //snd_pcm_sw_params_malloc(&alsa_swparams);
snd_pcm_sw_params_alloca(&alsa_swparams);
if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0)
{
@@ -388,7 +513,6 @@
free(alsa_device);
snd_pcm_hw_params_free(alsa_hwparams);
- snd_pcm_sw_params_free(alsa_swparams);
if ((err = snd_pcm_drain(alsa_handler)) < 0)
{
@@ -487,10 +611,11 @@
plays 'len' bytes of 'data'
returns: number of bytes played
*/
+
static int play(void* data, int len, int flags)
{
int got_len;
-
+
got_len = snd_pcm_writei(alsa_handler, data, len / 4);
//if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) {
More information about the MPlayer-dev-eng
mailing list