Skip to content

ffmpeg_dec: decode pipeline, platform, topology fixups and test tooling - #11390

Draft
lgirdwood wants to merge 7 commits into
thesofproject:mainfrom
lgirdwood:topic/ffmpeg-decode-fixes
Draft

lgirdwood wants to merge 7 commits into
thesofproject:mainfrom
lgirdwood:topic/ffmpeg-decode-fixes

Conversation

@lgirdwood

@lgirdwood lgirdwood commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Summary

This series contains the remaining core, topology, and tooling updates for ffmpeg_dec compressed audio decode support on top of the merged ffmpeg_dec integration (#11284 / #11343):

  1. audio: src: align the SRC delay line allocation to SOF_FRAME_BYTE_ALIGN
    • Use mod_alloc_align(..., SOF_FRAME_BYTE_ALIGN) for cd->delay_lines so SIMD circular buffer accesses in the SRC filter do not fault when ffmpeg_dec is paired with an SRC stage.
  2. platform: cavs: initialize DP scheduler on primary core
    • Call scheduler_dp_init() unconditionally during platform_init() on CAVS/ACE platforms when CONFIG_SOF_USERSPACE_APPLICATION=y so DP modules (such as ffmpeg_dec) can be scheduled on core 0 as well as secondary cores.
  3. topology2: compr-ffmpeg: use COMPR_DECODER_CORE_ID and add Opus target
    • Parameterize the ffmpeg_dec pipeline and component core_id via COMPR_DECODER_CORE_ID, size COMPR_FFMPEG_DEC_HEAP to 256 KiB to cover the 64 KiB PCM staging buffer and decoder working set, and add the sof-hda-generic-ffmpeg-opus-compr build target.
  4. topology2: add ffmpeg_dec benchmark test topology
    • Add the playback benchmark topology (ffmpeg_dec32, HDA and SoundWire) with DP scheduling and decoder stack/heap budgets for ffmpeg_dec.
  5. tools: test: add ffmpeg_dec FLAC test vector generator script
    • Add tools/test/audio/ffmpeg_dec_prepare.sh referenced by src/audio/ffmpeg_dec/TESTING.md to generate raw FLAC frames, 34-byte STREAMINFO extradata, and reference S32_LE PCM vectors.
  6. audio: host: align remaining compress drain bytes to dma_copy_align
    • Round the remaining committed compress drain byte count in host_get_copy_bytes_normal() up to MAX(dma_sample_bytes, hd->dma_copy_align) for the DMA transfer/reload, and clamp the bytes copied into the downstream sink in host_common_update() to the actual payload remainder (consuming any trailing DMA padding from the source DMA buffer).
  7. audio: ffmpeg_dec: strip container header before lazy backend configure
    • Embed extradata inline in struct ffmpeg_dec_comp_data (avoiding mod_alloc() on the user-mode DP thread) and strip the container header before lazy backend configuration so stream-embedded setup headers (such as FLAC STREAMINFO) are extracted before avcodec_open2().

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Decoder heap undersizing, excess DMA bytes published downstream, and backend initialization on the shared LL thread risk allocation failures, payload corruption, and audio stalls; benchmark routing and SoundWire integration are also incomplete.

5 open issues
What changed in this PR

This PR updates SOF’s ffmpeg_dec runtime integration, topology configuration, and test tooling for compressed audio decoding.

Changes:

  • Adjusts SRC allocation alignment, primary-core DP scheduler initialization, and compressed-stream drain alignment.
  • Stores codec extradata inline and extracts container headers before lazy backend configuration.
  • Parameterizes decoder core selection, adds an Opus target and benchmark fragments, and provides FLAC test-vector preparation.
File Description
tools/​topology/​topology2/​platform/​intel/​compr-ffmpeg.conf Uses configurable decoder core selection.
tools/​topology/​topology2/​platform/​intel/​compr-default.conf Updates comments to cover both decoder implementations.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_s32.conf Adds S32 decoder benchmark instances.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_s24.conf Adds S24 decoder benchmark instances.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_s16.conf Adds S16 decoder benchmark instances.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_route.conf Adds playback and capture benchmark routes.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_controls_playback.conf Adds commented playback control placeholders.
tools/​topology/​topology2/​include/​bench/​ffmpeg_dec_controls_capture.conf Adds commented capture control placeholders.
tools/​topology/​topology2/​development/​tplg-targets.cmake Registers the FFmpeg Opus compressed-playback target.
tools/​topology/​topology2/​development/​tplg-targets-bench.cmake Adds FFmpeg to S32 benchmark target generation.
tools/​topology/​topology2/​cavs-benchmark-hda.conf Includes the decoder class and S32 benchmark selection.
tools/​test/​audio/​ffmpeg_dec_prepare.sh Generates FLAC data, STREAMINFO, and reference PCM.
src/​platform/​intel/​cavs/​platform.c Initializes the enabled DP scheduler during platform startup.
src/​audio/​src/​src_common.c Requests eight-byte alignment for SRC delay lines.
src/​audio/​host-zephyr.c Rounds drain remainder to DMA copy alignment.
src/​audio/​ffmpeg_dec/​ffmpeg_dec.h Replaces the extradata pointer with inline storage.
src/​audio/​ffmpeg_dec/​ffmpeg_dec.c Updates extradata handling and strips headers before backend configuration.

Review effort: Balanced

Comment thread src/audio/host-zephyr.c Resolved
Comment thread src/audio/src/src_common.c Resolved
@lgirdwood
lgirdwood force-pushed the topic/ffmpeg-decode-fixes branch from 2c699be to 33474be Compare November 3, 2026 20:48
@lgirdwood

Copy link
Copy Markdown
Member Author

Addressed review comments:

  1. src/audio/src/src_common.c: Shortened the comment to a single line and used SOF_FRAME_BYTE_ALIGN in mod_alloc_align().
  2. src/audio/host-zephyr.c: Kept the DMA transfer/reload aligned to hd->dma_copy_align in host_get_copy_bytes_normal(), and clamped the bytes copied into the downstream sink in host_common_update() to the actual committed payload remainder (consuming any trailing DMA padding from the source DMA buffer).
  3. tools/topology/topology2/platform/intel/compr-default.conf & tplg-targets.cmake: Updated COMPR_FFMPEG_DEC_HEAP to 262144 (256 KiB) for the default and Opus compress targets to cover the 64 KiB PCM staging buffer, input bounce buffer, and decoder working set.
  4. tools/topology/topology2/include/bench/ffmpeg_dec_s{16,24,32}.conf: Configured scheduler_domain "DP", stack_bytes_requirement 65536, and heap_bytes_requirement 262144 on the benchmark decoder widget.
  5. tools/topology/topology2/cavs-benchmark-sdw.conf: Added <ffmpeg_dec.conf> and the ffmpeg_dec32 BENCH_CONFIG entry for the SoundWire benchmark targets.
  6. tools/topology/topology2/include/bench/ffmpeg_dec_route.conf: Removed the second decoder instance from the microphone capture path and routed capture directly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two critical issues remain: extradata pointer checks break warning-as-error builds, and successful padded DMA copies can leave padding unconsumed and the read pointer misaligned.

2 open issues
5 resolved since last review

Review effort: Balanced

Comment thread src/audio/ffmpeg_dec/ffmpeg_dec.h Resolved
Comment thread src/audio/host-zephyr.c Resolved
Comment thread src/audio/host-zephyr.c Resolved
@lgirdwood
lgirdwood force-pushed the topic/ffmpeg-decode-fixes branch from 33474be to 034bde0 Compare November 4, 2026 13:04
@lgirdwood

Copy link
Copy Markdown
Member Author

Updated to address the review comments and tested on damsel-fly (Panther Lake / ACE 3.0) built with the local LLVM + HiFi compiler:

  1. src/audio/ffmpeg_dec/ffmpeg_dec.c & ffmpeg_dec-ffmpeg.c: Removed redundant cd->extradata pointer truthiness checks after switching extradata to an inline array, checking cd->extradata_size only.
  2. src/audio/host-zephyr.c: Added a descriptive comment explaining the compress drain EOS clamping in host_common_update(), and changed the return check on dma_buffer_copy_from() to if (ret >= 0 && bytes > copy_bytes) before consuming trailing DMA alignment padding.
  3. Additional fixes uncovered during damsel-fly testing:
    • Use source_drop_data() instead of source_release_data() when consuming container bytes in ffmpeg_dec_skip_container() (since the preceding source_release_data(src, 0) resets src->requested_read_frag_size = 0, causing subsequent source_release_data(src, N) calls to return -ENODATA without advancing the read pointer).
    • Free cd->eos_msg with mod_ipc_msg_free(mod, cd->eos_msg) instead of ipc_msg_free() in ffmpeg_dec_free() to match mod_ipc_msg_w_ext_init() and avoid a double-free on module teardown.
  4. Hardware verification on damsel-fly (PTL / ACE 3.0):
    • cplay -v -c 0 -d 50 /root/ffmpeg_test/test_short.mp3 -> play_samples: exit success, Finish Playing.... Close Normally
    • cplay -v -I FLAC -c 0 -d 50 /root/ffmpeg_test/test.flac -> play_samples: exit success, Finish Playing.... Close Normally

@lgirdwood lgirdwood left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last patch needs rebased/squashed with the others. Lets also put our per codec logic in per codec files to keep things simple.

Comment thread src/audio/ffmpeg_dec/ffmpeg_dec.c Resolved
@lgirdwood
lgirdwood force-pushed the topic/ffmpeg-decode-fixes branch from 034bde0 to fb97632 Compare November 4, 2026 16:47
@lgirdwood

Copy link
Copy Markdown
Member Author

Updated PR to address review comments:

  • Rebased onto latest origin/main (80b14b070) and squashed the ffmpeg_dec changes.
  • Split per-codec logic (decoder lookup, max frame samples, extradata validation, and container stripping) into dedicated per-codec files behind struct ffmpeg_dec_codec_ops:
    • src/audio/ffmpeg_dec/ffmpeg_dec-flac.c
    • src/audio/ffmpeg_dec/ffmpeg_dec-mp3.c
    • src/audio/ffmpeg_dec/ffmpeg_dec-aac.c
    • src/audio/ffmpeg_dec/ffmpeg_dec-opus.c
  • Updated the lazy avcodec_open2() comments in ffmpeg_dec.c and ffmpeg_dec-ffmpeg.c to reflect the current per-core IPC/IDC dispatch flow.
  • Retested FLAC, MP3, and AAC compressed playback (cplay -c 0 -d 50) on damsel-fly (PTL / ACE 3.0) built with the local LLVM + HiFi compiler.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical issues remain: undersized per-instance heaps cause bind/prepare failures, and explicitly requested codecs disabled in Kconfig silently fall back to an incompatible default decoder.

3 open issues
1 resolved since last review

Review effort: Balanced

Comment thread src/audio/ffmpeg_dec/ffmpeg_dec.c Resolved
The HiFi FIR cores in the SRC filter issue 64-bit AE_L32X2/AE_S32X2
circular accesses into cd->delay_lines and fault (EXCCAUSE 9) on a
4-byte-aligned base. Allocate cd->delay_lines with SOF_FRAME_BYTE_ALIGN
alignment rather than relying on the default mod_alloc() alignment.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Initialize scheduler_dp_init() in CAVS platform_init() when
CONFIG_ZEPHYR_DP_SCHEDULER is enabled, matching ACE platform_init().
This allows data-processing (DP) scheduled modules such as ffmpeg_dec
to run on the primary core on cAVS platforms (e.g. Tiger Lake).

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Use the COMPR_DECODER_CORE_ID define instead of a hardcoded core_id 1 on
the ffmpeg_dec widget, size COMPR_FFMPEG_DEC_HEAP to 512 KiB to cover
the 64 KiB PCM staging buffer and decoder working set, and add the
sof-hda-generic-ffmpeg-opus-compr topology build target.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add the ffmpeg_dec component to the playback benchmark harness (HDA and
SoundWire) with DP scheduling and decoder stack/heap budgets so a
topology instantiating the module can be built and driven by testbench
or on target.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add tools/test/audio/ffmpeg_dec_prepare.sh to generate FLAC test
vectors, STREAMINFO extradata blobs, and bit-exact S32_LE reference PCM
files for verifying the ffmpeg_dec module, as referenced in
src/audio/ffmpeg_dec/TESTING.md.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
In host_get_copy_bytes_normal(), the remaining committed compress drain
bytes (hd->drain_bytes - hd->total_data_processed) were rounded up only
to dma_sample_bytes before clamping dma_copy_bytes. However, the return
value of host_get_copy_bytes_normal() is rounded down to
hd->dma_copy_align (e.g. 32 bytes on HDA). When the final tail of a
compressed stream is smaller than hd->dma_copy_align, ALIGN_DOWN()
rounds dma_copy_bytes down to zero, preventing hd->total_data_processed
from ever reaching hd->drain_bytes and stalling compress drain EOS.

Round the remaining drain byte count up to MAX(dma_sample_bytes,
hd->dma_copy_align) for the DMA transfer/reload, and clamp the bytes
copied into the downstream sink in host_common_update() to the actual
payload remainder (consuming any trailing DMA padding from the source
DMA buffer) so stale HDA bytes are never published to the decoder.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…handling

Refactor codec-specific container parsing, frame sizing, decoder lookup,
and extradata validation into dedicated per-codec files
(ffmpeg_dec-flac.c, ffmpeg_dec-mp3.c, ffmpeg_dec-aac.c,
ffmpeg_dec-opus.c) behind struct ffmpeg_dec_codec_ops.

Additionally fix several issues in the container stripping, heap sizing,
and module lifecycle paths:
1. Run container stripping before the lazy backend configure block in
   ffmpeg_dec_process() so avcodec_open2() does not open the FLAC
   decoder with empty extradata before STREAMINFO is parsed, and update
   the lazy-open comments to reflect the current per-core IPC/IDC flow.
2. Reject explicitly requested IPC snd_codec IDs without an enabled
   codec_ops entry with -ENOTSUP instead of falling back to the default
   decoder, and avoid multiplying max_frame_bytes by out_channels twice
   in ffmpeg_dec_prepare().
3. Embed the extradata buffer inline in struct ffmpeg_dec_comp_data
   (checking extradata_size rather than pointer non-nullness) so
   ffmpeg_dec_store_extradata() does not call mod_alloc() from the
   user-mode DP thread.
4. Use source_drop_data() instead of source_release_data() when
   consuming container bytes, since the preceding
   source_release_data(src, 0) resets src->requested_read_frag_size to 0
   and causes subsequent source_release_data(src, N) calls to fail with
   -ENODATA without advancing the source read pointer.
5. Free cd->eos_msg with mod_ipc_msg_free() instead of ipc_msg_free()
   in ffmpeg_dec_free() to match mod_ipc_msg_w_ext_init() and avoid a
   double-free on module teardown.
6. Size FFMPEG_DEC_HEAP_BYTES in ffmpeg_dec-builtin-alloc.c to 576 KiB
   across all codecs (since -DSOF_AAC_LC_ONLY=1 already eliminates the
   unused SBR/PS and non-LC MDCT tables), leaving sufficient L2 SRAM in
   sof_heap for the 64 KiB DP stack and module heap.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
@lgirdwood
lgirdwood force-pushed the topic/ffmpeg-decode-fixes branch from fb97632 to dd7b795 Compare November 5, 2026 20:36
@lgirdwood

Copy link
Copy Markdown
Member Author

Updated PR to address the latest review comments and re-trigger CI:

  1. src/audio/ffmpeg_dec/ffmpeg_dec.c:
    • Reject explicitly requested IPC snd_codec IDs without an enabled ffmpeg_dec_codec_ops entry with -ENOTSUP in ffmpeg_dec_init() instead of silently falling back to the default decoder.
    • Fix max_frame_bytes calculation in ffmpeg_dec_prepare() to avoid multiplying by out_channels twice (cd->out_frame_bytes from sink_get_frame_bytes(sink) already includes out_channels).
  2. tools/topology/topology2/:
    • Increase COMPR_FFMPEG_DEC_HEAP in platform/intel/compr-default.conf and development/tplg-targets.cmake (Opus override) and heap_bytes_requirement in include/bench/ffmpeg_dec_s{16,24,32}.conf from 262144 (256 KiB) to 524288 (512 KiB) so per-instance userspace vregions cover the 192 KiB DP output ring, 64 KiB PCM staging buffer, input/packet scratch buffers, and decoder working set.
  3. Rebased onto latest origin/main (414a8a228) to re-run the two CI jobs that hit GitHub Actions runner No space left on device errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants