You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
6.8 KiB
183 lines
6.8 KiB
package xyz.doikki.videoplayer.exo;
|
|
|
|
import android.content.Context;
|
|
import android.net.Uri;
|
|
import android.text.TextUtils;
|
|
|
|
import com.google.android.exoplayer2.C;
|
|
import com.google.android.exoplayer2.MediaItem;
|
|
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
|
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource;
|
|
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
|
|
import com.google.android.exoplayer2.source.MediaSource;
|
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
|
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
|
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
|
import com.google.android.exoplayer2.source.rtsp.RtspMediaSource;
|
|
import com.google.android.exoplayer2.upstream.DataSource;
|
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
|
import com.google.android.exoplayer2.upstream.cache.Cache;
|
|
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
|
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.lang.reflect.Field;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
|
|
import okhttp3.OkHttpClient;
|
|
|
|
public final class ExoMediaSourceHelper {
|
|
|
|
private static ExoMediaSourceHelper sInstance;
|
|
|
|
private final String mUserAgent;
|
|
private final Context mAppContext;
|
|
private OkHttpDataSource.Factory mHttpDataSourceFactory;
|
|
private OkHttpClient mOkClient = null;
|
|
private Cache mCache;
|
|
|
|
private ExoMediaSourceHelper(Context context) {
|
|
mAppContext = context.getApplicationContext();
|
|
mUserAgent = Util.getUserAgent(mAppContext, mAppContext.getApplicationInfo().name);
|
|
}
|
|
|
|
public static ExoMediaSourceHelper getInstance(Context context) {
|
|
if (sInstance == null) {
|
|
synchronized (ExoMediaSourceHelper.class) {
|
|
if (sInstance == null) {
|
|
sInstance = new ExoMediaSourceHelper(context);
|
|
}
|
|
}
|
|
}
|
|
return sInstance;
|
|
}
|
|
|
|
public void setOkClient(OkHttpClient client) {
|
|
mOkClient = client;
|
|
}
|
|
|
|
public MediaSource getMediaSource(String uri) {
|
|
return getMediaSource(uri, null, false);
|
|
}
|
|
|
|
public MediaSource getMediaSource(String uri, Map<String, String> headers) {
|
|
return getMediaSource(uri, headers, false);
|
|
}
|
|
|
|
public MediaSource getMediaSource(String uri, boolean isCache) {
|
|
return getMediaSource(uri, null, isCache);
|
|
}
|
|
|
|
public MediaSource getMediaSource(String uri, Map<String, String> headers, boolean isCache) {
|
|
Uri contentUri = Uri.parse(uri);
|
|
if ("rtmp".equals(contentUri.getScheme())) {
|
|
return new ProgressiveMediaSource.Factory(new RtmpDataSourceFactory(null))
|
|
.createMediaSource(MediaItem.fromUri(contentUri));
|
|
} else if ("rtsp".equals(contentUri.getScheme())) {
|
|
return new RtspMediaSource.Factory().createMediaSource(MediaItem.fromUri(contentUri));
|
|
}
|
|
int contentType = inferContentType(uri);
|
|
DataSource.Factory factory;
|
|
if (isCache) {
|
|
factory = getCacheDataSourceFactory();
|
|
} else {
|
|
factory = getDataSourceFactory();
|
|
}
|
|
if (mHttpDataSourceFactory != null) {
|
|
setHeaders(headers);
|
|
}
|
|
switch (contentType) {
|
|
case C.TYPE_DASH:
|
|
return new DashMediaSource.Factory(factory).createMediaSource(MediaItem.fromUri(contentUri));
|
|
case C.TYPE_HLS:
|
|
return new HlsMediaSource.Factory(factory).createMediaSource(MediaItem.fromUri(contentUri));
|
|
default:
|
|
case C.TYPE_OTHER:
|
|
return new ProgressiveMediaSource.Factory(factory).createMediaSource(MediaItem.fromUri(contentUri));
|
|
}
|
|
}
|
|
|
|
private int inferContentType(String fileName) {
|
|
fileName = fileName.toLowerCase();
|
|
if (fileName.contains(".mpd") || fileName.contains("type=mpd")) {
|
|
return C.TYPE_DASH;
|
|
} else if (fileName.contains("m3u8")) {
|
|
return C.TYPE_HLS;
|
|
} else {
|
|
return C.TYPE_OTHER;
|
|
}
|
|
}
|
|
|
|
private DataSource.Factory getCacheDataSourceFactory() {
|
|
if (mCache == null) {
|
|
mCache = newCache();
|
|
}
|
|
return new CacheDataSource.Factory()
|
|
.setCache(mCache)
|
|
.setUpstreamDataSourceFactory(getDataSourceFactory())
|
|
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR);
|
|
}
|
|
|
|
private Cache newCache() {
|
|
return new SimpleCache(
|
|
new File(mAppContext.getExternalCacheDir(), "exo-video-cache"),//缓存目录
|
|
new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现
|
|
new ExoDatabaseProvider(mAppContext));
|
|
}
|
|
|
|
/**
|
|
* Returns a new DataSource factory.
|
|
*
|
|
* @return A new DataSource factory.
|
|
*/
|
|
private DataSource.Factory getDataSourceFactory() {
|
|
return new DefaultDataSourceFactory(mAppContext, getHttpDataSourceFactory());
|
|
}
|
|
|
|
/**
|
|
* Returns a new HttpDataSource factory.
|
|
*
|
|
* @return A new HttpDataSource factory.
|
|
*/
|
|
private DataSource.Factory getHttpDataSourceFactory() {
|
|
if (mHttpDataSourceFactory == null) {
|
|
mHttpDataSourceFactory = new OkHttpDataSource.Factory(mOkClient)
|
|
.setUserAgent(mUserAgent)/*
|
|
.setAllowCrossProtocolRedirects(true)*/;
|
|
}
|
|
return mHttpDataSourceFactory;
|
|
}
|
|
|
|
private void setHeaders(Map<String, String> headers) {
|
|
if (headers != null && headers.size() > 0) {
|
|
//如果发现用户通过header传递了UA,则强行将HttpDataSourceFactory里面的userAgent字段替换成用户的
|
|
if (headers.containsKey("User-Agent")) {
|
|
String value = headers.remove("User-Agent");
|
|
if (!TextUtils.isEmpty(value)) {
|
|
try {
|
|
Field userAgentField = mHttpDataSourceFactory.getClass().getDeclaredField("userAgent");
|
|
userAgentField.setAccessible(true);
|
|
userAgentField.set(mHttpDataSourceFactory, value.trim());
|
|
} catch (Exception e) {
|
|
//ignore
|
|
}
|
|
}
|
|
}
|
|
Iterator<String> iter = headers.keySet().iterator();
|
|
while (iter.hasNext()) {
|
|
String k = iter.next();
|
|
String v = headers.get(k);
|
|
if (v != null)
|
|
headers.put(k, v.trim());
|
|
}
|
|
mHttpDataSourceFactory.setDefaultRequestProperties(headers);
|
|
}
|
|
}
|
|
|
|
public void setCache(Cache cache) {
|
|
this.mCache = cache;
|
|
}
|
|
}
|
|
|