안녕하세요.
현재 ffmpeg 을 ndk를 이용해 빌드해서 ffmpeg.so 라이브러리 파일을 만드는 데 까지는 성공 했습니다.
만들어진 ffmpeg.so 을 이용하기 위해 아래와 같이 jni wrapper를 추가 했습니다.
문제는 java 소스에서 만들어진 테스트를 위해 만든 jni 함수(stringFromJNI())를 호출 하면
"The application *** has stopped unexpectedly" 창이 뜨기만 하고 제대로 동작을 안 하네요.
이전에 빌드 할때도 고생했는데, 지금 이문제도 일주일째 고생 중입니다.
어떤 해결 방법이라도 좋으니, 한줄의 멘트라도 부탁드립니다. ㅜㅜ;
제가 작성한 소스는 아래와 같습니다.
** SDK JAVA Source : ffmpegTest.java, ffmpegRun.java
(1) ffmpegTest.java
package com.ndk.ffmpeg;
import android.app.Activity;
public class ffmpegTest extends Activity {
// Native
ffmpegRun nativeLib;
String szconfig = " -i /sdcard/file.mpg -vcodec mpeg4 aaa.mpg";
String szreturn = "";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
// Native
nativeLib = new ffmpegRun();
szreturn = nativeLib.set_config(szconfig);
TextView tv = new TextView(this);
tv.setText( nativeLib.stringFromJNI( )); //문제 부분
//tv.setText( szreturn );
setContentView(tv);
}
}
(2) ffmpegRun.java
package com.ndk.ffmpeg;
public class ffmpegRun implements Runnable {
static boolean m_bret = false;
static String m_szconfig = " -i /sdcard/file.mpg -vcodec mpeg4 aaa.mpg";
public native String stringFromJNI();
public native String unimplementedStringFromJNI();
private static synchronized final native int mod_1run (String name, String sztoken);
static{
try {
System.out.println ( "[AdDBCache] Module load try ffmpeg : " + System.getProperty("java.library.path"));
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"));
}
}
public String set_config ( String sz_config ) {
m_szconfig = sz_config + "ffmpegRun";
return m_szconfig;
}
public void run_core ( String sz_file, String sz_token ) {
int n_stat;
m_bret = false;
n_stat = mod_1run ( m_szconfig, sz_token );
m_bret = true;
}
public void run () {
run_core ( "", "");
}
}
** NDK C Source : ffmpeg.c
(1) ffmpeg.c
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_ndk_ffmpeg_ffmpegRun_stringFromJNI (JNIEnv *, jobject);
JNIEXPORT jstring JNICALL Java_com_ndk_ffmpeg_ffmpegRun_unimplementedStringFromJNI (JNIEnv *, jobject);
JNIEXPORT jint JNICALL Java_com_ndk_ffmpeg_ffmpegRun_mod_1run (JNIEnv *, jclass, jstring, jstring);
#ifdef __cplusplus
}
#endif //__cplusplus
int m_argc = 0;
int M_MAX_ARGC = 30;
char *m_pargv [30];
int dynamic_ffpmeg_main (int argc, char **argv);
JNIEXPORT jstring JNICALL Java_com_ndk_ffmpeg_ffmpegRun_stringFromJNI (JNIEnv *env, jobject obj)
{
return (*env)->NewStringUTF(env, "Hello JNI from real ffmpeg!");
}
JNIEXPORT jstring JNICALL Java_com_ndk_ffmpeg_ffmpegRun_unimplementedStringFromJNI(JNIEnv *env, jobject obj)
{
return (*env)->NewStringUTF(env, "Bye JNI from real ffmpeg!");
}
JNIEXPORT jint JNICALL Java_com_ndk_ffmpeg_ffmpegRun_mod_1run(JNIEnv *env, jclass clazz, jstring pj1, jstring pj2)
{
jint ji;
jboolean ic;
char sz_temp [1024];
char seps [] = " ";
char *psztoken, *pszdata;
int i = 0;
const char *pszname;
pszname = (*env)->GetStringUTFChars(env, pj1, &ic);
sprintf ( sz_temp, "ffmpeg %s ", pszname );
if ( ic == JNI_TRUE ) (*env)->ReleaseStringUTFChars(env, pj1, pszname);
printf ( "[DEBUG] %s\n", sz_temp );
psztoken = strtok ( sz_temp, seps );
while ( psztoken != NULL ) {
m_pargv [ m_argc] = ( char *)malloc ( strlen ( psztoken));
strcpy ( m_pargv [ m_argc], psztoken );
m_argc++;
psztoken = strtok ( NULL, seps);
}
for ( i = 0; i < m_argc; i++ ) {
printf ( "argc[%d] = %s\n", i, m_pargv[i]);
}
dynamic_ffpmeg_main ( m_argc, m_pargv );
ji = 0;
return ji;
}
안녕하세요~ 그냥가자님~
ffmpeg 관련 질문에 답변 많이 해 주신분이시죠? 넘 반갑습니다~ ^^*
일단 말씀 해 주신 2가지 중 클린 후 리빌드 해 보았는데욤. 증상이 같습니다.
extern ''C"는 ffmpeg.c 윗부분에 있었는데 제가 여기에 누락 시켜서 다시 추가 했습니다.
혹시 ffmpeg.so 빌드 옵션이나 빌드 시의 문제가 아닐까 하는데...도체 알 수 있는 방법이 없어서요.
jni wrapper 가 제대로 동작 하는지는 확인 하기 위해서 임의로 ffmpeg.c를 만들어 Java_com_ndk_ffmpeg_ffmpegRun_stringFromJNI() 함수만 추가해서 .so 파일을 생성 후 호출 했을 때는 제대로 동작하는데요, 진짜 ffmpeg.c에 위에처럼 추가해서 .so 파일을 만들면 위의 증상과 같네요..ㅜㅜ 제가 잘 못 한 부분이 어디일까요?...




NDK를 하실때는 안드로이드 프로젝트를 항상 클린후 리빌드 하세요... 가끔 못찾는경우 있답니다.
수동빌드 추천....
설마 CPP로 빌드하신건 아니겠죠... extern "C"로 메소드 선언을 감싸두는게 보험입니다.