diff --git a/app/src/main/java/com/github/tvbox/osc/base/App.java b/app/src/main/java/com/github/tvbox/osc/base/App.java index 8ce45a06..56eccca9 100644 --- a/app/src/main/java/com/github/tvbox/osc/base/App.java +++ b/app/src/main/java/com/github/tvbox/osc/base/App.java @@ -92,7 +92,7 @@ public class App extends MultiDexApplication { public static P2PClass getp2p() { try { if (p == null) { - p = new P2PClass(instance.getExternalCacheDir().getAbsolutePath()); + p = new P2PClass(FileUtils.getExternalCachePath()); } return p; } catch (Exception e) { diff --git a/app/src/main/java/com/github/tvbox/osc/player/ExoPlayer.java b/app/src/main/java/com/github/tvbox/osc/player/ExoPlayer.java index c7e7d6ba..9748bf73 100644 --- a/app/src/main/java/com/github/tvbox/osc/player/ExoPlayer.java +++ b/app/src/main/java/com/github/tvbox/osc/player/ExoPlayer.java @@ -5,7 +5,6 @@ import android.util.Pair; import com.github.tvbox.osc.util.LOG; import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; @@ -15,9 +14,7 @@ import xyz.doikki.videoplayer.exo.ExoMediaPlayer; import com.google.android.exoplayer2.C; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; public class ExoPlayer extends ExoMediaPlayer { @@ -28,11 +25,12 @@ public class ExoPlayer extends ExoMediaPlayer { // 3. 获取所有轨道信息 public TrackInfo getTrackInfo() { TrackInfo data = new TrackInfo(); - MappingTrackSelector.MappedTrackInfo mappedInfo = getMappingTrackSelector().getCurrentMappedTrackInfo(); + MappingTrackSelector.MappedTrackInfo mappedInfo = trackSelector.getCurrentMappedTrackInfo(); if (mappedInfo == null) return data; - DefaultTrackSelector.Parameters params = ((DefaultTrackSelector) getMappingTrackSelector()).getParameters(); + DefaultTrackSelector.Parameters params = trackSelector.getParameters(); for (int rendererIndex = 0; rendererIndex < mappedInfo.getRendererCount(); rendererIndex++) { int type = mappedInfo.getRendererType(rendererIndex); + if(type!=C.TRACK_TYPE_AUDIO && type!=C.TRACK_TYPE_TEXT)continue; TrackGroupArray groups = mappedInfo.getTrackGroups(rendererIndex); DefaultTrackSelector.SelectionOverride override = params.getSelectionOverride(rendererIndex, groups); boolean hasSelected = false; @@ -63,7 +61,7 @@ public class ExoPlayer extends ExoMediaPlayer { bean.selected = selected; if (type == C.TRACK_TYPE_AUDIO) { data.addAudio(bean); - } else if (type == C.TRACK_TYPE_TEXT) { + } else { data.addSubtitle(bean); } } @@ -72,13 +70,10 @@ public class ExoPlayer extends ExoMediaPlayer { return data; } - protected MappingTrackSelector getMappingTrackSelector() { - if (mTrackSelector instanceof MappingTrackSelector) { - return (MappingTrackSelector) mTrackSelector; - } - throw new IllegalStateException("trackSelector 必须是 MappingTrackSelector 类型"); - } + + /** 缓存:key=播放地址,value=已选的 {groupIndex, trackIndex} */ + private static final Map> mTrackOverrideCache = new HashMap<>(); /** * 设置当前播放的音轨 * @param groupIndex 音轨组的索引 @@ -86,7 +81,6 @@ public class ExoPlayer extends ExoMediaPlayer { */ public void setTrack(int groupIndex, int trackIndex) { try { - DefaultTrackSelector trackSelector = (DefaultTrackSelector) getMappingTrackSelector(); MappingTrackSelector.MappedTrackInfo mappedInfo = trackSelector.getCurrentMappedTrackInfo(); if (mappedInfo == null) { LOG.i("echo-setTrack: MappedTrackInfo is null"); @@ -107,11 +101,41 @@ public class ExoPlayer extends ExoMediaPlayer { builder.clearSelectionOverrides(audioRendererIndex); builder.setSelectionOverride(audioRendererIndex, audioGroups, newOverride); trackSelector.setParameters(builder.build()); + + // 缓存到 map:下次同一路径播放时使用 + if (currentPlayPath != null) { + mTrackOverrideCache.put(currentPlayPath, Pair.create(groupIndex, trackIndex)); + } } catch (Exception e) { LOG.i("echo-setTrack error: " + e.getMessage()); } } + + //加载上一次选中的音轨 + public void loadDefaultTrack() { + Pair pair = mTrackOverrideCache.get(currentPlayPath); + if (pair == null) return; + + MappingTrackSelector.MappedTrackInfo mappedInfo = trackSelector.getCurrentMappedTrackInfo(); + if (mappedInfo == null) return; + + int audioRendererIndex = findAudioRendererIndex(mappedInfo); + if (audioRendererIndex == C.INDEX_UNSET) return; + + TrackGroupArray audioGroups = mappedInfo.getTrackGroups(audioRendererIndex); + int groupIndex = pair.first; + int trackIndex = pair.second; + if (!isTrackIndexValid(audioGroups, groupIndex, trackIndex)) return; + + DefaultTrackSelector.SelectionOverride override = new DefaultTrackSelector.SelectionOverride(groupIndex, trackIndex); + + DefaultTrackSelector.ParametersBuilder builder = trackSelector.buildUponParameters(); + builder.clearSelectionOverrides(audioRendererIndex); + builder.setSelectionOverride(audioRendererIndex, audioGroups, override); + trackSelector.setParameters(builder.build()); + } + /** * 查找音频渲染器索引 */ diff --git a/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java b/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java index de1482cf..f38d39e5 100644 --- a/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java +++ b/app/src/main/java/com/github/tvbox/osc/player/IjkMediaPlayer.java @@ -15,6 +15,7 @@ import com.orhanobut.hawk.Hawk; import java.io.File; import java.net.URI; import java.net.URLEncoder; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -26,6 +27,7 @@ import xyz.doikki.videoplayer.ijk.IjkPlayer; public class IjkMediaPlayer extends IjkPlayer { private IJKCode codec = null; + protected String currentPlayPath; public IjkMediaPlayer(Context context, IJKCode codec) { super(context); @@ -127,6 +129,7 @@ public class IjkMediaPlayer extends IjkPlayer { } setDataSourceHeader(headers); mMediaPlayer.setOption(tv.danmaku.ijk.media.player.IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "ijkio,ffio,async,cache,crypto,file,dash,http,https,ijkhttphook,ijkinject,ijklivehook,ijklongurl,ijksegment,ijktcphook,pipe,rtp,tcp,tls,udp,ijkurlhook,data"); + currentPlayPath = path; super.setDataSource(path, null); } @@ -219,10 +222,16 @@ public class IjkMediaPlayer extends IjkPlayer { .replace(" ", ""); } + /** 缓存:key=播放地址,value=已选的 {trackIndex} */ + private static final Map mTrackIndexCache = new HashMap<>(); public void setTrack(int trackIndex) { int audioSelected = mMediaPlayer.getSelectedTrack(ITrackInfo.MEDIA_TRACK_TYPE_AUDIO); int subtitleSelected = mMediaPlayer.getSelectedTrack(ITrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT); if (trackIndex!=audioSelected && trackIndex!=subtitleSelected){ + // 缓存到 map:下次同一路径播放时使用 + if (currentPlayPath != null) { + mTrackIndexCache.put(currentPlayPath, trackIndex); + } mMediaPlayer.selectTrack(trackIndex); } } @@ -231,4 +240,15 @@ public class IjkMediaPlayer extends IjkPlayer { mMediaPlayer.setOnTimedTextListener(listener); } + public void loadDefaultTrack(TrackInfo trackInfo) { + Integer trackIndex = mTrackIndexCache.get(currentPlayPath); + if (trackIndex == null) { + if(trackInfo!=null && trackInfo.getAudio().size()>1){ + int firsIndex=trackInfo.getAudio().get(0).index; + setTrack(firsIndex); + } + return; + }; + setTrack(trackIndex); + } } \ No newline at end of file diff --git a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java index 6862cfaf..2d656bfb 100644 --- a/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java +++ b/app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java @@ -24,6 +24,7 @@ import androidx.recyclerview.widget.DiffUtil; import com.chad.library.adapter.base.BaseQuickAdapter; import com.github.tvbox.osc.R; import com.github.tvbox.osc.api.ApiConfig; +import com.github.tvbox.osc.base.App; import com.github.tvbox.osc.bean.IJKCode; import com.github.tvbox.osc.bean.ParseBean; import com.github.tvbox.osc.bean.SourceBean; @@ -41,6 +42,8 @@ import com.github.tvbox.osc.util.PlayerHelper; import com.github.tvbox.osc.util.ScreenUtils; import com.github.tvbox.osc.util.SubtitleHelper; import com.github.tvbox.osc.util.VideoParseRuler; +import com.github.tvbox.osc.util.thunder.Jianpian; +import com.github.tvbox.osc.util.thunder.Thunder; import com.lzy.okgo.OkGo; import com.lzy.okgo.callback.AbsCallback; import com.lzy.okgo.model.HttpHeaders; @@ -1414,4 +1417,11 @@ public class VodController extends BaseController { } } } + + public void stopOther() + { + Thunder.stop(false);//停止磁力下载 + Jianpian.finish();//停止p2p下载 + App.getInstance().setDashData(null); + } } \ No newline at end of file diff --git a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java index 8470d156..fb984d4e 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/activity/PlayActivity.java @@ -586,11 +586,8 @@ public class PlayActivity extends BaseActivity { if (trackInfo != null && trackInfo.getSubtitle().size() > 0) { mController.mSubtitleView.hasInternal = true; } - //默认选中第一个音轨 一般第一个音轨是国语 - if (trackInfo != null && trackInfo.getAudio().size() > 1) { - int firsIndex=trackInfo.getAudio().get(0).index; - ((IjkMediaPlayer)(mVideoView.getMediaPlayer())).setTrack(firsIndex); - } + //默认选中第一个音轨 一般第一个音轨是国语 && 加载上一次选中的 + ((IjkMediaPlayer)mVideoView.getMediaPlayer()).loadDefaultTrack(trackInfo); ((IjkMediaPlayer)(mVideoView.getMediaPlayer())).setOnTimedTextListener(new IMediaPlayer.OnTimedTextListener() { @Override public void onTimedText(IMediaPlayer mp, IjkTimedText text) { @@ -603,6 +600,10 @@ public class PlayActivity extends BaseActivity { } }); } + if(mVideoView.getMediaPlayer() instanceof ExoPlayer){ + //加载上一次选中的 + ((ExoPlayer) mVideoView.getMediaPlayer()).loadDefaultTrack(); + } mController.mSubtitleView.bindToMediaPlayer(mVideoView.getMediaPlayer()); mController.mSubtitleView.setPlaySubtitleCacheKey(subtitleCacheKey); String subtitlePathCache = (String)CacheManager.getCache(MD5.string2MD5(subtitleCacheKey)); @@ -837,9 +838,7 @@ public class PlayActivity extends BaseActivity { } stopLoadWebView(true); stopParse(); - Thunder.stop(false);//停止磁力下载 - Jianpian.finish();//停止p2p下载 - App.getInstance().setDashData(null); + mController.stopOther(); } private VodInfo mVodInfo; @@ -953,6 +952,7 @@ public class PlayActivity extends BaseActivity { stopParse(); initParseLoadFound(); + mController.stopOther(); if(mVideoView!=null) mVideoView.release(); subtitleCacheKey = mVodInfo.sourceKey + "-" + mVodInfo.id + "-" + mVodInfo.playFlag + "-" + mVodInfo.playIndex+ "-" + vs.name + "-subt"; progressKey = mVodInfo.sourceKey + mVodInfo.id + mVodInfo.playFlag + mVodInfo.playIndex + vs.name; diff --git a/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java b/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java index 217d338f..fe8fa343 100644 --- a/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java +++ b/app/src/main/java/com/github/tvbox/osc/ui/fragment/PlayFragment.java @@ -599,17 +599,15 @@ public class PlayFragment extends BaseLazyFragment { private void initSubtitleView() { TrackInfo trackInfo = null; - if (mVideoView.getMediaPlayer() instanceof IjkMediaPlayer) { - trackInfo = ((IjkMediaPlayer)(mVideoView.getMediaPlayer())).getTrackInfo(); + AbstractPlayer mediaPlayer = mVideoView.getMediaPlayer(); + if (mediaPlayer instanceof IjkMediaPlayer) { + trackInfo = ((IjkMediaPlayer)mediaPlayer).getTrackInfo(); if (trackInfo != null && trackInfo.getSubtitle().size() > 0) { mController.mSubtitleView.hasInternal = true; } - //默认选中第一个音轨 一般第一个音轨是国语 - if (trackInfo != null && trackInfo.getAudio().size() > 1) { - int firsIndex=trackInfo.getAudio().get(0).index; - ((IjkMediaPlayer)(mVideoView.getMediaPlayer())).setTrack(firsIndex); - } - ((IjkMediaPlayer)(mVideoView.getMediaPlayer())).setOnTimedTextListener(new IMediaPlayer.OnTimedTextListener() { + //默认选中第一个音轨 一般第一个音轨是国语 && 加载上一次选中的 + ((IjkMediaPlayer)mediaPlayer).loadDefaultTrack(trackInfo); + ((IjkMediaPlayer)mediaPlayer).setOnTimedTextListener(new IMediaPlayer.OnTimedTextListener() { @Override public void onTimedText(IMediaPlayer mp, IjkTimedText text) { if(text==null)return; @@ -621,6 +619,10 @@ public class PlayFragment extends BaseLazyFragment { } }); } + if(mediaPlayer instanceof ExoPlayer){ + //加载上一次选中的 + ((ExoPlayer) mediaPlayer).loadDefaultTrack(); + } mController.mSubtitleView.bindToMediaPlayer(mVideoView.getMediaPlayer()); mController.mSubtitleView.setPlaySubtitleCacheKey(subtitleCacheKey); String subtitlePathCache = (String)CacheManager.getCache(MD5.string2MD5(subtitleCacheKey)); @@ -873,9 +875,7 @@ public class PlayFragment extends BaseLazyFragment { } stopLoadWebView(true); stopParse(); - Thunder.stop(true);//停止磁力下载 - Jianpian.finish();//停止p2p下载 - App.getInstance().setDashData(null); + mController.stopOther(); } private VodInfo mVodInfo; @@ -997,6 +997,7 @@ public class PlayFragment extends BaseLazyFragment { stopParse(); initParseLoadFound(); + mController.stopOther(); if(mVideoView!=null) mVideoView.release(); subtitleCacheKey = mVodInfo.sourceKey + "-" + mVodInfo.id + "-" + mVodInfo.playFlag + "-" + mVodInfo.playIndex+ "-" + vs.name + "-subt"; progressKey = mVodInfo.sourceKey + mVodInfo.id + mVodInfo.playFlag + mVodInfo.playIndex + vs.name; diff --git a/gradle.properties b/gradle.properties index 848e153d..306a3be4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,4 @@ android.useAndroidX=true android.enableJetifier=true IsDebug=true #build on off -#org.gradle.jvmargs=-Xmx2048m --add-opens java.base/java.io=ALL-UNNAMED \ No newline at end of file +org.gradle.jvmargs=-Xmx2048m --add-opens java.base/java.io=ALL-UNNAMED \ No newline at end of file diff --git a/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaPlayer.java b/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaPlayer.java index 076b3685..35dde7d5 100644 --- a/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaPlayer.java +++ b/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaPlayer.java @@ -53,6 +53,10 @@ public class ExoMediaPlayer extends AbstractPlayer implements Player.Listener { private RenderersFactory mRenderersFactory; protected TrackSelector mTrackSelector; + protected DefaultTrackSelector trackSelector; + + protected String currentPlayPath; + public ExoMediaPlayer(Context context) { mAppContext = context.getApplicationContext(); mMediaSourceHelper = ExoMediaSourceHelper.getInstance(context); @@ -76,7 +80,7 @@ public class ExoMediaPlayer extends AbstractPlayer implements Player.Listener { if (VideoViewManager.getConfig().mIsEnableLog && mTrackSelector instanceof MappingTrackSelector) { mInternalPlayer.addAnalyticsListener(new EventLogger((MappingTrackSelector) mTrackSelector, "ExoPlayer")); } - + if(trackSelector == null)trackSelector=(DefaultTrackSelector)mTrackSelector; mInternalPlayer.addListener(this); } @@ -95,6 +99,7 @@ public class ExoMediaPlayer extends AbstractPlayer implements Player.Listener { @Override public void setDataSource(String path, Map headers) { Log.i("Tvbox-runtime","echo-setDataSource:"+path); + currentPlayPath = path; mMediaSource = mMediaSourceHelper.getMediaSource(path, headers); } diff --git a/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaSourceHelper.java b/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaSourceHelper.java index 48ed5587..23fd7011 100644 --- a/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaSourceHelper.java +++ b/player/src/main/java/xyz/doikki/videoplayer/exo/ExoMediaSourceHelper.java @@ -124,11 +124,19 @@ public final class ExoMediaSourceHelper { private Cache newCache() { return new SimpleCache( - new File(mAppContext.getExternalCacheDir(), "exo-video-cache"),//缓存目录 + new File(externalCacheDir(), "exo-video-cache"),//缓存目录 new LeastRecentlyUsedCacheEvictor(512 * 1024 * 1024),//缓存大小,默认512M,使用LRU算法实现 new ExoDatabaseProvider(mAppContext)); } + private File externalCacheDir() + { + File externalCacheDir = mAppContext.getExternalCacheDir(); + if (externalCacheDir == null){ + externalCacheDir = mAppContext.getCacheDir(); + } + return externalCacheDir; + } /** * Returns a new DataSource factory. *