如下配置參數多數是針對直播起播速度優化的,在咱們項目中已經獲得了商業驗證 先同步給你們: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