|
1 | | -# FFmpeg audio decoder module (ffmpeg_dec) |
2 | | - |
3 | | -Wraps FFmpeg's `libavcodec` audio decoders behind the SOF `module_interface`, |
4 | | -decoding a compressed elementary stream to PCM inside the DSP. First target |
5 | | -codec is **FLAC**. |
6 | | - |
7 | | -## Design |
8 | | - |
9 | | -The SOF glue and the decoder are separated so the integration can be validated |
10 | | -without libavcodec: |
11 | | - |
12 | | -- `ffmpeg_dec.c` — SOF module core: `init` / `prepare` / `process_raw_data` / |
13 | | - `set_configuration` / `reset` / `free`, plus the LLEXT manifest. Input is the |
14 | | - compressed byte stream (raw data), output is interleaved PCM. Decoding is |
15 | | - delegated to a `struct ffmpeg_dec_backend`. |
16 | | -- `ffmpeg_dec-stub.c` — dependency-free passthrough backend. Lets CI build and |
17 | | - exercise the module (pipeline, IPC config, LLEXT packaging) with **no** FFmpeg |
18 | | - libraries. Selected by `CONFIG_COMP_FFMPEG_DEC_STUB`. |
19 | | -- `ffmpeg_dec-ffmpeg.c` — real backend driving the standalone `libavcodec` |
20 | | - send-packet / receive-frame API. A raw stream is framed on-DSP with an |
21 | | - `AVCodecParser` (`av_parser_parse2`); decode is forced single-threaded |
22 | | - (`thread_count = 1`). Requires pre-compiled static libraries and headers under |
23 | | - `third_party/` (see below). |
24 | | -- `ffmpeg_dec.h` — private data (`struct ffmpeg_dec_comp_data`) and the backend |
25 | | - interface. |
26 | | - |
27 | | -The codec setup header (e.g. FLAC STREAMINFO) is delivered as a binary control |
28 | | -via `set_configuration` and stored as `extradata`, which the libavcodec backend |
29 | | -installs before `avcodec_open2()`. |
30 | | - |
31 | | -## Build |
32 | | - |
33 | | -- **Stub (default for testing/CI):** `CONFIG_COMP_FFMPEG_DEC=y` (or `=m` for |
34 | | - LLEXT) with `CONFIG_COMP_FFMPEG_DEC_STUB=y`. No external dependencies. |
35 | | -- **Real decoder:** `CONFIG_COMP_FFMPEG_DEC=m`, `CONFIG_COMP_FFMPEG_DEC_STUB=n`. |
36 | | - Requires cross-compiled decoder-only FFmpeg static libraries installed as: |
37 | | - - `third_party/lib/libavcodec.a`, `libavutil.a`, `libswresample.a` |
38 | | - - `third_party/include/libavcodec/…`, `libavutil/…`, `libswresample/…` |
39 | | - Configure FFmpeg with `--disable-everything --disable-avformat |
40 | | - --disable-pthreads --enable-decoder=flac --enable-parser=flac` (plus the |
41 | | - target cross-compile flags). |
42 | | - |
43 | | -## Files |
44 | | - |
45 | | -- `Kconfig` — `COMP_FFMPEG_DEC` (tristate) and `COMP_FFMPEG_DEC_STUB`. |
46 | | -- `CMakeLists.txt` / `llext/CMakeLists.txt` — static and LLEXT builds; the LLEXT |
47 | | - target name is `ffmpeg_dec` and links the FFmpeg libraries in the non-stub |
48 | | - branch. |
49 | | -- `ffmpeg_dec.toml` / `llext/llext.toml.h` — rimage module manifest |
50 | | - (`UUIDREG_STR_FFMPEG_DEC`); OBS is sized above IBS since PCM out ≫ compressed |
51 | | - in. |
52 | | - |
53 | | -## Status / TODO |
54 | | - |
55 | | -- Codec id is currently hard-coded to FLAC in `init`; wire it from topology/IPC |
56 | | - init config for other codecs. |
57 | | -- Output is assumed to already match the sink sample format; add |
58 | | - `libswresample` (or a fixed-point path) for format/rate conversion. |
59 | | -- Topology and host test tooling for end-to-end (bit-exact) FLAC decode. |
| 1 | +# FFmpeg Audio Processing Module (`ffmpeg_dec`) |
| 2 | + |
| 3 | +Wraps FFmpeg's `libavcodec` and `libavfilter` libraries behind the SOF `module_interface`. This module enables running on-DSP audio decoders, encoders, and real-time audio filter graphs. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- **Decoder Mode**: Decodes compressed audio streams (e.g., FLAC, MP3) to raw PCM. |
| 10 | +- **Encoder Mode**: Encodes raw PCM streams to compressed formats (e.g., MP3 using `libshine`). |
| 11 | +- **Filter Mode**: Runs FFmpeg's `libavfilter` graphs directly on raw PCM data (e.g., `afftdn` for noise reduction). |
| 12 | +- **Embedded-Optimized**: Supports single-threaded execution, memory shims for dynamic allocation, and LLEXT packaging. |
| 13 | +- **CI-Friendly**: Includes a pass-through stub backend to allow pipeline, IPC, and topology verification without external dependencies. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Architecture & Data Flow |
| 18 | + |
| 19 | +The following Mermaid diagram illustrates the module's internal architecture and the interaction between the SOF pipeline, the `ffmpeg_dec` core, and its backend translation units: |
| 20 | + |
| 21 | +```mermaid |
| 22 | +graph TD |
| 23 | + %% Audio Data Flow |
| 24 | + InBuf[Input Audio Buffer] -->|Raw Bytes or PCM| Core[ffmpeg_dec.c Core] |
| 25 | + Core -->|Pass-through| BackendStub[ffmpeg_dec-stub.c Stub] |
| 26 | + Core -->|Process| BackendFFmpeg[ffmpeg_dec-ffmpeg.c FFmpeg Backend] |
| 27 | + |
| 28 | + BackendFFmpeg -->|Parse/Decode/Filter| Libavcodec[libavcodec / libavfilter] |
| 29 | + Libavcodec -->|Output PCM Frame| Core |
| 30 | + BackendStub -->|Pass-through S16/S32| Core |
| 31 | + Core -->|Interleaved PCM or Encoded Bytes| OutBuf[Output Audio Buffer] |
| 32 | +
|
| 33 | + %% Control Flow |
| 34 | + IPC[SOF IPC set_configuration] -.->|Metadata/Extradata| Core |
| 35 | + Core -.->|avcodec_open2 / init| Libavcodec |
| 36 | +``` |
| 37 | + |
| 38 | +### Modular Design |
| 39 | +- **`ffmpeg_dec.c` (Core Glue)**: Implements the standard `module_interface` functions (`init`, `prepare`, `process`, `reset`, `free`). |
| 40 | +- **`ffmpeg_dec-stub.c`**: Pass-through stub backend that bypasses FFmpeg libraries. |
| 41 | +- **`ffmpeg_dec-ffmpeg.c` / `ffmpeg_dec-filter.c` / `ffmpeg_dec-encode.c`**: Real backend implementations interfacing with `libavcodec` and `libavfilter`. |
| 42 | +- **`ffmpeg_dec-shims.c`**: Overrides dynamic memory allocations (`malloc`, `realloc`, `free`, `calloc`) inside FFmpeg to use SOF's `rballoc` pools. |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## Build Instructions |
| 47 | + |
| 48 | +### 1. Stub Mode (Default / CI / Staging) |
| 49 | +No external libraries are required. The module acts as a simple pass-through. |
| 50 | +```ini |
| 51 | +CONFIG_COMP_FFMPEG_DEC=y # or =m for LLEXT |
| 52 | +CONFIG_COMP_FFMPEG_DEC_STUB=y |
| 53 | +``` |
| 54 | + |
| 55 | +### 2. Real FFmpeg Backend |
| 56 | +Requires pre-compiled static libraries and headers placed under the `third_party/` directory of the workspace. |
| 57 | +```ini |
| 58 | +CONFIG_COMP_FFMPEG_DEC=m |
| 59 | +CONFIG_COMP_FFMPEG_DEC_STUB=n |
| 60 | +``` |
| 61 | + |
| 62 | +#### Configuring the FFmpeg Build |
| 63 | +When cross-compiling FFmpeg for Xtensa DSP targets, disable unnecessary components to minimize code size: |
| 64 | +```bash |
| 65 | +./configure \ |
| 66 | + --target-os=none \ |
| 67 | + --arch=xtensa \ |
| 68 | + --enable-cross-compile \ |
| 69 | + --disable-everything \ |
| 70 | + --disable-avformat \ |
| 71 | + --disable-pthreads \ |
| 72 | + --enable-decoder=flac,mp3 \ |
| 73 | + --enable-encoder=mp3 \ |
| 74 | + --enable-parser=flac,mpegaudio \ |
| 75 | + --enable-filter=afftdn \ |
| 76 | + --enable-static \ |
| 77 | + --disable-shared |
| 78 | +``` |
| 79 | + |
| 80 | +#### Useful Kconfig Options |
| 81 | +- `CONFIG_FFMPEG_DEC_FILTER_MODE`: Configures the module to run as a PCM filter graph instead of a decoder. |
| 82 | +- `CONFIG_FFMPEG_DEC_FLOAT_MATH`: Automatically selected to pull in optimized floating-point shims (`fastmathf.c`). |
| 83 | +- `CONFIG_FFMPEG_DEC_COLD_SPLIT`: Relocates initialization tables and code to DRAM to conserve fast SRAM. |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## Usage & Topology |
| 88 | + |
| 89 | +### 1. Decoder Mode |
| 90 | +The topology should feed compressed bytes (e.g., from a host gateway) into the decoder input pin. The decoder outputs decoded PCM. |
| 91 | +- **Initialization**: Provide codec-specific setup data (e.g., FLAC `STREAMINFO` or MP3 headers) via IPC bytes control `set_configuration`. |
| 92 | +- **Buffer Period**: Keep period size large enough (typically 10ms or 20ms) to reduce parsing overhead. |
| 93 | + |
| 94 | +### 2. Filter Mode |
| 95 | +The module is placed in the capture or playback pipeline as a normal 1-in / 1-out effect. |
| 96 | +- **Routing Example**: |
| 97 | +``` |
| 98 | +DAI Copier (Mic Capture) ---> [ ffmpeg_dec (Filter Mode) ] ---> Host Copier (PCM) |
| 99 | +``` |
| 100 | +- **Control**: Filter coefficients and parameters can be set dynamically via standard TLV bytes controls. |
0 commit comments