Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFMpeg on Android, undefined references to libavcodec functions, although it is listed on command line

I have a problem with unresolved references to ffmpeg's libavcodec functions, so far failed to find the answer in other places (including my mind) :)

Let me describe my setup - it takes space, but is really basic, it might be that I'm failing to see some error...

I built an FFMPeg with ndk r5 toolchain, ffmpeg port I got from http://bambuser.com/opensource (as recommended in other questions here). It built fine, so I put several static libraries in my project like this:

<project>/jni/bambuser_ffmpeg/libavcodec.a
<project>/jni/bambuser_ffmpeg/libavformat.a
<project>/jni/bambuser_ffmpeg/libavcore.a
<project>/jni/bambuser_ffmpeg/libavutil.a

Next, I created an Android.mk in bambuser_ffmpeg folder to list these libs as a prebuilt ones:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavcore
LOCAL_SRC_FILES := libavcore.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavformat
LOCAL_SRC_FILES := libavformat.a
include $(PREBUILT_STATIC_LIBRARY)

(same for other two libs)

Next, I have another module which references these libs in its Android.mk, sets up include paths, etc:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpegtest
LOCAL_STATIC_LIBRARIES := bambuser-libavcodec bambuser-libavcore bambuser-libavformat bambuser-libavutil
LOCAL_SRC_FILES := ffmpeg_test.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../bambuser_ffmpeg/include
LOCAL_LDLIBS    := -llog -lz

include $(BUILD_SHARED_LIBRARY)

And finally I have my ffmpeg_test.cpp which is really basic, like this:

#include <jni.h>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}

extern "C" {
    JNIEXPORT jint JNICALL Java_com_the7art_ffmpegtest_PaintThread_testFFMpeg(JNIEnv* env, jobject obj, jstring fileName);
}

JNIEXPORT jint JNICALL Java_com_the7art_ffmpegtest_PaintThread_testFFMpeg(JNIEnv* env, jobject obj, jstring fileName)
{
    av_register_all();
    return 0;
}

When I run ndk-build, it compiles fine, but when linking it prints an unresolved reference to almost every function in libavcodec. Looks like only this lib's functions are failing to be located:

/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(allformats.o): In function `av_register_all':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/allformats.c:47: undefined reference to `avcodec_register_all'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `parse_frame_rate':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:3240: undefined reference to `av_parse_video_rate'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `parse_image_size':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:3234: undefined reference to `av_parse_video_size'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `flush_packet_queue':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:1277: undefined reference to `av_free_packet'
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:1283: undefined reference to `av_free_packet'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `get_audio_frame_size':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:766: undefined reference to `av_get_bits_per_sample'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `ff_interleave_add_packet':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:2909: undefined reference to `av_dup_packet'
and so on...

I fail to figure why this is happening. I tried running ndk-build V=1 to check the actual linking command, and libavcodec is sitting there perfectly right, like it should. All other ffmpeg libs are there too.

Any hints?

like image 946
dimsuz Avatar asked Mar 17 '11 10:03

dimsuz


2 Answers

The following Android.mk works for me, including handling the target arch. The result of running the bambuser build.sh is copied from .../build/ffmpeg to /jni/lib/ffmpeg. I'm using PREBUILD_SHARED_LIBRARY rather than PREBUILT_STATIC_LIBRARY as the OP did.

LOCAL_PATH := $(call my-dir)

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

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

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

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

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

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

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

include $(CLEAR_VARS)

LOCAL_MODULE    := mynativecode
LOCAL_SRC_FILES := native.c
LOCAL_SHARED_LIBRARIES := libavcore libavdevice libavfilter libavutil libswscale libavformat
LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib \
                -L$(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/lib \
                -lavcore \
                -lavformat \
                -lavcodec \
                -lavdevice \
                -lavfilter \
                -lavutil \
                -lswscale \
                -llog \
                -lz \
                -ldl \
                -lgcc

include $(BUILD_SHARED_LIBRARY)

I also had to change the bambuser build.sh to modify the --soname-prefix argument to include my package name rather than bambusers.

        FLAGS="--target-os=linux --cross-prefix=arm-linux-androideabi- --arch=arm"
        FLAGS="$FLAGS --sysroot=$SYSROOT"
-       FLAGS="$FLAGS --soname-prefix=/data/data/com.bambuser.broadcaster/lib/"
+       FLAGS="$FLAGS --soname-prefix=/data/data/<my package name here>/lib/"
        FLAGS="$FLAGS --enable-shared --disable-symver"
        FLAGS="$FLAGS --enable-small --optimization-flags=-O2"
like image 89
Fasaxc Avatar answered Oct 06 '22 05:10

Fasaxc


I've been using ffmpeg for some Android work too. I do my build a bit different though. I take the lib*.a files and the include dir from the bambuser.com build and just directly include them in my jni directory, my Android.mk looks like this:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ndk1
LOCAL_SRC_FILES := native.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -lavformat -lavcodec -lavdevice -lavfilter -lavutil -lswscale -llog -ljnigraphics -lz -ldl -lgcc

include $(BUILD_SHARED_LIBRARY)

There might be some cruft in there, but maybe it'll help point you in the right direction. I tried following some of the forms laid out in the NDK example projects like you have. Bundling up the libs into a module and then referencing that. But ended up falling back on the simple direct include just to get things working, and so far haven't had reason to revisit it.

like image 25
mikerowehl Avatar answered Oct 06 '22 03:10

mikerowehl