Linking FFmpeg 8.1 CLI into an Android NDK Shared Library: Header Resolution and Symbol Errors
I am attempting to build a custom video processing engine for Android using FFmpeg 8.1. Instead of re-implementing the muxing logic using libavformat/libavcodec APIs, I want to “library-ify” the FFmpeg CLI tool and call it via JNI also I am intentionally avoiding ffmpeg-kit to keep the binary minimal.
I have successfully cross-compiled FFmpeg on a macOS (M5 chip) for arm64-v8a (NDK r28), targeting API 24.
The Strategy:
-
I modified
fftools/ffmpeg.cby renamingmaintoint sm_engine_exec(int argc, char** argv). -
I am building FFmpeg with
--enable-picto ensure compatibility with an Android.so.
My JNI Implementation:
extern "C" {
#include
#include
// My custom prototype from fftools/ffmpeg.c
int sm_engine_exec(int argc, char** argv);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_harrshbermann_SocialMate_google_logEvent2(JNIEnv *env, jobject thiz, jstring video_path, jstring audio_path, jstring out_path) {
const char *v_path = env->GetStringUTFChars(video_path, nullptr);
const char *a_path = env->GetStringUTFChars(audio_path, nullptr);
const char *o_path = env->GetStringUTFChars(out_path, nullptr);
const char *argv[] = { "ffmpeg", "-i", v_path, "-i", a_path, "-c", "copy", "-map", "0:v:0", "-map", "1:a:0", "-shortest", "-y", o_path, NULL };
int argc = 14;
int result = sm_engine_exec(argc, (char**)argv);
// Release strings...
return result;
}
The Problem:
-
Header Issues: When compiling the JNI wrapper, I get “file not found” errors for headers used within
ffmpeg.c(likecmdutils.h) because they aren’t in the standardinclude/folder aftermake install. -
Linker Errors: Even when I fix the headers, the linker fails to find
sm_engine_execor its dependencies (likestdin_interaction,dec_free,term_init) because they reside infftools/*.o, which aren’t included in the standard.alibraries.
My Build Configuration:
./configure \
--prefix=$OUTPUT \
--target-os=android \
--arch=aarch64 \
--cpu=armv8-a \
--enable-cross-compile \
--sysroot=$TOOLCHAIN/sysroot \
--cc=$CC \
--cxx=$CXX \
--ar=$AR \
--ranlib=$RANLIB \
--nm=$NM \
--strip=$STRIP \
--extra-cflags="-fPIC -fPIE" \
--extra-ldflags="-fPIC -fPIE" \
--enable-static \
--disable-shared \
--enable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-debug \
--disable-programs \
--enable-small
Questions:
-
Correct Pathing: How should I structure my CMake/NDK build to include non-public headers from the
fftools/source directory? -
Bundling CLI Logic: Is there a standard way to force FFmpeg to output a
libffmpeg_cli.astatic library that encapsulatesffmpeg.cand its dependencies (ffmpeg_opt.c,ffmpeg_dec.c, etc.)? -
FFmpeg-Kit Internals: How does
ffmpeg-kit(or similar projects) successfully wrap the CLI into a shared library? Do they manually create a static archive of allfftools/*.oobjects? -
CLI via .so: Is it architecturally sound to use FFmpeg’s CLI code as a static library within an Android
.so, or are there hidden pitfalls with global state/threading?
Read more here: Source link
