添加依赖
api 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8
倒入so文件 自行编译下载
ijkffmpeg.so
ijksdl.so
ijkplayer.so
//初始化SurfaceTexture
var textureView: TextureView? = null
fun addTextureView() {
if (textureView != null) mBinding.surfaceContainer.removeView(textureView)
textureView = TextureView(requireContext())
textureView?.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
//在这里初始化播放器
initPlayer()
}
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
return false
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
}
}
var layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER)
mBinding.surfaceContainer.addView(textureView, layoutParams)
}
//初始化 IjkMediaPlayer
fun initPlayer(){
ijkMediaPlayer = IjkMediaPlayer()
ijkMediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC)
////1为硬解 0为软解
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0)
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1)
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1)
//使用opensles把文件从java层拷贝到native层
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0)
//视频格式
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32.toLong())
//跳帧处理(-1~120)。CPU处理慢时,进行跳帧处理,保证音视频同步
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1)
//0为一进入就播放,1为进入时不播放
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0)
////域名检测
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0)
//设置是否开启环路过滤: 0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48)
//最大缓冲大小,单位kb
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024 * 1024)
//某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1)
//是否重连
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1)
//http重定向https
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1)
//设置seekTo能够快速seek到指定位置并播放
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek")
//播放前的探测Size,默认是1M, 改小一点会出画面更快
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 1024 * 10)
//1变速变调状态 0变速不变调状态
ijkMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "soundtouch", 1)
try {
var urlPlay ="https://media.w3.org/2010/05/sintel/trailer.mp4"
ijkMediaPlayer?.setDataSource(urlPlay)
ijkMediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC)
ijkMediaPlayer?.setScreenOnWhilePlaying(true)
ijkMediaPlayer?.prepareAsync()
ijkMediaPlayer?.setSurface( Surface(textureView?.surfaceTexture))
ijkMediaPlayer?.setOnPreparedListener(object: IMediaPlayer.OnPreparedListener{
override fun onPrepared(p0: IMediaPlayer?) {
ijkMediaPlayer?.start()
}
})
} catch ( e: IOException) {
e.printStackTrace()
}
}
//xml布局
<FrameLayout
android:id="@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>