1. 程式人生 > >vlc 播放器的播放進度條的時間不重新整理

vlc 播放器的播放進度條的時間不重新整理

有些視訊如(rmvb)視訊在使用vlc播放器播放時會出現進度條不能重新整理的問題,
通過Java層程式碼找到重新整理進度條的介面。是通過public native long getLength()(MediaPlayer Java檔案中);本地函式得到具體要更新的值。

jlong Java_org_videolan_libvlc_MediaPlayer_getTime(JNIEnv *env,
jobject thiz) {
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return -1;
return libvlc_media_player_get_time(p_obj->u.p_mp); }

而libvlc_media_player_get_time 所在位置是在vlc庫中,這段程式碼實在Linux中編譯通過的。在vlc/lib/media_player.c檔案中實現。

libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
{
input_thread_t *p_input_thread;
libvlc_time_t i_time;

p_input_thread = libvlc_get_input_thread ( p_mi );
if( !p_input_thread )
    return -1;

i_time = from_mtime(var_GetInteger( p_input_thread , "time" ));
vlc_object_release( p_input_thread );
return i_time; }

而具體的進度是通過讀取p_input_thread這個指標結構體的變數而得到的。

VLC_USED static inline int64_t var_GetInteger( vlc_object_t *p_obj,
const char *psz_name ) {
vlc_value_t val;
if( !var_GetChecked( p_obj, psz_name, VLC_VAR_INTEGER, &val ) )
return val.i_int;
else
return 0; }

下面函式就是通過在p_obj中查詢“time”關鍵字,把對應的記憶體值賦給變數val,得到時間。
現在要去分析這個input_thread_t *p_input_thread變數是什麼時候被建立,並且是哪個執行緒在實時的進行對其維護更新的。
帶著問題我們分析,這個函式讀取的時候視訊檔案已經在播放了。

void Java_org_videolan_libvlc_MediaPlayer_nativePlay(JNIEnv *env,
jobject thiz) {
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return;
libvlc_media_player_play(p_obj->u.p_mp); }

這個函式就是負責播放的函式。

var_AddCallback( p_input_thread, “program-scrambled”,
input_scrambled_changed, p_mi );
var_AddCallback( p_input_thread, “intf-event”, input_event_changed, p_mi );
add_es_callbacks( p_input_thread, p_mi );

if( input_Start( p_input_thread ) )
{
    unlock_input(p_mi);
    del_es_callbacks( p_input_thread, p_mi );
    var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
     。。。。。。
}

這段程式碼是libvlc_media_player_play函式實現的一段程式碼,通過input_Start函式將p_input_thread作為實參。

int input_Start( input_thread_t *p_input ) {
assert( !p_input->p->is_running );
/* Create thread and wait for its readiness. */
p_input->p->is_running = !vlc_clone( &p_input->p->thread,
Run, p_input, VLC_THREAD_PRIORITY_INPUT );
if( !p_input->p->is_running )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, “cannot create input thread” );
return VLC_EGENERIC;
}
return VLC_SUCCESS; }

使用vlc_clone函式建立執行緒,

int vlc_clone (vlc_thread_t th, void (entry) (void ), void *data,
int priority) {
(void) priority;
return vlc_clone_attr (th, entry, data, false); }

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

這個的這個start_routine函式就是vlc_clone( &p_input->p->thread, Run, p_input, VLC_THREAD_PRIORITY_INPUT ); 傳遞進來的Run函式。
vlc_clone函式在vlc\src\input\input.c檔案中,Run函式也在本檔案中。

/******************************************************************* * Run: main thread loop * This is the “normal” thread that spawns the input processing chain, * reads the stream, cleans up and waits
*******************************************************************/ static void *Run( void *obj ) {
input_thread_t p_input = (input_thread_t )obj;

vlc_interrupt_set(&p_input->p->interrupt);

if( !Init( p_input ) )
{
    MainLoop( p_input, true ); /* FIXME it can be wrong (like with VLM) */

    /* Clean up */
    End( p_input );
}

input_SendEventDead( p_input );
return NULL; }

主函式MainLoop有點想Linux系統中init程序啟動後進入的函式名稱。

上面是對整個vlc播放器原始碼的分析,至於對time當前時間不更新,是解碼時間的引數有問題,我的解決方法,直接升級ffmpeg解碼模組。找到ffmpeg原始碼所在目錄,修改sh檔案。將下載最新的原始碼拷貝進去編譯。生成靜態庫。問題完美解決。