详见我的简书 http://www.jianshu.com/p/9b0675da8380
1 背景
公司的底层播放器实际上是ffplayer作为基础修改的,当然需要好好学习研究。 记录下来,作为以后备忘。(发觉人老了,就容易忘事)。ps 入坑需谨慎,很容易入门到放弃。
2 分析入口
分析的连接https://github.com/Bilibili/ijkplayer
版本号: 0.8.1.2 android版
基本上IjkPlayer的接口和MediaPlayer接口一致。http://www.jianshu.com/p/55fbfd5b564a
每次我们发觉分析源码总找不到下口的地方,实际上就是没找到分析的入口。那在哪里呢?当然看源码demo了。https://github.com/Bilibili/ijkplayer/blob/5b73bf7eae66a3942e2689ecbe6e51b679abe161/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/activities/VideoActivity.java
这个类里面的onCreate 方法里面:
![](https://i-blog.csdnimg.cn/blog_migrate/019de10163f1beb5a902420277ffe2b7.webp?x-image-process=image/format,png)
实际上初始化,作者已注释了 init player。我们来看看初始化里做了什么?
3 IjkMediaPlayer.loadLibrariesOnce(null);
这个很简单load了几个需要的lib(ijkffmpeg,ijksdl,ijkplayer)
![](https://i-blog.csdnimg.cn/blog_migrate/16595fbdf2561df663efe9236cda7131.webp?x-image-process=image/format,png)
事实上这里还有隐藏逻辑,看其中源码,你会发现,卧槽,我都找不到定义jni的方法名,熟悉jni的同学知道,jni方法名是Java+ 全类名 命名,可是你会发觉比如你想找到_start方法,你是找不到的。 这里使用的一个trick , 事实上我觉得这对写代码的人,
提高了写作效率,但可读性没那么高。在jni加载lib的时候,会首先查找JNI_OnLoad() 方法,同理卸载的时候JNI_OnUnload()。我们看下他都干了些啥?
a. 这个是ijkplayer_jni做的
static JNINativeMethod g_methods[] = {
{
"_setDataSource",
"(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
(void *) IjkMediaPlayer_setDataSourceAndHeaders
},
{ "_setDataSourceFd", "(I)V", (void *) IjkMediaPlayer_setDataSourceFd },
{ "_setDataSource", "(Ltv/danmaku/ijk/media/player/misc/IMediaDataSource;)V", (void *)IjkMediaPlayer_setDataSourceCallback },
{ "_setAndroidIOCallback", "(Ltv/danmaku/ijk/media/player/misc/IAndroidIO;)V", (void *)IjkMediaPlayer_setAndroidIOCallback },
{ "_setVideoSurface", "(Landroid/view/Surface;)V", (void *) IjkMediaPlayer_setVideoSurface },
{ "_prepareAsync", "()V", (void *) IjkMediaPlayer_prepareAsync },
{ "_start", "()V", (void *) IjkMediaPlayer_start },
{ "_stop", "()V", (void *) IjkMediaPlayer_stop },
{ "seekTo", "(J)V", (void *) IjkMediaPlayer_seekTo },
{ "_pause", "()V", (void *) IjkMediaPlayer_pause },
{ "isPlaying", "()Z", (void *) IjkMediaPlayer_isPlaying },
{ "getCurrentPosition", "()J", (void *) IjkMediaPlayer_getCurrentPosition },
{ "getDuration", "()J", (void *) IjkMediaPlayer_getDuration },
{ "_release", "()V", (void *) IjkMediaPlayer_release },
{ "_reset", "()V", (void *) IjkMediaPlayer_reset },
{ "setVolume", "(FF)V", (void *) IjkMediaPlayer_setVolume },
{ "getAudioSessionId", "()I", (void *) IjkMediaPlayer_getAudioSessionId },
{ "native_init", "()V", (void *) IjkMediaPlayer_native_init },
{ "native_setup", "(Ljava/lang/Object;)V", (void *) IjkMediaPlayer_native_setup },
{ "native_finalize", "()V", (void *) IjkMediaPlayer_native_finalize },
{ "_setOption", "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },
{ "_setOption", "(ILjava/lang/String;J)V", (void *) IjkMediaPlayer_setOptionLong },
{ "_getColorFormatName", "(I)Ljava/lang/String;", (void *) IjkMediaPlayer_getColorFormatName },
{ "_getVideoCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getVideoCodecInfo },
{ "_getAudioCodecInfo", "()Ljava/lang/String;", (void *) IjkMediaPlayer_getAudioCodecInfo },
{ "_getMediaMeta", "()Landroid/os/Bundle;", (void *) IjkMediaPlayer_getMediaMeta },
{ "_setLoopCount", "(I)V", (void *) IjkMediaPlayer_setLoopCount },
{ "_getLoopCount", "()I", (void *) IjkMediaPlayer_getLoopCount },
{ "_getPropertyFloat", "(IF)F", (void *) ijkMediaPlayer_getPropertyFloat },
{ "_setPropertyFloat", "(IF)V", (void *) ijkMediaPlayer_setPropertyFloat },
{ "_getPropertyLong", "(IJ)J", (void *) ijkMediaPlayer_getPropertyLong },
{ "_setPropertyLong", "(IJ)V", (void *) ijkMediaPlayer_setPropertyLong },
{ "_setStreamSelected", "(IZ)V", (void *) ijkMediaPlayer_setStreamSelected },
{ "native_p