Skip to content

Commit d81b938

Browse files
lrgirdwoclaude
andcommitted
audio: ffmpeg_dec: add MP3 encoder via libshine
FFmpeg has no native MP3 encoder, so add MP3 encode through libshine, a small fixed-point encoder (good fit for a DSP - no float dependency). libshine is a west-pinned project; ffmpeg.cmake cross-builds it (its lib needs no config.h and its autotools CLI/shared link cannot work bare-metal, so the objects are compiled and archived directly), generates a shine.pc, and enables --enable-libshine --enable-encoder=libshine in FFmpeg. FFmpeg's require_pkg_config link test for -lshine pulls newlib malloc and hence Zephyr-runtime symbols (z_errno_wrap, ...) that only exist at module load; a configure-test-only stub is passed via --extra-ldflags so the test links (--extra-ldflags does not affect the static-archive build). Gated by CONFIG_FFMPEG_ENC_MP3. Verified building for ace30 (ptl): libshine.a cross-builds and libavcodec.a contains the libshine encoder. A module encode path (PCM->MP3) is a separate build mode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c70c0ce commit d81b938

3 files changed

Lines changed: 84 additions & 1 deletion

File tree

src/audio/ffmpeg_dec/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ config FFMPEG_DEC_MP3
5151
MPEG-1/2 Layer III decoder. Enables --enable-decoder=mp3 and the
5252
mpegaudio parser in the libavcodec build. Uses the float math layer.
5353

54+
config FFMPEG_ENC_MP3
55+
bool "MP3 encoder (libshine, fixed-point)"
56+
help
57+
MPEG-1 Layer III encoder via libshine, a small fixed-point encoder
58+
(west-pinned; FFmpeg has no native MP3 encoder). Cross-builds libshine
59+
and enables --enable-libshine --enable-encoder=libshine. Fixed-point, so
60+
no float math dependency. The encoder is built into the archive; a module
61+
encode path (PCM->MP3) is a separate build mode.
62+
5463
comment "FFmpeg audio filters (libavfilter; need the avfilter-graph backend to run)"
5564

5665
config FFMPEG_FILTER_AFFTDN

src/audio/ffmpeg_dec/ffmpeg.cmake

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,74 @@ if(CONFIG_FFMPEG_DEC_COLD_SPLIT)
103103
${FFMPEG_INSTALL_DIR}/lib/libswresample.a)
104104
endif()
105105

106+
# --- 3b. MP3 encoder via libshine (fixed-point; FFmpeg has no native one) ---
107+
set(_ff_cfg_env "PATH=${_tc_dir}:$ENV{PATH}")
108+
set(_ff_shine_cfg "")
109+
set(_ff_shine_dep "")
110+
if(CONFIG_FFMPEG_ENC_MP3)
111+
set(SHINE_SRC "${sof_top_dir}/../modules/audio/shine")
112+
if(NOT EXISTS "${SHINE_SRC}/src/lib/layer3.h")
113+
message(FATAL_ERROR "ffmpeg_dec: libshine source not at '${SHINE_SRC}'; run 'west update'")
114+
endif()
115+
set(SHINE_INSTALL "${CMAKE_CURRENT_BINARY_DIR}/shine-install")
116+
file(MAKE_DIRECTORY "${SHINE_INSTALL}/lib/pkgconfig" "${SHINE_INSTALL}/include/shine")
117+
# pkg-config file for FFmpeg's require_pkg_config libshine.
118+
file(WRITE "${SHINE_INSTALL}/lib/pkgconfig/shine.pc"
119+
"prefix=${SHINE_INSTALL}
120+
libdir=\${prefix}/lib
121+
includedir=\${prefix}/include
122+
Name: shine
123+
Description: Shine fixed-point MP3 encoder
124+
Version: 3.1.1
125+
Libs: -L\${libdir} -lshine
126+
Cflags: -I\${includedir}
127+
")
128+
# FFmpeg's -lshine link *test* pulls newlib malloc -> Zephyr runtime syms
129+
# (z_errno_wrap, ...) that only exist at module load. Provide dummies so the
130+
# configure test links; --extra-ldflags only affects tests, not the .a build.
131+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/shine_cfgstub.c"
132+
"int z_errno_wrap(void){return 0;}
133+
void *stdout;
134+
int open(const char *p, int f, ...){return -1;}
135+
void *sbrk(int i){return (void *)-1;}
136+
")
137+
# libshine's lib needs no config.h; build the objects directly and archive
138+
# (its autotools CLI/shared link cannot work bare-metal).
139+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/shine-build.sh"
140+
"#!/bin/sh
141+
set -e
142+
export PATH=${_tc_dir}:\$PATH
143+
mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/shine-obj
144+
for f in ${SHINE_SRC}/src/lib/*.c; do
145+
${CMAKE_C_COMPILER} -O2 -fPIC -mtext-section-literals -DSHINE_HAVE_BSWAP_H \\
146+
-I${SHINE_SRC}/src/lib -c \"\$f\" \\
147+
-o ${CMAKE_CURRENT_BINARY_DIR}/shine-obj/\$(basename \"\$f\").o
148+
done
149+
${_ff_cross_prefix}ar rcs ${SHINE_INSTALL}/lib/libshine.a ${CMAKE_CURRENT_BINARY_DIR}/shine-obj/*.o
150+
cp ${SHINE_SRC}/src/lib/layer3.h ${SHINE_INSTALL}/include/shine/layer3.h
151+
${CMAKE_C_COMPILER} -fPIC -c ${CMAKE_CURRENT_BINARY_DIR}/shine_cfgstub.c \\
152+
-o ${CMAKE_CURRENT_BINARY_DIR}/shine_cfgstub.o
153+
")
154+
add_custom_command(
155+
OUTPUT "${SHINE_INSTALL}/lib/libshine.a" "${CMAKE_CURRENT_BINARY_DIR}/shine_cfgstub.o"
156+
COMMAND sh "${CMAKE_CURRENT_BINARY_DIR}/shine-build.sh"
157+
VERBATIM)
158+
add_custom_target(shine_ext DEPENDS "${SHINE_INSTALL}/lib/libshine.a")
159+
160+
set(_ff_cfg_env "PATH=${_tc_dir}:$ENV{PATH}" "PKG_CONFIG_PATH=${SHINE_INSTALL}/lib/pkgconfig")
161+
set(_ff_shine_cfg --enable-libshine --enable-encoder=libshine --pkg-config=pkg-config
162+
"--extra-ldflags=${CMAKE_CURRENT_BINARY_DIR}/shine_cfgstub.o")
163+
set(_ff_shine_dep shine_ext)
164+
message(STATUS "ffmpeg_dec: enabling MP3 encoder via libshine (${SHINE_SRC})")
165+
endif()
166+
106167
# --- 4. Configure + make + install (out-of-tree; source must be clean) ---
107168
ExternalProject_Add(ffmpeg_ext
169+
DEPENDS ${_ff_shine_dep}
108170
SOURCE_DIR "${SOF_FFMPEG_SRC_DIR}"
109171
BUILD_IN_SOURCE 0
110172
CONFIGURE_COMMAND
111-
${CMAKE_COMMAND} -E env "PATH=${_tc_dir}:$ENV{PATH}"
173+
${CMAKE_COMMAND} -E env ${_ff_cfg_env}
112174
<SOURCE_DIR>/configure
113175
--prefix=${FFMPEG_INSTALL_DIR}
114176
--enable-cross-compile --target-os=none --arch=xtensa
@@ -121,6 +183,7 @@ ExternalProject_Add(ffmpeg_ext
121183
--disable-runtime-cpudetect --disable-debug
122184
--enable-avcodec --enable-avutil --enable-swresample
123185
--enable-decoder=${_ff_dec_csv} --enable-parser=${_ff_par_csv}
186+
${_ff_shine_cfg}
124187
--enable-small --enable-pic
125188
"--extra-cflags=${_ff_extra_cflags}"
126189
BUILD_COMMAND

west.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ manifest:
1717
# the 'revision:' SHA below.
1818
- name: ffmpeg
1919
url-base: https://github.com/lgirdwood
20+
# libshine fixed-point MP3 encoder for FFMPEG_ENC_MP3 (upstream mirror).
21+
- name: shine
22+
url-base: https://github.com/toots
2023

2124
# When upgrading projects here please run git log --oneline in the
2225
# project and if not too long then include the output in your commit
@@ -57,6 +60,14 @@ manifest:
5760
revision: bc25d8d606e63c1ae8663fc0523adad908bc29e5
5861
remote: ffmpeg
5962

63+
# libshine: small fixed-point MP3 encoder for FFMPEG_ENC_MP3 (FFmpeg has no
64+
# native MP3 encoder). Cross-built by ffmpeg.cmake.
65+
- name: shine
66+
repo-path: shine
67+
path: modules/audio/shine
68+
revision: ab5e3526b64af1a2eaa43aa6f441a7312e013519
69+
remote: shine
70+
6071
- name: zephyr
6172
repo-path: zephyr
6273
revision: ef5cfd369f4a0ab3601db9a23c1da8c406cc1a72

0 commit comments

Comments
 (0)