您的位置:首页 > 理论基础 > 计算机网络

Exoplayer使用记录3-网络播放相关的一些事

2018-02-25 00:37 232 查看

Exoplayer使用记录3-网络播放相关的一些事

By Xdestiny. 2018/2/5

概述

网络播放本来其实没啥好说的,毕竟ExoPlayer都已经封装的很完善了。但毕竟有时候还需要一些特殊功能,例如缓存功能、限制下载速度,等等。

缓存功能

对于在线播放来说,缓存可以说不可或缺的。那么在ExoPlayer中要怎么做呢?先翻翻文档好了。果然,有一个
SimpleCache
是可以使用的。那么,大体上来说,缓存功能可以这么做

- 首先搞一个用于下载、删除缓存的接口。利用
SimpleCache
将视频存储在本地的某一个位置

- 读取URL的时候,同样声明一个
SimpleCache
到同样的路径。这样Exoplayer内部会匹配URL与缓存文件。如果之前有缓存,那么就能够直接使用缓存

下载速度限制

有了缓存功能,那么就又来了个新问题…缓存的时候总不好把人带宽占满吧?那么就需要限制下下载速度

老样子,先上Issue上搜搜有啥思路没。搜一下立刻发现已经有人问过了

Is there a method to limit the downloading bandwidth

里面也给了个思路,大致是对
DataSource
进行一些限制。其实,在缓存的时候,必然会启动一个线程进行下载的操作,那么可以在这个时候线程进行一段时间,然后暂停一段时间。

具体代码

class MyCache(activity: Activity, uri: String, isExternalCache: Boolean = true)
: CacheDataSource.EventListener
{
private val TAG = "MyCache"
private val MAX_BYTE_SIZE: Long = 4L*1024*1024*1024
private val m_context = activity
private val m_isExternalCache = isExternalCache
private val m_uri = uri
private val simpleCache = SimpleCache(File(if(m_isExternalCache) m_context.externalCacheDir else m_context.cacheDir, "media_cache"), NoOpCacheEvictor())
private val cacheDataSourceFactory = CacheDataSourceFactory(simpleCache, DefaultDataSourceFactory(m_context, Util.getUserAgent(m_context, "ExoPlayerBridge"), DefaultBandwidthMeter()),
FileDataSourceFactory(), CacheDataSinkFactory(simpleCache, Long.MAX_VALUE), 0, this)
var IsCaching = false
private set(value) {field = value}
get() = field
var LimitSpeedRatio: Float = 0.0f
var CacheByte: Long = Math.max(0, simpleCache.getCachedBytes(m_uri, 0, MAX_BYTE_SIZE))
get() = field
private set(value) { field = value }
var ContentByte: Long = -1
get() = simpleCache.getContentLength(m_uri)
var CachedSpace: Long = 0
get() = simpleCache.cacheSpace
private var th : Thread? = null

init{

}

fun PreCache(){
//缓存功能
if(!m_uri.startsWith("http") || IsCaching) return
Log.d(TAG, "Start cache. Uri = $m_uri")
LimitSpeedRatio = 0.0f //限速比例
th = thread(true){
IsCaching = true
val dataSpec = DataSpec(Uri.parse(m_uri))
val dataSource = cacheDataSourceFactory.createDataSource()
try{
dataSource.open(dataSpec)
val scratchSpace = ByteArray(32 * 1024)
var bytesRead = 0
CacheByte = 0
var miliSec = 0L
while (bytesRead != C.RESULT_END_OF_INPUT && IsCaching) {
val lastMiliSec = System.currentTimeMillis()
CacheByte += bytesRead
bytesRead = dataSource.read(scratchSpace, 0, scratchSpace.size)
miliSec += System.currentTimeMillis() - lastMiliSec
if(miliSec > 100 && LimitSpeedRatio > 0.01){
Thread.sleep((LimitSpeedRatio * 100L).toLong())
miliSec = 0
}
}
}
catch (e : IOException){
Log.e(TAG, e.toString())
}
finally {
try{
IsCaching = false
dataSource.close()
}
catch (e : Exception){
e.printStackTrace()
}
}
}
}

fun CleanCache(){
//删除缓存
if(!m_uri.startsWith("http") || IsCaching) return
Log.d(TAG, "Clean cache. Uri = $m_uri")
simpleCache.getCachedSpans(m_uri)?.forEach { it -> simpleCache.removeSpan(it) }
CacheByte = 0
}

fun StopCache(){
//停止缓存
if(!m_uri.startsWith("http") || !IsCaching) return
Log.d(TAG, "Stop cache. Uri = $m_uri")
IsCaching = false
}

override fun onCachedBytesRead(cacheSizeBytes: Long, cachedBytesRead: Long) {

}

}


这里我省略很多东西,比如空间满了之类的…

之后就是在建立
ExoPlayer
的时候,将
SimpleCache
作为参数输入即可

exoPlayer = MyExoPlayer(MyTrackRenderersFactory(activity, null, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF, videoCnt, audioCnt),
DefaultTrackSelector())
simpleCache = SimpleCache(File(m_context.externalCacheDir, "media_cache"), NoOpCacheEvictor())
cacheDataSourceFactory = CacheDataSourceFactory(simpleCache,  DefaultHttpDataSourceFactory(Util.getUserAgent(m_context, "ExoPlayer"), DefaultBandwidthMeter()),
FileDataSourceFactory(), null, 0, this)
videoSource = ExtractorMediaSource(Uri.parse(url), cacheDataSourceFactory, DefaultExtractorsFactory(), null, null, url)
exoPlayer.prepare(videoSource)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  exoplayer
相关文章推荐