2

I'm building ffmpeg following the same pattern as halfninja's build: make the ffmpeg's main available from Java through JNI. I built ffmpeg with the following options:

./configure \
    --prefix=$PREFIX \
    --disable-shared \
    --enable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-doc \
    --disable-symver \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS"

$PREFIX, TOOLCHAIN, … being set to corresponding folders from my NDK. $ADDI_CFLAGS is set to -marm and $ADDI_LDFLAGS and $ADDITIONAL_CONFIGURE_FLAGS are both unset. The resulting static libraries are created:

$ ls -1 android/arm/lib/
libavcodec.a
libavdevice.a
libavfilter.a
libavformat.a
libavutil.a
libswresample.a
libswscale.a
pkgconfig

I expose them with an Android.mk file, ffmpeg being built in $NDK/sources/ffmpeg-2.1.1:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= lib/libavdevice.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE:= libwsresample
LOCAL_SRC_FILES:= lib/libswresample.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

So, up to there, everything looks good. Now, I try to build the ffmpeg binary equivalent as a static library. I copied (and didn't change a single character for now) ffmpeg.c, ffmpeg.h, cmdutils.c, cmdutils.h, ffmpeg_opt.cand ffmpeg_filter.c in my jni folder. I also have two directly JNI-related files in this folder (copied from halfninja's build, I just changed the package name). Here's the relevant Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1
LOCAL_CFLAGS := -Wdeprecated-declarations
LOCAL_MODULE := videokit
ANDROID_LIB := -landroid
LOCAL_LDLIBS += -llog -ljnigraphics -lz 
LOCAL_SRC_FILES := videokit/com_rfc_video_ffmpeg_Videokit.c videokit/ffmpeg.c videokit/cmdutils.c videokit/ffmpeg_opt.c videokit/ffmpeg_filter.c
LOCAL_SHARED_LIBRARIES := libavdevice libavformat libavfilter libavcodec libwscale libavutil libswresample libswscale libpostproc
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.1.1/android/arm)

Everything compiles fine, but doesn't link. Here are the first errors:

[armeabi] SharedLibrary  : libvideokit.so
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063: error: undefined reference to 'swresample_version'
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063: error: undefined reference to 'swresample_configuration'
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:558: error: undefined reference to 'swr_get_class'
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:561: error: undefined reference to 'swr_alloc'
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:563: error: undefined reference to 'swr_free'
/Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/ffmpeg_opt.o: in function show_help_default:jni/videokit/ffmpeg_opt.c:2464: error: undefined reference to 'swr_get_class'

What I don't understand is that these functions are defined and available in libswresample.a, which I'm linking to:

arm-linux-androideabi-nm /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1/android/arm/lib/libswresample.a  | grep -i -e swr_get_class -e swresample_version
000001d4 T swr_get_class
00000178 T swresample_version

What am I doing wrong? Is there another, maybe simpler way to expose ffmpeg as a static library available via JNI? (I don't use halfninja's because I need at least ffmpeg 1.1, while his is in 0.9).

Marc Plano-Lesay
  • 6,808
  • 10
  • 44
  • 75

1 Answers1

3

Your names got a bit scrambled: in one place, you called it libwsresample, elsewhere libswresample.

Check all names for consistency.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Nice catch, thanks! I left work for now, will keep you up to date tomorrow. – Marc Plano-Lesay Dec 02 '13 at 18:02
  • 1
    Actually, thank you for a clear description of up-to-date build procedure, people have been looking for this, e.g. http://stackoverflow.com/questions/20194696/how-to-use-android-ndk-r9b-to-compile-ffmpeg-for-android – Alex Cohn Dec 03 '13 at 19:14
  • 1
    Just for completion: here's a complete how-to I wrote to get latest FFmpeg release working on Android. https://enoent.fr/blog/2014/06/20/compile-ffmpeg-for-android/ – Marc Plano-Lesay Jun 20 '14 at 08:47
  • @AlexCohn Could you look at http://stackoverflow.com/questions/27519462/ndk-undefined-reference-error-can-not-create-shared-library – support_ms Dec 17 '14 at 06:55