有些视频如(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文件。将下载最新的源码拷贝进去编译。生成静态库。问题完美解决。