|
|
|
|
@ -2,20 +2,31 @@ package com.fongmi.android.tv.player; |
|
|
|
|
|
|
|
|
|
import android.graphics.Color; |
|
|
|
|
import android.net.Uri; |
|
|
|
|
import android.text.TextUtils; |
|
|
|
|
|
|
|
|
|
import com.fongmi.android.tv.App; |
|
|
|
|
import com.fongmi.android.tv.bean.Result; |
|
|
|
|
import com.fongmi.android.tv.utils.FileUtil; |
|
|
|
|
import com.google.android.exoplayer2.C; |
|
|
|
|
import com.google.android.exoplayer2.DefaultRenderersFactory; |
|
|
|
|
import com.google.android.exoplayer2.MediaItem; |
|
|
|
|
import com.google.android.exoplayer2.PlaybackException; |
|
|
|
|
import com.google.android.exoplayer2.RenderersFactory; |
|
|
|
|
import com.google.android.exoplayer2.database.DatabaseProvider; |
|
|
|
|
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider; |
|
|
|
|
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; |
|
|
|
|
import com.google.android.exoplayer2.extractor.ExtractorsFactory; |
|
|
|
|
import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory; |
|
|
|
|
import com.google.android.exoplayer2.extractor.ts.TsExtractor; |
|
|
|
|
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; |
|
|
|
|
import com.google.android.exoplayer2.source.MediaSource; |
|
|
|
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; |
|
|
|
|
import com.google.android.exoplayer2.trackselection.TrackSelector; |
|
|
|
|
import com.google.android.exoplayer2.ui.CaptionStyleCompat; |
|
|
|
|
import com.google.android.exoplayer2.upstream.DataSource; |
|
|
|
|
import com.google.android.exoplayer2.upstream.DefaultDataSource; |
|
|
|
|
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; |
|
|
|
|
import com.google.android.exoplayer2.upstream.HttpDataSource; |
|
|
|
|
import com.google.android.exoplayer2.upstream.cache.Cache; |
|
|
|
|
import com.google.android.exoplayer2.upstream.cache.CacheDataSource; |
|
|
|
|
import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor; |
|
|
|
|
@ -23,53 +34,75 @@ import com.google.android.exoplayer2.upstream.cache.SimpleCache; |
|
|
|
|
import com.google.android.exoplayer2.util.MimeTypes; |
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
public class ExoUtil { |
|
|
|
|
|
|
|
|
|
private static HttpDataSource.Factory httpDataSourceFactory; |
|
|
|
|
private static DataSource.Factory dataSourceFactory; |
|
|
|
|
private static ExtractorsFactory extractorsFactory; |
|
|
|
|
private static DatabaseProvider database; |
|
|
|
|
private static Cache cache; |
|
|
|
|
|
|
|
|
|
public static TrackSelector buildTrackSelector() { |
|
|
|
|
DefaultTrackSelector trackSelector = new DefaultTrackSelector(App.get()); |
|
|
|
|
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("zh").setIgnoredTextSelectionFlags(C.SELECTION_FLAG_DEFAULT | C.SELECTION_FLAG_FORCED)); |
|
|
|
|
return trackSelector; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static RenderersFactory buildRenderersFactory() { |
|
|
|
|
return new DefaultRenderersFactory(App.get()).setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static CaptionStyleCompat getCaptionStyle() { |
|
|
|
|
return new CaptionStyleCompat(Color.WHITE, Color.TRANSPARENT, Color.TRANSPARENT, CaptionStyleCompat.EDGE_TYPE_OUTLINE, Color.BLACK, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static MediaSource getSource(Result result, int errorCode) { |
|
|
|
|
return getSource(result.getHeaders(), result.getPlayUrl() + result.getUrl(), errorCode, getConfig(result)); |
|
|
|
|
return getSource(result.getHeaders(), result.getPlayUrl() + result.getUrl(), result.getSub(), errorCode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static MediaSource getSource(Map<String, String> headers, String url, int errorCode) { |
|
|
|
|
return getSource(headers, url, errorCode, Collections.emptyList()); |
|
|
|
|
return getSource(headers, url, null, errorCode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static MediaSource getSource(Map<String, String> headers, String url, String sub, int errorCode) { |
|
|
|
|
return new DefaultMediaSourceFactory(getDataSourceFactory(headers), getExtractorsFactory()).createMediaSource(getMediaItem(url, sub, errorCode)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static MediaSource getSource(Map<String, String> headers, String url, int errorCode, List<MediaItem.SubtitleConfiguration> config) { |
|
|
|
|
private static MediaItem getMediaItem(String url, String sub, int errorCode) { |
|
|
|
|
MediaItem.Builder builder = new MediaItem.Builder().setUri(Uri.parse(url.trim())); |
|
|
|
|
if (errorCode == PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED) builder.setMimeType(MimeTypes.APPLICATION_OCTET); |
|
|
|
|
else if (errorCode == PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED) builder.setMimeType(MimeTypes.APPLICATION_M3U8); |
|
|
|
|
if (config.size() > 0) builder.setSubtitleConfigurations(config); |
|
|
|
|
return new DefaultMediaSourceFactory(getDataSourceFactory(headers)).createMediaSource(builder.build()); |
|
|
|
|
if (!TextUtils.isEmpty(sub)) builder.setSubtitleConfigurations(getSubtitles(sub)); |
|
|
|
|
return builder.build(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static List<MediaItem.SubtitleConfiguration> getConfig(Result result) { |
|
|
|
|
if (result.getSub().isEmpty()) return Collections.emptyList(); |
|
|
|
|
private static List<MediaItem.SubtitleConfiguration> getSubtitles(String sub) { |
|
|
|
|
List<MediaItem.SubtitleConfiguration> items = new ArrayList<>(); |
|
|
|
|
String[] subs = result.getSub().split("\\$\\$\\$"); |
|
|
|
|
for (String sub : subs) { |
|
|
|
|
String[] divide = sub.split("#"); |
|
|
|
|
items.add(new MediaItem.SubtitleConfiguration.Builder(Uri.parse(divide[2])).setLabel(divide[0]).setMimeType(divide[1]).setLanguage("zh").build()); |
|
|
|
|
} |
|
|
|
|
for (String text : sub.split("\\$\\$\\$")) items.add(getSubtitle(text.split("#"))); |
|
|
|
|
return items; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static synchronized DataSource.Factory getHttpDataSourceFactory(Map<String, String> headers) { |
|
|
|
|
return new DefaultHttpDataSource.Factory().setDefaultRequestProperties(headers).setConnectTimeoutMs(5000).setReadTimeoutMs(5000).setAllowCrossProtocolRedirects(true); |
|
|
|
|
private static MediaItem.SubtitleConfiguration getSubtitle(String[] split) { |
|
|
|
|
return new MediaItem.SubtitleConfiguration.Builder(Uri.parse(split[2])).setLabel(split[0]).setMimeType(split[1]).setLanguage("zh").build(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static synchronized ExtractorsFactory getExtractorsFactory() { |
|
|
|
|
if (extractorsFactory == null) extractorsFactory = new DefaultExtractorsFactory().setTsExtractorFlags(DefaultTsPayloadReaderFactory.FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS).setTsExtractorTimestampSearchBytes(TsExtractor.DEFAULT_TIMESTAMP_SEARCH_BYTES * 3); |
|
|
|
|
return extractorsFactory; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static synchronized HttpDataSource.Factory getHttpDataSourceFactory() { |
|
|
|
|
if (httpDataSourceFactory == null) httpDataSourceFactory = new DefaultHttpDataSource.Factory().setConnectTimeoutMs(5000).setReadTimeoutMs(5000).setAllowCrossProtocolRedirects(true); |
|
|
|
|
return httpDataSourceFactory; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static synchronized DataSource.Factory getDataSourceFactory(Map<String, String> headers) { |
|
|
|
|
DefaultDataSource.Factory upstreamFactory = new DefaultDataSource.Factory(App.get(), getHttpDataSourceFactory(headers)); |
|
|
|
|
return buildReadOnlyCacheDataSource(upstreamFactory, getCache()); |
|
|
|
|
if (dataSourceFactory == null) dataSourceFactory = buildReadOnlyCacheDataSource(new DefaultDataSource.Factory(App.get(), getHttpDataSourceFactory()), getCache()); |
|
|
|
|
httpDataSourceFactory.setDefaultRequestProperties(headers); |
|
|
|
|
return dataSourceFactory; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static CacheDataSource.Factory buildReadOnlyCacheDataSource(DataSource.Factory upstreamFactory, Cache cache) { |
|
|
|
|
|