vlc-android最新原始碼截圖功能實現
前言
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截圖成功!
相關文章
- canvas實現截圖功能Canvas
- C#實現截圖功能C#
- 支付寶截圖反饋功能實現
- js實現視訊截圖,視訊批量截圖,canvas實現JSCanvas
- Python網頁截圖/螢幕截圖/截長圖如何實現?Python網頁
- 實現Google帶截圖功能的web反饋外掛GoWeb
- 硬解碼播放器上如何實現截GIF功能?播放器
- WiFiAp探究實錄--功能實現與原始碼分析WiFi原始碼
- 原生JS實現影片截圖JS
- Selenium IDE 如何實現截圖IDE
- Android長截圖的實現Android
- selenium實現螢幕截圖
- 用python實現植物大戰殭屍(遊戲截圖+動態演示+原始碼分享)Python遊戲原始碼
- 直播系統app原始碼,藉助django 實現顯示圖片功能APP原始碼Django
- 影片直播系統原始碼,C語言實現圖片合成功能原始碼C語言
- 直播商城原始碼,實現商城客服聊天,傳送文字、圖片的功能原始碼
- 從0到1,手把手帶你開發截圖工具ScreenCap------001實現基本的截圖功能
- html2canvas實現瀏覽器截圖的原理(包含原始碼分析的通用方法)HTMLCanvas瀏覽器原始碼
- selenium提供的截圖功能
- python 三種方式實現截圖Python
- PHP如何實現網頁截圖?PHP網頁
- spring原始碼解析:元註解功能的實現Spring原始碼
- Android 截圖實現的幾種方式Android
- iPhone 11怎麼截圖?詳解最新蘋果iPhone 11截圖方法iPhone蘋果
- 劃詞高亮功能的實現附帶開原始碼原始碼
- app直播原始碼如何實現直播間紅包功能APP原始碼
- canvas拼圖功能實現Canvas
- 直播app系統原始碼,使用element ui隱藏元件實現圖片預覽功能APP原始碼UI元件
- Python實戰:截圖識別文字,過萬使用量版本!(附原始碼!!)Python原始碼
- 分享一個圖片驗證碼功能的實現
- 直播app原始碼,HTML + jQuery 實現輪播圖APP原始碼HTMLjQuery
- 如何實現直播間原始碼重要的簡訊驗證碼功能原始碼
- html2canvas-實現頁面截圖HTMLCanvas
- javascript實現網頁截圖匯出方案JavaScript網頁
- 根據原始碼模擬實現express框架常用功能原始碼Express框架
- 直播平臺原始碼開發,簽到功能的實現原始碼
- 相親交友原始碼開發,前端如何實現水印功能?原始碼前端
- 直播app原始碼,map實現購物車選擇功能APP原始碼
- 線上直播系統原始碼,Node.js中使用Koa實現上傳圖片功能原始碼Node.js