您的位置:首页 > 移动开发 > Android开发

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截图成功!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码 vlc