[关闭]
@Awille 2022-09-08T15:56:16.000000Z 字数 1907 阅读 481

ExoPlayer(版本2.10.8)缓存文件组织结构

Android Exoplayer 缓存


1、缓存文件组织结构

1.1 具体的磁盘存储文件

首先看下视频存储文件:
SeaTalk_IMG_1662603829.png-277kB
红框部分为具体的视频文件,蓝框部分为存储的uid,只作为标记用途。
缓存文件命名格式为:

"视频id_文件所代表的视频开始byte位置_创建时间戳.v3.exo”

后缀中的.v3.exo为写死的后缀,如果后续exoPlayer缓存文件组织结构变更,可以根据该后缀加以区分。

1.2 数据库信息

database_store.png-132.3kB
可以看到数据库为exoplayer_internal.db
该数据库下的信息存储为:
Exo_form_info.png-380.8kB
下面两个表与exoplayer版本信息相关,可以主要关注上面两张表
先看1.1中文件对应在数据库中的存储信息:
image.png-238.1kB
存储的信息为文件名、文件大小、最后一次读取或修改的时间戳。
其中文件名就包含了 视频id、文件对应视频起始位置。

同一个视频,id是一致,并且存在多个缓存文件,他们是由下面这张表来组织的
cache_index.png-167.8kB
该表存储了视频id, 视频key(我们项目中未对key做自定义处理,默认使用url作为key),以及一个byte数据。

byte数组中对应的信息为:

"exo_len":Key for content length in bytes (type: long).
"exo_redir":Key for redirected uri (type: String).
"custom_":自定义信息

1.3 对应在JVM中的数据对象信息结构

每一个存储的缓存文件,对应的java对象数据结构为:
image.png-173.2kB
而一个视频对应的所有存储文件信息为:
image.png-112.3kB

可以看到,这两个数据结构与 数据库的信息是意义对应的,CacheContent中用一个TreeSet的结构持有了SimpleCacheSpan列表。

并且ExoPlayer内部会在CacheContentIndex对象中归集所有视频的缓存文件信息:
image.png-171.1kB
CacheContentIndex中keyToContent : HashMap 存储了缓存文件的所有信息。
CacheContentIndex被ExoPlayer的SimpleCache所持有,我们在new SimpleCache时,内部流程会加载数据库的所有信息并装填到CacheContentIndex当中。

com.google.android.exoplayer2.upstream.cache.SimpleCache#SimpleCache(java.io.File,
com.google.android.exoplayer2.upstream.cache.CacheEvictor,
com.google.android.exoplayer2.upstream.cache.CachedContentIndex,
com.google.android.exoplayer2.upstream.cache.CacheFileMetadataIndex)

image.png-318kB

后续我们查询缓存大小时都是在内存中进行的不会有文件IO操作。 但是后续对缓存文件读取会更新数据库表中的last_touch_timestamp字段。

2、多个播放器播放同一url视频时的文件读写操作

可以看看simpleCache中获取缓存的逻辑:
image.png-456.9kB
可以看到,已缓存文件读是允许多个播放器来读取的,对于写操作,是独占的。

播放器内部提供了block_on_cache的标志位,当有一个播放器在写缓存文件时,其他播放器尝试读或写该文件,当block_on_cache为true时,阻塞等待,当block_on_cache为false时,可不等待该文件直接网络拉取视频进行播放,但是该case下,第二个播放器不会边播边缓存。

3、自定缓存key

Exoplayer提供了一些开放接口做了支持
* 在DataSourceFactory传入自定义的CacheKeyFactory

public interface CacheKeyFactory {

  /**
   * Returns a cache key for the given {@link DataSpec}.
   *
   * @param dataSpec The data being cached.
   */
  String buildCacheKey(DataSpec dataSpec);
}
public Factory setCustomCacheKey(String customCacheKey) {
  Assertions.checkState(!isCreateCalled);
  this.customCacheKey = customCacheKey;
  return this;
}
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注