最近的项目中用到了视频播放及录像功能,因而下了一个vlc4android编译。这一纪录一下编译环境配置和编译过程中遇到的问题。
1.环境配置
debian3.2.4 amd64
android-sdk-linux ( 22.6)
android-ndk-r9d
具体过程见:
https://wiki.videolan.org/AndroidCompile/
2.编译过程出现的问题
2.1
(cd speex-git && patch -fp1) < ../../contrib/src/speex/no-ogg.patch
patching file configure.ac
Hunk #1 FAILED at 112.
1 out of 1 hunk FAILED -- saving rejects to file configure.ac.rej
patching file libspeex/Makefile.am
Hunk #1 FAILED at 11.
1 out of 1 hunk FAILED -- saving rejects to file libspeex/Makefile.am.rej
patching file src/Makefile.am
Hunk #1 FAILED at 11.
Hunk #2 FAILED at 24.
2 out of 2 hunks FAILED -- saving rejects to file src/Makefile.am.rej
make: *** [speex] Error 1
解决方法:在该网站http://downloads.videolan.org/contrib/ 下载speex-git.tar.gz放在vlc/contrib/tarballs目录下覆盖掉原来的speex-git.tar.gz文件。
2.2
make[3]: Leaving directory `/home/wxx/newvlc/android/vlc/contrib/android/gmp/mpn'
make[2]: *** [install-recursive] Error 1
make[2]: Leaving directory `/home/wxx/newvlc/android/vlc/contrib/android/gmp'
make[1]: *** [install] Error 2
make[1]: Leaving directory `/home/wxx/newvlc/android/vlc/contrib/android/gmp'
tmp-udiv.s: Assembler messages:
tmp-udiv.s:85: Error: ARM register expected -- `str r1,[ r0 ]'
tmp-udiv.s:136: Error: ARM register expected -- `str r1,[ r0 ]'
上面这两个错误致错原因是一样的,解决方法:
将下面这个patch文件放在vlc/contrib/android/gmp目录下,例如保存命名为ggmp.diff
--- a/mpn/arm/udiv.asm
+++ b/mpn/arm/udiv.asm
@@ -48,7 +48,7 @@ L(oop): divstep(n1,n0,d)
teq r12, #0
bne L(oop)
- str n1, [ rem_ptr ] C store remainder
+ str n1, [rem_ptr] C store remainder
adc r0, n0, n0 C quotient: add last carry from divstep
bx lr
@@ -87,7 +87,7 @@ L(oop2):
addcs n0, n0, #1 C adjust quotient
L(_even_divisor):
- str n1, [ rem_ptr ] C store remainder
+ str n1, [rem_ptr] C store remainder
mov r0, n0 C quotient
ldmfd sp!, { r8, pc }
EPILOGUE(mpn_udiv_qrnnd)
然后在该目录执行 patch -p1 < ggmp.diff即可。
2.3
configure: error: libavcodec versions 56 and later are not supported yet.
/home/wxx/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: .././vlc/contrib/arm-linux-androideabi/lib/libavcodec.a(opusdec.o): in function opus_decode_packet:libavcodec/opusdec.c:377: error: undefined reference to 'avresample_is_open'
/home/wxx/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: .././vlc/contrib/arm-linux-androideabi/lib/libavcodec.a(opusdec.o): in function
libavcodec versions 55 and later are not supported yet
最好的方法是更改vlc/contrib/src/ffmpeg该目录下rules.mak的FFMPEG_SNAPURL值。
2.4
c compiler cannot create executables
这个错误很可能是sdk 或 ndk 的版本错了(32/64),不过我未作验证。
添加录像功能的patch文件链接https://patches.videolan.org/patch/606/,放在vlc目录下保存为xxx.diff,然后执行 patch -p1 < xxx.diff。可能有的地方不成功,自行添加即可。
在jni/libvlcjni.c后面添加函数:
jboolean Java_org_videolan_libvlc_LibVLC_takeSnapShot(JNIEnv *env, jobject thiz,jint number, jstring path, jint width,jint height)
{
jboolean isCopy;
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
/* Get C string */
const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
if (mp)
if(libvlc_video_take_snapshot(mp, (int)number,psz_path , (int)width,(int)height)==0)
return JNI_TRUE;
return JNI_FALSE;
}
jboolean Java_org_videolan_libvlc_LibVLC_videoRecordStart(JNIEnv *env, jobject thiz,jstring path)
{
jboolean isCopy;
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
/* Get C string */
const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
//const char* psz_filename=(*env)->GetStringUTFChars(env, filename, &isCopy);
if (mp)
if(libvlc_media_player_record_start(mp,psz_path)==0)
return JNI_TRUE;
return JNI_FALSE;
}
jboolean Java_org_videolan_libvlc_LibVLC_videoRecordStop(JNIEnv *env, jobject thiz)
{
jboolean isCopy;
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
/* Get C string */
if (mp)
if(libvlc_media_player_record_stop(mp)==0)
return JNI_TRUE;
return JNI_FALSE;
}
jboolean Java_org_videolan_libvlc_LibVLC_videoIsRecording(JNIEnv *env, jobject thiz)
{
jboolean isCopy;
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
if (mp)
if(libvlc_media_player_is_recording(mp))
return JNI_TRUE;
return JNI_FALSE;
}
jboolean Java_org_videolan_libvlc_LibVLC_videoIsRecordable(JNIEnv *env, jobject thiz)
{
jboolean isCopy;
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
if (mp)
if(libvlc_media_player_is_recordable(mp))
return JNI_TRUE;
return JNI_FALSE;
}
jint Java_org_videolan_libvlc_LibVLC_getState(JNIEnv *env, jobject thiz)
{
libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
if (mp){
libvlc_state_t state=libvlc_media_player_get_state(mp);
return (jint)state;
}
else
return -1;
}
然后在LibVLC.java中添加接口:
public native boolean takeSnapShot( int num, String file, int width, int height);
public native boolean videoRecordStart(String path);
public native boolean videoRecordStop();
public native boolean videoIsRecording();
public native boolean videoIsRecordable();
public native int getState();
public boolean takeSnapShot(String file, int width, int height) {
return takeSnapShot(0, file, width, height);
}
刚在提到的截图时去掉画中画和路径提示,只需要在vlc/src/vout_intf.c的VoutSaveSnapshot函数中注释掉
VoutOsdSnapshot( p_vout, p_picture, psz_filename );
就可以了。
参考:http://bbs.csdn.net/topics/390671446
https://dev.openwrt.org/ticket/14231
https://patches.videolan.org/patch/606/
资料下载: