需要的两个库,ffmpeg和SDL,其编译方法在前文中都有叙述。
在开发时,需要把这两个编译好的库文件:libffmpeg.so和libSDL.so放入<ndk-path>/platforms/android-8/arch-arm/usr/lib/下面;在调试和运行时,需要用adb push到Android的/system/lib/下面。
(本文所述的项目版本有所出入,并且很长时间没有维护过。再次强烈推荐各位只是当作参考,领略大意。建议用vlc官方的android版本进行尝试,与本文思想相同,却可以省掉很多不必要的麻烦。)
本文示例的播放器下载地址是 https://github.com/pkuembedded/TVplayer。这个播放器是我们实验室自己开发的,目前尚不完善在不断更新中,但是基本的播放功能都有了。读者可以根据自己的兴趣按照本文思路移植其他功能强大的开源播放器,包括自己开发的播放器。新建工程时,要选择和编译ffmpeg和SDL一致的Android的版本以及ndk、sdk版本。
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)其中:
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"); }
void Java_com_player_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj){ /* This interface 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函数删去了。