UnsatisfiedLInkError Linking to FFMPEG with NDK
Asked Answered
R

1

7

I compiled FFMPEG for android using bambuser's files. The compile runs fine. No errors. I also made sure to change the package name in build.sh. However, once I try to link to the files, the phone throws an UnsatisfiedLinkError. This is the Androkd.mk file:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
MY_LIB_PATH := ffmpeg-android/build/ffmpeg/armeabi/lib
LOCAL_MODULE := bambuser-libavcore
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavcore.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavformat
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavformat.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavcodec
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavcodec.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavdevice
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavdevice.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavfilter
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavfilter.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavutil
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libavutil.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libswscale
LOCAL_SRC_FILES := $(MY_LIB_PATH)/libswscale.so
include $(PREBUILT_SHARED_LIBRARY)


#local_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libtest_jni
LOCAL_SRC_FILES := libtest/video.c

LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
        $(LOCAL_PATH)/ffmpeg-android/ffmpeg 
        LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -L$(LOCAL_PATH)/ffmpeg-android/build/ffmpeg/armeabi/lib/ -lavformat -lavcodec -lavdevice -lavfilter -lavutil -lswscale -llog -lz -lm
        #dl -lgcc

        include $(BUILD_SHARED_LIBRARY)

Video.c is dead simple:

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

#include <jni.h>  
#include <string.h>  
#include <stdio.h>
#include <android/log.h>  

void Java_com_bukabros_videolivewallpaper_Opengl2Renderer_loadNthFrame3
       (JNIEnv * env, jobject this, jstring fileName)  {

       jboolean isCopy;  
         const char * szLogThis = (*env)->GetStringUTFChars(env, fileName, &isCopy);  

          __android_log_print(ANDROID_LOG_DEBUG, "NDK: ", "NDK:LC: [%s]", szLogThis); 
          }   

Tne corresponding Java code is also simple:

 private native void loadNthFrame3(String fileName);

 static {  
System.loadLibrary("libtest_jni");  
 }  

But I get this error:

E/AndroidRuntime(11489): FATAL EXCEPTION: main

E/AndroidRuntime(11489): java.lang.ExceptionInInitializerError

E/AndroidRuntime(11489):    at com.bukabros.videolivewallpaper.VideoLiveWallpaper$CubeEngine.<init>(VideoLiveWallpaper.java:147)

E/AndroidRuntime(11489):    at com.bukabros.videolivewallpaper.VideoLiveWallpaper.onCreateEngine(VideoLiveWallpaper.java:120)

E/AndroidRuntime(11489):    at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:814)

E/AndroidRuntime(11489):    at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:61)

E/AndroidRuntime(11489):    at android.os.Handler.dispatchMessage(Handler.java:99)

E/AndroidRuntime(11489):    at android.os.Looper.loop(Looper.java:123)

E/AndroidRuntime(11489):    at android.app.ActivityThread.main(ActivityThread.java:4627)

E/AndroidRuntime(11489):    at java.lang.reflect.Method.invokeNative(Native Method)

E/AndroidRuntime(11489):    at java.lang.reflect.Method.invoke(Method.java:521)

E/AndroidRuntime(11489):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)

E/AndroidRuntime(11489):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)

E/AndroidRuntime(11489):    at dalvik.system.NativeStart.main(Native Method)

E/AndroidRuntime(11489): Caused by: java.lang.UnsatisfiedLinkError: Library libtest_jni not found

E/AndroidRuntime(11489):    at java.lang.Runtime.loadLibrary(Runtime.java:461)

E/AndroidRuntime(11489):    at java.lang.System.loadLibrary(System.java:557)

E/AndroidRuntime(11489):    at com.bukabros.videolivewallpaper.Opengl2Renderer.<clinit>(Opengl2Renderer.java:389)

E/AndroidRuntime(11489):    ... 12 more

I tried manually loading the prebuilt shared libraries (the bambuser files) in Java (using System.loadLibrary) but then it tells me that the files are not found.

If it helps, here's the output of readelf:

 0x00000001 (NEEDED)                     Shared library: [libc.so]
  0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
   0x00000001 (NEEDED)                     Shared library: [libm.so]
    0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libavformat.so]
     0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libavcodec.so]
      0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libavdevice.so]
       0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libavfilter.so]
        0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libavutil.so]
     0x00000001 (NEEDED)                     Shared library: [/data/data/com.bukabros.videolivewallpaper/lib/libswscale.so]
      0x00000001 (NEEDED)                     Shared library: [liblog.so]
       0x00000001 (NEEDED)                     Shared library: [libz.so]
        0x00000001 (NEEDED)                     Shared library: [libdl.so]
         0x0000000e (SONAME)                     Library soname: [libtest_jni.so]
          0x00000010 (SYMBOLIC)                   0x0
           0x00000004 (HASH)                       0xd4
            0x00000005 (STRTAB)                     0x250
         0x00000006 (SYMTAB)                     0x130
          0x0000000a (STRSZ)                      712 (bytes)
           0x0000000b (SYMENT)                     16 (bytes)
            0x00000003 (PLTGOT)                     0x174c
             0x00000002 (PLTRELSZ)                   32 (bytes)
              0x00000014 (PLTREL)                     REL
               0x00000017 (JMPREL)                     0x55c
                0x6ffffffe (VERNEED)                    0x53c
             0x6fffffff (VERNEEDNUM)                 1
              0x6ffffff0 (VERSYM)                     0x518
               0x00000000 (NULL)                       0x0

Oh yeah. I'm using ndk r5.

Radiotherapy answered 8/6, 2011 at 4:33 Comment(1)
thx for posting your Androkd.mk it was very useful!Drifter
R
14

Looks like I found the answer. The problem is that when you load the library in Java (System.loadLibrary), you can NOT use the "lib" prefix. I also had to manually load the ffmpeg libraries in Java. The moral of the story is that you should always read the docs and don't give up:-) Here's the correct code:

 static {  
System.loadLibrary("avcore");
System.loadLibrary("avformat");
System.loadLibrary("avcodec");
System.loadLibrary("avdevice");
System.loadLibrary("avfilter");
System.loadLibrary("avutil");
System.loadLibrary("swscale");
System.loadLibrary("test_jni");  
 }  
Radiotherapy answered 8/6, 2011 at 17:32 Comment(1)
Very useful! Need to inform other, for the System.loadLibrary("test_jni"); You need to check your last local_module which name you set it to video.c for example like this LOCAL_MODULE := libtest_jni LOCAL_SRC_FILES := libtest/video.c *** if you set it like this like this LOCAL_MODULE := video LOCAL_SRC_FILES := libtest/video.c then you need to use System.loadLibrary("video");Superpatriot

© 2022 - 2024 — McMap. All rights reserved.