3838#include <sys/stat.h>
3939#include <fcntl.h>
4040#include <errno.h>
41+ #include <math.h>
4142#include <sys/poll.h>
4243#include <pthread.h>
4344#include <sys/prctl.h>
@@ -446,6 +447,9 @@ static char* Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extra
446447 return (ac3_software_decode ) ? "A_IPCM" : "A_AC3" ;
447448 case AV_CODEC_ID_EAC3 :
448449 return (eac3_software_decode ) ? "A_IPCM" : "A_EAC3" ;
450+ case AV_CODEC_ID_AC4 :
451+ /* No kernel AC-4 writer — always software decode via librempeg. */
452+ return "A_IPCM" ;
449453 case AV_CODEC_ID_DTS :
450454 return (dts_software_decode ) ? "A_IPCM" : "A_DTS" ;
451455 case AV_CODEC_ID_WMAV1 :
@@ -635,6 +639,8 @@ static void FFMPEGThread(Context_t *context)
635639 SwrContext * swr = NULL ;
636640 AVFrame * decoded_frame = NULL ;
637641 int32_t out_sample_rate = 44100 ;
642+ int ac4_immersive_ok = 0 ; /* librempeg AC-4 may fill only ch[0] — promote once others wake */
643+ int ac4_probe_streak = 0 ;
638644#if HAVE_CH_LAYOUT
639645 AVChannelLayout out_channel_layout ;
640646 av_channel_layout_default (& out_channel_layout , 2 );
@@ -1187,7 +1193,44 @@ static void FFMPEGThread(Context_t *context)
11871193 out_channels = 2 ;
11881194 }
11891195
1190- av_opt_set_chlayout (swr , "in_chlayout" , & c -> ch_layout , 0 );
1196+ /* librempeg AC-4 immersive only fills ch[0] today;
1197+ * probe upper channels for signal, latch full
1198+ * layout on first non-zero hit, else feed mono. */
1199+ AVChannelLayout in_chl_ac4 ;
1200+ av_channel_layout_copy (& in_chl_ac4 , & c -> ch_layout );
1201+ if (c -> codec_id == AV_CODEC_ID_AC4 && in_chl_ac4 .nb_channels > 2 )
1202+ {
1203+ if (!ac4_immersive_ok && decoded_frame &&
1204+ (enum AVSampleFormat )c -> sample_fmt == AV_SAMPLE_FMT_FLTP )
1205+ {
1206+ int nch = in_chl_ac4 .nb_channels ;
1207+ int probe = (decoded_frame -> nb_samples < 1024 ) ? decoded_frame -> nb_samples : 1024 ;
1208+ float peak0 = 0.0f , peak_rest = 0.0f ;
1209+ const float * p0 = (const float * )decoded_frame -> extended_data [0 ];
1210+ if (p0 ) for (int i = 0 ; i < probe ; ++ i ) {
1211+ float a = fabsf (p0 [i ]); if (a > peak0 ) peak0 = a ;
1212+ }
1213+ for (int ch = 1 ; ch < nch ; ++ ch ) {
1214+ const float * p = (const float * )decoded_frame -> extended_data [ch ];
1215+ if (!p ) continue ;
1216+ for (int i = 0 ; i < probe ; ++ i ) {
1217+ float a = fabsf (p [i ]); if (a > peak_rest ) peak_rest = a ;
1218+ }
1219+ }
1220+ if (peak0 > 0.01f && peak_rest > peak0 * 0.3f ) {
1221+ if (++ ac4_probe_streak >= 8 ) ac4_immersive_ok = 1 ;
1222+ } else {
1223+ ac4_probe_streak = 0 ;
1224+ }
1225+ }
1226+ if (!ac4_immersive_ok )
1227+ {
1228+ av_channel_layout_uninit (& in_chl_ac4 );
1229+ av_channel_layout_default (& in_chl_ac4 , 1 );
1230+ }
1231+ }
1232+
1233+ av_opt_set_chlayout (swr , "in_chlayout" , & in_chl_ac4 , 0 );
11911234 av_opt_set_chlayout (swr , "out_chlayout" , & out_channel_layout , 0 );
11921235 av_opt_set_sample_fmt (swr , "out_sample_fmt" , AV_SAMPLE_FMT_S16 , 0 );
11931236 av_opt_set_sample_fmt (swr , "in_sample_fmt" , c -> sample_fmt , 0 );
@@ -1205,7 +1248,9 @@ static void FFMPEGThread(Context_t *context)
12051248#endif
12061249 av_opt_set_int (swr , "in_sample_rate" , c -> sample_rate , 0 );
12071250 av_opt_set_int (swr , "out_sample_rate" , out_sample_rate , 0 );
1208-
1251+ /* Matrix peak cap: 1.0 anti-clips 5.1; 3.0 keeps 7.1.4 audible. */
1252+ av_opt_set_double (swr , "rematrix_maxval" ,
1253+ (out_channels >= 10 ) ? 3.0 : 1.0 , 0 );
12091254
12101255 e = swr_init (swr );
12111256 if (e < 0 )
@@ -1243,7 +1288,10 @@ static void FFMPEGThread(Context_t *context)
12431288 ((AVStream * ) audioTrack -> stream )-> time_base .num * (int64_t )out_sample_rate * c -> sample_rate );
12441289
12451290 currentAudioPts = audioTrack -> pts = pts = calcPts (cAVIdx , audioTrack -> stream , next_out_pts );
1246- out_samples = swr_convert (swr , & output [0 ], out_samples , (const uint8_t * * ) & decoded_frame -> data [0 ], in_samples );
1291+ /* extended_data is sized for nb_channels; data[0..7] only
1292+ * has 8 slots which would overflow for 7.1.4 (12 channels). */
1293+ out_samples = swr_convert (swr , & output [0 ], out_samples ,
1294+ (const uint8_t * * ) decoded_frame -> extended_data , in_samples );
12471295
12481296 //////////////////////////////////////////////////////////////////////
12491297 // Update pcmExtradata according to decode parameters
0 commit comments