[MPlayer-dev-eng] [RFC] 6-channel AAC and channel reordering
Dominik 'Rathann' Mierzejewski
dominik at rangers.eu.org
Mon Oct 30 23:16:10 CET 2006
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
-------------- next part --------------
--- 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:
More information about the MPlayer-dev-eng
mailing list