From caa8b1ff834470b7ced1e8481614585bfd8052ab Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 12 Nov 2026 18:44:44 +0200 Subject: [PATCH 1/2] audio: cadence: support RAW AAC decoding with IPC4 Accept RAW AAC alongside MPEG-4 ADTS and select the Cadence bitstream format explicitly. Configure the external sample rate and stereo output selection from the codec parameters for RAW input. During drain, the host can supply zero-filled padding after the last AAC payload. Passing this padding to the RAW decoder causes a fatal error before the existing EOS detection can run. Supply zero input bytes for all-zero RAW AAC buffers when EOS is expected, allowing the decoder to flush its remaining output and complete drain. Validated with a signed PTL build and mocked EOS regression tests. DUT testing confirmed AAC LC M4A playback at 24 kHz mono and 48 kHz stereo, with drain completion verified for the 24 kHz mono stream. Signed-off-by: Peter Ujfalusi --- .../module_adapter/module/cadence_ipc4.c | 75 ++++++++++++++++--- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/audio/module_adapter/module/cadence_ipc4.c b/src/audio/module_adapter/module/cadence_ipc4.c index d47c15e0550e..ac5917ac13ce 100644 --- a/src/audio/module_adapter/module/cadence_ipc4.c +++ b/src/audio/module_adapter/module/cadence_ipc4.c @@ -136,28 +136,37 @@ static int cadence_configure_mp3_enc_params(struct processing_module *mod) return 0; } +/** Configure AAC output and the external stream parameters needed for RAW input. */ static int cadence_configure_aac_dec_params(struct processing_module *mod) { struct cadence_codec_data *cd = module_get_private_data(mod); struct module_config *setup_cfg = &cd->setup_cfg; struct comp_dev *dev = mod->dev; - struct snd_codec *codec_params; - int bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_ADTS; + const struct snd_codec *codec_params; + int bitstream_format; + int sample_rate; + int to_stereo; int word_size; int ret; - /* check bitstream format. Only MPEG-4 ADTS supported for now */ - if (setup_cfg->avail) { - codec_params = (struct snd_codec *)cd->setup_cfg.data; - if (codec_params->format != SND_AUDIOSTREAMFORMAT_MP4ADTS) { - comp_err(dev, "Unsupported AAC format: %d", codec_params->format); - return -EINVAL; - } - } else { + if (!setup_cfg->avail) { comp_err(dev, "No setup config available for AAC decoder"); return -EINVAL; } + codec_params = setup_cfg->data; + switch (codec_params->format) { + case SND_AUDIOSTREAMFORMAT_MP4ADTS: + bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_ADTS; + break; + case SND_AUDIOSTREAMFORMAT_RAW: + bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_RAW; + break; + default: + comp_err(dev, "Unsupported AAC format: %d", codec_params->format); + return -EINVAL; + } + /* AAC decoder module only supports 16bit or 24 bits for word size */ switch (cd->base_cfg.audio_fmt.depth) { case IPC4_DEPTH_16BIT: @@ -193,6 +202,30 @@ static int cadence_configure_aac_dec_params(struct processing_module *mod) comp_warn(dev, "applied param bitstream format return code: %#x", ret); } + if (bitstream_format == XA_AACDEC_EBITSTREAM_TYPE_AAC_RAW) { + sample_rate = codec_params->sample_rate; + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, + XA_AACDEC_CONFIG_PARAM_EXTERNAL_SAMPLERATE, &sample_rate, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply external sample rate: error: %#x", ret); + return ret; + } + comp_warn(dev, "applied external sample rate return code: %#x", ret); + } + + to_stereo = codec_params->ch_out == 2; + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, + XA_AACDEC_CONFIG_PARAM_TO_STEREO, &to_stereo, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply stereo output: error: %#x", ret); + return ret; + } + comp_warn(dev, "applied stereo output return code: %#x", ret); + } + } + return 0; } @@ -448,6 +481,26 @@ static int cadence_codec_prepare(struct processing_module *mod, return 0; } +/** Detect zero-filled host padding while draining RAW AAC. */ +static bool cadence_raw_aac_input_is_padding(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct module_data *codec = &mod->priv; + const uint8_t *input = codec->mpd.in_buff; + const struct snd_codec *codec_params = cd->setup_cfg.data; + uint32_t offset; + + if (!mod->dev->expect_eos || cd->api_id != CADENCE_CODEC_AAC_DEC_ID || + !cd->setup_cfg.avail || codec_params->format != SND_AUDIOSTREAMFORMAT_RAW) + return false; + + for (offset = 0; offset < codec->mpd.avail; offset++) + if (input[offset]) + return false; + + return true; +} + static int cadence_codec_process(struct processing_module *mod, struct sof_source **sources, int num_of_sources, struct sof_sink **sinks, int num_of_sinks) { @@ -495,6 +548,8 @@ static int cadence_codec_process(struct processing_module *mod, struct sof_sourc cadence_copy_data_from_buffer(codec->mpd.in_buff, src_ptr, codec->mpd.in_buff_size, src_bytes, source_buffer_start); codec->mpd.avail = codec->mpd.in_buff_size; + if (cadence_raw_aac_input_is_padding(mod)) + codec->mpd.avail = 0; comp_dbg(dev, "cadence_codec_process() start"); From d61093c9da8b6b081ca00fa3056e79700d132a31 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 13 Nov 2026 08:45:53 +0200 Subject: [PATCH 2/2] audio: cadence: support ADIF and MPEG-2 ADTS Map ADIF to the Cadence AAC ADIF bitstream mode and accept MPEG-2 ADTS using the ADTS parser. The decoder parses the MPEG ID from the ADTS stream; MPEG_ID and ORIGINAL_OR_COPY are decoder-reported values, not configuration parameters. --- src/audio/module_adapter/module/cadence_ipc4.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/audio/module_adapter/module/cadence_ipc4.c b/src/audio/module_adapter/module/cadence_ipc4.c index ac5917ac13ce..3a4489e24dcf 100644 --- a/src/audio/module_adapter/module/cadence_ipc4.c +++ b/src/audio/module_adapter/module/cadence_ipc4.c @@ -156,9 +156,13 @@ static int cadence_configure_aac_dec_params(struct processing_module *mod) codec_params = setup_cfg->data; switch (codec_params->format) { + case SND_AUDIOSTREAMFORMAT_MP2ADTS: case SND_AUDIOSTREAMFORMAT_MP4ADTS: bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_ADTS; break; + case SND_AUDIOSTREAMFORMAT_ADIF: + bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_ADIF; + break; case SND_AUDIOSTREAMFORMAT_RAW: bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_RAW; break;