10

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 functionget_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?


  • Is there any chance your code is going to be released open-sourced? Or could you just help me by providing a very basic structure (i.e. where to put the .so or .a files, how to call it in the Android app)? I tried both your original procedure and the answer below, but neither worked. Thanks for any hints! - slhck
  • @slhck Maybe I could email you my Android.mk's and zipped dir, though it's not very complex there, write me to dimsuz at gmail com. As an alternative I guess you could just ask a specific question here, describe your problem, maybe someone will find a solution :) - dimsuz

3 답변


2

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.


  • That worked just fine, thank you very much! :) - dimsuz
  • What I also found is the misterious phrase "NDK does not support combining static libraries", but I'm not sure what it means - in the end static libraries are just collections of object files, so if i specify them on command line, they should be linked all together in the specified order. That was the case, but it didn't work for some reason. Maybe i don't know some detail :) - dimsuz
  • Eh, now another thing. av_open_input_file returns -2 (no such file or directory) when I try to open a file from /sdcard/myfile.mp4 (it surely exists, i have permissions in androidmanifest.xml, etc). Did you have such issue maybe, know the solution? :) - dimsuz
  • Actually, yes. If you're using the defaults from the bambuser.com build they have the file protocol turned off. I have that turned on in the version I've been using, and I refer to the file as 'file:/sdcard/myfile.mp4' in my code. - mikerowehl
  • oh, thanks much! I guess I'll recompile with file protocol enabled and try again. I guess it would take a lot of time to find this out without your hint, thanks! :) - dimsuz

5

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"


  • Thank you! Did you manage to get it play something? :) Because after I compiled it, I fail to play anything (see my last comment to the answer above) - dimsuz
  • Yes. I had to enable the file protocol and the codec/demuxer that my file was using. Bambuser's config disables all but the couple of codecs that they use. - Fasaxc
  • Aha. I suspect that this might be my problem. I tried to enable mp4 codec and open mp4 file, but it won't open. I started to think that maybe I need to enable some more codecs maybe even try to enable all of them :) Did you enable only specific ones or all? - dimsuz
  • I just enabled the ones I needed. You'll need the file protocol along with the 264 demuxer and the 264 decoder and maybe a couple of other things by trial and error. Do ./configure --help and then try the --list-xyz options to find out what's available. - Fasaxc
  • Which my package name?! I don't have any android project yet! I just want to compile ffmpeg for ARM! It's ok in ubuntu, but in windows I get this error: "Unknown option "--soname-prefix=/data/data/com.bambuser.broadcaster/lib/"" - Dr.jacky

0

when you build ffmpeg should use android-14 or lower,like this:

export NDK=/Users/luoye/Downloads/android-ndk-r11c
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-8/arch-arm
export PREFIX=../simplefflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe
--disable-ffplay
--disable-ffmpeg
--disable-ffserver
--disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -         Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" 
}

build_one

make
make install

Linked


Latest