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.
 
 
 
 
 
JY-TVBoxOS/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaSourceHelper.java

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;
}
}