[RFC] 6-channel AAC and channel reordering
The problem: 6-channel AAC has a different channel order than MPlayer outputs. MPlayer wants: 0 - front left 1 - front right 2 - rear left 3 - rear right 4 - front center 5 - lfe MPlayer gets: 0 - front center 1 - front left 2 - front right 3 - rear left 4 - rear right 5 - lfe -------------------------------------------------------------------------- For a test source you can probably use any recent hd trailer from Apple. Or: http://movies.apple.com/movies/universal/king_kong/king_kong-tlr_h480p.mov This works fine because AAC does the downmixing internally: $ mplayer king_kong-tlr_h480p.mov -channels 2 This sounds odd -- the channels are definitely mixed up: $ mplayer king_kong-tlr_h480p.mov -channels 6 If you don't have a 5.1 speaker setup (I don't either), then you can do a quick-n-dirty downmix: $ mplayer king_kong-tlr_h480p.mov -channels 6 \ -af pan=2:0.4:0:0:0.4:0.2:0:0:0.2:0.3:0.3:0.5:0.5 ...or an hrtf one: $ mplayer king_kong-tlr_h480p.mov -channels 6 -af hrtf Either way, you'll hear that the channel position isn't right. -------------------------------------------------------------------------- The attached patch uses af_channels to handle the reordering. ad_faad.c:init() sets up a routing map and af.c:af_init() uses that map to put a channels filter at the beginning of the audio chain. Try the above examples with a patched mplayer -- they should work correctly. As far as I know the patch doesn't break anything. Probably it does, but not that I know of. :) Anyway, I don't consider it finished. Some notes: * It would probably be ideal to have faad handle the reordering, but I don't see a way to do that. * If this kind of approach seems acceptable, I should switch to af_pan to handle upmixing and downmixing where channels have to be split or combined. * I don't have any code to deal with 3- or 4- channel AAC. With af_pan I could probably upmix or downmix these appropriately to match the output channel order. Does anyone have a sample? * This could be applied to audio formats other than AAC, of course. Does anyone have an example of another format that could benefit? -------------------------------------------------------------------------- So, what do you think? Am I barking up the wrong tree or should I keep working in this direction? -Corey Index: libaf/af.c =================================================================== RCS file: /cvsroot/mplayer/main/libaf/af.c,v retrieving revision 1.51 diff -u -r1.51 af.c --- libaf/af.c 20 Oct 2005 09:12:28 -0000 1.51 +++ libaf/af.c 22 Feb 2006 09:04:06 -0000 @@ -355,17 +355,40 @@ // Check if this is the first call if(!s->first){ - // Add all filters in the list (if there are any) - if(!s->cfg.list){ // To make automatic format conversion work - if(!af_append(s,s->first,"dummy")) - return -1; + /* remap channels if the codec/demuxer provides a channel map */ + if (s->chan_map) { + af_control_ext_t arg; + arg.ch = s->input.nch; + af_instance_t *af = NULL; + af=af_append(s, s->first, "channels"); + /* set up af_channels to route */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTER, &s->input.nch))) + return -1; + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_NR, &s->input.nch))) + return -1; + /* set up each route */ + for (arg.ch = 0; arg.ch < s->input.nch; ++arg.ch) { + arg.arg = s->chan_map + 2*arg.ch; /* two by two... */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTING, &arg))) + return -1; + } + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS, &s->input.nch))) + return -1; + if (AF_OK != af_reinit(s,af)) + return -1; } - else{ + // Add all filters in the list (if there are any) + if (s->cfg.list) { while(s->cfg.list[i]){ if(!af_append(s,s->last,s->cfg.list[i++])) return -1; } } + // To make automatic format conversion work + if (!s->first){ + if(!af_append(s,s->first,"dummy")) + return -1; + } } // Init filters @@ -711,3 +734,23 @@ { data->bps = af_fmt2bits(data->format)/8; } + +int *af_set_channel_map(int channels, char *routes){ + int *chan_map, *ptr; + ptr=chan_map=malloc(2 * channels * sizeof(int)); + if (!chan_map) { + mp_msg(MSGT_DEMUX, MSGL_ERR, "set_channel_map: cannot malloc for %d channels\n", channels); + return 0; + } + while (channels-- > 0) { + if (*routes == '\0' || *(routes+1) == '\0') { + mp_msg(MSGT_DEMUX, MSGL_ERR, "set_channel_map: not enough routes\n"); + free(chan_map); + return 0; + } + /* two by two... */ + *ptr++ = *routes++ - '0'; + *ptr++ = *routes++ - '0'; + } + return chan_map; +} Index: libaf/af.h =================================================================== RCS file: /cvsroot/mplayer/main/libaf/af.h,v retrieving revision 1.28 diff -u -r1.28 af.h --- libaf/af.h 1 Oct 2005 12:55:34 -0000 1.28 +++ libaf/af.h 22 Feb 2006 09:04:06 -0000 @@ -104,6 +104,7 @@ af_data_t output; // Configuration for this stream af_cfg_t cfg; + int *chan_map; }af_stream_t; /********************************************* @@ -329,6 +330,16 @@ */ void af_fix_parameters(af_data_t *data); +/** + * \brief set up channel remapping + * \param number of output channels + * \param string of from-to routes + * \return int array of routes + * + * Makes an int array from a string of provided routes. + */ +int *af_set_channel_map(int channels, char *routes); + /** Memory reallocation macro: if a local buffer is used (i.e. if the filter doesn't operate on the incoming buffer this macro must be called to ensure the buffer is big enough. Index: libmpcodecs/ad_faad.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/ad_faad.c,v retrieving revision 1.24 diff -u -r1.24 ad_faad.c --- libmpcodecs/ad_faad.c 12 Jan 2006 20:04:34 -0000 1.24 +++ libmpcodecs/ad_faad.c 22 Feb 2006 09:04:06 -0000 @@ -154,6 +154,23 @@ mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate, faac_channels); sh->channels = faac_channels; if (audio_output_channels <= 2) sh->channels = faac_channels > 1 ? 2 : 1; + + /* re-map channels */ + switch (sh->channels) { + default: + case 1: /* no action needed */ + case 2: /* no action needed */ + case 3: /* no suitable default behavior? */ + case 4: /* no suitable default behavior? */ + break; + case 5: /* mplayer treats this like 6-channel */ + case 6: + sh->chan_map = af_set_channel_map(6, "04" "10" "21" "32" "43" "55"); + break; + case 7: /* not supported by mplayer? */ + break; + } + sh->samplerate = faac_samplerate; sh->samplesize=2; //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate; Index: libmpcodecs/dec_audio.c =================================================================== RCS file: /cvsroot/mplayer/main/libmpcodecs/dec_audio.c,v retrieving revision 1.50 diff -u -r1.50 dec_audio.c --- libmpcodecs/dec_audio.c 16 Feb 2006 22:43:42 -0000 1.50 +++ libmpcodecs/dec_audio.c 22 Feb 2006 09:04:06 -0000 @@ -309,6 +309,7 @@ // filter config: memcpy(&afs->cfg,&af_cfg,sizeof(af_cfg_t)); + afs->chan_map = sh_audio->chan_map; mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_BuildingAudioFilterChain, afs->input.rate,afs->input.nch,af_fmt2str_short(afs->input.format), Index: libmpdemux/stheader.h =================================================================== RCS file: /cvsroot/mplayer/main/libmpdemux/stheader.h,v retrieving revision 1.42 diff -u -r1.42 stheader.h --- libmpdemux/stheader.h 18 Feb 2006 09:26:39 -0000 1.42 +++ libmpdemux/stheader.h 22 Feb 2006 09:04:07 -0000 @@ -18,6 +18,7 @@ int samplerate; int samplesize; int channels; + int *chan_map; int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) int i_bps; // == bitrate (compressed bytes/sec) // in buffers:
Reviving an old, forgotten patch... On Wednesday, 22 February 2006 at 11:01, Corey Hickey wrote:
The problem: 6-channel AAC has a different channel order than MPlayer outputs.
MPlayer wants: 0 - front left 1 - front right 2 - rear left 3 - rear right 4 - front center 5 - lfe
MPlayer gets: 0 - front center 1 - front left 2 - front right 3 - rear left 4 - rear right 5 - lfe
-------------------------------------------------------------------------- For a test source you can probably use any recent hd trailer from Apple. Or: http://movies.apple.com/movies/universal/king_kong/king_kong-tlr_h480p.mov
This works fine because AAC does the downmixing internally: $ mplayer king_kong-tlr_h480p.mov -channels 2
This sounds odd -- the channels are definitely mixed up: $ mplayer king_kong-tlr_h480p.mov -channels 6
If you don't have a 5.1 speaker setup (I don't either), then you can do a quick-n-dirty downmix: $ mplayer king_kong-tlr_h480p.mov -channels 6 \ -af pan=2:0.4:0:0:0.4:0.2:0:0:0.2:0.3:0.3:0.5:0.5
...or an hrtf one: $ mplayer king_kong-tlr_h480p.mov -channels 6 -af hrtf
Either way, you'll hear that the channel position isn't right.
-------------------------------------------------------------------------- The attached patch uses af_channels to handle the reordering. ad_faad.c:init() sets up a routing map and af.c:af_init() uses that map to put a channels filter at the beginning of the audio chain. Try the above examples with a patched mplayer -- they should work correctly.
As far as I know the patch doesn't break anything. Probably it does, but not that I know of. :) Anyway, I don't consider it finished. Some notes:
* It would probably be ideal to have faad handle the reordering, but I don't see a way to do that.
* If this kind of approach seems acceptable, I should switch to af_pan to handle upmixing and downmixing where channels have to be split or combined.
* I don't have any code to deal with 3- or 4- channel AAC. With af_pan I could probably upmix or downmix these appropriately to match the output channel order. Does anyone have a sample?
* This could be applied to audio formats other than AAC, of course. Does anyone have an example of another format that could benefit?
-------------------------------------------------------------------------- So, what do you think? Am I barking up the wrong tree or should I keep working in this direction?
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 With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies. OK to apply? Regards, R. -- MPlayer developer and RPMs maintainer: http://rpm.greysector.net/mplayer/ There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
On Wednesday, 22 February 2006 at 11:01, Corey Hickey wrote:
The problem: 6-channel AAC has a different channel order than MPlayer outputs.
MPlayer wants: 0 - front left 1 - front right 2 - rear left 3 - rear right 4 - front center 5 - lfe
MPlayer gets: 0 - front center 1 - front left 2 - front right 3 - rear left 4 - rear right 5 - lfe
-------------------------------------------------------------------------- For a test source you can probably use any recent hd trailer from Apple. Or: http://movies.apple.com/movies/universal/king_kong/king_kong-tlr_h480p.mov
This works fine because AAC does the downmixing internally: $ mplayer king_kong-tlr_h480p.mov -channels 2
This sounds odd -- the channels are definitely mixed up: $ mplayer king_kong-tlr_h480p.mov -channels 6
If you don't have a 5.1 speaker setup (I don't either), then you can do a quick-n-dirty downmix: $ mplayer king_kong-tlr_h480p.mov -channels 6 \ -af pan=2:0.4:0:0:0.4:0.2:0:0:0.2:0.3:0.3:0.5:0.5
...or an hrtf one: $ mplayer king_kong-tlr_h480p.mov -channels 6 -af hrtf
Either way, you'll hear that the channel position isn't right.
-------------------------------------------------------------------------- The attached patch uses af_channels to handle the reordering. ad_faad.c:init() sets up a routing map and af.c:af_init() uses that map to put a channels filter at the beginning of the audio chain. Try the above examples with a patched mplayer -- they should work correctly.
As far as I know the patch doesn't break anything. Probably it does, but not that I know of. :) Anyway, I don't consider it finished. Some notes:
* It would probably be ideal to have faad handle the reordering, but I don't see a way to do that.
* If this kind of approach seems acceptable, I should switch to af_pan to handle upmixing and downmixing where channels have to be split or combined.
* I don't have any code to deal with 3- or 4- channel AAC. With af_pan I could probably upmix or downmix these appropriately to match the output channel order. Does anyone have a sample?
* This could be applied to audio formats other than AAC, of course. Does anyone have an example of another format that could benefit?
-------------------------------------------------------------------------- So, what do you think? Am I barking up the wrong tree or should I keep working in this direction?
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
With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies.
OK to apply?
Regards, R.
------------------------------------------------------------------------
--- MPlayer-20538/libmpcodecs/ad_faad.c.chmap 2006-10-02 01:21:07.000000000 +0200 +++ MPlayer-20538/libmpcodecs/ad_faad.c 2006-10-30 21:57:34.000000000 +0100 @@ -152,6 +152,23 @@ mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate, faac_channels); sh->channels = faac_channels; if (audio_output_channels <= 2) sh->channels = faac_channels > 1 ? 2 : 1; + + /* re-map channels */ + switch (sh->channels) { + default: + case 1: /* no action needed */ + case 2: /* no action needed */ + case 3: /* no suitable default behavior? */ + case 4: /* no suitable default behavior? */ + break; + case 5: /* mplayer treats this like 6-channel */ + case 6: + sh->chan_map = af_set_channel_map(6, "04" "10" "21" "32" "43" "55"); + break; + case 7: /* not supported by mplayer? */ + break; + } + sh->samplerate = faac_samplerate; sh->samplesize=2; //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate; --- MPlayer-20538/libmpcodecs/dec_audio.c.chmap 2006-10-08 16:11:51.000000000 +0200 +++ MPlayer-20538/libmpcodecs/dec_audio.c 2006-10-30 21:57:34.000000000 +0100 @@ -311,6 +311,7 @@
// filter config: memcpy(&afs->cfg,&af_cfg,sizeof(af_cfg_t)); + afs->chan_map = sh_audio->chan_map;
mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_BuildingAudioFilterChain, afs->input.rate,afs->input.nch,af_fmt2str_short(afs->input.format), --- MPlayer-20538/libaf/af.h.chmap 2006-06-05 19:40:44.000000000 +0200 +++ MPlayer-20538/libaf/af.h 2006-10-30 21:57:34.000000000 +0100 @@ -104,6 +104,7 @@ af_data_t output; // Configuration for this stream af_cfg_t cfg; + int *chan_map; }af_stream_t;
/********************************************* @@ -329,6 +330,16 @@ */ void af_fix_parameters(af_data_t *data);
+/** + * \brief set up channel remapping + * \param number of output channels + * \param string of from-to routes + * \return int array of routes + * + * Makes an int array from a string of provided routes. + */ +int *af_set_channel_map(int channels, char *routes); + /** Memory reallocation macro: if a local buffer is used (i.e. if the filter doesn't operate on the incoming buffer this macro must be called to ensure the buffer is big enough. --- MPlayer-20538/libaf/af.c.chmap 2006-09-19 00:59:44.000000000 +0200 +++ MPlayer-20538/libaf/af.c 2006-10-30 21:57:34.000000000 +0100 @@ -359,17 +359,40 @@
// Check if this is the first call if(!s->first){ - // Add all filters in the list (if there are any) - if(!s->cfg.list){ // To make automatic format conversion work - if(!af_append(s,s->first,"dummy")) - return -1; + /* remap channels if the codec/demuxer provides a channel map */ + if (s->chan_map) { + af_control_ext_t arg; + arg.ch = s->input.nch; + af_instance_t *af = NULL; + af=af_append(s, s->first, "channels"); + /* set up af_channels to route */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTER, &s->input.nch))) + return -1; + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_NR, &s->input.nch))) + return -1; + /* set up each route */ + for (arg.ch = 0; arg.ch < s->input.nch; ++arg.ch) { + arg.arg = s->chan_map + 2*arg.ch; /* two by two... */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTING, &arg))) + return -1; + } + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS, &s->input.nch))) + return -1; + if (AF_OK != af_reinit(s,af)) + return -1; } - else{ + // Add all filters in the list (if there are any) + if (s->cfg.list) { while(s->cfg.list[i]){ if(!af_append(s,s->last,s->cfg.list[i++])) return -1; } } + // To make automatic format conversion work + if (!s->first){ + if(!af_append(s,s->first,"dummy")) + return -1; + } }
// Init filters @@ -709,3 +732,23 @@ { data->bps = af_fmt2bits(data->format)/8; } + +int *af_set_channel_map(int channels, char *routes){ + int *chan_map, *ptr; + ptr=chan_map=malloc(2 * channels * sizeof(int)); + if (!chan_map) { + mp_msg(MSGT_DEMUX, MSGL_ERR, "set_channel_map: cannot malloc for %d channels\n", channels); + return 0; + } + while (channels-- > 0) { + if (*routes == '\0' || *(routes+1) == '\0') { + mp_msg(MSGT_DEMUX, MSGL_ERR, "set_channel_map: not enough routes\n"); + free(chan_map); + return 0; + } + /* two by two... */ + *ptr++ = *routes++ - '0'; + *ptr++ = *routes++ - '0'; + } + return chan_map; +} --- MPlayer-20538/libmpdemux/stheader.h.chmap 2006-08-29 23:20:01.000000000 +0200 +++ MPlayer-20538/libmpdemux/stheader.h 2006-10-30 21:57:34.000000000 +0100 @@ -19,6 +19,7 @@ int samplerate; int samplesize; int channels; + int *chan_map; int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) int i_bps; // == bitrate (compressed bytes/sec) // in buffers:
------------------------------------------------------------------------
_______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu http://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
I don't see any difference in code between this patch and the old one by Corey. Did you by any chance attach the wrong file? Frank
On Monday, 30 October 2006 at 23:50, Frank Aurich wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch... [...] than without it). Attached a version updated to current SVN, although the old patch still applies. [...] I don't see any difference in code between this patch and the old one by Corey. Did you by any chance attach the wrong file?
No, but it's exactly the same patch, only with updated line numbers to apply without warnings against current SVN. Now the only thing missing is 6->4 downmix in libfaad/ad_faad and I can enjoy my 4.0 setup completely. ;) Regards, R. -- MPlayer developer and RPMs maintainer: http://rpm.greysector.net/mplayer/ There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
Yeah, I have a bad habit of leaving old patches alone...
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 one or two ideas of ways to implement reasonably user-friendly upmixing and downmixing configurations (that can be specified in the config file). When I wrote the original patch, I was thinking it would be nice to use pan (instead of channels) to do the remapping and remixing at the same time, but now I think it would be better to remix as a second step in order to conserve programming sanity. Like this: decoder [1]---> channel-remap [2]---> remixing [3]---> output where: [1] is arbitrary channel order [2] is consistent channel order [3] is remixed the way the user wants
With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies.
OK to apply?
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. In any case, the patch I posted was mostly a proof-of-concept, but I guess it works. Looking back, I see two things I might do differently. (a) The chan_map array could just be a string, with creation of *int pointers for af->control happening right before they're needed. This would obviate the need for a separate af_set_channel_map() funcion. (b) If (a) is done, then it would be easy to make sure the length of the array is as expected and prevent reading beyond the end. I'll go ahead and make those changes and see if it works. -Corey
On Tuesday, 31 October 2006 at 01:06, Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
Yeah, I have a bad habit of leaving old patches alone...
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.
I have one or two ideas of ways to implement reasonably user-friendly upmixing and downmixing configurations (that can be specified in the config file). When I wrote the original patch, I was thinking it would be nice to use pan (instead of channels) to do the remapping and remixing at the same time, but now I think it would be better to remix as a second step in order to conserve programming sanity.
Like this: decoder [1]---> channel-remap [2]---> remixing [3]---> output where: [1] is arbitrary channel order [2] is consistent channel order [3] is remixed the way the user wants
With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies.
OK to apply?
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.
In any case, the patch I posted was mostly a proof-of-concept, but I guess it works. Looking back, I see two things I might do differently.
(a) The chan_map array could just be a string, with creation of *int pointers for af->control happening right before they're needed. This would obviate the need for a separate af_set_channel_map() funcion.
(b) If (a) is done, then it would be easy to make sure the length of the array is as expected and prevent reading beyond the end.
I'll go ahead and make those changes and see if it works.
Great. I guess nobody was interested because nobody who cared had access to >2ch speaker setup. Could you also take care of WMA? See the recent thread on -users for details. Regards, R. -- MPlayer developer and RPMs maintainer: http://rpm.greysector.net/mplayer/ There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
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@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
In any case, the patch I posted was mostly a proof-of-concept, but I guess it works. Looking back, I see two things I might do differently.
(a) The chan_map array could just be a string, with creation of *int pointers for af->control happening right before they're needed. This would obviate the need for a separate af_set_channel_map() funcion.
That turned out to actually be messier, so I just changed it so the function is only called in af.c instead of in each decoder.
(b) If (a) is done, then it would be easy to make sure the length of the array is as expected and prevent reading beyond the end.
I'll go ahead and make those changes and see if it works.
Great. I guess nobody was interested because nobody who cared had access to >2ch speaker setup. Could you also take care of WMA? See the recent thread on -users for details.
I'm going to send an updated patch soon. -Corey
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@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
Giacomo Comes wrote:
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.
I agree. Those seem to be the most common configurations, and for now I don't think it's worth supporting others. It's definitely possible to remix odd configurations into the closest common configuration, but, without an abundance of samples or demand, I think it would complicate the current effort. Perhaps in the future.
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.
Thanks. I'll take a look.
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.
Yes, but not a lot.
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).
Perhaps.
Corey, can you integrate the ideas of this patch in yours?
Yes, one way or another. If I can see how, I want to compare the efficiency of doing the reordering within each ae_*.c vs. adding af_channels to the end of the filter chain just like I'm currently doing at the beginning. ...but not until I get home from work today. Thanks again, Corey
On Mon, Oct 30, 2006 at 04:06:07PM -0800, Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
Yeah, I have a bad habit of leaving old patches alone...
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 one or two ideas of ways to implement reasonably user-friendly upmixing and downmixing configurations (that can be specified in the config file). When I wrote the original patch, I was thinking it would be nice to use pan (instead of channels) to do the remapping and remixing at the same time, but now I think it would be better to remix as a second step in order to conserve programming sanity.
Like this: decoder [1]---> channel-remap [2]---> remixing [3]---> output where: [1] is arbitrary channel order [2] is consistent channel order [3] is remixed the way the user wants
With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies.
OK to apply?
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.
The patch has not been committed. Later (if I have time) or tomorrow I will point you to the original patch and I will post also a new one I made that extend the original one. Giacomo
In any case, the patch I posted was mostly a proof-of-concept, but I guess it works. Looking back, I see two things I might do differently.
(a) The chan_map array could just be a string, with creation of *int pointers for af->control happening right before they're needed. This would obviate the need for a separate af_set_channel_map() funcion.
(b) If (a) is done, then it would be easy to make sure the length of the array is as expected and prevent reading beyond the end.
I'll go ahead and make those changes and see if it works.
-Corey _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu http://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
--
Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
Yeah, I have a bad habit of leaving old patches alone...
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 one or two ideas of ways to implement reasonably user-friendly upmixing and downmixing configurations (that can be specified in the config file). When I wrote the original patch, I was thinking it would be nice to use pan (instead of channels) to do the remapping and remixing at the same time, but now I think it would be better to remix as a second step in order to conserve programming sanity.
Like this: decoder [1]---> channel-remap [2]---> remixing [3]---> output where: [1] is arbitrary channel order [2] is consistent channel order [3] is remixed the way the user wants
With that, it seems to be working fine (certainly the trailer sounds better than without it). Attached a version updated to current SVN, although the old patch still applies.
OK to apply?
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.
In any case, the patch I posted was mostly a proof-of-concept, but I guess it works. Looking back, I see two things I might do differently.
(a) The chan_map array could just be a string, with creation of *int pointers for af->control happening right before they're needed. This would obviate the need for a separate af_set_channel_map() funcion.
(b) If (a) is done, then it would be easy to make sure the length of the array is as expected and prevent reading beyond the end.
I'll go ahead and make those changes and see if it works.
-Corey
There you go: http://thread.gmane.org/gmane.comp.video.mplayer.devel/36195/ Frank
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
All right, here's an update. I'm sleepy by now, so there might be something wrong that's easily spotted with fresh eyes. I'll take a closer look tomorrow, but it should be testable. New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to. * remapping for 6-channel PCM (see below) On 2006-07-30, Alexander 'Lazy Ranma' Ponyatikh sent a patch for decoding 6-channel PCM directly into each correct channel. I benchmarked it, and it seems a bit slower than using af_channels, probably because it calls demux_read_data() repeatedly and only reads two samples at a time. I tested on a 6-channel wav file made from The Matrix DVD. It is 8177.3 seconds long. Each number is the user-time average of three tests, but there really wasn't much variation. The command is: $ time mplayer -ao pcm:fast:file=/dev/null -channels 6 audiodump.wav method user time % of play time ------------------------------------------------------------ original (incorrect channels): 9.099s 0.11127% using af_channels to remap: 15.057s 0.18413% reading into each channel: 30.296s 0.37048% By the way, Alexander, if you're reading this, don't think I'm denigrating your work; the information you sent is helpful and I might end up applying your ae_*.c patches. Also, if you come up with a faster approach for ad_pcm, feel free to submit it and we can consider using that instead of af_channels for PCM decoding. -Corey Index: libmpcodecs/ad_pcm.c =================================================================== --- libmpcodecs/ad_pcm.c (revision 20547) +++ libmpcodecs/ad_pcm.c (working copy) @@ -22,6 +22,21 @@ WAVEFORMATEX *h=sh_audio->wf; sh_audio->i_bps=h->nAvgBytesPerSec; sh_audio->channels=h->nChannels; + /* re-map channels */ + switch (sh_audio->channels) { + case 1: /* no action needed */ + case 2: /* no action needed */ + /* more mappings should be added when documentation or samples are found */ + case 3: /* unknown? */ + case 4: /* unknown? */ + case 5: /* unknown? */ + break; + case 6: + sh_audio->chan_map = "00" "11" "24" "35" "42" "53"; + break; + default: + break; + } sh_audio->samplerate=h->nSamplesPerSec; sh_audio->samplesize=(h->wBitsPerSample+7)/8; sh_audio->sample_format=AF_FORMAT_S16_LE; // default Index: libmpcodecs/ad_faad.c =================================================================== --- libmpcodecs/ad_faad.c (revision 20547) +++ libmpcodecs/ad_faad.c (working copy) @@ -152,6 +152,23 @@ mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate, faac_channels); sh->channels = faac_channels; if (audio_output_channels <= 2) sh->channels = faac_channels > 1 ? 2 : 1; + + /* re-map channels */ + switch (sh->channels) { + default: + case 1: /* no action needed */ + case 2: /* no action needed */ + case 3: /* no suitable default behavior? */ + case 4: /* no suitable default behavior? */ + break; + case 5: /* mplayer treats this like 6-channel */ + case 6: + sh->chan_map = "04" "10" "21" "32" "43" "55"; + break; + case 7: /* not supported by mplayer? */ + break; + } + sh->samplerate = faac_samplerate; sh->samplesize=2; //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate; Index: libmpcodecs/ad_dmo.c =================================================================== --- libmpcodecs/ad_dmo.c (revision 20547) +++ libmpcodecs/ad_dmo.c (working copy) @@ -40,6 +40,21 @@ } sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec; sh_audio->channels=chans; + /* re-map channels */ + switch (chans) { + case 1: /* no action needed */ + case 2: /* no action needed */ + /* more mappings should be added when documentation or samples are found */ + case 3: /* unknown? */ + case 4: /* unknown? */ + case 5: /* unknown? */ + break; + case 6: + sh_audio->chan_map = "00" "11" "24" "35" "42" "53"; + break; + default: + break; + } sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; sh_audio->samplesize=2; sh_audio->audio_in_minsize=4*sh_audio->wf->nBlockAlign; Index: libmpcodecs/dec_audio.c =================================================================== --- libmpcodecs/dec_audio.c (revision 20547) +++ libmpcodecs/dec_audio.c (working copy) @@ -311,6 +311,7 @@ // filter config: memcpy(&afs->cfg,&af_cfg,sizeof(af_cfg_t)); + afs->chan_map = sh_audio->chan_map; mp_msg(MSGT_DECAUDIO, MSGL_V, MSGTR_BuildingAudioFilterChain, afs->input.rate,afs->input.nch,af_fmt2str_short(afs->input.format), Index: libmpdemux/stheader.h =================================================================== --- libmpdemux/stheader.h (revision 20547) +++ libmpdemux/stheader.h (working copy) @@ -19,6 +19,7 @@ int samplerate; int samplesize; int channels; + char *chan_map; int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) int i_bps; // == bitrate (compressed bytes/sec) // in buffers: Index: libaf/af.c =================================================================== --- libaf/af.c (revision 20547) +++ libaf/af.c (working copy) @@ -359,17 +359,47 @@ // Check if this is the first call if(!s->first){ + + /* remap channels if the codec/demuxer provides a channel map */ + if (s->chan_map) { + int *routes; + af_control_ext_t arg; + arg.ch = s->input.nch; + af_instance_t *af = NULL; + af = af_append(s, s->first, "channels"); + /* check/set up the routes */ + if (! (routes = af_set_channel_map(s->input.nch, s->chan_map)) ) + return -1; + /* set up af_channels to route */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTER, &s->input.nch))) + return -1; + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_NR, &s->input.nch))) + return -1; + /* pass each route to af_channels */ + for (arg.ch = 0; arg.ch < s->input.nch; ++arg.ch) { + arg.arg = routes + 2*arg.ch; /* two by two... */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS_ROUTING, &arg))) + return -1; + } + /* try it! */ + if (!af || (AF_OK != af->control(af, AF_CONTROL_CHANNELS, &s->input.nch))) + return -1; + if (AF_OK != af_reinit(s,af)) + return -1; + } + // Add all filters in the list (if there are any) - if(!s->cfg.list){ // To make automatic format conversion work - if(!af_append(s,s->first,"dummy")) - return -1; - } - else{ + if (s->cfg.list) { while(s->cfg.list[i]){ if(!af_append(s,s->last,s->cfg.list[i++])) return -1; } } + // To make automatic format conversion work + if (!s->first){ + if(!af_append(s,s->first,"dummy")) + return -1; + } } // Init filters @@ -709,3 +739,22 @@ { data->bps = af_fmt2bits(data->format)/8; } + +int *af_set_channel_map(int channels, char *chan_map){ + int *routes, *ptr; + if (strlen(chan_map) != 2*channels) { + af_msg(AF_MSG_ERROR, "channel map: incorrect num. of routes in channel map\n"); + return NULL; + } + ptr = routes = malloc(2 * channels * sizeof(int)); + if (!chan_map) { + mp_msg(MSGT_DEMUX, MSGL_ERR, "set_channel_map: cannot malloc for %d channels\n", channels); + return 0; + } + while (channels-- > 0) { + /* two by two... */ + *ptr++ = *chan_map++ - '0'; + *ptr++ = *chan_map++ - '0'; + } + return routes; +} Index: libaf/af.h =================================================================== --- libaf/af.h (revision 20547) +++ libaf/af.h (working copy) @@ -104,6 +104,7 @@ af_data_t output; // Configuration for this stream af_cfg_t cfg; + char *chan_map; }af_stream_t; /********************************************* @@ -329,6 +330,17 @@ */ void af_fix_parameters(af_data_t *data); +/** + * \brief set up channel remapping + * \param number of output channels + * \param string of from-to routes + * \return int array of routes, NULL if error + * + * Makes an int array from a string of provided routes. + * Checks that number of routes matches channels. + */ +int *af_set_channel_map(int channels, char *chan_map); + /** Memory reallocation macro: if a local buffer is used (i.e. if the filter doesn't operate on the incoming buffer this macro must be called to ensure the buffer is big enough.
On Tuesday, 31 October 2006 at 07:53, Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
All right, here's an update. I'm sleepy by now, so there might be something wrong that's easily spotted with fresh eyes. I'll take a closer look tomorrow, but it should be testable.
I'll test it today.
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to.
Yay! I can test it.
* remapping for 6-channel PCM (see below)
Sample? Or can I make a sample with mplayer -channels 6 -ao pcm file.ac3? Regards, R. -- MPlayer developer and RPMs maintainer: http://rpm.greysector.net/mplayer/ There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
Dominik 'Rathann' Mierzejewski wrote:
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to.
Yay! I can test it.
Thanks.
* remapping for 6-channel PCM (see below)
Sample? Or can I make a sample with mplayer -channels 6 -ao pcm file.ac3?
You can, but the file will have the channels in "mplayer order" and not in "microsoft order", unless you also apply the patch to ao_pcm that Giacomo just sent (assuming it works). There's also a file in the wild here: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples/Microsoft/... from this page: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html -Corey
On Tuesday, 31 October 2006 at 18:04, Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to.
Yay! I can test it.
Thanks.
... but I have to build 32bit mplayer first. :(
* remapping for 6-channel PCM (see below)
Sample? Or can I make a sample with mplayer -channels 6 -ao pcm file.ac3?
You can, but the file will have the channels in "mplayer order" and not in "microsoft order", unless you also apply the patch to ao_pcm that Giacomo just sent (assuming it works).
There's also a file in the wild here: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples/Microsoft/... from this page: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html
Thanks, works beautifully. Also, it made me discover I have my left and right speakers swapped. Regards, R. -- MPlayer developer and RPMs maintainer: http://rpm.greysector.net/mplayer/ There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
All right, here's an update. I'm sleepy by now, so there might be something wrong that's easily spotted with fresh eyes. I'll take a closer look tomorrow, but it should be testable.
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to. * remapping for 6-channel PCM (see below)
Both tested for correct 5.1 output, works like a charm. Thanks! Frank
Frank Aurich wrote:
Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
All right, here's an update. I'm sleepy by now, so there might be something wrong that's easily spotted with fresh eyes. I'll take a closer look tomorrow, but it should be testable.
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to. * remapping for 6-channel PCM (see below)
Both tested for correct 5.1 output, works like a charm.
Thanks for testing. -Corey
On Tue, Oct 31, 2006 at 03:49:28PM -0800, Corey Hickey wrote:
Frank Aurich wrote:
Corey Hickey wrote:
Dominik 'Rathann' Mierzejewski wrote:
Reviving an old, forgotten patch...
All right, here's an update. I'm sleepy by now, so there might be something wrong that's easily spotted with fresh eyes. I'll take a closer look tomorrow, but it should be testable.
New stuff: * a little cleaner; better error checking * remapping for 6-channel WMA (in ad_dmo.c) This is UNTESTED. I won't apply it without testing later, but somebody else can test it now if they want to. * remapping for 6-channel PCM (see below)
Both tested for correct 5.1 output, works like a charm.
Thanks for testing.
So are you going to commit or what? :) Diego
participants (5)
-
Corey Hickey -
Diego Biurrun -
Dominik 'Rathann' Mierzejewski -
Frank Aurich -
Giacomo Comes