如下配置参数多数是针对直播起播速度优化的,在咱们项目中已经获得了商业验证 先同步给你们:mMediaPlayer -> IjkMediaPlayer 类引用markdown
//指对指定帧不作环路滤波, 能够节省CPU. 48(AVDISCARD_ALL) 全部帧都不作环路滤波
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48)
//抛弃全部非引用
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 8)
//设置播放前的探测时间 1,达到首屏秒开效果
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1L)
//设置播放前的最大探测时间
mMediaPlayer?.setOption(1, "analyzemaxduration", 100L)
//播放前的探测Size,默认是1M, 改小一点会出画面更快
mMediaPlayer?.setOption(1, "probesize", 1024L * 32)
//每处理一个packet以后刷新io上下文
mMediaPlayer?.setOption(1, "flush_packets", 1L)
//是否开启预缓冲,通常直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验
mMediaPlayer?.setOption(4, "packet-buffering", 0L)
//跳帧处理,放CPU处理较慢时,进行跳帧处理,保证播放流程,画面和声音同步
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 5)
//等待开始以后才渲染
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "render-wait-start", 1)
// 设置播放最大帧数 (能够根据网速来动态设置)
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-fps", 60)
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "max_delay", 0)
if (DeviceUtil.isDecoderSupport()) {
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1)
} else {
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0)
}
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fpsprobesize", 60)
//由于项目中屡次调用播放器,有网络视频,resp,本地视频,还有wifi上http视频,因此得清空DNS才能播放WIFI上的视频
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 0)
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", -1)
//若是是rtsp协议,能够优先用tcp(默认是用udp)
mMediaPlayer?.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp")
复制代码
/** * Created by kpa(billkp@yeah.net) * 2021/5/17 * Describe: **/
class DeviceUtil {
companion object {
/** * 判断是否支持硬解 */
fun isDecoderSupport(): Boolean {
return isH265DecoderSupport() || isH265HWDecoderSupport()
}
/** * 检测是否支持H265硬编码 * @return 检测结果 */
private fun isH265EncoderSupport(): Boolean {
val result = false
val count = MediaCodecList.getCodecCount()
for (i in 0 until count) {
val info = MediaCodecList.getCodecInfoAt(i)
val name = info.name
val b = info.isEncoder
if (b && name.contains("hevc")) {
return true
}
}
return false
}
/** * 检测是否支持H265硬解码 * @return 检测结果 */
private fun isH265DecoderSupport(): Boolean {
val count = MediaCodecList.getCodecCount()
for (i in 0 until count) {
val info = MediaCodecList.getCodecInfoAt(i)
val name = info.name
if (name.contains("decoder") && name.contains("hevc")) {
return true
}
}
return false
}
/** * 是否支持硬解 */
private fun isH265HWDecoderSupport(): Boolean {
val codecList = MediaCodecList(MediaCodecList.REGULAR_CODECS)
// 获取设备支持的全部 codec 信息
val codecInfos: Array<MediaCodecInfo> = codecList.codecInfos
for (i in codecInfos.indices) {
val codecInfo: MediaCodecInfo = codecInfos[i]
// 解码codec & 解码器名称包含'hevc' & 不是软件codec
if (!codecInfo.isEncoder && (codecInfo.name.contains("hevc")
&& !isSWCodec(codecInfo.name))
) {
return true
}
}
return false
}
/** * 是否为软件 codec * @param codecName * @return */
private fun isSWCodec(codecName: String): Boolean {
if (codecName.startsWith("OMX.google.")) {
return true
}
return !codecName.startsWith("OMX.")
}
}
}
复制代码
虽然打开硬解能提高起播速度,可是硬解是存在一些问题的网络
硬解,是视频解码的一种方法,也是一种破解限制的方法,是指不依赖于CPU硬件资源,经过专用的设备(子卡,硬件中设计了专门的解码电路)单独完成视频解码。随着CPU与GPU技术的改进,不能经过使用CPU仍是GPU进行解码来判断使用了硬解仍是软解。tcp
这是百度给的定义,专用设备单独完成视频解码, 我怀疑这个专用设备在有的手机上可能比软解还差,可是没找到证据,因此暂起可使用,等我找到证据后再作处理。你们要是有证据咱们一块儿处理。oop