Skip to content

Commit

Permalink
Turn CacheUtil into stateful CacheWriter
Browse files Browse the repository at this point in the history
- The new CacheWriter is simplified somewhat
- Blocking on PriorityTaskManager.proceed is moved out of
  CacheWriter and into the Downloader tasks. This is because
  we want to shift only the caching parts of the Downloaders
  onto their Executors, whilst keeping the blocking parts on
  the main Downloader threads. Else we can end up "using"
  the Executor threads indefinitely whilst they're blocked.

Issue: #5978
PiperOrigin-RevId: 313222923
  • Loading branch information
ojw28 committed May 27, 2020
1 parent a1c72c0 commit d88f5f4
Show file tree
Hide file tree
Showing 6 changed files with 422 additions and 367 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.upstream.cache.CacheWriter;
import com.google.android.exoplayer2.upstream.cache.CacheWriter.ProgressListener;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.PriorityTaskManager.PriorityTooLowException;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

/** A downloader for progressive media streams. */
public final class ProgressiveDownloader implements Downloader {

private static final int BUFFER_SIZE_BYTES = 128 * 1024;

private final DataSpec dataSpec;
private final CacheDataSource dataSource;
private final AtomicBoolean isCanceled;
Expand Down Expand Up @@ -104,18 +104,35 @@ public void download(@Nullable ProgressListener progressListener) throws IOExcep
if (isCanceled.get()) {
return;
}

CacheWriter cacheWriter =
new CacheWriter(
dataSource,
dataSpec,
/* allowShortContent= */ false,
isCanceled,
/* temporaryBuffer= */ null,
progressListener == null ? null : new ProgressForwarder(progressListener));

@Nullable PriorityTaskManager priorityTaskManager = dataSource.getUpstreamPriorityTaskManager();
if (priorityTaskManager != null) {
priorityTaskManager.add(C.PRIORITY_DOWNLOAD);
}
try {
CacheUtil.cache(
dataSource,
dataSpec,
progressListener == null ? null : new ProgressForwarder(progressListener),
isCanceled,
/* enableEOFException= */ true,
/* temporaryBuffer= */ new byte[BUFFER_SIZE_BYTES]);
boolean finished = false;
while (!finished && !isCanceled.get()) {
if (priorityTaskManager != null) {
priorityTaskManager.proceed(dataSource.getUpstreamPriority());
}
try {
cacheWriter.cache();
finished = true;
} catch (PriorityTooLowException e) {
// The next loop iteration will block until the task is able to proceed.
}
}
} catch (InterruptedException e) {
// The download was canceled.
} finally {
if (priorityTaskManager != null) {
priorityTaskManager.remove(C.PRIORITY_DOWNLOAD);
Expand All @@ -137,7 +154,7 @@ public void remove() {
dataSource.getCache().removeResource(dataSource.getCacheKeyFactory().buildCacheKey(dataSpec));
}

private static final class ProgressForwarder implements CacheUtil.ProgressListener {
private static final class ProgressForwarder implements CacheWriter.ProgressListener {

private final ProgressListener progressListener;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
import com.google.android.exoplayer2.upstream.cache.Cache;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
import com.google.android.exoplayer2.upstream.cache.CacheWriter;
import com.google.android.exoplayer2.upstream.cache.ContentMetadata;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.PriorityTaskManager.PriorityTooLowException;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -175,18 +176,32 @@ public final void download(@Nullable ProgressListener progressListener) throws I
segmentsDownloaded)
: null;
byte[] temporaryBuffer = new byte[BUFFER_SIZE_BYTES];
for (int i = 0; i < segments.size(); i++) {
CacheUtil.cache(
dataSource,
segments.get(i).dataSpec,
progressNotifier,
isCanceled,
/* enableEOFException= */ true,
temporaryBuffer);
if (progressNotifier != null) {
progressNotifier.onSegmentDownloaded();
int segmentIndex = 0;
while (!isCanceled.get() && segmentIndex < segments.size()) {
if (priorityTaskManager != null) {
priorityTaskManager.proceed(dataSource.getUpstreamPriority());
}
CacheWriter cacheWriter =
new CacheWriter(
dataSource,
segments.get(segmentIndex).dataSpec,
/* allowShortContent= */ false,
isCanceled,
temporaryBuffer,
progressNotifier);
try {
cacheWriter.cache();
segmentIndex++;
if (progressNotifier != null) {
progressNotifier.onSegmentDownloaded();
}
} catch (PriorityTooLowException e) {
// The next loop iteration will block until the task is able to proceed, then try and
// download the same segment again.
}
}
} catch (InterruptedException e) {
// The download was canceled.
} finally {
if (priorityTaskManager != null) {
priorityTaskManager.remove(C.PRIORITY_DOWNLOAD);
Expand Down Expand Up @@ -293,7 +308,7 @@ private static boolean canMergeSegments(DataSpec dataSpec1, DataSpec dataSpec2)
&& dataSpec1.httpRequestHeaders.equals(dataSpec2.httpRequestHeaders);
}

private static final class ProgressNotifier implements CacheUtil.ProgressListener {
private static final class ProgressNotifier implements CacheWriter.ProgressListener {

private final ProgressListener progressListener;

Expand Down
Loading

0 comments on commit d88f5f4

Please sign in to comment.