Skip to content

Commit 668859d

Browse files
authored
Merge pull request #4 from WXbet/aml-audio-fixes
container_ffmpeg: AC-4 audio support
2 parents ca7150c + ca78343 commit 668859d

1 file changed

Lines changed: 51 additions & 3 deletions

File tree

container/container_ffmpeg.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
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

Comments
 (0)