Commit 27bad919b096000e8c4443695db3ed5d6e6dd749

Authored by YangShuai
1 parent c11cdbc9

1 视频新增边看边缓存功能

Showing 17 changed files with 274 additions and 86 deletions
.idea/inspectionProfiles/Project_Default.xml 0 → 100644
  1 +<component name="InspectionProjectProfileManager">
  2 + <profile version="1.0">
  3 + <option name="myName" value="Project Default" />
  4 + <inspection_tool class="AndroidLintLockedOrientationActivity" enabled="false" level="ERROR" enabled_by_default="false" />
  5 + <inspection_tool class="AndroidLintSourceLockedOrientationActivity" enabled="false" level="ERROR" enabled_by_default="false" />
  6 + </profile>
  7 +</component>
0 8 \ No newline at end of file
... ...
app/strike/src/main/AndroidManifest.xml
... ... @@ -34,20 +34,20 @@
34 34 </provider>
35 35 <activity
36 36 android:name="com.cnlive.strike.demo.activity.tiktok.TikTokViewPager2Activity"
37   - android:screenOrientation="fullSensor" />
  37 + android:screenOrientation="portrait" />
38 38 <activity
39 39 android:name="com.cnlive.strike.demo.activity.tiktok.TikTokRecycleActivity"
40   - android:screenOrientation="fullSensor" />
  40 + android:screenOrientation="portrait" />
41 41 <activity
42 42 android:name="com.cnlive.strike.demo.activity.tiktok.DemoTikTokActivity"
43   - android:screenOrientation="fullSensor" />
  43 + android:screenOrientation="portrait" />
44 44 <activity
45 45 android:name="com.cnlive.strike.demo.activity.tiktok.TikTokVerticalViewPagerActivity"
46   - android:screenOrientation="fullSensor" />
  46 + android:screenOrientation="portrait"/>
47 47 <activity
48 48 android:name="com.cnlive.strike.demo.activity.ExoPlayerActivity"
49 49 android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
50   - android:screenOrientation="fullSensor" />
  50 + android:screenOrientation="portrait" />
51 51 <activity android:name="com.cnlive.strike.demo.activity.CNplayerActivity" />
52 52 <activity android:name="com.cnlive.strike.demo.activity.DemoAnimActivity" />
53 53 <activity
... ...
app/strike/src/main/java/com/cnlive/strike/DemoApplication.java
... ... @@ -101,7 +101,7 @@ public class DemoApplication extends BaseApplication {
101 101 // .setPlayerFactory(ThunderMediaPlayerFactory.create())
102 102 .setPlayerFactory(ExoMediaPlayerFactory.create())
103 103 .setRenderViewFactory(TextureRenderViewFactory.create())
104   - .setEnableOrientation(true)
  104 + .setEnableOrientation(false)
105 105 // .setEnableAudioFocus(false)
106 106 // .setScreenScaleType(VideoView.SCREEN_SCALE_MATCH_PARENT)
107 107 // .setAdaptCutout(false)
... ...
app/strike/src/main/java/com/cnlive/strike/demo/activity/ExoPlayerActivity.java
... ... @@ -18,10 +18,13 @@ import com.google.android.exoplayer2.source.hls.HlsMediaSource;
18 18 import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
19 19 import com.google.android.exoplayer2.util.Util;
20 20 import com.google.android.exoplayer2.video.VideoListener;
  21 +import com.libs.video.util.cache.PreloadManager;
21 22 import com.libs.video.util.cache.ProxyVideoCacheManager;
22 23 import com.libs.video.video.exoplayer.component.DefaultErrorView;
23 24 import com.libs.video.video.exoplayer.component.DefaultYoukuPrepareView;
24 25 import com.libs.video.video.exoplayer.play.CNVideoView;
  26 +import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaSourceHelper;
  27 +import com.libs.video.video.exoplayer.util.PlayCacheUtils;
25 28 import com.libs.video.video.test.CNLiveVideoView;
26 29 import com.libs.video.video.test.VideoPlayer;
27 30 import com.libs.video.video.exoplayer.component.DefaultAdControlView;
... ... @@ -44,6 +47,7 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
44 47 private static final String URL_AD = "https://gslb.miaopai.com/stream/IR3oMYDhrON5huCmf7sHCfnU5YKEkgO2.mp4";
45 48  
46 49 private StandardVideoController mController;
  50 + private PreloadManager mPreloadManager;
47 51  
48 52 @Override
49 53 protected int getBindLayoutId() {
... ... @@ -82,7 +86,6 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
82 86 player.prepare(hlsMediaSource);
83 87  
84 88  
85   -
86 89 mController = new StandardVideoController(this);
87 90 DefaultAdControlView adControlView = new DefaultAdControlView(this);
88 91 adControlView.setListener(new DefaultAdControlView.AdControlListener() {
... ... @@ -96,15 +99,13 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
96 99 playVideo();
97 100 }
98 101 });
99   - DefaultErrorView errorView=new DefaultErrorView(this);
100   - mController.addControlComponent(adControlView,new DefaultYoukuPrepareView(me),errorView);
  102 + DefaultErrorView errorView = new DefaultErrorView(this);
  103 + mController.addControlComponent(adControlView, new DefaultYoukuPrepareView(me), errorView);
101 104 //直播
102   - HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this);
103   - String proxyUrl = cacheServer.getProxyUrl(URL_AD);
104   - binding.playerView.setUrl(proxyUrl);
105   -// binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
  105 +// binding.playerView.setUrl(proxyUrl);
  106 + binding.playerView.setUrl("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8", true);
106 107 binding.playerView.setVideoController(mController);
107   - binding.playerView.setScreenScaleType(CNVideoView.SCREEN_SCALE_16_9);
  108 +// binding.playerView.setScreenScaleType(CNVideoView.SCREEN_SCALE_16_9);
108 109 binding.playerView.start();
109 110 //监听播放结束
110 111 // binding.playerView.addOnStateChangeListener(new CNVideoView.SimpleOnStateChangeListener() {
... ... @@ -154,7 +155,7 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
154 155 private void playVideo() {
155 156 binding.playerView.release();
156 157 mController.removeAllControlComponent();
157   - mController.addDefaultControlComponent("正片", true);
  158 + mController.addDefaultControlComponent("正片", false);
158 159 //重新设置数据
159 160 // List<String> list = new ArrayList<>();
160 161 // list.add("http://sbslive.cnrmobile.com/storage/storage4/76/23/10/14de52115893fb5371b7e064f910ab7b.3gp");
... ... @@ -162,8 +163,8 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
162 163 // list.add("http://ffyl.vods2.cnlive.com/223/vod/2018/1120/223_88c98ab1395f4762b703fbdd9d59d2e5/ff80808166c2a45201672f14a9933131_800.m3u8");
163 164 // list.add("http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8");
164 165 // binding.playerView.setDataSource(list);
165   - binding.playerView.setUrl("rtmp://tyzg.rtmps2.cnlive.com/live-tyzg-577/577_999");
166   -
  166 + binding.playerView.setUrl("https://qq.com-ok-qq.com/20191005/24249_f5e36323/index.m3u8", true);
  167 +// binding.playerView.setUrl("rtmp://tyzg.rtmps2.cnlive.com/live-tyzg-577/577_999");
167 168 //开始播放
168 169 binding.playerView.start();
169 170 }
... ... @@ -187,4 +188,6 @@ public class ExoPlayerActivity extends BaseActivity implements VideoListener, Pl
187 188 // });
188 189 }
189 190  
  191 +
  192 +
190 193 }
... ...
cloud/video/src/main/java/com/danikula/videocache/StorageUtils.java
... ... @@ -37,7 +37,7 @@ public final class StorageUtils {
37 37 * <i>("/Android/data/[app_package_name]/cache")</i> (if card is mounted and app has appropriate permission) or
38 38 * on device's file system depending incoming parameters.
39 39 *
40   - * @param context Application context
  40 + * @param context Application context
41 41 * @return Cache {@link File directory}.<br />
42 42 * <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
43 43 * {@link Context#getCacheDir() Context.getCacheDir()} returns null).
... ... @@ -58,6 +58,26 @@ public final class StorageUtils {
58 58 }
59 59  
60 60 /**
  61 + * 获取缓存路径
  62 + *
  63 + * @param context
  64 + * @return
  65 + */
  66 + public static String getCacheDirectoryPath(Context context) {
  67 + String appCacheDir = null;
  68 + if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
  69 + appCacheDir = context.getExternalCacheDir().getAbsolutePath();
  70 + }
  71 + if (appCacheDir == null) {
  72 + appCacheDir = context.getCacheDir().getAbsolutePath();
  73 + }
  74 + if (appCacheDir == null) {
  75 + appCacheDir = "/data/data/" + context.getPackageName() + "/cache/";
  76 + }
  77 + return appCacheDir;
  78 + }
  79 +
  80 + /**
61 81 * delete directory
62 82 */
63 83 public static boolean deleteFiles(File root) {
... ...
cloud/video/src/main/java/com/libs/video/util/cache/ProxyVideoCacheManager.java
... ... @@ -20,7 +20,7 @@ public class ProxyVideoCacheManager {
20 20  
21 21 private static HttpProxyCacheServer newProxy(Context context) {
22 22 return new HttpProxyCacheServer.Builder(context)
23   - .maxCacheSize(512 * 1024 * 1024) // 512MB for cache
  23 + .maxCacheSize(1024 * 1024 * 1024) // 512MB for cache
24 24 //缓存路径,不设置默认在sd_card/Android/data/[app_package_name]/cache中
25 25 // .cacheDirectory()
26 26 .build();
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/PlayErrorException.java
... ... @@ -5,8 +5,6 @@ import android.text.TextUtils;
5 5  
6 6 import androidx.annotation.IntDef;
7 7  
8   -import com.cnlive.core.libs.base.util.StatusBarConfig;
9   -
10 8 import java.lang.annotation.Retention;
11 9 import java.lang.annotation.RetentionPolicy;
12 10  
... ... @@ -19,26 +17,20 @@ public class PlayErrorException extends Exception {
19 17 public static final int TYPE_OUT_OF_MEMORY = 2;//内存溢出
20 18 public static final int TYPE_UNEXPECTED_ERROR = 3;//未知错误
21 19 public static final int TYPE_RENDERER_ERROR = 4;//渲染异常
22   - public static final int TYPE_MediaPlayer_IOException = 5;
23   - public static final int TYPE_MediaPlayer_IllegalArgumentException = 6;
24   - public static final int TYPE_MediaPlayer_SecurityException = 7;
25   - public static final int TYPE_MediaPlayer_IllegalStateException = 8;
26   - public static final int TYPE_MediaPlayer_unknownException = 9;
27   - public static final int TYPE_MediaPlayer_ON_ERROR = 10;
28   -
29   -
  20 + public static final int TYPE_IllegalArgumentException = 5;
  21 + public static final int TYPE_SecurityException = 6;
  22 + public static final int TYPE_IllegalStateException = 7;
  23 + public static final int TYPE_TIMED_OUT_ERROR = 9;//播放超时错误
  24 + public static final int TYPE_MEDIA_UNSUPPORTED_ERROR = 10;//不支持的媒体类型
  25 + public static final int TYPE_MEDIA_SERVER_DIED_ERROR = 11;//媒体服务器挂机(应用必须释放对象,然后开启新的实例)
  26 + public static final int TYPE_OTHER_ERROR = 12;//其他错误
30 27 private int errorType;//错误类型
31 28 private String errorMsg;//错误信息
32 29  
33 30  
34   - private MediaPlayer mediaPlayer;
35   - private int mediaPlayer_what;
36   - private int mediaPlayer_extra;
37   -
38   -
39 31 @IntDef({TYPE_NETWORK_ERROR, TYPE_SOURCE_ERROR, TYPE_OUT_OF_MEMORY, TYPE_UNEXPECTED_ERROR, TYPE_RENDERER_ERROR,
40   - TYPE_MediaPlayer_IOException, TYPE_MediaPlayer_IllegalArgumentException, TYPE_MediaPlayer_SecurityException,
41   - TYPE_MediaPlayer_IllegalStateException, TYPE_MediaPlayer_unknownException, TYPE_MediaPlayer_ON_ERROR})
  32 + TYPE_IllegalArgumentException, TYPE_SecurityException, TYPE_IllegalStateException,
  33 + TYPE_TIMED_OUT_ERROR,TYPE_MEDIA_UNSUPPORTED_ERROR,TYPE_MEDIA_SERVER_DIED_ERROR,TYPE_OTHER_ERROR})
42 34 @Retention(RetentionPolicy.SOURCE)
43 35 public @interface Type {
44 36 }
... ... @@ -70,27 +62,4 @@ public class PlayErrorException extends Exception {
70 62 this.errorMsg = errorMsg;
71 63 }
72 64  
73   - public MediaPlayer getMediaPlayer() {
74   - return mediaPlayer;
75   - }
76   -
77   - public void setMediaPlayer(MediaPlayer mediaPlayer) {
78   - this.mediaPlayer = mediaPlayer;
79   - }
80   -
81   - public int getMediaPlayer_what() {
82   - return mediaPlayer_what;
83   - }
84   -
85   - public void setMediaPlayer_what(int mediaPlayer_what) {
86   - this.mediaPlayer_what = mediaPlayer_what;
87   - }
88   -
89   - public int getMediaPlayer_extra() {
90   - return mediaPlayer_extra;
91   - }
92   -
93   - public void setMediaPlayer_extra(int mediaPlayer_extra) {
94   - this.mediaPlayer_extra = mediaPlayer_extra;
95   - }
96 65 }
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/component/DebugInfoView.java
... ... @@ -13,7 +13,7 @@ import android.widget.TextView;
13 13 import com.libs.video.video.exoplayer.PlayErrorException;
14 14 import com.libs.video.video.exoplayer.controller.ControlWrapper;
15 15 import com.libs.video.video.exoplayer.controller.IControlComponent;
16   -import com.libs.video.video.exoplayer.play.AndroidMediaPlayerFactory;
  16 +import com.libs.video.video.exoplayer.playerCore.mediaplayer.AndroidMediaPlayerFactory;
17 17 import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaPlayerFactory;
18 18 import com.libs.video.video.exoplayer.util.PlayerUtils;
19 19  
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/controller/MediaPlayerControl.java
... ... @@ -9,7 +9,6 @@ import com.libs.video.video.exoplayer.play.AbstractPlayer;
9 9 */
10 10 public interface MediaPlayerControl {
11 11  
12   -// int getMediaCount();
13 12  
14 13 void start();
15 14  
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/AbstractPlayer.java
1 1 package com.libs.video.video.exoplayer.play;
2 2  
  3 +import android.content.Context;
3 4 import android.content.res.AssetFileDescriptor;
4 5 import android.view.Surface;
5 6 import android.view.SurfaceHolder;
... ... @@ -53,11 +54,29 @@ public abstract class AbstractPlayer {
53 54 */
54 55 public abstract void setDataSource(String path, Map<String, String> headers);
55 56  
  57 +
  58 + public abstract void setDataSource(String path, Map<String, String> headers, boolean isCache);
  59 +
56 60 /**
57 61 * 用于播放raw和asset里面的视频文件
58 62 */
59 63 public abstract void setDataSource(AssetFileDescriptor fd);
60 64  
  65 +// /**
  66 +// * 清除全部视频缓存
  67 +// *
  68 +// * @param context
  69 +// */
  70 +// public abstract void clearAllCache(Context context);
  71 +//
  72 +// /**
  73 +// * 根据url清除指定视频缓存
  74 +// *
  75 +// * @param context
  76 +// * @param url
  77 +// */
  78 +// public abstract void clearDefaultCache(Context context, String url);
  79 +
61 80 /**
62 81 * 播放
63 82 */
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/CNVideoView.java
... ... @@ -128,6 +128,8 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
128 128 */
129 129 private int mPlayerBackgroundColor;
130 130  
  131 + private boolean isCache;//是否边缓存边播放
  132 +
131 133 // private List<String> dataSource;
132 134 // private int curentPlayIndex;
133 135  
... ... @@ -237,7 +239,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
237 239 if (mProgressManager != null) {
238 240 mCurrentPosition = mProgressManager.getSavedProgress(mUrl);
239 241 }
240   - initPlayer();
  242 + initPlayer();
241 243 //添加渲染视图
242 244 addDisplay();
243 245 startPrepare(false);
... ... @@ -272,7 +274,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
272 274 * 初始化播放器
273 275 */
274 276 protected void initPlayer() {
275   - if (null==mMediaPlayer){
  277 + if (null == mMediaPlayer) {
276 278 //初始化播放器
277 279 mMediaPlayer = mPlayerFactory.createPlayer(getContext());
278 280 }
... ... @@ -341,7 +343,7 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
341 343 mMediaPlayer.setDataSource(mAssetFileDescriptor);
342 344 return true;
343 345 } else if (!TextUtils.isEmpty(mUrl)) {
344   - mMediaPlayer.setDataSource(mUrl, mHeaders);
  346 + mMediaPlayer.setDataSource(mUrl, mHeaders, isCache);
345 347 return true;
346 348 }
347 349 return false;
... ... @@ -657,13 +659,24 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
657 659 /**
658 660 * 设置视频地址
659 661 */
660   - public void setUrl(String url) {
  662 + public void setUrl(String url, boolean isCache) {
  663 + this.isCache = isCache;
661 664 // dataSource.clear();
662 665 // dataSource.add(url);
663 666 // curentPlayIndex = 0;
664 667 setUrl(url, null);
665 668 }
666 669  
  670 + /**
  671 + * 设置视频地址
  672 + */
  673 + public void setUrl(String url) {
  674 + this.isCache = false;
  675 +// dataSource.clear();
  676 +// dataSource.add(url);
  677 +// curentPlayIndex = 0;
  678 + setUrl(url, null);
  679 + }
667 680 // public void setDataSource(List<String> url) {
668 681 // dataSource.clear();
669 682 // dataSource.addAll(url);
... ... @@ -944,14 +957,14 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
944 957 * 设置控制器,传null表示移除控制器
945 958 */
946 959 public void setVideoController(@Nullable BaseVideoController mediaController) {
947   - if (null==mMediaPlayer){
  960 + if (null == mMediaPlayer) {
948 961 //初始化播放器
949 962 mMediaPlayer = mPlayerFactory.createPlayer(getContext());
950 963 }
951 964 mPlayerContainer.removeView(mVideoController);
952 965 mVideoController = mediaController;
953 966 if (mediaController != null) {
954   - mediaController.setMediaPlayer(this,mMediaPlayer);
  967 + mediaController.setMediaPlayer(this, mMediaPlayer);
955 968 LayoutParams params = new LayoutParams(
956 969 ViewGroup.LayoutParams.MATCH_PARENT,
957 970 ViewGroup.LayoutParams.MATCH_PARENT);
... ... @@ -1150,8 +1163,9 @@ public class CNVideoView&lt;P extends AbstractPlayer&gt; extends FrameLayout
1150 1163 /**
1151 1164 * 视频缩放类型
1152 1165 */
1153   - @IntDef({SCREEN_SCALE_DEFAULT,SCREEN_SCALE_16_9,SCREEN_SCALE_4_3,SCREEN_SCALE_MATCH_PARENT,SCREEN_SCALE_ORIGINAL,SCREEN_SCALE_CENTER_CROP})
  1166 + @IntDef({SCREEN_SCALE_DEFAULT, SCREEN_SCALE_16_9, SCREEN_SCALE_4_3, SCREEN_SCALE_MATCH_PARENT, SCREEN_SCALE_ORIGINAL, SCREEN_SCALE_CENTER_CROP})
1154 1167 @Retention(RetentionPolicy.SOURCE)
1155 1168 public @interface screenScalType {
1156 1169 }
  1170 +
1157 1171 }
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/VideoViewConfig.java
... ... @@ -2,6 +2,7 @@ package com.libs.video.video.exoplayer.play;
2 2  
3 3  
4 4  
  5 +import com.libs.video.video.exoplayer.playerCore.mediaplayer.AndroidMediaPlayerFactory;
5 6 import com.libs.video.video.exoplayer.render.RenderViewFactory;
6 7 import com.libs.video.video.exoplayer.render.texture.TextureRenderViewFactory;
7 8  
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/playerCore/exoplayer/ExoMediaPlayer.java
... ... @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.video.VideoListener;
31 31 import com.libs.video.video.exoplayer.PlayErrorException;
32 32 import com.libs.video.video.exoplayer.play.AbstractPlayer;
33 33 import com.libs.video.video.exoplayer.play.VideoViewManager;
  34 +import com.libs.video.video.exoplayer.util.PlayCacheUtils;
34 35  
35 36 import java.util.Map;
36 37  
... ... @@ -80,7 +81,6 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
80 81 Clock.DEFAULT)
81 82 .build();
82 83 setOptions();
83   -
84 84 //播放器日志
85 85 if (VideoViewManager.getConfig().mIsEnableLog && mTrackSelector instanceof MappingTrackSelector) {
86 86 exoPlayer.addAnalyticsListener(new EventLogger((MappingTrackSelector) mTrackSelector, "ExoPlayer"));
... ... @@ -114,10 +114,16 @@ public class ExoMediaPlayer extends AbstractPlayer implements VideoListener, Pla
114 114 }
115 115  
116 116 @Override
  117 + public void setDataSource(String path, Map<String, String> headers, boolean isCache) {
  118 + mMediaSource = mMediaSourceHelper.getMediaSource(path, headers,isCache);
  119 + }
  120 +
  121 + @Override
117 122 public void setDataSource(AssetFileDescriptor fd) {
118 123 //no support
119 124 }
120 125  
  126 +
121 127 @Override
122 128 public void start() {
123 129 if (exoPlayer == null)
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/playerCore/exoplayer/ExoMediaSourceHelper.java
... ... @@ -4,6 +4,7 @@ import android.content.Context;
4 4 import android.net.Uri;
5 5 import android.text.TextUtils;
6 6  
  7 +import com.danikula.videocache.StorageUtils;
7 8 import com.google.android.exoplayer2.C;
8 9 import com.google.android.exoplayer2.database.ExoDatabaseProvider;
9 10 import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
... ... @@ -36,6 +37,8 @@ public final class ExoMediaSourceHelper {
36 37 private Context mAppContext;
37 38 private HttpDataSource.Factory mHttpDataSourceFactory;
38 39 private Cache mCache;
  40 + private final int CACHE_SIZE = 1024;//缓存大小1G
  41 + public static final String CACHE_DIR = "exo-video-cache";
39 42  
40 43 private ExoMediaSourceHelper(Context context) {
41 44 mAppContext = context.getApplicationContext();
... ... @@ -117,11 +120,15 @@ public final class ExoMediaSourceHelper {
117 120 CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
118 121 }
119 122  
120   - private Cache newCache() {
121   - return new SimpleCache(
122   - new File(mAppContext.getExternalCacheDir(), "exo-video-cache"),//缓存目录
123   - new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现
124   - new ExoDatabaseProvider(mAppContext));
  123 + public Cache newCache() {
  124 + if (null == mCache) {
  125 + return new SimpleCache(
  126 + new File(StorageUtils.getCacheDirectoryPath(mAppContext), CACHE_DIR),//缓存目录
  127 + new LeastRecentlyUsedCacheEvictor(CACHE_SIZE * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现
  128 + new ExoDatabaseProvider(mAppContext));
  129 + } else {
  130 + return mCache;
  131 + }
125 132 }
126 133  
127 134 /**
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/AndroidMediaPlayer.java renamed to cloud/video/src/main/java/com/libs/video/video/exoplayer/playerCore/mediaplayer/AndroidMediaPlayer.java
1   -package com.libs.video.video.exoplayer.play;
  1 +package com.libs.video.video.exoplayer.playerCore.mediaplayer;
2 2  
3 3 import android.content.Context;
4 4 import android.content.res.AssetFileDescriptor;
... ... @@ -6,10 +6,16 @@ import android.media.AudioManager;
6 6 import android.media.MediaPlayer;
7 7 import android.net.Uri;
8 8 import android.os.Build;
  9 +import android.text.TextUtils;
9 10 import android.view.Surface;
10 11 import android.view.SurfaceHolder;
11 12  
  13 +import com.danikula.videocache.HttpProxyCacheServer;
  14 +import com.danikula.videocache.StorageUtils;
  15 +import com.libs.video.util.cache.ProxyVideoCacheManager;
12 16 import com.libs.video.video.exoplayer.PlayErrorException;
  17 +import com.libs.video.video.exoplayer.play.AbstractPlayer;
  18 +import com.libs.video.video.exoplayer.util.PlayCacheUtils;
13 19  
14 20 import java.io.IOException;
15 21 import java.util.Map;
... ... @@ -48,6 +54,20 @@ public class AndroidMediaPlayer extends AbstractPlayer {
48 54 }
49 55  
50 56 @Override
  57 + public void setDataSource(String path, Map<String, String> headers, boolean isCache) {
  58 + try {
  59 + if (isCache) {
  60 + mMediaPlayer.setDataSource(mAppContext, Uri.parse(PlayCacheUtils.getCachePath(mAppContext,path)), headers);
  61 + } else {
  62 + //不缓存
  63 + mMediaPlayer.setDataSource(mAppContext, Uri.parse(path), headers);
  64 + }
  65 + } catch (IOException e) {
  66 + e.printStackTrace();
  67 + }
  68 + }
  69 +
  70 + @Override
51 71 public void setDataSource(AssetFileDescriptor fd) {
52 72 try {
53 73 mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
... ... @@ -56,6 +76,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
56 76 }
57 77 }
58 78  
  79 +
59 80 /**
60 81 * 获取当前异常
61 82 *
... ... @@ -64,15 +85,16 @@ public class AndroidMediaPlayer extends AbstractPlayer {
64 85 private void getException(Exception e) {
65 86 PlayErrorException errorException = null;
66 87 if (e instanceof IOException) {
67   - errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IOException, e.getMessage());
  88 + //资源错误
  89 + errorException = new PlayErrorException(PlayErrorException.TYPE_SOURCE_ERROR, e.getMessage());
68 90 } else if (e instanceof IllegalArgumentException) {
69   - errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalArgumentException, e.getMessage());
  91 + errorException = new PlayErrorException(PlayErrorException.TYPE_IllegalArgumentException, e.getMessage());
70 92 } else if (e instanceof SecurityException) {
71   - errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_SecurityException, e.getMessage());
  93 + errorException = new PlayErrorException(PlayErrorException.TYPE_SecurityException, e.getMessage());
72 94 } else if (e instanceof IllegalStateException) {
73   - errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalStateException, e.getMessage());
  95 + errorException = new PlayErrorException(PlayErrorException.TYPE_IllegalStateException, e.getMessage());
74 96 } else {
75   - errorException = new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_unknownException, e.getMessage());
  97 + errorException = new PlayErrorException(PlayErrorException.TYPE_UNEXPECTED_ERROR, e.getMessage());
76 98 }
77 99 mPlayerEventListener.onError(errorException);
78 100 }
... ... @@ -132,7 +154,7 @@ public class AndroidMediaPlayer extends AbstractPlayer {
132 154 try {
133 155 mMediaPlayer.seekTo((int) time);
134 156 } catch (IllegalStateException e) {
135   - mPlayerEventListener.onError(new PlayErrorException(PlayErrorException.TYPE_MediaPlayer_IllegalStateException, e.getMessage()));
  157 + mPlayerEventListener.onError(new PlayErrorException(PlayErrorException.TYPE_IllegalStateException, e.getMessage()));
136 158  
137 159 }
138 160 }
... ... @@ -226,10 +248,28 @@ public class AndroidMediaPlayer extends AbstractPlayer {
226 248 @Override
227 249 public boolean onError(MediaPlayer mp, int what, int extra) {
228 250 PlayErrorException errorException = new PlayErrorException();
229   - errorException.setErrorType(PlayErrorException.TYPE_MediaPlayer_ON_ERROR);
230   - errorException.setMediaPlayer(mp);
231   - errorException.setMediaPlayer_what(what);
232   - errorException.setMediaPlayer_extra(extra);
  251 + switch (what) {
  252 + //播放超时错误
  253 + case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
  254 + errorException.setErrorType(PlayErrorException.TYPE_TIMED_OUT_ERROR);
  255 + errorException.setErrorMsg("播放超时错误");
  256 + break;
  257 + //不支持的媒体类型
  258 + case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
  259 + errorException.setErrorType(PlayErrorException.TYPE_MEDIA_UNSUPPORTED_ERROR);
  260 + errorException.setErrorMsg("不支持的媒体类型");
  261 + break;
  262 + //媒体服务器挂机(应用必须释放对象,然后开启新的实例)
  263 + case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
  264 + errorException.setErrorType(PlayErrorException.TYPE_MEDIA_SERVER_DIED_ERROR);
  265 + errorException.setErrorMsg("媒体服务器挂机(应用必须释放对象,然后开启新的实例)");
  266 + break;
  267 + default:
  268 + errorException.setErrorType(PlayErrorException.TYPE_OTHER_ERROR);
  269 + errorException.setErrorMsg("其他错误:" + what);
  270 + break;
  271 + }
  272 +
233 273 mPlayerEventListener.onError(errorException);
234 274 return true;
235 275 }
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/play/AndroidMediaPlayerFactory.java renamed to cloud/video/src/main/java/com/libs/video/video/exoplayer/playerCore/mediaplayer/AndroidMediaPlayerFactory.java
1   -package com.libs.video.video.exoplayer.play;
  1 +package com.libs.video.video.exoplayer.playerCore.mediaplayer;
2 2  
3 3 import android.content.Context;
4 4  
  5 +import com.libs.video.video.exoplayer.play.PlayerFactory;
  6 +
5 7 public class AndroidMediaPlayerFactory extends PlayerFactory<AndroidMediaPlayer> {
6 8  
7 9 public static AndroidMediaPlayerFactory create() {
... ...
cloud/video/src/main/java/com/libs/video/video/exoplayer/util/PlayCacheUtils.java 0 → 100644
  1 +package com.libs.video.video.exoplayer.util;
  2 +
  3 +import android.content.Context;
  4 +import android.text.TextUtils;
  5 +
  6 +import com.danikula.videocache.HttpProxyCacheServer;
  7 +import com.danikula.videocache.StorageUtils;
  8 +import com.libs.video.util.cache.ProxyVideoCacheManager;
  9 +import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaPlayerFactory;
  10 +import com.libs.video.video.exoplayer.playerCore.exoplayer.ExoMediaSourceHelper;
  11 +import com.libs.video.video.exoplayer.playerCore.mediaplayer.AndroidMediaPlayerFactory;
  12 +
  13 +import java.io.File;
  14 +
  15 +/**
  16 + * 播放缓存工具
  17 + */
  18 +public class PlayCacheUtils {
  19 + public static String getCachePath(Context mAppContext, String path) {
  20 + String result = "";
  21 + if (null == mAppContext || TextUtils.isEmpty(path)) {
  22 + return result;
  23 + }
  24 + if (path.contains("m3u8")) {
  25 + result = path;
  26 + } else if (null != mAppContext && !TextUtils.isDigitsOnly(path) && !path.contains(StorageUtils.getCacheDirectoryPath(mAppContext))) {
  27 + HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(mAppContext);
  28 + if (!cacheServer.isCached(path)) {
  29 + String proxyUrl = cacheServer.getProxyUrl(path);
  30 + result = proxyUrl;
  31 + }
  32 + }
  33 + return result;
  34 + }
  35 +
  36 + /**
  37 + * 目前exoplayer是全部删除
  38 + *
  39 + * @param context
  40 + * @param url
  41 + */
  42 + public void clearDefaultCache(Context context, String url) {
  43 + //获取当前播放核心
  44 + Object object = PlayerFactoryUtils.getCurrentPlayerFactory();
  45 + if (null != object) {
  46 + if (object instanceof ExoMediaPlayerFactory) {
  47 + File file = new File(StorageUtils.getCacheDirectoryPath(context), ExoMediaSourceHelper.CACHE_DIR);//缓存目录
  48 + if (null == file) {
  49 + return;
  50 + }
  51 + if (file.exists()) {
  52 + deleteFile(file);
  53 + }
  54 + } else if (object instanceof AndroidMediaPlayerFactory) {
  55 + ProxyVideoCacheManager.clearDefaultCache(context, url);
  56 + }
  57 + }
  58 + }
  59 +
  60 + public static void clearAllCache(Context context) {
  61 + //获取当前播放核心
  62 +// Object object = PlayerFactoryUtils.getCurrentPlayerFactory();
  63 +// if (null != object) {
  64 +// if (object instanceof ExoMediaPlayerFactory) {
  65 + File file = new File(StorageUtils.getCacheDirectoryPath(context), ExoMediaSourceHelper.CACHE_DIR);//缓存目录
  66 + if (null == file) {
  67 + return;
  68 + }
  69 + if (file.exists()) {
  70 + deleteFile(file);
  71 + }
  72 +// } else if (object instanceof AndroidMediaPlayerFactory) {
  73 + ProxyVideoCacheManager.clearAllCache(context);
  74 +// }
  75 +// }
  76 +
  77 +
  78 + }
  79 +
  80 + /**
  81 + * 删除文件
  82 + *
  83 + * @param file
  84 + */
  85 + private static void deleteFile(File file) {
  86 + if (file.exists()) { // 判断文件是否存在
  87 + if (file.isFile()) { // 判断是否是文件
  88 + file.delete(); // delete()方法 你应该知道 是删除的意思;
  89 + } else if (file.isDirectory()) { // 否则如果它是一个目录
  90 + File files[] = file.listFiles(); // 声明目录下所有的文件 files[];
  91 + for (File file1 : files) { // 遍历目录下所有的文件
  92 + deleteFile(file1); // 把每个文件 用这个方法进行迭代
  93 + }
  94 + }
  95 + file.delete();
  96 + } else {
  97 +
  98 + }
  99 + }
  100 +
  101 +}
... ...