研究VLC-android有一段時間了,昨天在測試vlc-android播放在線視頻時,發現特別不流暢,根據播放表現,我覺得是讀取網絡數據的緩沖(buffer size)過小的原因,但是vlc-android播放視頻在android層就一個readmedia接口,並沒有設置參數的函數,所以第一反應是通過修改vlc的源代碼,然后重新編譯庫文件,達到修改buffer size的目的。
第一步。。上網查找,遇到有一個人跟我有相似的問題,但是並沒有解決方案(事實證明這個人在某種程度上誤導了我),於是去google用英文搜 vlc stream buffer ,搜到的都是 PC端的解決辦法( TOOLS->preference->ALL->stream_out_put),於是在linux下用grep命令找這個字段(樓主水平有限。。歡迎各位指教更好的方法),最后找到和這個值對應的變量sout-mux-caching,這個變量是在vlc源代碼中src/stream_output/stream_output.c中被函數sout_MuxSendBuffer調用的,根據函數名字也可以看出這個是把分離器得到的buffer傳送給解碼器解碼並輸出的,sout-mux-caching的大小也就是決定了最后一次性輸出畫面和聲音的時間長度等等(如果有問題歡迎指出)。
於是找到這個變量的默認值,在modules.c中,默認值1500,改成15000后,編譯並運行庫后發現沒有改變,跟沒改一樣,google直接搜sout-mux-caching,發現有人跟我一樣的問題。
隨后我想到,可能不是輸出buffer的問題,而是緩存buffer的問題,網速太慢導致上一個緩沖區被解碼播放后下一個緩沖區還沒讀滿,導致播放不流暢。。
於是我在google里找了一下,發現有一個神奇的東西叫 vlc network caching,這個應該才是我們要找的東西,在tools->preferences->input/codecs里,往下拉,會看到(NM的隱藏這么深)。
用老辦法,linux下grep 關鍵字(windows下可以在搜索欄打content: 加上搜索的內容,效果差不多),用到network-caching的模塊就多了,搜索可以發現基本和network input有關的模塊都用到這個參數,udp,tcp,ftp,live555等等。。。
然后更狗血的東西出現了
在vlc-android的/jni/libvlcjni中有這么一句話
libvlc_media_add_option(p_md,":network-caching=1500")
這句話是在libvlcjni.c中的newmedia包含的
貼上完整的一段
libvlc_media_t *new_media(jlong instance, JNIEnv *env, jobject thiz, jstring fileLocation, bool noOmx, bool noVideo) { libvlc_instance_t *libvlc = (libvlc_instance_t*)(intptr_t)instance; jboolean isCopy; const char *psz_location = (*env)->GetStringUTFChars(env, fileLocation, &isCopy); libvlc_media_t *p_md = libvlc_media_new_location(libvlc, psz_location); (*env)->ReleaseStringUTFChars(env, fileLocation, psz_location); if (!p_md) return NULL; if (!noOmx) { jclass cls = (*env)->GetObjectClass(env, thiz); jmethodID methodId = (*env)->GetMethodID(env, cls, "useIOMX", "()Z"); if ((*env)->CallBooleanMethod(env, thiz, methodId)) { /* * Set higher caching values if using iomx decoding, since some omx * decoders have a very high latency, and if the preroll data isn't * enough to make the decoder output a frame, the playback timing gets * started too soon, and every decoded frame appears to be too late. * On Nexus One, the decoder latency seems to be 25 input packets * for 320x170 H.264, a few packets less on higher resolutions. * On Nexus S, the decoder latency seems to be about 7 packets. */ libvlc_media_add_option(p_md, ":file-caching=4500"); libvlc_media_add_option(p_md, ":network-caching=1500"); libvlc_media_add_option(p_md, ":codec=mediacodec,iomx,all"); } if (noVideo) libvlc_media_add_option(p_md, ":no-video"); } return p_md; }
看過源代碼都知道readmedia會首先掃描傳入地址mLocation,然后用new_media()將傳入的多媒體地址映射為一個vlc_media_t實例,最后傳到playlist里去播放
於是,修改代碼就變得異常簡單,不用改源文件了,直接改network-caching為自己想要的值,然后重新編譯一遍即可。
改完測試,還是不太盡如人意,不過比以前的好多了。。最后,最好讓network-caching和sout-mux-caching的值一致。
啰嗦一句, libvlc_media_add_option(p_md, ":codec=mediacodec,iomx,all");
這句話的意思是把解碼方式強制變為iomx嗎?