dimsuz dimsuz - 6 months ago 78
Android Question

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?

Answer

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.

Comments