提交 293b17f8 编写于 作者: G guoshuyu

cache logic

上级 f121bffb
......@@ -3,6 +3,7 @@ package com.example.gsyvideoplayer;
import android.app.Application;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.player.IJKPlayerManager;
import com.shuyu.gsyvideoplayer.utils.GSYVideoType;
//import com.squareup.leakcanary.LeakCanary;
......@@ -37,7 +38,7 @@ public class GSYApplication extends Application {
//GSYVideoType.setRenderType(GSYVideoType.SUFRACE);
//GSYVideoType.setRenderType(GSYVideoType.GLSURFACE);
//GSYVideoManager.instance().setLogLevel(IjkMediaPlayer.IJK_LOG_SILENT);
//IJKPlayerManager.setLogLevel(IjkMediaPlayer.IJK_LOG_SILENT);
//GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL);
}
......
......@@ -40,9 +40,6 @@ public class DetailExoListPlayer extends GSYBaseActivityDetail<GSYExo2PlayerView
setContentView(R.layout.activity_deatil_exo_list_player);
ButterKnife.bind(this);
//初始化 GSYExoVideoManager context
GSYExoVideoManager.instance().initContext(this);
//GSYBaseActivityDetail 的 普通模式初始化
initVideo();
......
......@@ -6,20 +6,17 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.Surface;
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
import com.shuyu.gsyvideoplayer.cache.ICacheManager;
import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager;
import com.shuyu.gsyvideoplayer.listener.GSYMediaPlayerListener;
import com.shuyu.gsyvideoplayer.model.GSYModel;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.EXO2PlayerManager;
import com.shuyu.gsyvideoplayer.player.IJKPlayerManager;
import com.shuyu.gsyvideoplayer.player.IPlayerManager;
import com.shuyu.gsyvideoplayer.player.PlayerFactory;
import com.shuyu.gsyvideoplayer.player.SystemPlayerManager;
import com.shuyu.gsyvideoplayer.utils.Debuger;
import com.shuyu.gsyvideoplayer.utils.GSYVideoType;
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge;
......@@ -131,15 +128,20 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
* 删除默认所有缓存文件
*/
public void clearAllDefaultCache(Context context) {
clearDefaultCache(context, null);
clearDefaultCache(context, null, null);
}
/**
* 删除url对应默认缓存文件
*
* @param cacheDir 可以为空,空目录清除默认
* @param url 可以为空,空目录清除默认
*/
public void clearDefaultCache(Context context, String url) {
public void clearDefaultCache(Context context, @Nullable File cacheDir, @Nullable String url) {
if (cacheManager != null) {
cacheManager.clearCache(context, url);
cacheManager.clearCache(context, cacheDir, url);
} else {
getCacheManager(videoType).clearCache(context, cacheDir, url);
}
}
......@@ -406,10 +408,14 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
return cacheManager != null && cacheManager.hadCached();
}
@Override
public boolean cachePreview(Context context, File cacheDir, String url) {
return getCacheManager(videoType).cachePreview(context, cacheDir, url);
}
@Override
public void clearCache(Context context, String url) {
clearDefaultCache(context, url);
public void clearCache(Context context, File cacheDir, String url) {
clearDefaultCache(context, cacheDir, url);
}
......@@ -444,11 +450,11 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
if (playerManager != null) {
playerManager.release();
}
setNeedMute(false);
if (cacheManager != null) {
cacheManager.release();
}
bufferPoint = 0;
setNeedMute(false);
cancelTimeOutBuffer();
break;
case HANDLER_RELEASE_SURFACE:
......@@ -467,13 +473,13 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
if (playerManager != null) {
playerManager.release();
}
playerManager = getPlayManager(videoType);
cacheManager = getCacheManager(videoType);
if (cacheManager != null) {
cacheManager.setCacheAvailableListener(this);
}
playerManager.initVideoPlayer(context, msg, optionModelList, cacheManager);
setNeedMute(needMute);
IMediaPlayer mediaPlayer = playerManager.getMediaPlayer();
mediaPlayer.setOnCompletionListener(this);
......@@ -624,11 +630,11 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
this.needTimeOutOther = needTimeOutOther;
}
/**
* 设置log输入等级
*/
public void setLogLevel(int logLevel) {
IJKPlayerManager.setLogLevel(logLevel);
public IPlayerManager getCurPlayerManager() {
return playerManager;
}
public ICacheManager getCurCacheManager() {
return cacheManager;
}
}
......@@ -32,8 +32,8 @@ public class CacheFactory {
switch (videoType) {
case GSYVideoType.IJKEXOPLAYER2:
if (sCacheMode == EXO_DEFAULT) {
//TODO 针对exoPlayer的cache处理
return null;
//针对exoPlayer的source cache处理
return new ExoPlayerCacheManager();
}
case GSYVideoType.SYSTEMPLAYER:
case GSYVideoType.IJKPLAYER:
......@@ -43,7 +43,7 @@ public class CacheFactory {
}
/**
* 设置缓存模式
* 设置缓存模式, 默认EXO使用Source缓存,其他使用proxy缓存
*
* @param mode CACHE_NULL、EXO_CACHE_PROXY、EXO_DEFAULT
*/
......
package com.shuyu.gsyvideoplayer.cache;
import android.content.Context;
import android.net.Uri;
import java.io.File;
import java.util.Map;
import tv.danmaku.ijk.media.exo2.ExoSourceManager;
import tv.danmaku.ijk.media.exo2.IjkExo2MediaPlayer;
import tv.danmaku.ijk.media.player.IMediaPlayer;
/**
* ExoPlayer专用
* Created by guoshuyu on 2018/5/21.
*/
public class ExoPlayerCacheManager implements ICacheManager {
protected ExoSourceManager mExoSourceManager;
@Override
public void doCacheLogic(Context context, IMediaPlayer mediaPlayer, String url, Map<String, String> header, File cachePath) {
if (!(mediaPlayer instanceof IjkExo2MediaPlayer)) {
throw new UnsupportedOperationException("ExoPlayerCacheManager only support IjkExo2MediaPlayer");
}
IjkExo2MediaPlayer exoPlayer = ((IjkExo2MediaPlayer) mediaPlayer);
mExoSourceManager = exoPlayer.getExoHelper();
//通过自己的内部缓存机制
exoPlayer.setCache(true);
exoPlayer.setCacheDir(cachePath);
exoPlayer.setDataSource(context, Uri.parse(url), header);
}
@Override
public void clearCache(Context context, File cachePath, String url) {
ExoSourceManager.clearCache(context, cachePath, url);
}
@Override
public void release() {
mExoSourceManager = null;
}
@Override
public boolean hadCached() {
return mExoSourceManager != null && mExoSourceManager.hadCached();
}
@Override
public boolean cachePreview(Context context, File cacheDir, String url) {
return ExoSourceManager.cachePreView(context, cacheDir, url);
}
@Override
public void setCacheAvailableListener(ICacheAvailableListener cacheAvailableListener) {
}
}
......@@ -15,12 +15,14 @@ public interface ICacheManager {
void doCacheLogic(Context context, IMediaPlayer mediaPlayer, String url, Map<String, String> header, File cachePath);
void clearCache(Context context, String url);
void clearCache(Context context, File cachePath, String url);
void release();
boolean hadCached();
boolean cachePreview(Context context, File cacheDir, String url);
void setCacheAvailableListener(ICacheAvailableListener cacheAvailableListener);
interface ICacheAvailableListener {
......
......@@ -84,7 +84,7 @@ public class ProxyCacheManager implements ICacheManager, CacheListener {
}
@Override
public void clearCache(Context context, String url) {
public void clearCache(Context context, File cachePath, String url) {
if (TextUtils.isEmpty(url)) {
String path = StorageUtils.getIndividualCacheDirectory
(context.getApplicationContext()).getAbsolutePath();
......@@ -92,9 +92,9 @@ public class ProxyCacheManager implements ICacheManager, CacheListener {
} else {
Md5FileNameGenerator md5FileNameGenerator = new Md5FileNameGenerator();
String name = md5FileNameGenerator.generate(url);
if (mCacheDir != null) {
String tmpPath = mCacheDir.getAbsolutePath() + File.separator + name + ".download";
String path = mCacheDir.getAbsolutePath() + File.separator + name ;
if (cachePath != null) {
String tmpPath = cachePath.getAbsolutePath() + File.separator + name + ".download";
String path = cachePath.getAbsolutePath() + File.separator + name;
CommonUtil.deleteFile(tmpPath);
CommonUtil.deleteFile(path);
} else {
......@@ -121,6 +121,16 @@ public class ProxyCacheManager implements ICacheManager, CacheListener {
}
}
@Override
public boolean cachePreview(Context context, File cacheDir, String url) {
HttpProxyCacheServer proxy = getProxy(context.getApplicationContext(), cacheDir);
if (proxy != null) {
//此处转换了url,然后再赋值给mUrl。
url = proxy.getProxyUrl(url);
}
return (!url.startsWith("http"));
}
@Override
public boolean hadCached() {
return mCacheFile;
......@@ -157,6 +167,7 @@ public class ProxyCacheManager implements ICacheManager, CacheListener {
return new HttpProxyCacheServer.Builder(context.getApplicationContext())
.headerInjector(new UserAgentHeadersInjector()).build();
}
/**
* for android video cache header
*/
......@@ -209,6 +220,6 @@ public class ProxyCacheManager implements ICacheManager, CacheListener {
ProxyCacheManager.instance().newProxy(context, file)) : proxy;
}
}
}
......@@ -899,17 +899,27 @@ public abstract class GSYVideoControlView extends GSYVideoView implements View.O
secProgress = getGSYVideoManager().getBufferedPercentage();
}
if (secProgress > 94) secProgress = 100;
if (secProgress != 0 && !getGSYVideoManager().isCacheFile()) {
mProgressBar.setSecondaryProgress(secProgress);
}
setSecondaryProgress(secProgress);
mTotalTimeTextView.setText(CommonUtil.stringForTime(totalTime));
if (currentTime > 0)
mCurrentTimeTextView.setText(CommonUtil.stringForTime(currentTime));
if (mBottomProgressBar != null) {
if (progress != 0) mBottomProgressBar.setProgress(progress);
if (secProgress != 0 && !getGSYVideoManager().isCacheFile())
setSecondaryProgress(secProgress);
}
}
protected void setSecondaryProgress(int secProgress) {
if (mProgressBar != null ) {
if (secProgress != 0 && !getGSYVideoManager().isCacheFile()) {
mProgressBar.setSecondaryProgress(secProgress);
}
}
if (mBottomProgressBar != null) {
if (secProgress != 0 && !getGSYVideoManager().isCacheFile()) {
mBottomProgressBar.setSecondaryProgress(secProgress);
}
}
}
......@@ -1005,8 +1015,8 @@ public abstract class GSYVideoControlView extends GSYVideoView implements View.O
protected boolean isShowNetConfirm() {
return !mUrl.startsWith("file") && !mUrl.startsWith("android.resource") && !CommonUtil.isWifiConnected(getContext())
&& mNeedShowWifiTip && !getGSYVideoManager().isCacheFile();
return !mOriginUrl.startsWith("file") && !mOriginUrl.startsWith("android.resource") && !CommonUtil.isWifiConnected(getContext())
&& mNeedShowWifiTip && !getGSYVideoManager().cachePreview(mContext.getApplicationContext(), mCachePath, mOriginUrl);
}
private class ProgressTimerTask extends TimerTask {
......
......@@ -681,15 +681,13 @@ public abstract class GSYVideoView extends GSYTextureRenderView implements GSYMe
* 清除当前缓存
*/
public void clearCurrentCache() {
//只有都为true时,才是缓存文件
if (getGSYVideoManager().isCacheFile() && mCache) {
//是否为缓存文件
Debuger.printfError(" mCacheFile Local Error " + mUrl);
//可能是因为缓存文件除了问题
CommonUtil.deleteFile(mUrl.replace("file://", ""));
Debuger.printfError("Play Error " + mUrl);
mUrl = mOriginUrl;
getGSYVideoManager().clearCache(mContext, mCachePath, mOriginUrl);
} else if (mUrl.contains("127.0.0.1")) {
getGSYVideoManager().clearCache(getContext(), mOriginUrl);
getGSYVideoManager().clearCache(getContext(), mCachePath, mOriginUrl);
}
}
......
......@@ -61,6 +61,8 @@ public interface GSYVideoViewBridge {
boolean isCacheFile();
void clearCache(Context context, String url);
boolean cachePreview(Context context, File cacheDir, String url);
void clearCache(Context context, File clearCache, String url);
}
......@@ -3,6 +3,7 @@ package tv.danmaku.ijk.media.exo2;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
......@@ -22,12 +23,15 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.Cache;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheSpan;
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import com.google.android.exoplayer2.util.Util;
import java.io.File;
import java.util.Map;
import java.util.NavigableSet;
/**
* Created by guoshuyu on 2018/5/18.
......@@ -37,14 +41,20 @@ public class ExoSourceManager {
private static final String TAG = "ExoSourceManager";
private static final long DEFAULT_MAX_SIZE = 512 * 1024 * 1024;
public static final int TYPE_RTMP = 4;
protected Context mAppContext;
protected static Cache mCache;
protected Cache mCache;
protected Context mAppContext;
protected Map<String, String> mMapHeadData;
protected String mDataSource;
private boolean isCached = false;
public static ExoSourceManager newInstance(Context context, @Nullable Map<String, String> mapHeadData) {
return new ExoSourceManager(context, mapHeadData);
}
......@@ -55,6 +65,7 @@ public class ExoSourceManager {
}
public MediaSource getMediaSource(String dataSource, boolean preview, boolean cacheEnable, boolean isLooping, File cacheDir) {
mDataSource = dataSource;
Uri contentUri = Uri.parse(dataSource);
int contentType = inferContentType(dataSource);
MediaSource mediaSource;
......@@ -109,11 +120,10 @@ public class ExoSourceManager {
}
}
/**
* 本地缓存目录
*/
public Cache getCache(Context context, File cacheDir) {
public static synchronized Cache getCacheSingleInstance(Context context, File cacheDir) {
String dirs = context.getCacheDir().getAbsolutePath();
if (cacheDir != null) {
dirs = cacheDir.getAbsolutePath();
......@@ -122,13 +132,14 @@ public class ExoSourceManager {
String path = dirs + File.separator + "exo";
boolean isLocked = SimpleCache.isCacheFolderLocked(new File(path));
if (!isLocked) {
mCache = new SimpleCache(new File(path), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 100));
mCache = new SimpleCache(new File(path), new LeastRecentlyUsedCacheEvictor(DEFAULT_MAX_SIZE));
}
}
return mCache;
}
public void release() {
isCached = false;
if (mCache != null) {
try {
mCache.release();
......@@ -139,17 +150,53 @@ public class ExoSourceManager {
}
}
/**
* Cache需要release之后才能clear
*
* @param context
* @param cacheDir
* @param url
*/
public static void clearCache(Context context, File cacheDir, String url) {
try {
Cache cache = getCacheSingleInstance(context, cacheDir);
if (!TextUtils.isEmpty(url)) {
if (cache != null) {
CacheUtil.remove(cache, CacheUtil.generateKey(Uri.parse(url)));
}
} else {
if (cache != null) {
for (String key : cache.getKeys()) {
CacheUtil.remove(cache, key);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean cachePreView(Context context, File cacheDir, String url) {
return resolveCacheState(getCacheSingleInstance(context, cacheDir), url);
}
public boolean hadCached() {
return isCached;
}
/**
* 获取SourceFactory,是否带Cache
*/
private DataSource.Factory getDataSourceFactoryCache(Context context, boolean cacheEnable, boolean preview, File cacheDir) {
if (cacheEnable) {
Cache cache = getCache(context, cacheDir);
return new CacheDataSourceFactory(cache, getDataSourceFactory(context, preview), CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
} else {
return getDataSourceFactory(context, preview);
Cache cache = getCacheSingleInstance(context, cacheDir);
if (cache != null) {
isCached = resolveCacheState(cache, mDataSource);
return new CacheDataSourceFactory(cache, getDataSourceFactory(context, preview), CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
}
}
return getDataSourceFactory(context, preview);
}
/**
......@@ -170,4 +217,32 @@ public class ExoSourceManager {
}
return dataSourceFactory;
}
/**
* 根据缓存块判断是否缓存成功
*
* @param cache
*/
private static boolean resolveCacheState(Cache cache, String url) {
boolean isCache = true;
if (!TextUtils.isEmpty(url)) {
String key = CacheUtil.generateKey(Uri.parse(url));
if (!TextUtils.isEmpty(key)) {
NavigableSet<CacheSpan> cachedSpans = cache.getCachedSpans(key);
if (cachedSpans.size() == 0) {
isCache = false;
} else {
long contentLength = cache.getContentLength(key);
long currentLength = 0;
for (CacheSpan cachedSpan : cachedSpans) {
currentLength += cache.getCachedLength(key, cachedSpan.position, cachedSpan.length);
}
isCache = currentLength >= contentLength;
}
} else {
isCache = false;
}
}
return isCache;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册