基于移动平台的多媒体框架——移植播放器到Android上
今天很成功地将我们自己开发的基于ffmpeg播放器移植到了Android上,并且在tablet上面测试成功。按照本文提供的思路,可以移植所有基于ffmpeg的播放器到Android上。
准备工作:
需要的两个库,ffmpeg和SDL,其编译方法在前文中都有叙述。
在开发时,需要把这两个编译好的库文件:libffmpeg.so和libSDL.so放入<ndk-path>/platforms/android-8/arch-arm/usr/lib/下面;在调试和运行时,需要用adb push到Android的/system/lib/下面。
本文示例的播放器下载地址是https://github.com/pkuembedded/TVplayer。这个播放器是我们实验室自己开发的,目前尚不完善在不断更新中,但是基本的播放功能都有了。读者可以根据自己的兴趣按照本文思路移植其他功能强大的开源播放器,包括自己开发的播放器。
第一步:eclipse中新建一个Android工程。
为了与PC Linux版的TVplayer区分,该工程名为TVplayer_Android。包名为com.player,类名为TVplayer。
新建工程时,要选择和编译ffmpeg和SDL一致的Android的版本以及ndk、sdk版本。
第二步:将待移植的播放器导入该工程。
在TVplayer_Android目录下新建jni/src.将TVplayer下的src中所有c文件与h文件复制到TVplayer_Android/jni/src中,以准备用NDK编译。
新建TVplayer_Android/jni/Android.mk。内容为:
LOCAL_PATH := $(call my-dir)/src
include $(CLEAR_VARS)
LOCAL_MODULE := TVplayer
LOCAL_SRC_FILES := \
audio.c \
display.c \
file.c \
queue.c \
sync.c \
TVplayer.c \
video.c
LOCAL_C_INCLUDES += /home/baby/workspace/SDL-1.3.0-6050/include/
LOCAL_C_INCLUDES += /home/baby/workspace/avs/ffmpeg-0.8.7/
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lffmpeg -lSDL -llog
include $(BUILD_SHARED_LIBRARY)
其中:
LOCAL_SRC_FILES开头的一行后面加入需要编译的源文件。
LOCAL_C_INCLUDES开头的两行用来包含c库的头文件,将你的ffmpeg和SDL的头文件目录加在此处。
LOCAL_LDLIBS开头的一行中,加-llog便于调试。
第三步:实现java类。
为了让Android支持SDL,需要SDL源文件中的SDLActivity.java文件。将SDLActivity.java复制到与我们自己的TVplayer.java同级目录。
修改TVplayer.java为:
public class TVplayer extends SDLActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
这里采用的方法是用自己的类继承SDLActivity类,在onCreate方法中调用父类方法。简单起见也可以直接把SDLActivity类改名为TVplayer,为了以后方面添加其他类而不至于太臃肿,没有采用这种方法。SDLActivity.java要稍作修改:将原来的System.loadLibrary函数全部注释,然后在原位置添加一句System.loadLibrary("TVplayer");结果如下:
static {
//System.loadLibrary("SDL");
//System.loadLibrary("SDL_image");
//System.loadLibrary("SDL_mixer");
//System.loadLibrary("SDL_ttf");
//System.loadLibrary("main");
System.loadLibrary("TVplayer");
}
第四步:修改c文件。 www.zzzyk.com
TVplayer_Android/jni/src/TVplayer.c文件也要修改:
实现java中的native函数,如下:
void Java_com_player_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj){
/* This inte易做图ce could expand with ABI negotiation, calbacks, etc. */
SDL_Android_Init(env, cls);
/* Run the application code! */
int status;
char *argv[2];
argv[0] = strdup("SDL_app");
argv[1] = NULL;
//status = main(1, argv);
status = main(2, argv);
/* We exit here for consistency with other platforms. */
exit(status);
// Java_org_libsdl_app_SDLActivity_nativeInit(env, cls, obj);
}
void Java_com_player_SDLActivity_nativeQuit(JNIEnv* env, jclass cls, jobject obj){
Java_org_libsdl_app_SDLActivity_nativeQuit(env, cls, obj);
}
void Java_com_player_SDLActivity_onNativeResize(JNIEnv* env, jclass cls, jobject obj, int x, int y, int format){
Java_org_libsdl_app_SDLActivity_onNativeResize(env, cls, obj, x, y, format);
}
void Java_com_player_SDLActivity_onNativeAccel(JNIEnv* env, jclass cls, jobject obj, float x, float y, float z){
Java_org_libsdl_app_SDLActivity_onNativeAccel(env, cls, obj, x, y, z);
}
实现方法其实就是调用SDL原来的实现方法。如果你运行过上一篇的移植SDL的例子,了解整个流程,就可以在SDL中找到这些相应的函数。
添加完这些函数之后,java就会调用SDL为Android设计的初始化方法,就可以把原来main函数中调用的SDL_Init函数删去了。
第五步:编译运行:
首先在工程目录下ndk-build,生成libTVplayer.so。
然后在eclipse中编译运行。
摘自 BABY的专栏
补充:移动开发 , Android ,