vlc-android最新源码截图功能实现
2018-01-30 09:59
489 查看
前言
2018/1月 vlc-android最新源码截图功能实现项目需要vlc截图的功能,但是默认的vlc源码编译是不包含截图功能的,所以需要在源码中设置相应的编译选项,并且在jni中添加相应的接口。
网上能搜到好几篇基于 vlc android截图功能实现的文档,实现方式都一样,都是对android/configure.sh进行修改,删掉其中的–disable-sout,另外保存图片为png格式,需要让ffmpeg增加–enable-encoder=png的 编码器(在android/vlc/contrib/src/ffmpeg/rules.mak中修改),然后在libvlcjni.c中增加截图函数。照着 这样的方式在最新的vlc android中并不能实现截图功能。以下分析原因。
按照网上的方式,在\vlc-android\libvlc\jni\libvlcjni.c中增加函数:
jboolean Java_org_videolan_vlc_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; }
注:最新的源码中没有getMediaPlayer方法,获取libvlc_media_player_t可通过:
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz); libvlc_media_player_t *mp = gp_obj->u.p_mp;
在\vlc-android\libvlc\src\org\videolan\libvlc\LibVlc.java中增加native函数的接口
private native boolean takeSnapShot( int num, String file, int width, int height);
和调用方法
public boolean takeSnapShot(String file, int width, int height) { return takeSnapShot(0, file, width, height); }
但是当我在上层通过takeSnapShot截图时没有任何反应,于是打log发现libvlcjni.c中调用libvlc_video_take_snapshot时返回的是JNI_FALSE,于是分析下libvlc_video_take_snapshot函数的流程:
\vlc-android\libvlc\jni\Libvlcjni.c Java_org_videolan_libvlc_LibVLC_nativeTakeSnapShot ==> \vlc-android\vlc\lib\video.c libvlc_video_take_snapshot==>GetVout==>GetVouts==> \vlc-android\vlc\lib\media_player.c libvlc_get_input_thread(libvlc_media_player_t *p_mi)
发现libvlc_get_input_thread中有一句:
p_input_thread = p_mi->input.p_thread;
由于传入的libvlc_media_player_t取得的p_mi->input.p_thread为空导致出错;
通过源码全局搜索发现只有在
\vlc-android\vlc\lib\media_player.c libvlc_media_player_play(libvlc_media_player_t *p_mi)
中会对p_mi->input.p_thread赋值,
所以只要能拿到libvlc_media_player_play中的libvlc_media_player_t 传入libvlc_video_take_snapshot即可;
由于调用libvlc_media_player_play是在:
\vlc-android\libvlc\jni\Libvlcjni-mediaplayer.c Java_org_videolan_libvlc_MediaPlayer_nativePlay()
所以我把:
\vlc-android\libvlc\jni\Libvlcjni.c Java_org_videolan_libvlc_LibVLC_nativeTakeSnapShot
放在
\vlc-android\libvlc\jni\Libvlcjni-mediaplayer.c jboolean Java_org_videolan_libvlc_MediaPlayer_nativeTakeSnapShot(JNIEnv *env, jobject thiz,jint number, jstring path, jint width,jint height) { vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz); if (!p_obj) return JNI_FALSE; jboolean isCopy; /* Get C string */ const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy); if (p_obj->u.p_mp) { if(libvlc_video_take_snapshot(p_obj->u.p_mp, (int)number, psz_path , (int)width, (int)height)==0){ return JNI_TRUE; } } return JNI_FALSE; }
同样的native函数接口和调用方法挪到
\vlc-android\libvlc\src\org\videolan\libvlc\Mediaplayer.java
改完再次调用takeSnapShot截图发现libvlc_video_take_snapshot时返回的是JNI_TRUE,看来是成功了一半了。但是仍然还有报错:
E/VLC (16492): [b8c39ae8/406c] libvlc video output: Encoding support not compiled-in! E/VLC (16492): [b8c39ae8/406c] libvlc video output: Failed to convert image for snapshot
大概意思是编码器没有编译进来。
搜索发现报错的源码在:
\vlc-android\vlc\src\Missing.c #undef sout_EncoderCreate encoder_t *sout_EncoderCreate( vlc_object_t *p_this ) { msg_Err (p_this, "Encoding support not compiled-in!"); return NULL; }
搜索发现在 \vlc-android\vlc\src\streamoutput\Streamoutput.c也有sout_EncoderCreate的实现
\vlc-android\vlc\src\Missing.c #undef sout_EncoderCreate encoder_t *sout_EncoderCreate( vlc_object_t *p_this ) { return vlc_custom_create( p_this, sizeof( encoder_t ), "encoder" ); }
猜测是编译时需要开启某个配置才会把Stream_output.c编译进来,否则就会编译Missing.c
应该就是和前言中说到的那个–disable-sout有关,想必sout就是指Stream_output,但是我下载的最新的vlc源码并没有android/configure.sh这个文件,于是全局搜索–disable-sout,在/vlc-android/compile-libvlc.sh中发现–disable-sout的踪影
########################### # VLC BOOTSTRAP ARGUMENTS # ########################### VLC_BOOTSTRAP_ARGS="\ --disable-disc \ --enable-dvdread \ --enable-dvdnav \ --disable-dca \ --disable-out \ ...... " ########################### # VLC CONFIGURE ARGUMENTS # ########################### VLC_CONFIGURE_ARGS="\ --disable-nls \ --enable-live555 --enable-realrtsp \ --enable-avformat \ --enable-swscale \ ...... --disable-out \ "
尝试先把VLC BOOTSTRAP ARGUMENTS中的–disable-out删除,再次编译,发现会下载几个依赖包,但是此时还是没有编译Stream_output;
接着尝试把VLC CONFIGURE ARGUMENTS中的–disable-out删除,再次编译,发现还是没有编译到Stream_output,观察了一下编译打印的信息发现:
running CONFIG_SHELL=/bin/bash /bin/bash ../configure –host=arm-linux-androideabi –build=x86_64-unknown-linux –with-contrib=/workspace/huanghengwei/work2/r52-v6.0/src/emb_android/vlc/src/vlc-android/vlc/contrib/arm-linux-androideabi –enable-neon –disable-nls –enable-live555 –enable-realrtsp –enable-avformat –enable-swscale –enable-avcodec –enable-opus –enable-opensles –enable-matroska –enable-taglib –enable-dvbpsi –disable-vlc –disable-shared –disable-update-check –disable-vlm –disable-dbus –enable-lua –disable-vcd –disable-v4l2 –enable-dvdread –enable-dvdnav –disable-bluray –disable-linsys –disable-decklink –disable-libva –disable-dv1394 –enable-mod –disable-sid –disable-gme –disable-tremor –disable-mad –enable-mpg123 –disable-dca –disable-sdl-image –enable-zvbi –disable-fluidsynth –enable-fluidlite –disable-jack –disable-pulse –disable-alsa –disable-samplerate –disable-sdl –disable-xcb –disable-qt –disable-skins2 –disable-mtp –disable-notify –enable-libass –disable-svg –disable-udev –enable-libxml2 –disable-caca –enable-gles2 –disable-goom –disable-projectm –disable-sout –enable-vorbis –disable-faad –disable-x264 –disable-schroedinger –disable-vncclient –disable-vnc –enable-jpeg
这里列出来的选项就是VLC CONFIGURE ARGUMENTS中列的,其中还是有–disable-sout,可见删除了disable-sout之后VLC CONFIGURE ARGUMENTS并没有被重新识别,于是在–compile-libvlc.sh中查看VLC CONFIGURE ARGUMENTS相关的脚本内容:
if [ ! -e ./config.h -o "$RELEASE" = 1 ]; then CFLAGS="${VLC_CFLAGS} ${EXTRA_CFLAGS}" \ CXXFLAGS="${VLC_CXXFLAGS} ${EXTRA_CFLAGS} ${EXTRA_CXXFLAGS}" \ CC="${CROSS_TOOLS}clang" \ CXX="${CROSS_TOOLS}clang++" \ NM="${CROSS_TOOLS}nm" \ STRIP="${CROSS_TOOLS}strip" \ RANLIB="${CROSS_TOOLS}ranlib" \ AR="${CROSS_TOOLS}ar" \ PKG_CONFIG_LIBDIR=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \ PKG_CONFIG_PATH=$VLC_SRC_DIR/contrib/$TARGET_TUPLE/lib/pkgconfig \ PATH=../contrib/bin:$PATH \ sh ../configure --host=$TARGET_TUPLE --build=x86_64-unknown-linux \ --with-contrib=${VLC_SRC_DIR}/contrib/${TARGET_TUPLE} \ ${EXTRA_PARAMS} ${VLC_CONFIGURE_ARGS} ${OPTS} checkfail "vlc: configure failed" fi
从脚本中可见,要重新识别VLC CONFIGURE ARGUMENTS要么把config.h删了,要么在编译的时候带上–release,我试着编译时带上–release,终于编译到Stream_output了。替换了编译后的库,调用takeSnapShot截图成功!
相关文章推荐
- Android传感器之-方向传感器Orientation功能实现与源码
- Android开发之拍照功能实现(附源码)
- 【Android应用开发】-(13)屏幕截图功能--截取全屏,无需Root(附源码)
- 【Android应用开发】-(13)屏幕截图功能--截取全屏,无需Root(附源码)
- Android短信功能实现源码
- android源码资料以及功能实现
- Android开发之拍照功能实现(附源码)
- 【源码】实现Android闹钟功能使用HTML+JS,并附带Alarm代码分享
- android使用百度地图、定位SDK实现地图和定位功能!(最新、可用+吐槽)
- 使用Java实现系统托盘功能的介绍(附源码以及截图)
- android使用百度地图、定位SDK实现地图和定位功能!(最新、可用+吐槽)
- Android实现截图功能(可根据该代码进行扩展功能)
- android中 代码实现截图功能(静态+动态视频)
- Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能(附源码)
- 更改VLC源码 实现使用libVLC录像功能
- Android实现截图功能(可根据该代码进行扩展功能)
- [置顶] 更改VLC源码 实现使用libVLC录像功能
- Android源码中屏幕截图的实现
- 基于Android源码开发的来电接通振动功能实现
- Android-屏幕截图功能实现