我对ffmpeg的libavcodec函数的未解析引用有问题,到目前为止未能在其他地方找到答案(包括我的想法):)
让我描述一下我的设置 - 它需要空间,但实际上是基本的,可能是因为我没有看到一些错误......
我使用ndk r5工具链构建了一个FFMPeg,ffmpeg是我从http://bambuser.com/opensource获得的端口(在此处的其他问题中推荐)。它构建得很好,所以我在我的项目中放了几个静态库:
<project>/jni/bambuser_ffmpeg/libavcodec.a
<project>/jni/bambuser_ffmpeg/libavformat.a
<project>/jni/bambuser_ffmpeg/libavcore.a
<project>/jni/bambuser_ffmpeg/libavutil.a
接下来,我在bambuser_ffmpeg文件夹中创建了一个Android.mk,将这些库列为预建库:
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)
接下来,我有另一个模块在其Android.mk中引用这些库,设置包含路径等:
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)
最后我的ffmpeg_test.cpp非常基本,就像这样:
#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;
}
当我运行 ndk-build 时,它编译得很好,但是在链接时会打印出一个未解析的引用,几乎是 libavcodec 中的每个函数。看起来只有这个lib的功能无法找到:
/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...
我无法弄清楚为什么会这样。我尝试运行 ndk-build V = 1 来检查实际的链接命令,并且 libavcodec 完全正确地坐在那里,就像它应该的那样。所有其他ffmpeg库也都在那里。
任何提示?
答案 0 :(得分:5)
以下Android.mk适用于我,包括处理目标arch。运行bambuser build.sh的结果从... / build / ffmpeg复制到/ jni / lib / ffmpeg。 OP正在使用PREBUILD_SHARED_LIBRARY而不是PREBUILT_STATIC_LIBRARY。
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)
我还必须更改bambuser build.sh来修改--soname-prefix参数以包含我的包名而不是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"
答案 1 :(得分:2)
我一直在使用ffmpeg进行一些Android工作。我的构建有点不同。我从bambuser.com构建中获取了lib * .a文件和include目录,并直接将它们包含在我的jni目录中,我的Android.mk看起来像这样:
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)
那里可能有一些残骸,但也许它会帮助你找到正确的方向。我试着像你一样遵循NDK示例项目中列出的一些表单。将lib捆绑到一个模块然后引用它。但最终又回到简单的直接包括只是为了让事情有效,到目前为止还没有理由重新审视它。
答案 2 :(得分:0)
当你构建ffmpeg时应该使用android-14或更低版本,如下所示:
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