github地址:https://github.com/Bilibili/ijkplayer
AndroidStudio gradle导入
allprojects {
repositories {
jcenter()
}
}
dependencies {
# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
# ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
}
ijkplayer java层面源码分析
Java入口类IjkMediaPlayer
IjkMediaPlayer类实现了IMediaPlayer接口,IMediaPlayer定义了所有MediaPlayer相关的公共方法和常量,要了解ijkplayer能为我们做些什么事,主要看这个接口的方法。
IjkMediaPlayer实现了IMediaPlayer的所有方法,并且和Native的交互都在这里处理。我们使用ijkplayer来开发项目,一般来说只需要使用到该类。
IjkMediaPlayer 初始化构造函数时,初始化加载了对应平台下需要的几个so库,一般如下所示:
public static void loadLibrariesOnce(IjkLibLoader libLoader) {
Class var1 = IjkMediaPlayer.class;
synchronized(IjkMediaPlayer.class) {
if (!mIsLibLoaded) {
if (libLoader == null) {
libLoader = sLocalLibLoader;
}
libLoader.loadLibrary("ijkffmpeg");
libLoader.loadLibrary("ijksdl");
libLoader.loadLibrary("ijkplayer");
mIsLibLoaded = true;
}
}
}
设置显示控件(Surface)
即设置视频sink(输出目标),ijkPlayer提供了两个方法,分别如下:
setDisplay(SurfaceHolder sh)
setSurface(Surface surface)
当只需要音频输出时,不要调用这两个方法。
另外,如果使用setSurface()设置sink,则调用setScreenOnWhilePlaying()没有效果,该方法的作用是使得播放时屏幕常亮,SurfaceHolder有提供屏幕常亮的方法,而Surface没有。如果使用了setSurface()方法,那么屏幕常亮的逻辑就要由外部自己处理。
public void setSurface(Surface surface) {
if (this.mScreenOnWhilePlaying && surface != null) {
DebugLog.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
}
this.mSurfaceHolder = null;
this._setVideoSurface(surface);
this.updateSurfaceScreenOn();
}
设置数据源(Data Source)
ijkPlayer支持多种数据源,所有设置数据源的方法都是setDataSource(),通过参数类型来区分数据源:
// 从content provider中获取数据
setDataSource(Context context, Uri uri)
setDataSource(Context context, Uri uri, Map<String, String> headers)
// 从文件描述符中获取数据
setDataSource(FileDescriptor fd)
// 从file(本地文件)、http、rtsp、rtmp服务器中获取数据
setDataSource(String path)
setDataSource(String path, Map<String, String> headers)
// 自定义数据源
setDataSource(IMediaDataSource mediaDataSource)
显然,如果我们使用rtmp协议做流媒体开发时使用的是第三类方法。相信大家都注意到了,一些方法里面会有个headers参数,这些参数我们后续再另外讨论。
简易类图(只把一些重要的类标记出来)
说明:
ijkplayer 集成了三种播放器实现:
AndroidMediaPlayer:即安卓系统自带的播放器 MediaPlayer,基于 MediaCodec、AudioTrack 等安卓系统 API.
IjkExoMediaPlayer:即谷歌新推出的 ExoPlayer,同样是基于 MediaCodec、AudioTrack 等安卓系统 API,但相比 MediaPlayer 具有支持 DASH、高级 HLS、自定义扩展等优点。
IjkMediaPlayer:基于 FFmpeg 的 ffplay,集成了 MediaCodec 硬解码器、Opengl 渲染方式等。
ijkplayer中遇到的问题
ijkplayer中遇到的问题汇总: https://juejin.cn/post/6844903694845083655
IjkPlayer播放器秒开优化以及常用Option设置: https://www.jianshu.com/p/843c86a9e9ad
ijk seek不准,会回跳的问题: https://blog.csdn.net/weixin_33894640/article/details/94117716