Android NDK和FFMPEG:findLibrary返回null

3
我正在使用这个链接来构建NDK上的FFmpeg: roman10的Android NDK r9d - FFmpeg教程 该链接显示了如何编译,但未清楚说明如何使用它。是否有人可以给我指导?谢谢。
在从我的项目根目录运行ndk-build之后,我能够在libs/armeabiobj/local/armeabi目录下生成.so文件。现在我遇到了findLibrary返回null的问题?现在该怎么办?
java.lang.UnsatisfiedLinkError: Couldn't load libavutil from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.palak.androidffmpegroman-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.palak.androidffmpegroman-2, /vendor/lib, /system/lib]]]: findLibrary returned null

        at java.lang.Runtime.loadLibrary(Runtime.java:358)
        at java.lang.System.loadLibrary(System.java:526)
        at com.palak.androidffmpegroman.MainActivity.<clinit>(MainActivity.java:175)
        at java.lang.Class.newInstanceImpl(Native Method)
        at java.lang.Class.newInstance(Class.java:1208)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2101)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
        at android.app.ActivityThread.access$800(ActivityThread.java:135)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
        at dalvik.system.NativeStart.main(Native Method)

我的项目结构:
我的build_android.sh文件:
  #!/bin/bash
NDK=$HOME/NDK/android-ndk-r10d
SYSROOT=$NDK/platforms/android-19/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86
function build_one
{
sudo ./configure \
    --prefix=$PREFIX \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU 
ADDI_CFLAGS="-marm"
build_one

我正在使用Ndk r10、ffmpeg 2.5.4和ubuntu x86进行操作。

编辑:Android.mk

LOCAL_PATH:= /home/palak/NDK/ffmpeg-2.5.4/android/arm

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

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

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

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

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

include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= lib/libswresample-1.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

在jni文件夹下的Android.mk:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := tutorial01
LOCAL_SRC_FILES := tutorial01.c
LOCAL_LDLIBS := -llog -ljnigraphics -lz 
LOCAL_SHARED_LIBRARIES := avformat avcodec swscale avutil

include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.5.4/android/arm)

我只期待像 LOCAL_MODULE:= libavutil 这样提到的模块出现为 .so 文件。你认为应该有一个 libffmpeg.so 吗? - weston
感谢您的到来,好的,那么您接下来该怎么做呢?我的意思是要把什么放在jni文件夹中,然后如何执行ndk-build命令?需要一些帮助。 - Palak Darji
能否帮我们一个大忙...请在编译或制作.so文件时制作一个教程视频。我已经卡了5天了,但没有得到结果...我成功地制作了.a文件,但没有制作.so文件...请帮帮我。 - Ahmad Arslan
我会在有空的时候去做它。 - Palak Darji
兄弟,你能让它工作了吗?我正在做完全相同的教程,现在遇到了完全相同的问题。 - bad_keypoints
显示剩余2条评论
4个回答

0
你确定你使用的手机具有 armeabi 处理器吗?在 Application.mk 文件中添加 armeabiv7,它将编译 libs 文件夹中适用于 armeabiv7 手机所需的文件。
APP_ABI := armeabi armeabi-v7a x86

这应该可以工作。


0

ndk-build期间,您使用名称libavutil来引用libavutil-54.so。这很好,但运行时库仍然被称为libavutil-54.so。此外,您的其他模块,包括tutorial01,也知道它的名称,因此在libs/armeabi中重命名它也是错误的。

您需要类似于:

static {
    System.loadLibrary("avutil-54");
    System.loadLibrary("avcodec-56");
    System.loadLibrary("avformat-56");
    System.loadLibrary("swscale-3");
    System.loadLibrary("tutorial01");
}

在最近的Android版本中,系统将自动解析本地外部引用,因此只需调用即可。
static {
    System.loadLibrary("tutorial01");
}

嘿,Alex,我设法编译和运行了我的项目...虽然我尝试了上面的解决方案,但实际上问题出在我的Android.mk文件上,现在已经解决了。对浪费你的时间感到抱歉。非常感谢。 - Palak Darji

0

替换你的

LOCAL_SHARED_LIBRARIES := avformat avcodec swscale avutil 

使用

LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libavfilter libswresample 

在您的Jni文件夹中的Android.mk文件中。

并像下面这样加载库

static {

  System.loadLibrary("avutil-54");
  System.loadLibrary("avcodec-56");
  System.loadLibrary("avformat-56");
  System.loadLibrary("swscale-3");
  System.loadLibrary("avfilter-5");
  System.loadLibrary("swresample-1");
  System.loadLibrary("tutorial01");

}

我之前尝试过那种方法,但并没有什么帮助。最终,我通过使用PREBUILT_SHARED_LIBRARY libffmpeg.so的方式成功运行了我的项目。感谢你的努力。 - Palak Darji
如果使用新的gradle-experimental插件进行NDK构建呢? - IgorGanapolsky

0
LOCAL_MODULE:= libavutil

-->

LOCAL_MODULE:= avutil # libavutil.so

示例(曾经有效): https://github.com/18446744073709551615/reDroid/blob/master/jni/Android.mk

更新:
再次强调:您不需要在库名称中添加lib前缀;
LOCAL_MODULE:= avutil 将为您提供libavutil.so

其次,您向loadLibrary()传递的参数是什么?同样,它应该是"avutil",对于libavutil.so

如果您遇到问题,最好的方法是从NDK中的hello-jni示例开始(your-ndk-dir/samples/hello-jni/

/* this is used to load the 'hello-jni' library on application
 * startup. The library has already been unpacked into
 * /data/data/com.example.hellojni/lib/libhello-jni.so <== !!!!!!!!!!!!!
 * at installation time by the package manager.
 */
static {
    System.loadLibrary("hello-jni");
}

一旦示例编译并运行,您可以将您的库添加到其中并使其正常工作。


这意味着找不到库文件。在apk中有吗?有时在apk中会有两个库,一个在lib/armeabi中,另一个只在lib/armeabi-v7a中。 - 18446744073709551615
@PalakDarji 共享库是否都已加载? - Ramesh
我已经编辑了我的问题。我在我的项目中看到了两个新目录:1)lib / armeabi下的所有.so文件,2)obj / local / armeabi下的所有.so文件。但我仍然收到错误消息:“findLibrary返回null”。 - Palak Darji
嗨,我已经使用了没有前缀和后缀的“avformat”。但是什么都没有帮助。这是我加载库的方式:在静态块中使用System.loadLibrary(“avutil”)。 - Palak Darji
然后从hello-jni开始。自然法则是所有复杂的工作系统都是较不复杂的工作系统的修改(而从损坏的系统中得出的系统永远不会)。从hello-jni开始,逐渐进行修改。 - 18446744073709551615
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接