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

Giacomo Comes comes at naic.edu
Fri Nov 16 17:11:41 CET 2007


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.

Ciao
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