[MPlayer-dev-eng] [RFC] 6-channel AAC and channel reordering
Giacomo Comes
comes at naic.edu
Tue Oct 31 15:44:04 CET 2006
On Mon, Oct 30, 2006 at 10:18:09PM -0800, Corey Hickey wrote:
> Dominik 'Rathann' Mierzejewski wrote:
> >>> I've tested it on my 4.0 setup and I didn't hear the front center and lfe
> >>> channels until I downmixed it to 4ch:
> >>> mplayer -af
> >>> pan=4:1:0:0:0:0:1:0:0:0:0:1:0:0:0:0:1:0.25:0.25:0:0:0.25:0.25:0:0 \
> >>> return,_the_h720p.mov
> >> That makes sense, since mplayer is outputting 6 channels, and on your
> >> system the last two aren't hooked up to anything. One thing, though: do
> >> you have channels=6 in your config file, or did you specify -channels 6
> >> on your command line? If not, then I'm confused, since as far as I know
> >> mplayer tells libfaad to downmix to 2 channels be default.
> >
> > I have channels=4.
>
> Ok, that'll do it too.
>
> >> For some reason I have a nagging feeling that somebody else proposed a
> >> different approach and that it might have been committed, but I can't
> >> dig up the patch. Maybe I'm imagining things.
> >
> > I can't recall any such thing.
>
> Giacomo pointed out enough for me to go by. See the following, and lots
> of replies in that thread.
>
> To: mplayer-dev-eng at mplayerhq.hu
> From: Alexander 'Lazy Ranma' Ponyatikh
> Subject: [MPlayer-dev-eng] [PATCH] channel reordering for 6ch audio
> Date: Sat, 29 Jul 2006 20:39:44 +0400
I have been working on extending the patches submitted some time ago
by Alexander in order to support in the correct order 4/5/6 channels sound stream.
6 channels is easy because you can only have 3f+2r+lfe.
With 5 channels there are more combinations: 3f+2r, 2f+2r+lfe, 3f+1r+lfe
and with 4 channels: 2f+2r, 3f+1r, 3f+lfe, 2f+1r+lfe
Currently there is no way in mplayer/mencoder (and in libavcodec) to specify the number of
front/rear/lfe channels, you can only specify the sum of them with the option -channels.
For this reason the patches currently assume the following configurations:
6ch 3f+2r+lfe
5ch 3f+2r
4ch 2f+2r
because this is what you get with libavcodec ac3 encoder.
The changes to ad_faad.c, ad_pcm.c, ae_lavc.c, ae_pcm.c and ao_pcm.c
are just extension of the previous patches. Assuming that the original patches
were correct, they should also be. The changes to ae_faac.c instead are completly
new, check them carefully.
I was planning to submit the patch before rc1 was released, but I didn't have the time.
Also as Corey has noticed, channel reordering introduces some overhead.
May be we can add an option like -nochanreorder the tell mplayer/mencoder to not
do channels reordering (keeping maximum speed in case it is required).
Corey, can you integrate the ideas of this patch in yours?
Giacomo
-------------- next part --------------
diff -Nraub mplayer.ori/libmpcodecs/ad_faad.c mplayer/libmpcodecs/ad_faad.c
--- mplayer.ori/libmpcodecs/ad_faad.c 2006-10-08 15:58:28.000000000 -0400
+++ mplayer/libmpcodecs/ad_faad.c 2006-10-10 12:10:09.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+0)*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+0)*sh->samplesize, sh->samplesize*1); // C
+ if (sh->channels == 6)
+ memcpy(buf+len+(i+5)*sh->samplesize,faac_sample_buffer+(i+5)*sh->samplesize, sh->samplesize*1); // 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-09-12 11:58:43.000000000 -0400
+++ mplayer/libmpcodecs/ad_pcm.c 2006-10-10 13:15:11.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 2006-10-08 15:57:44.000000000 -0400
+++ mplayer/libmpcodecs/ae_faac.c 2006-10-12 23:43:25.000000000 -0400
@@ -97,6 +97,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;
+ uint16_t tmp16;
+ uint32_t tmp32;
+ for (i = 0; i < len; i += encoder->params.channels*divisor) {
+ if (divisor == 4)
+ tmp32 = ((uint32_t*)(src+i))[4];
+ else
+ tmp16 = ((uint16_t*)(src+i))[4];
+ memmove(src+i+divisor, src+i, 4*divisor);
+ if (divisor == 4)
+ ((uint32_t*)(src+i))[0] = tmp32;
+ else
+ ((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 2006-09-12 11:58:52.000000000 -0400
+++ mplayer/libmpcodecs/ae_lavc.c 2006-10-13 22:54:47.000000000 -0400
@@ -102,6 +102,17 @@
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) {
+ //Codec wants: L C R SL SR LFE
+ //We have: L R SL SR C LFE
+ int i;
+ uint16_t tmp;
+ for (i = 0; i < size; i += encoder->params.channels*2) {
+ tmp = ((uint16_t*)(src+i))[4];
+ memmove(src+i+4, src+i+2, 3*2);
+ ((uint16_t*)(src+i))[1] = 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 2006-06-05 15:43:08.000000000 -0400
+++ mplayer/libmpcodecs/ae_pcm.c 2006-10-10 23:06:51.000000000 -0400
@@ -37,7 +37,27 @@
static int encode_pcm(audio_encoder_t *encoder, uint8_t *dest, void *src, int nsamples, int max_size)
{
max_size = min(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-06-05 15:46:03.000000000 -0400
+++ mplayer/libao2/ao_pcm.c 2006-10-10 09:48:30.000000000 -0400
@@ -205,8 +205,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