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:

  1. I modified fftools/ffmpeg.c by renaming main to int sm_engine_exec(int argc, char** argv).

  2. I am building FFmpeg with --enable-pic to ensure compatibility with an Android .so.

My JNI Implementation:

extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    // 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:

  1. Header Issues: When compiling the JNI wrapper, I get "file not found" errors for headers used within ffmpeg.c (like cmdutils.h) because they aren't in the standard include/ folder after make install.

  2. Linker Errors: Even when I fix the headers, the linker fails to find sm_engine_exec or its dependencies (like stdin_interaction, dec_free, term_init) because they reside in fftools/*.o, which aren't included in the standard .a libraries.

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:

  1. Correct Pathing: How should I structure my CMake/NDK build to include non-public headers from the fftools/ source directory?

  2. Bundling CLI Logic: Is there a standard way to force FFmpeg to output a libffmpeg_cli.a static library that encapsulates ffmpeg.c and its dependencies (ffmpeg_opt.c, ffmpeg_dec.c, etc.)?

  3. 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 all fftools/*.o objects?

  4. 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?

0
Apr 24 at 10:56 AM
User AvatarHARRSH BERMANN
#android#ffmpeg#android-ndk#android-ffmpeg

No answer found for this question yet.