Index: libfaad2/decoder.c
===================================================================
--- libfaad2/decoder.c	(リビジョン 29813)
+++ libfaad2/decoder.c	(作業コピー)
@@ -289,7 +289,8 @@
             hDecoder->object_type = adts.profile + 1;
 
             *samplerate = get_sample_rate(hDecoder->sf_index);
-            *channels = (adts.channel_configuration > 6) ?
+            *channels = (adts.channel_configuration > 6 ||
+                         adts.channel_configuration == 0) ?
                 2 : adts.channel_configuration;
         }
 
@@ -866,6 +867,13 @@
         if ((hInfo->error = adts_frame(&adts, &ld)) > 0)
             goto error;
 
+        /* ADTS.ch_config is set to 0 when dual-mono, 2-2, 2-1 in ISDB.
+           FIXME: but always assume dual-mono to avoid parsing PCE.
+                  (use of 2-2, 2-1 config is discouraged anyway. )
+         */    
+        if (adts.channel_configuration == 0)
+            adts.channel_configuration = 2;
+
         if (adts.channel_configuration != hDecoder->fr_channels)
         {
             //hDecoder->postSeekResetFlag = 1;
@@ -967,6 +975,9 @@
 
     /* Make a channel configuration based on either a PCE or a channelConfiguration */
     create_channel_config(hDecoder, hInfo);
+    // restore hInfo->pce_set which was increased by "in-stream" PCE
+    if (hDecoder->pce_set >= 2)
+        hDecoder->pce_set -= 2;
 
     /* number of samples in this frame */
     hInfo->samples = frame_len*output_channels;
@@ -1107,6 +1118,9 @@
     return sample_buffer;
 
 error:
+    // restore hInfo->pce_set which was increased by "in-stream" PCE
+    if (hDecoder->pce_set >= 2)
+        hDecoder->pce_set -= 2;
 
     faad_endbits(&ld);
 
Index: libfaad2/syntax.c
===================================================================
--- libfaad2/syntax.c	(リビジョン 29813)
+++ libfaad2/syntax.c	(作業コピー)
@@ -462,10 +462,12 @@
             case ID_PCE:
                 /* 14496-4: 5.6.4.1.2.1.3: */
                 /* program_configuration_element()'s in access units shall be ignored */
-                program_config_element(pce, ld);
-                //if ((hInfo->error = program_config_element(pce, ld)) > 0)
-                //    return;
-                //hDecoder->pce_set = 1;
+                // modified by 0p1pp1, for dual-mono etc. in ISDB-T/S
+                // see ARB-STD-B32 ...
+                // program_config_element(pce, ld);
+                if ((hInfo->error = program_config_element(pce, ld)) > 0)
+                    return;
+                hDecoder->pce_set += 2; // will be restored later
                 break;
             case ID_FIL:
                 /* one sbr_info describes a channel_element not a channel! */
Index: libmpcodecs/ad_faad.c
===================================================================
--- libmpcodecs/ad_faad.c	(リビジョン 29813)
+++ libmpcodecs/ad_faad.c	(作業コピー)
@@ -145,6 +145,10 @@
     sh->a_in_buffer_len -= (faac_init > 0)?faac_init:0; // how many bytes init consumed
     // XXX FIXME: shouldn't we memcpy() here in a_in_buffer ?? --A'rpi
 
+    if(faac_channels <= 2) { // fix nch for later config changes (to 5.1ch)
+      faac_conf->downMatrix = 1;
+      faacDecSetConfiguration(faac_hdec, faac_conf);
+    }
   } else { // We have ES DS in codecdata
     faacDecConfigurationPtr faac_conf = faacDecGetCurrentConfiguration(faac_hdec);
     if (audio_output_channels <= 2) {
@@ -296,16 +300,17 @@
       mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: Successfully decoded frame (%ld Bytes)!\n",
       sh->samplesize*faac_finfo.samples);
 
-      if (sh->channels != faac_finfo.channels)
+      if (sh->channels != faac_finfo.channels ||
+          sh->samplerate != faac_finfo.samplerate)
       {
-          mp_msg(MSGT_DECAUDIO, MSGL_DBG2, "FAAD: changed the number of channels(to %d)\n", faac_finfo.channels);
+          mp_msg(MSGT_DECAUDIO, MSGL_INFO, "FAAD: changed audio configuration to (%dch, %ldHz)\n", faac_finfo.channels, faac_finfo.samplerate);
           sh->channels = faac_finfo.channels;
-      }
-      if (sh->samplerate != faac_finfo.samplerate)
-      {
-          mp_msg(MSGT_DECAUDIO, MSGL_DBG2, "FAAD: changed the sampling rate(to %lu)\n", faac_finfo.samplerate);
           sh->samplerate = faac_finfo.samplerate;
+          //sh->o_bps will be updated later in fill_audio_out_buffers()
+          sh->reconfig = 1;
+          return len;
       }
+      sh->reconfig = 0;
 
       if (sh->channels >= 5)
         reorder_channel_copy_nch(faac_sample_buffer,Index: libmpcodecs/dec_audio.c
===================================================================
--- libmpcodecs/dec_audio.c	(リビジョン 29813)
+++ libmpcodecs/dec_audio.c	(作業コピー)
@@ -370,7 +370,7 @@
 	int minlen = len - sh->a_buffer_len;
 	int maxlen = sh->a_buffer_size - sh->a_buffer_len;
 	int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen);
-	if (ret <= 0) {
+	if (ret <= 0 || sh->reconfig) {
 	    error = -1;
 	    len = sh->a_buffer_len;
 	    break;
Index: libmpdemux/stheader.h
===================================================================
--- libmpdemux/stheader.h	(リビジョン 29813)
+++ libmpdemux/stheader.h	(作業コピー)
@@ -70,6 +70,7 @@
   int pts_bytes; // bytes output by decoder after last known pts
   char* lang; // track language
   int default_track;
+  int reconfig; // whether to re-configure audio filter at the next iteration
 } sh_audio_t;
 
 typedef struct {
Index: mencoder.c
===================================================================
--- mencoder.c	(リビジョン 29813)
+++ mencoder.c	(作業コピー)
@@ -320,6 +320,13 @@
 
 //---------------------------------------------------------------------------
 
+// Needed for reconfiguring audio stream
+static struct {
+    int new_srate;
+    muxer_stream_t *mux_a;
+    audio_encoder_t *aencoder;
+} reconf_data;
+
 static int dec_audio(sh_audio_t *sh_audio,unsigned char* buffer,int total){
     int size=0;
     int at_eof=0;
@@ -327,6 +334,21 @@
 	int len=total-size;
 		if(len>MAX_OUTBURST) len=MAX_OUTBURST;
 		if (decode_audio(sh_audio, len) < 0) at_eof=1;
+		if (sh_audio->reconfig) {
+			int out_srate = reconf_data.mux_a->wf->nSamplesPerSec;
+			int out_channels = reconf_data.mux_a->wf->nChannels;
+			int out_format = reconf_data.aencoder->input_format;
+			if (!init_audio_filters(sh_audio, reconf_data.new_srate,
+						&out_srate, &out_channels,
+						&out_format)) {
+				mp_msg(MSGT_CPLAYER, MSGL_FATAL,
+				       MSGTR_NoMatchingFilter);
+				mencoder_exit(1, NULL);
+			}
+			reconf_data.mux_a->wf->nSamplesPerSec = out_srate;
+			reconf_data.mux_a->wf->nChannels = out_channels;
+			at_eof = 0;
+		}
 		if(len>sh_audio->a_out_buffer_len) len=sh_audio->a_out_buffer_len;
 		fast_memcpy(buffer+size,sh_audio->a_out_buffer,len);
 		sh_audio->a_out_buffer_len-=len; size+=len;
@@ -910,6 +932,11 @@
       mencoder_exit(1,NULL);
     }
 }
+
+reconf_data.mux_a = mux_a;
+reconf_data.new_srate = new_srate;
+reconf_data.aencoder = aencoder;
+
 switch(mux_a->codec){
 case ACODEC_COPY:
     if (playback_speed != 1.0) mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_NoSpeedWithFrameCopy);
Index: mplayer.c
===================================================================
--- mplayer.c	(リビジョン 29813)
+++ mplayer.c	(作業コピー)
@@ -1604,7 +1604,14 @@
 ///@}
 // OSDMsgStack
 
+// for "in-stream" audio config switch
+void reconfig_audio_chain(void) {
+  if(!build_afilter_chain(mpctx->sh_audio, &ao_data))
+    mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter);
 
+  return;
+}
+
 void reinit_audio_chain(void) {
 if(mpctx->sh_audio){
   current_module="init_audio_codec";
@@ -2044,6 +2051,14 @@
 
     current_module="play_audio";
 
+    if (mpctx->sh_audio->reconfig) {
+        mpctx->sh_audio->o_bps = mpctx->sh_audio->channels *
+                                 mpctx->sh_audio->samplerate *
+                                 mpctx->sh_audio->samplesize;
+        if(!build_afilter_chain(mpctx->sh_audio, &ao_data))
+            mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter);
+    }
+
     while (1) {
 	int sleep_time;
 	// all the current uses of ao_data.pts seem to be in aos that handle
@@ -2108,6 +2123,9 @@
 	    mp_msg(MSGT_CPLAYER, MSGL_WARN, "Audio output truncated at end.\n");
 	    sh_audio->a_out_buffer_len = 0;
 	}
+
+        if (sh_audio->reconfig)
+            break;
     }
     return 1;
 }

