FFmpeg: java.lang.UnsatisfiedLinkError while calli

2019-09-07 04:33发布

问题:

I need to take a picture file and an audio file and create a video. I know that it's possible to do with the help of

Runtime.getRuntime().exec("ffmpeg -i image.jpeg -i audio.mp3 out.avi") 

but only for rooted devices, so I've tried to create JNI wrapper for main() from ffmpeg.c and call it from my Activity like here: http://demo860.blogspot.com/2010/07/android-ffmpeg-dynamic-module-jni.html

1.This code is in ffmpeg.c :

int m_argc = 0;
char *m_pargv [30];

int dynamic_ffpmeg_main (int argc, char **argv);
jint JNICALL Java_com_ccmedia_codec_ffmpeg_mod_1run ( JNIEnv *, jclass, jstring,     jstring );

jint JNICALL Java_com_ccmedia_codec_ffmpeg_mod_1run ( JNIEnv *env, jclass class, jstring pj1, jstring pj2)
{
    // as in http://demo860.blogspot.com/2010/07/android-ffmpeg-dynamic-module-jni.html
}

int dynamic_ffpmeg_main(int argc, char **argv)
{
// as in http://demo860.blogspot.com/2010/07/android-ffmpeg-dynamic-module-jni.html
}

int main(int argc, char **argv)
{
    dynamic_ffpmeg_main ( argc, argv );
    return 0;
}

2.This code is in my .java:

public class FFmpegCreator implements Runnable {

    static boolean m_bret = false;
static String m_szconfig = " -i /sdcard/file.mpg -vcodec mpeg4 aaa.mpg";

//public native String unimplementedStringFromJNI();

static {
    try {

        System.out.println("[AdDBCache] Module load try ffmpeg : "
                + System.getProperty("java.library.path"));

        // System.load("/sdcard/arm_and/bin/libffmpeg.so");

        System.loadLibrary("ffmpeg");

        System.out.println("[AdDBCache] Module load success");

    }

    catch (Exception e) {

        System.out.println("[AdDBCache] Module load err : "
                + System.getProperty("java.library.path"));

    }

}

private static synchronized final native int Java_com_ccmedia_codec_ffmpeg_mod_1run(String name, String sztoken);

public void set_config(String sz_config) {

    m_szconfig = sz_config;

}

public void run_core(String sz_file, String sz_token) {

    int n_stat;
    m_bret = false;
    n_stat = Java_com_ccmedia_codec_ffmpeg_mod_1run(m_szconfig, sz_token);
    m_bret = true;

}

public void run() {

    run_core("", "");

}
}

3.And this in my Activity:

FFmpegCreator f = new FFmpegCreator ();
new Thread(f).start();

But I have

E/AndroidRuntime(25682): java.lang.UnsatisfiedLinkError: Java_com_ccmedia_codec_ffmpeg_mod_1run .

And I can't understand why... FFmpeg build was successful... Could anyone help me, please? I'll really appreciate if you could help me. Thank you.

回答1:

The problem is the naming of the native method Java_com_ccmedia_codec_ffmpeg_mod_1run on the Java side. You should just give it a normal method name, without all of the Java_package... parts. Then to match this to a C function you need to use the package and class that the method belongs. The most fool-proof way to do this is to update the Java side first:

public class FFmpegCreator implements Runnable {
    // ...

    private static synchronized final native int mod_1run(String name, String sztoken);

    //...
}

and then run javah on the class:

$ javah -o FFmpegCreator.h -classpath bin/classes com.yourpackage.FFmpegCreator

(replace bin/classes with the directory where your .class files are compiled, and com.yourpackage with the package that FFmpegCreator is within). If you look at the FFmpegCreator.h it generates it will include the correct signature for your native method.