[MPlayer-users] Re: Problems w/ AC3 pass-through on SB Live!

joy ping joy at pingfm.org
Wed Aug 21 20:21:01 CEST 2002


ok, i did a fast hack and did completly rewrote the iec958
initialization for alsa. its a striped down version from ac3dec
without support for professional mode.
the patch should aply against current mplayer_0.9pre6. it will *not*
aply against current cvs, but it will aply against the cvs-version
three days ago. so if you have a really brand new mplayer-cvs-version
downgrade ao_alsa9.c to a version at least three days ago. sorry for
the inconveniennce but its another branch in my local cvs.
note: you don't need to pass any subopts to this version anymore
'iec958' is the only selectable device and should work with all iec958
capable devices. also spdif-playback and other switches will be set on
the fly.
please check the patch, and report success/failure.

the patch should be aplyed directly against ao_alsa9.c in libao2 like:
cp ao_alsa9_spdif_rewrite.patch mplayer/libao2
patch ao_alsa9.c ao_alsa9_spdif_rewrite.patch


On Wed, Aug 21, 2002 at 06:03:35PM +0300, Simo Salam wrote:
> [Automatic answer: RTFM (read DOCS, FAQ), also read DOCS/bugreports.html]
> Actually I too have a problem similar to this one. My soundcard is a SB
> Live! 5.1 and I'm using alsa09 rc1. This is what my lspci output looks
> like:
> 
> 00:07.5 Multimedia audio controller: VIA Technologies, Inc. AC97 Audio
> Controller (rev 50)
> 00:0c.0 Multimedia audio controller: Creative Labs SB Live! EMU10000
> (rev 07)
> 00:0c.1 Input device controller: Creative Labs SB Live! (rev 07)
> 
> I'm also using kernel 2.4.18 and mplayer from cvs (currently maybe a
> week old). My external receiver is a Sony.
> 
> The problem is strange and it goes like this. If I try to get ac3
> passthrough either from dvd or a divx movie using a command similar to:
> 
> amixer sset "IEC958 Optical Raw" on
> mplayer -ao alsa9:hw:0,3 -ac hwac3
>  .
>  .
>  .
> alsa-init: testing and bugreports are welcome.
> alsa-init: requested format: 48000 Hz, 2 channels, AC3
> alsa-init: soundcard set to hw:0,3
> device: 3, subdevice: 0
> hw:0
> alsa-spdif-init: cant set spdif-trough automatically
> Start playing...
> 
> it either starts playing sound in all 5+1 speakers for a while, but does
> not 'light up' the blue light on the receiver which usually indicates
> that the sony has detected an ac3 stream. But after a while, and usually
> immediately after doing some seeking in the movie, the blue lights on
> the receiver light up, and the receiver informs what kind of stream it
> has detected, but at the same time mutes the sound on all the speakers.
> So it's either no sound and proper lights or vice versa for me. xine, on
> the other hand, works properly for me also regarding the ac3 passthrough
> but otherwise sucks badly compared to mplayer so i'm using mplayer (btw.
> thanks to all the developers of mplayer, its an awesome player).
> 
> I've connected my card to the receiver with a coaxial cable and I've
> compiled mplayer with gcc-3.1. Can't think of anything else that might
> have an influence on this. 
> 
> Anyhow, hope this information is of some use
> 
> --s
> 
> > 
> > i will take a look at it. but i will be in holidays (without notebook;)
> > for a few weeks, so don't expect fast solutions. maybe i get it to
> > place some docs somewhere about how far i get till now with my
> > rewriting ideas, so somebody could fix this.
> > i thought that it would be really easy but currently i have no idea
> > where the fscking bug could be that it doesn't work for you. basically the
> > mechanism is the same as in ac3dec or lovely xine without setting the
> > spdif-playback-switch automagically. most confusing is that the
> > current routine seems to work for others also with a *'SBlive'*, 
> > so if we start to make a new init it may work for you but the 
> > other half will start to cry 'my digital out don't work'. 
> > but we will see...
> > 
> > 
> > -- 
> > regards
> > 
> > ____-
> > joy
> > 
> > ________/\---------%%%___________-----------
> > webcast every sunday 2000 cest at pingfm.org
> > 
> > pgp key at: x-hkp://wwwkeys.de.pgp.net
> > 
> > _______________________________________________
> > RTFM!!!  http://www.MPlayerHQ.hu/DOCS
> > Search:  http://www.MPlayerHQ.hu/cgi-bin/htsearch
> > http://mplayerhq.hu/mailman/listinfo/mplayer-users
> 
> 
> 
> _______________________________________________
> RTFM!!!  http://www.MPlayerHQ.hu/DOCS
> Search:  http://www.MPlayerHQ.hu/cgi-bin/htsearch
> http://mplayerhq.hu/mailman/listinfo/mplayer-users

-- 
regards

____-
joy

________/\---------%%%___________-----------
webcast every sunday 2000 cest at pingfm.org

pgp key at: x-hkp://wwwkeys.de.pgp.net
-------------- next part --------------
--- /usr/local2/cvs_work/mplayer/mplayer_user/libao2/ao_alsa9.c	Fri Jul 19 19:17:24 2002
+++ /home/joy/devel/cvs_work/mplayer/libao2/ao_alsa9.c	Wed Aug 21 19:23:53 2002
@@ -47,7 +47,7 @@
 static snd_pcm_format_t alsa_format;
 static snd_pcm_hw_params_t *alsa_hwparams;
 static snd_pcm_sw_params_t *alsa_swparams;
-static char *alsa_device;
+const char *alsa_device;
 
 /* possible 4096, original 8192 
  * was only needed for calculating chunksize? */
@@ -73,134 +73,7 @@
 #undef BUFFERTIME
 #define SET_CHUNKSIZE
 #undef USE_POLL
-
-snd_pcm_t *spdif_init(char *pcm_name)
-{
-	//char *pcm_name = "hw:0,2"; /* first card second device */
-	static snd_aes_iec958_t spdif;
-	static snd_aes_iec958_t spdif_test;
-	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 = 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;
-	snd_ctl_elem_id_t *elem_id;
-	unsigned int elem_device;
-	const char *elem_name;
-        char ctl_name[12];
-        int ctl_card;
-	//elem_id = 36;
-
-	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_id_alloca(&elem_id); 
-	snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM); //SND_CTL_ELEM_IFACE_MIXER
-        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)); //SWITCH
-	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\n", 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\n", snd_strerror(err));
-	 printf("alsa-spdif-init: cant set spdif-trough automatically\n");
-        goto __diga_end;
-       }
-       	//test area
-       /* elem_device = snd_ctl_elem_id_get_device(elem_id); */
-       /* elem_name = snd_ctl_elem_value_get_name(ctl);  */
-       /* snd_ctl_elem_value_get_iec958(ctl, &spdif); */
-       /* printf("spdif = %i, device = %i\n", &spdif, elem_device); */
-       /* printf("name = %s\n", elem_name); */
-	//end test area
-
-
-      snd_ctl_close(ctl_handler);
-      __diga_end:                                                       
-
-       }
-
-	{
-	  snd_pcm_hw_params_t *params;
-	  snd_pcm_sw_params_t *swparams;
-	  
-	  snd_pcm_hw_params_alloca(&params);
-	  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;
-}
+#undef SEP_SPDIF_INIT
 
 
 /* to set/get/query special features/parameters */
@@ -211,6 +84,8 @@
     return CONTROL_TRUE;
   case AOCONTROL_GET_VOLUME:
   case AOCONTROL_SET_VOLUME:
+#ifndef WORDS_BIGENDIAN 
+{ //seems to be a problem on macs?
     {
       ao_control_vol_t *vol = (ao_control_vol_t *)arg;
 
@@ -303,7 +178,17 @@
       snd_mixer_close(handle);
       return CONTROL_OK;
     }
+}// end big-endian
+#endif
+#ifdef WORDS_BIGENDIAN
+{
+  {
+    return (CONTROL_UNKNOWN);
   }
+}
+#endif
+    
+  } //end witch
   return(CONTROL_UNKNOWN);
 }
 
@@ -344,49 +229,60 @@
     //ao_data.buffersize = MAX_OUTBURST; // was 16384
 
     switch (format)
-    {
-	case AFMT_S8:
-	    alsa_format = SND_PCM_FORMAT_S8;
-	    break;
-	case AFMT_U8:
-	    alsa_format = SND_PCM_FORMAT_U8;
-	    break;
-	case AFMT_U16_LE:
-	    alsa_format = SND_PCM_FORMAT_U16_LE;
-	    break;
-	case AFMT_U16_BE:
-	    alsa_format = SND_PCM_FORMAT_U16_BE;
-	    break;
+      {
+      case AFMT_S8:
+	alsa_format = SND_PCM_FORMAT_S8;
+	break;
+      case AFMT_U8:
+	alsa_format = SND_PCM_FORMAT_U8;
+	break;
+      case AFMT_U16_LE:
+	alsa_format = SND_PCM_FORMAT_U16_LE;
+	break;
+      case AFMT_U16_BE:
+	alsa_format = SND_PCM_FORMAT_U16_BE;
+	break;
 #ifndef WORDS_BIGENDIAN
-	case AFMT_AC3:
+      case AFMT_AC3:
 #endif
-	case AFMT_S16_LE:
-	    alsa_format = SND_PCM_FORMAT_S16_LE;
-	    break;
+      case AFMT_S16_LE:
+	alsa_format = SND_PCM_FORMAT_S16_LE;
+	break;
 #ifdef WORDS_BIGENDIAN
-	case AFMT_AC3:
+      case AFMT_AC3:
 #endif
-	case AFMT_S16_BE:
-	    alsa_format = SND_PCM_FORMAT_S16_BE;
-	    break;
-	default:
-	    alsa_format = SND_PCM_FORMAT_MPEG;
-	    break;
-    }
+      case AFMT_S16_BE:
+	alsa_format = SND_PCM_FORMAT_S16_BE;
+	break;
+      case AFMT_S32_LE:
+	alsa_format = SND_PCM_FORMAT_S32_LE;
+	break;
+      case AFMT_S32_BE:
+	alsa_format = SND_PCM_FORMAT_S32_BE;
+	break;
+
+      default:
+	alsa_format = SND_PCM_FORMAT_MPEG;
+	break;
+      }
     
     switch(alsa_format)
-    {
-	case SND_PCM_FORMAT_S16_LE:
-	case SND_PCM_FORMAT_U16_LE:
-	    ao_data.bps *= 2;
-	    break;
-	case -1:
-	    printf("alsa-init: invalid format (%s) requested - output disabled\n",
-		audio_out_format_name(format));
-	    return(0);
-	default:
-	    break;	    
-    }
+      {
+      case SND_PCM_FORMAT_S16_LE:
+      case SND_PCM_FORMAT_U16_LE:
+	ao_data.bps *= 2;
+	break;
+      case SND_PCM_FORMAT_S32_LE:
+      case SND_PCM_FORMAT_S32_BE:
+	ao_data.bps *= 4;
+	break;
+      case -1:
+	printf("alsa-init: invalid format (%s) requested - output disabled\n",
+	       audio_out_format_name(format));
+	return(0);
+      default:
+	break;	    
+      }
     
     if (ao_subdevice) {
       //start parsing ao_subdevice, ugly and not thread safe!
@@ -441,6 +337,51 @@
       }
     } //end parsing ao_subdevice
 
+    /* switch for spdif
+     * sets opening sequence for SPDIF
+     * sets also the playback and other switches 'on the fly'
+     * while opening the abstract alias for the spdif subdevice
+     * 'iec958'
+     */
+    if (format == AFMT_AC3) {
+      char devstr[128];
+      unsigned char s[4];
+      int err, c;
+
+      switch (channels) {
+      case 1:
+      case 2:
+
+	s[0] = IEC958_AES0_NONAUDIO | 
+	  IEC958_AES0_CON_EMPHASIS_NONE;
+	s[1] = IEC958_AES1_CON_ORIGINAL | 
+	  IEC958_AES1_CON_PCM_CODER;
+	s[2] = 0;
+	s[3] = IEC958_AES3_CON_FS_48000;
+
+	sprintf(devstr, "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", 
+		s[0], s[1], s[2], s[3]);
+	//snprintf(devstr, ALSA_DEVICE_SIZE, 
+	//"default:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", 
+	//s[0], s[1], s[2], s[3]);
+	printf("alsa-spdif-init: playing AC3, %i channels\n", channels);
+	break;
+      case 4:
+	strcpy(devstr, "surround40");
+	break;
+    
+      case 6:
+	strcpy(devstr, "surround51");
+	break;
+
+      default:
+	fprintf(stderr, "%d channels are not supported\n", channels);
+	exit (0);
+      }
+
+      alsa_device = devstr;
+    }
+
     if (alsa_device == NULL)
       {
 	int tmp_device, tmp_subdevice, err;
@@ -492,15 +433,6 @@
 		printf("alsa-init: soundcard set to %s\n", alsa_device);
       }
 
-    // switch for spdif
-    // Try to initialize the SPDIF interface
-    if (format == AFMT_AC3) {
-      if (device_set)
-	alsa_handler = spdif_init(alsa_device);
-      else
-	alsa_handler = spdif_init("hw:0,2");
-    }
-
     //setting modes for block or nonblock-mode
     if (ao_noblock) {
       open_mode = SND_PCM_NONBLOCK;
@@ -512,7 +444,7 @@
       set_block_mode = 0;
       str_block_mode = "block-mode";
     }
-    //cvs cosmetics fix
+
     //sets buff/chunksize if its set manually
     if (ao_data.buffersize) {
       switch (ao_data.buffersize)


More information about the MPlayer-users mailing list