[MPlayer-dev-eng] [PATCH] Multi-channel reorder (aac, pcm and ac3)

Giacomo Comes comes at naic.edu
Mon Nov 19 04:15:08 CET 2007


On Mon, Nov 19, 2007 at 03:10:16AM +0800, Ulion wrote:
> 2007/11/17, Giacomo Comes <comes at naic.edu>:
> > Here is (hopefully) the final try to include the channels reordering
> > code in MPlayer.
> > There has been several (different) attempt to fix the problem and none
> > of them fully satisfies the developers (planar formats will do, but
> > none appears to be intrested in implementing that).
> >
> > People intrested can check the following threads for a refresh:
> >
> > [PATCH] channel reordering for 6ch audio
> > http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-July/044844.html
> >
> > [RFC] 6-channel AAC and channel reordering
> > http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-October/046963.html
> >
> > [PATCH] audio channel remapping
> > http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-November/047269.html
> >
> > [PATCH] [TEST FUNC] Multi-channel reorder function
> > http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2007-November/054820.html
> >
> > The patches I'm submitting are an extension of the ones submitted by
> > Alexander Ponyatikh and it seems they are the one with higher probability to
> > be accepted.
> >
> > Please let's discuss then now and find a final agreement.
> >
> 
>  	int n;
> +	if (encoder->params.channels == 6 || encoder->params.channels == 5 &&
> +	  !strcmp(lavc_acodec->name,"ac3") || !strcmp(lavc_acodec->name,"libfaac") ) {
> 
> should be if ( ( == || == ) && (!strcmp || !strcmp))

Of course. Thanks for noticing it.
Update attached.

Giacomo
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ad_faad.c mplayer/libmpcodecs/ad_faad.c
--- mplayer.ori/libmpcodecs/ad_faad.c	2007-08-31 12:32:31.000000000 -0400
+++ mplayer/libmpcodecs/ad_faad.c	2007-11-15 23:31:04.000000000 -0400
@@ -277,7 +277,20 @@
       /* XXX: samples already multiplied by channels! */
       mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: Successfully decoded frame (%ld Bytes)!\n",
       sh->samplesize*faac_finfo.samples);
+      
+      if (sh->channels == 6 || sh->channels == 5) {
+        //Source channel order: C L R  SL SR LFE
+        //We want:              L R SL SR C  LFE
+        int i;
+        for (i = 0; i < faac_finfo.samples; i += sh->channels) {
+          memcpy(buf+len+i*sh->samplesize,faac_sample_buffer+(i+1)*sh->samplesize, sh->samplesize*4);     // L R SL SR
+          memcpy(buf+len+(i+4)*sh->samplesize,faac_sample_buffer+i*sh->samplesize, sh->samplesize);       // C
+          if (sh->channels == 6)
+            memcpy(buf+len+(i+5)*sh->samplesize,faac_sample_buffer+(i+5)*sh->samplesize, sh->samplesize); // LFE
+        }
+      } else {      
       memcpy(buf+len,faac_sample_buffer, sh->samplesize*faac_finfo.samples);
+      }
       last_dec_len = sh->samplesize*faac_finfo.samples;
       len += last_dec_len;
       sh->pts_bytes += last_dec_len;
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ad_pcm.c mplayer/libmpcodecs/ad_pcm.c
--- mplayer.ori/libmpcodecs/ad_pcm.c	2006-11-16 16:07:23.000000000 -0400
+++ mplayer/libmpcodecs/ad_pcm.c	2007-11-15 23:35:48.000000000 -0400
@@ -17,6 +17,8 @@
 
 LIBAD_EXTERN(pcm)
 
+static void *tmp_buff = NULL;
+
 static int init(sh_audio_t *sh_audio)
 {
   WAVEFORMATEX *h=sh_audio->wf;
@@ -90,6 +92,8 @@
   }
   if (!sh_audio->samplesize) // this would cause MPlayer to hang later
     sh_audio->samplesize = 2;
+  if (sh_audio->channels == 6 || sh_audio->channels == 5)
+    tmp_buff = malloc(2 * sh_audio->samplesize);
   return 1;
 }
 
@@ -101,6 +105,10 @@
 
 static void uninit(sh_audio_t *sh)
 {
+  if (tmp_buff) {
+    free(tmp_buff);
+    tmp_buff = NULL;
+  }
 }
 
 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
@@ -126,5 +134,15 @@
       // based on channels in preinit()
       return -1;
   len=demux_read_data(sh_audio->ds,buf,len);
+  if (sh_audio->channels == 6 || sh_audio->channels == 5) {
+    //Source channel order: L R C  LFE SL SR   or  L R C  SL SR
+    //We want:              L R SL SR  C  LFE  or  L R SL SR C
+    int i, samples = len / sh_audio->samplesize;
+    for (i = 0; i < samples; i += sh_audio->channels) {
+      memcpy(tmp_buff, buf+(i+2)*sh_audio->samplesize, ((sh_audio->channels+1)%2+1)*sh_audio->samplesize); // C (LFE) -> tmp
+      memcpy(buf+(i+2)*sh_audio->samplesize, buf+(i+(sh_audio->channels+1)%2+3)*sh_audio->samplesize, 2*sh_audio->samplesize); // SL SR -> 2,3
+      memcpy(buf+(i+4)*sh_audio->samplesize, tmp_buff, ((sh_audio->channels+1)%2+1)*sh_audio->samplesize); // C (LFE) -> 4(,5)
+    }
+  }
   return len;
 }
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ae_faac.c mplayer/libmpcodecs/ae_faac.c
--- mplayer.ori/libmpcodecs/ae_faac.c	2007-04-09 13:05:37.000000000 -0400
+++ mplayer/libmpcodecs/ae_faac.c	2007-11-15 23:37:36.000000000 -0400
@@ -98,6 +98,25 @@
 
 static int encode_faac(audio_encoder_t *encoder, uint8_t *dest, void *src, int len, int max_size)
 {
+	if (encoder->params.channels == 6 || encoder->params.channels == 5) {
+		//Codec wants: C L R  SL SR LFE
+		//We have:     L R SL SR C  LFE
+		int i;
+		uint32_t tmp32;
+		uint16_t tmp16;
+		for (i = 0; i < len; i += encoder->params.channels*divisor) {
+			if (divisor == 4) {
+				tmp32 = ((uint32_t*)(src+i))[4];
+				memmove(src+i+divisor, src+i, 4*divisor);
+				((uint32_t*)(src+i))[0] = tmp32;
+			} else {
+				tmp16 = ((uint16_t*)(src+i))[4];
+				memmove(src+i+divisor, src+i, 4*divisor);
+				((uint16_t*)(src+i))[0] = tmp16;
+			}
+		}
+	}
+
 	// len is divided by the number of bytes per sample
 	enc_frame_size = faacEncEncode(faac,  (int32_t*) src,  len / divisor, dest, max_size);
 	
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ae_lavc.c mplayer/libmpcodecs/ae_lavc.c
--- mplayer.ori/libmpcodecs/ae_lavc.c	2007-09-10 23:04:12.000000000 -0400
+++ mplayer/libmpcodecs/ae_lavc.c	2007-11-15 23:39:35.000000000 -0400
@@ -111,6 +111,23 @@
 static int encode_lavc(audio_encoder_t *encoder, uint8_t *dest, void *src, int size, int max_size)
 {
 	int n;
+	if ( (encoder->params.channels == 6 || encoder->params.channels == 5) && 
+	  (!strcmp(lavc_acodec->name,"ac3") || !strcmp(lavc_acodec->name,"libfaac")) ) {
+		//Codec wants: L C R  SL SR LFE (ac3)
+		//Codec wants: C L R  SL SR LFE (aac)
+		//We have:     L R SL SR C  LFE
+		int i,d0,d1,d2,w;
+		uint16_t tmp;
+		if (!strcmp(lavc_acodec->name,"ac3"))
+			d1=4,d2=2,w=3*2,d0=d2/2;
+		else
+			d1=2,d2=0,w=4*2,d0=d2/2;
+		for (i = 0; i < size; i += encoder->params.channels*2) {
+			tmp = ((uint16_t*)(src+i))[4];
+			memmove(src+i+d1, src+i+d2, w);
+			((uint16_t*)(src+i))[d0] = tmp;
+		}
+	}
 	n = avcodec_encode_audio(lavc_actx, dest, size, src);
         compressed_frame_size = n;
 	return n;
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ae_pcm.c mplayer/libmpcodecs/ae_pcm.c
--- mplayer.ori/libmpcodecs/ae_pcm.c	2007-04-09 13:05:39.000000000 -0400
+++ mplayer/libmpcodecs/ae_pcm.c	2007-11-15 23:40:56.000000000 -0400
@@ -38,7 +38,27 @@
 static int encode_pcm(audio_encoder_t *encoder, uint8_t *dest, void *src, int nsamples, int max_size)
 {
 	max_size = FFMIN(nsamples, max_size);
+	if (encoder->params.channels == 6 || encoder->params.channels == 5) {
+		//Codec wants: L R C  LFE SL SR        L R C  SL SR
+		//We have:     L R SL SR  C  LFE       L R SL SR  C
+		max_size -= max_size % (2*encoder->params.channels);
+		int i;
+		for (i = 0; i < max_size; i += 2*encoder->params.channels) {
+			if (encoder->params.channels == 6) {
+				((uint32_t*)(dest+i))[0] = ((uint32_t*)(src+i))[0]; //L R   -> 0,1
+				((uint32_t*)(dest+i))[1] = ((uint32_t*)(src+i))[2]; //C LFE -> 2,3
+				((uint32_t*)(dest+i))[2] = ((uint32_t*)(src+i))[1]; //SL SR -> 4,5
+			} else {
+				((uint16_t*)(dest+i))[0] = ((uint16_t*)(src+i))[0]; //L     -> 0
+				((uint16_t*)(dest+i))[1] = ((uint16_t*)(src+i))[1]; //R     -> 1
+				((uint16_t*)(dest+i))[2] = ((uint16_t*)(src+i))[4]; //C     -> 2
+				((uint16_t*)(dest+i))[3] = ((uint16_t*)(src+i))[2]; //SL    -> 3
+				((uint16_t*)(dest+i))[4] = ((uint16_t*)(src+i))[3]; //SR    -> 4
+			}
+		}
+	} else {
 	memcpy(dest, src, max_size);
+	}
 	return max_size;
 }
 
-------------- next part --------------
diff -Nraub mplayer.ori/libao2/ao_pcm.c mplayer/libao2/ao_pcm.c
--- mplayer.ori/libao2/ao_pcm.c	2006-12-11 14:35:25.000000000 -0400
+++ mplayer/libao2/ao_pcm.c	2007-11-15 23:41:59.000000000 -0400
@@ -197,8 +197,20 @@
 	}
 #endif 
 
+	if (ao_data.channels == 6 || ao_data.channels == 5) {
+		int i, samplesize = wavhdr.bits/8;
+		for (i = 0; i < len; i += samplesize*ao_data.channels) {
+			//L R SL SR C LFE -> L R C LFE SL SR
+			//L R SL SR C     -> L R C     SL SR
+			fwrite(data+i, samplesize, 2, fp);
+			fwrite(data+i+4*samplesize, samplesize, (ao_data.channels+1)%2+1, fp);
+			fwrite(data+i+2*samplesize, samplesize, 2, fp);
+		}
+		len -= len % (ao_data.channels*samplesize);
+	} else {
 	//printf("PCM: Writing chunk!\n");
 	fwrite(data,len,1,fp);
+	}
 
 	if(ao_pcm_waveheader)
 		wavhdr.data_length += len;


More information about the MPlayer-dev-eng mailing list