[MPlayer-dev-eng] Re: [RFC] 6-channel AAC and channel reordering

Frank Aurich fa859178 at inf.tu-dresden.de
Mon Oct 30 23:50:04 CET 2006


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 at 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




More information about the MPlayer-dev-eng mailing list