1

I'm trying to use FFMPEG to crop a video using the Android NDK. I can successfully build ffmpeg, but I'm having problems with libavfilter. As soon as I include it in my LOCAL_SHARED_LIBRARIES in Android.mk, then I get this UnsatisfiedLinkError:

java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libavfilter.so" needed by "videocrop.so"; caused by cannot locate symbol "avcodec_find_best_pix_fmt_of_2" referenced by "libavfilter.so"...
        at java.lang.Runtime.loadLibrary(Runtime.java:371)
        at java.lang.System.loadLibrary(System.java:989)

(I'm trying to load my library in a static initializer on the Java side with System.loadLibrary).

The "avcodec_find_best_pix_fmt_of_2" function exists in libavcodec/avcodec.h, so I don't know why it can't locate it. The libavfilter.so file (as well as all the other libraries) seems to be building just fine and is located in the libs/ folder. I've tried editing the FFMPEG configuration and rebuilding, and also tried changing the the LOCAL_C_INCLUDES in Android.mk to include libavcodec's header files, but no luck with anything.

Here's my Android.mk for my module:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := videocrop
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := VideoCrop.c
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/../ffmpeg/ffmpeg/$(TARGET_ARCH)/include/libavcodec/
    LOCAL_SHARED_LIBRARIES := libavformat libavutil libavcodec libavfilter

    LOCAL_LDLIBS := -llog
    LOCAL_LDFLAGS +=-ljnigraphics

    include $(BUILD_SHARED_LIBRARY)

And here's my Android.mk for the ffmpeg libraries themselves, although its pretty straightforward:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libavfilter
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

LOCAL_PATH:= $(call my-dir)

I'm at wit's end. If anyone has any ideas it would be much appreciated.

gcgrant
  • 361
  • 5
  • 12
  • 1
    run `nm -D` to check that `avcodec_find_best_pix_fmt_of_2` is **`T`** in `ffmpeg/$(TARGET_ARCH_ABI)/lib/libavcodec.so`. It may be missing even if some **`.h`** file declares this function. – Alex Cohn Jan 17 '15 at 07:44
  • I'm on Mac, so there is no -D option, but running nm on libavcodec.so (or any of the built .so files) has no output. – gcgrant Jan 19 '15 at 16:43
  • You should use the **`nm`** from the relevant NDK toolchain, e.g. `/usr/local/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-nm`. And yes, it supports **`-D`**. – Alex Cohn Jan 19 '15 at 20:32
  • I have the same problem, and result running nm is (but how to solve it?): `U av_find_best_pix_fmt_of_2 U av_frame_set_best_effort_timestamp 000fa7ac T avcodec_find_best_pix_fmt2 000fa7a8 T avcodec_find_best_pix_fmt_of_2 000fa7b0 T avcodec_find_best_pix_fmt_of_list` – QZHua May 12 '16 at 07:28

1 Answers1

1

You need to load the libraries in reverse dependency order, e.g. like this:

System.loadLibrary("avutil");
System.loadLibrary("avcodec");
System.loadLibrary("avformat");
System.loadLibrary("swscale");
System.loadLibrary("avfilter");
System.loadLibrary("videocrop");

See e.g. this post for more details: Loading shared libs that depend on other shared libs

Community
  • 1
  • 1
mstorsjo
  • 12,983
  • 2
  • 39
  • 62
  • Unfortunately this didn't work either. This presents the same error, except at the line that loads "avfilter" instead of "videocrop". – gcgrant Jan 16 '15 at 20:00