Skip to content

Commit 7ce2250

Browse files
StypoxAudricV
authored andcommitted
Improve CacheFactory and PlayerDataSource code
1 parent ef20d9b commit 7ce2250

2 files changed

Lines changed: 94 additions & 133 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java

Lines changed: 11 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,107 +3,44 @@
33
import android.content.Context;
44

55
import androidx.annotation.NonNull;
6-
import androidx.annotation.Nullable;
76

87
import com.google.android.exoplayer2.upstream.DataSource;
98
import com.google.android.exoplayer2.upstream.DefaultDataSource;
10-
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
119
import com.google.android.exoplayer2.upstream.FileDataSource;
1210
import com.google.android.exoplayer2.upstream.TransferListener;
1311
import com.google.android.exoplayer2.upstream.cache.CacheDataSink;
1412
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
1513
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
1614

17-
import org.schabi.newpipe.player.datasource.YoutubeHttpDataSource;
18-
19-
/* package-private */ final class CacheFactory implements DataSource.Factory {
15+
final class CacheFactory implements DataSource.Factory {
2016
private static final int CACHE_FLAGS = CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR;
2117

22-
private final long maxFileSize;
2318
private final Context context;
24-
private final String userAgent;
2519
private final TransferListener transferListener;
2620
private final DataSource.Factory upstreamDataSourceFactory;
27-
private final SimpleCache simpleCache;
28-
29-
public static class Builder {
30-
private final Context context;
31-
private final String userAgent;
32-
private final TransferListener transferListener;
33-
private DataSource.Factory upstreamDataSourceFactory;
34-
private SimpleCache simpleCache;
35-
36-
Builder(@NonNull final Context context,
37-
@NonNull final String userAgent,
38-
@NonNull final TransferListener transferListener) {
39-
this.context = context;
40-
this.userAgent = userAgent;
41-
this.transferListener = transferListener;
42-
}
43-
44-
public void setUpstreamDataSourceFactory(
45-
@Nullable final DataSource.Factory upstreamDataSourceFactory) {
46-
this.upstreamDataSourceFactory = upstreamDataSourceFactory;
47-
}
48-
49-
public void setSimpleCache(@NonNull final SimpleCache simpleCache) {
50-
this.simpleCache = simpleCache;
51-
}
21+
private final SimpleCache cache;
5222

53-
public CacheFactory build() {
54-
if (simpleCache == null) {
55-
throw new IllegalStateException("No SimpleCache instance has been specified. "
56-
+ "Please specify one with setSimpleCache");
57-
}
58-
return new CacheFactory(context, userAgent, transferListener, simpleCache,
59-
upstreamDataSourceFactory);
60-
}
61-
}
62-
63-
private CacheFactory(@NonNull final Context context,
64-
@NonNull final String userAgent,
65-
@NonNull final TransferListener transferListener,
66-
@NonNull final SimpleCache simpleCache,
67-
@Nullable final DataSource.Factory upstreamDataSourceFactory) {
23+
CacheFactory(final Context context,
24+
final TransferListener transferListener,
25+
final SimpleCache cache,
26+
final DataSource.Factory upstreamDataSourceFactory) {
6827
this.context = context;
69-
this.userAgent = userAgent;
7028
this.transferListener = transferListener;
71-
this.simpleCache = simpleCache;
29+
this.cache = cache;
7230
this.upstreamDataSourceFactory = upstreamDataSourceFactory;
73-
74-
maxFileSize = PlayerHelper.getPreferredFileSize();
7531
}
7632

7733
@NonNull
7834
@Override
7935
public DataSource createDataSource() {
80-
81-
final DataSource.Factory upstreamDataSourceFactoryToUse;
82-
if (upstreamDataSourceFactory == null) {
83-
upstreamDataSourceFactoryToUse = new DefaultHttpDataSource.Factory()
84-
.setUserAgent(userAgent);
85-
} else {
86-
if (upstreamDataSourceFactory instanceof DefaultHttpDataSource.Factory) {
87-
upstreamDataSourceFactoryToUse =
88-
((DefaultHttpDataSource.Factory) upstreamDataSourceFactory)
89-
.setUserAgent(userAgent);
90-
} else if (upstreamDataSourceFactory instanceof YoutubeHttpDataSource.Factory) {
91-
upstreamDataSourceFactoryToUse =
92-
((YoutubeHttpDataSource.Factory) upstreamDataSourceFactory)
93-
.setUserAgentForNonMobileStreams(userAgent);
94-
} else {
95-
upstreamDataSourceFactoryToUse = upstreamDataSourceFactory;
96-
}
97-
}
98-
9936
final DefaultDataSource dataSource = new DefaultDataSource.Factory(context,
100-
upstreamDataSourceFactoryToUse)
37+
upstreamDataSourceFactory)
10138
.setTransferListener(transferListener)
10239
.createDataSource();
10340

10441
final FileDataSource fileSource = new FileDataSource();
105-
final CacheDataSink dataSink = new CacheDataSink(simpleCache, maxFileSize);
106-
return new CacheDataSource(simpleCache, dataSource, fileSource, dataSink, CACHE_FLAGS,
107-
null);
42+
final CacheDataSink dataSink
43+
= new CacheDataSink(cache, PlayerHelper.getPreferredFileSize());
44+
return new CacheDataSource(cache, dataSource, fileSource, dataSink, CACHE_FLAGS, null);
10845
}
10946
}

app/src/main/java/org/schabi/newpipe/player/helper/PlayerDataSource.java

Lines changed: 83 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import android.content.Context;
44
import android.util.Log;
55

6-
import androidx.annotation.NonNull;
76
import androidx.annotation.Nullable;
87

98
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider;
@@ -31,6 +30,7 @@
3130
import java.io.File;
3231

3332
public class PlayerDataSource {
33+
public static final String TAG = PlayerDataSource.class.getSimpleName();
3434

3535
public static final int LIVE_STREAM_EDGE_GAP_MILLIS = 10000;
3636

@@ -47,7 +47,7 @@ public class PlayerDataSource {
4747
* {@link YoutubeProgressiveDashManifestCreator}, {@link YoutubeOtfDashManifestCreator} and
4848
* {@link YoutubePostLiveStreamDvrDashManifestCreator}.
4949
*/
50-
private static final int MAXIMUM_SIZE_CACHED_GENERATED_MANIFESTS_PER_CACHE = 500;
50+
private static final int MAX_MANIFEST_CACHE_SIZE = 500;
5151

5252
/**
5353
* The folder name in which the ExoPlayer cache will be written.
@@ -61,44 +61,53 @@ public class PlayerDataSource {
6161
*/
6262
private static SimpleCache cache;
6363

64-
private final int continueLoadingCheckIntervalBytes;
65-
private final CacheFactory.Builder cacheDataSourceFactoryBuilder;
64+
65+
private final int progressiveLoadIntervalBytes;
66+
67+
// Generic Data Source Factories (without or with cache)
6668
private final DataSource.Factory cachelessDataSourceFactory;
69+
private final CacheFactory cacheDataSourceFactory;
6770

68-
public PlayerDataSource(@NonNull final Context context,
69-
@NonNull final String userAgent,
70-
@NonNull final TransferListener transferListener) {
71-
continueLoadingCheckIntervalBytes = PlayerHelper.getProgressiveLoadIntervalBytes(context);
72-
final File cacheDir = new File(context.getExternalCacheDir(), CACHE_FOLDER_NAME);
73-
if (!cacheDir.exists()) {
74-
//noinspection ResultOfMethodCallIgnored
75-
cacheDir.mkdir();
76-
}
71+
// YouTube-specific Data Source Factories (with cache)
72+
// They use YoutubeHttpDataSource.Factory, with different parameters each
73+
private final CacheFactory ytHlsCacheDataSourceFactory;
74+
private final CacheFactory ytDashCacheDataSourceFactory;
75+
private final CacheFactory ytProgressiveDashCacheDataSourceFactory;
7776

78-
if (cache == null) {
79-
final LeastRecentlyUsedCacheEvictor evictor
80-
= new LeastRecentlyUsedCacheEvictor(PlayerHelper.getPreferredCacheSize());
81-
cache = new SimpleCache(cacheDir, evictor, new StandaloneDatabaseProvider(context));
82-
Log.d(PlayerDataSource.class.getSimpleName(), "initExoPlayerCache: cacheDir = "
83-
+ cacheDir.getAbsolutePath());
84-
}
8577

86-
cacheDataSourceFactoryBuilder = new CacheFactory.Builder(context, userAgent,
87-
transferListener);
88-
cacheDataSourceFactoryBuilder.setSimpleCache(cache);
78+
public PlayerDataSource(final Context context,
79+
final String userAgent,
80+
final TransferListener transferListener) {
8981

82+
progressiveLoadIntervalBytes = PlayerHelper.getProgressiveLoadIntervalBytes(context);
83+
84+
// make sure the static cache was created: needed by CacheFactories below
85+
instantiateCacheIfNeeded(context);
86+
87+
// generic data source factories use DefaultHttpDataSource.Factory
9088
cachelessDataSourceFactory = new DefaultDataSource.Factory(context,
9189
new DefaultHttpDataSource.Factory().setUserAgent(userAgent))
9290
.setTransferListener(transferListener);
93-
94-
YoutubeProgressiveDashManifestCreator.getCache().setMaximumSize(
95-
MAXIMUM_SIZE_CACHED_GENERATED_MANIFESTS_PER_CACHE);
96-
YoutubeOtfDashManifestCreator.getCache().setMaximumSize(
97-
MAXIMUM_SIZE_CACHED_GENERATED_MANIFESTS_PER_CACHE);
91+
cacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
92+
new DefaultHttpDataSource.Factory().setUserAgent(userAgent));
93+
94+
// YouTube-specific data source factories use getYoutubeHttpDataSourceFactory()
95+
ytHlsCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
96+
getYoutubeHttpDataSourceFactory(false, false, userAgent));
97+
ytDashCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
98+
getYoutubeHttpDataSourceFactory(true, true, userAgent));
99+
ytProgressiveDashCacheDataSourceFactory = new CacheFactory(context, transferListener, cache,
100+
getYoutubeHttpDataSourceFactory(false, true, userAgent));
101+
102+
// set the maximum size to manifest creators
103+
YoutubeProgressiveDashManifestCreator.getCache().setMaximumSize(MAX_MANIFEST_CACHE_SIZE);
104+
YoutubeOtfDashManifestCreator.getCache().setMaximumSize(MAX_MANIFEST_CACHE_SIZE);
98105
YoutubePostLiveStreamDvrDashManifestCreator.getCache().setMaximumSize(
99-
MAXIMUM_SIZE_CACHED_GENERATED_MANIFESTS_PER_CACHE);
106+
MAX_MANIFEST_CACHE_SIZE);
100107
}
101108

109+
110+
//region Live media source factories
102111
public SsMediaSource.Factory getLiveSsMediaSourceFactory() {
103112
return getSSMediaSourceFactory().setLivePresentationDelayMs(LIVE_STREAM_EDGE_GAP_MILLIS);
104113
}
@@ -118,26 +127,26 @@ public DashMediaSource.Factory getLiveDashMediaSourceFactory() {
118127
getDefaultDashChunkSourceFactory(cachelessDataSourceFactory),
119128
cachelessDataSourceFactory);
120129
}
130+
//endregion
121131

132+
133+
//region Generic media source factories
122134
public HlsMediaSource.Factory getHlsMediaSourceFactory(
123135
@Nullable final HlsPlaylistParserFactory hlsPlaylistParserFactory) {
124-
final HlsMediaSource.Factory factory = new HlsMediaSource.Factory(
125-
cacheDataSourceFactoryBuilder.build());
126-
if (hlsPlaylistParserFactory != null) {
127-
factory.setPlaylistParserFactory(hlsPlaylistParserFactory);
128-
}
136+
final HlsMediaSource.Factory factory = new HlsMediaSource.Factory(cacheDataSourceFactory);
137+
factory.setPlaylistParserFactory(hlsPlaylistParserFactory);
129138
return factory;
130139
}
131140

132141
public DashMediaSource.Factory getDashMediaSourceFactory() {
133142
return new DashMediaSource.Factory(
134-
getDefaultDashChunkSourceFactory(cacheDataSourceFactoryBuilder.build()),
135-
cacheDataSourceFactoryBuilder.build());
143+
getDefaultDashChunkSourceFactory(cacheDataSourceFactory),
144+
cacheDataSourceFactory);
136145
}
137146

138147
public ProgressiveMediaSource.Factory getProgressiveMediaSourceFactory() {
139-
return new ProgressiveMediaSource.Factory(cacheDataSourceFactoryBuilder.build())
140-
.setContinueLoadingCheckIntervalBytes(continueLoadingCheckIntervalBytes);
148+
return new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
149+
.setContinueLoadingCheckIntervalBytes(progressiveLoadIntervalBytes);
141150
}
142151

143152
public SsMediaSource.Factory getSSMediaSourceFactory() {
@@ -147,42 +156,57 @@ public SsMediaSource.Factory getSSMediaSourceFactory() {
147156
}
148157

149158
public SingleSampleMediaSource.Factory getSingleSampleMediaSourceFactory() {
150-
return new SingleSampleMediaSource.Factory(cacheDataSourceFactoryBuilder.build());
159+
return new SingleSampleMediaSource.Factory(cacheDataSourceFactory);
151160
}
161+
//endregion
152162

153-
public DashMediaSource.Factory getYoutubeDashMediaSourceFactory() {
154-
cacheDataSourceFactoryBuilder.setUpstreamDataSourceFactory(
155-
getYoutubeHttpDataSourceFactory(true, true));
156-
return new DashMediaSource.Factory(
157-
getDefaultDashChunkSourceFactory(cacheDataSourceFactoryBuilder.build()),
158-
cacheDataSourceFactoryBuilder.build());
159-
}
160163

164+
//region YouTube media source factories
161165
public HlsMediaSource.Factory getYoutubeHlsMediaSourceFactory() {
162-
cacheDataSourceFactoryBuilder.setUpstreamDataSourceFactory(
163-
getYoutubeHttpDataSourceFactory(false, false));
164-
return new HlsMediaSource.Factory(cacheDataSourceFactoryBuilder.build());
166+
return new HlsMediaSource.Factory(ytHlsCacheDataSourceFactory);
167+
}
168+
169+
public DashMediaSource.Factory getYoutubeDashMediaSourceFactory() {
170+
return new DashMediaSource.Factory(
171+
getDefaultDashChunkSourceFactory(ytDashCacheDataSourceFactory),
172+
ytDashCacheDataSourceFactory);
165173
}
166174

167175
public ProgressiveMediaSource.Factory getYoutubeProgressiveMediaSourceFactory() {
168-
cacheDataSourceFactoryBuilder.setUpstreamDataSourceFactory(
169-
getYoutubeHttpDataSourceFactory(false, true));
170-
return new ProgressiveMediaSource.Factory(cacheDataSourceFactoryBuilder.build())
171-
.setContinueLoadingCheckIntervalBytes(continueLoadingCheckIntervalBytes);
176+
return new ProgressiveMediaSource.Factory(ytProgressiveDashCacheDataSourceFactory)
177+
.setContinueLoadingCheckIntervalBytes(progressiveLoadIntervalBytes);
172178
}
179+
//endregion
173180

174-
@NonNull
175-
private DefaultDashChunkSource.Factory getDefaultDashChunkSourceFactory(
181+
182+
//region Static methods
183+
private static DefaultDashChunkSource.Factory getDefaultDashChunkSourceFactory(
176184
final DataSource.Factory dataSourceFactory) {
177185
return new DefaultDashChunkSource.Factory(dataSourceFactory);
178186
}
179187

180-
@NonNull
181-
private YoutubeHttpDataSource.Factory getYoutubeHttpDataSourceFactory(
188+
private static YoutubeHttpDataSource.Factory getYoutubeHttpDataSourceFactory(
182189
final boolean rangeParameterEnabled,
183-
final boolean rnParameterEnabled) {
190+
final boolean rnParameterEnabled,
191+
final String userAgent) {
184192
return new YoutubeHttpDataSource.Factory()
185193
.setRangeParameterEnabled(rangeParameterEnabled)
186-
.setRnParameterEnabled(rnParameterEnabled);
194+
.setRnParameterEnabled(rnParameterEnabled)
195+
.setUserAgentForNonMobileStreams(userAgent);
196+
}
197+
198+
private static void instantiateCacheIfNeeded(final Context context) {
199+
if (cache == null) {
200+
final File cacheDir = new File(context.getExternalCacheDir(), CACHE_FOLDER_NAME);
201+
Log.d(TAG, "instantiateCacheIfNeeded: cacheDir = " + cacheDir.getAbsolutePath());
202+
if (!cacheDir.exists() && !cacheDir.mkdir()) {
203+
Log.w(TAG, "instantiateCacheIfNeeded: could not create cache dir");
204+
}
205+
206+
final LeastRecentlyUsedCacheEvictor evictor
207+
= new LeastRecentlyUsedCacheEvictor(PlayerHelper.getPreferredCacheSize());
208+
cache = new SimpleCache(cacheDir, evictor, new StandaloneDatabaseProvider(context));
209+
}
187210
}
211+
//endregion
188212
}

0 commit comments

Comments
 (0)