mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Make CacheUtil only about writing
A subsequent change will rename it to CacheWriter and make it instantiable. Issue: #5978 PiperOrigin-RevId: 312648623
This commit is contained in:
parent
1154e8098a
commit
4384ef5b73
3 changed files with 25 additions and 123 deletions
|
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.offline;
|
||||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Pair;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
|
|
@ -30,6 +29,7 @@ import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
|
import com.google.android.exoplayer2.upstream.cache.CacheKeyFactory;
|
||||||
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
|
import com.google.android.exoplayer2.upstream.cache.CacheUtil;
|
||||||
|
import com.google.android.exoplayer2.upstream.cache.ContentMetadata;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.PriorityTaskManager;
|
import com.google.android.exoplayer2.util.PriorityTaskManager;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
@ -136,11 +136,18 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
|
||||||
long contentLength = 0;
|
long contentLength = 0;
|
||||||
long bytesDownloaded = 0;
|
long bytesDownloaded = 0;
|
||||||
for (int i = segments.size() - 1; i >= 0; i--) {
|
for (int i = segments.size() - 1; i >= 0; i--) {
|
||||||
Segment segment = segments.get(i);
|
DataSpec dataSpec = segments.get(i).dataSpec;
|
||||||
Pair<Long, Long> segmentLengthAndBytesDownloaded =
|
String cacheKey = cacheKeyFactory.buildCacheKey(dataSpec);
|
||||||
CacheUtil.getCached(segment.dataSpec, cache, cacheKeyFactory);
|
long segmentLength = dataSpec.length;
|
||||||
long segmentLength = segmentLengthAndBytesDownloaded.first;
|
if (segmentLength == C.LENGTH_UNSET) {
|
||||||
long segmentBytesDownloaded = segmentLengthAndBytesDownloaded.second;
|
long resourceLength =
|
||||||
|
ContentMetadata.getContentLength(cache.getContentMetadata(cacheKey));
|
||||||
|
if (resourceLength != C.LENGTH_UNSET) {
|
||||||
|
segmentLength = resourceLength - dataSpec.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long segmentBytesDownloaded =
|
||||||
|
cache.getCachedBytes(cacheKey, dataSpec.position, segmentLength);
|
||||||
bytesDownloaded += segmentBytesDownloaded;
|
bytesDownloaded += segmentBytesDownloaded;
|
||||||
if (segmentLength != C.LENGTH_UNSET) {
|
if (segmentLength != C.LENGTH_UNSET) {
|
||||||
if (segmentLength == segmentBytesDownloaded) {
|
if (segmentLength == segmentBytesDownloaded) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.upstream.cache;
|
package com.google.android.exoplayer2.upstream.cache;
|
||||||
|
|
||||||
import android.util.Pair;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
|
@ -57,38 +56,6 @@ public final class CacheUtil {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY = CacheKeyFactory.DEFAULT;
|
public static final CacheKeyFactory DEFAULT_CACHE_KEY_FACTORY = CacheKeyFactory.DEFAULT;
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the cache to obtain the request length and the number of bytes already cached for a
|
|
||||||
* given {@link DataSpec}.
|
|
||||||
*
|
|
||||||
* @param dataSpec Defines the data to be checked.
|
|
||||||
* @param cache A {@link Cache} which has the data.
|
|
||||||
* @param cacheKeyFactory An optional factory for cache keys.
|
|
||||||
* @return A pair containing the request length and the number of bytes that are already cached.
|
|
||||||
*/
|
|
||||||
public static Pair<Long, Long> getCached(
|
|
||||||
DataSpec dataSpec, Cache cache, @Nullable CacheKeyFactory cacheKeyFactory) {
|
|
||||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
|
||||||
long position = dataSpec.position;
|
|
||||||
long requestLength = getRequestLength(dataSpec, cache, key);
|
|
||||||
long bytesAlreadyCached = 0;
|
|
||||||
long bytesLeft = requestLength;
|
|
||||||
while (bytesLeft != 0) {
|
|
||||||
long blockLength = cache.getCachedLength(key, position, bytesLeft);
|
|
||||||
if (blockLength > 0) {
|
|
||||||
bytesAlreadyCached += blockLength;
|
|
||||||
} else {
|
|
||||||
blockLength = -blockLength;
|
|
||||||
if (blockLength == Long.MAX_VALUE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
position += blockLength;
|
|
||||||
bytesLeft -= bytesLeft == C.LENGTH_UNSET ? 0 : blockLength;
|
|
||||||
}
|
|
||||||
return Pair.create(requestLength, bytesAlreadyCached);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches the data defined by {@code dataSpec}, skipping already cached data. Caching stops early
|
* Caches the data defined by {@code dataSpec}, skipping already cached data. Caching stops early
|
||||||
* if the end of the input is reached.
|
* if the end of the input is reached.
|
||||||
|
|
@ -157,23 +124,26 @@ public final class CacheUtil {
|
||||||
Assertions.checkNotNull(temporaryBuffer);
|
Assertions.checkNotNull(temporaryBuffer);
|
||||||
|
|
||||||
Cache cache = dataSource.getCache();
|
Cache cache = dataSource.getCache();
|
||||||
CacheKeyFactory cacheKeyFactory = dataSource.getCacheKeyFactory();
|
String cacheKey = dataSource.getCacheKeyFactory().buildCacheKey(dataSpec);
|
||||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
long requestLength = dataSpec.length;
|
||||||
long bytesLeft;
|
if (requestLength == C.LENGTH_UNSET) {
|
||||||
|
long resourceLength = ContentMetadata.getContentLength(cache.getContentMetadata(cacheKey));
|
||||||
|
if (resourceLength != C.LENGTH_UNSET) {
|
||||||
|
requestLength = resourceLength - dataSpec.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long bytesCached = cache.getCachedBytes(cacheKey, dataSpec.position, requestLength);
|
||||||
@Nullable ProgressNotifier progressNotifier = null;
|
@Nullable ProgressNotifier progressNotifier = null;
|
||||||
if (progressListener != null) {
|
if (progressListener != null) {
|
||||||
progressNotifier = new ProgressNotifier(progressListener);
|
progressNotifier = new ProgressNotifier(progressListener);
|
||||||
Pair<Long, Long> lengthAndBytesAlreadyCached = getCached(dataSpec, cache, cacheKeyFactory);
|
progressNotifier.init(requestLength, bytesCached);
|
||||||
progressNotifier.init(lengthAndBytesAlreadyCached.first, lengthAndBytesAlreadyCached.second);
|
|
||||||
bytesLeft = lengthAndBytesAlreadyCached.first;
|
|
||||||
} else {
|
|
||||||
bytesLeft = getRequestLength(dataSpec, cache, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long position = dataSpec.position;
|
long position = dataSpec.position;
|
||||||
|
long bytesLeft = requestLength;
|
||||||
while (bytesLeft != 0) {
|
while (bytesLeft != 0) {
|
||||||
throwExceptionIfCanceled(isCanceled);
|
throwExceptionIfCanceled(isCanceled);
|
||||||
long blockLength = cache.getCachedLength(key, position, bytesLeft);
|
long blockLength = cache.getCachedLength(cacheKey, position, bytesLeft);
|
||||||
if (blockLength > 0) {
|
if (blockLength > 0) {
|
||||||
// Skip already cached data.
|
// Skip already cached data.
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -206,15 +176,6 @@ public final class CacheUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getRequestLength(DataSpec dataSpec, Cache cache, String key) {
|
|
||||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
|
||||||
return dataSpec.length;
|
|
||||||
} else {
|
|
||||||
long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
|
||||||
return contentLength == C.LENGTH_UNSET ? C.LENGTH_UNSET : contentLength - dataSpec.position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and discards all data specified by the {@code dataSpec}.
|
* Reads and discards all data specified by the {@code dataSpec}.
|
||||||
*
|
*
|
||||||
|
|
@ -309,12 +270,6 @@ public final class CacheUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildCacheKey(
|
|
||||||
DataSpec dataSpec, @Nullable CacheKeyFactory cacheKeyFactory) {
|
|
||||||
return (cacheKeyFactory != null ? cacheKeyFactory : CacheKeyFactory.DEFAULT)
|
|
||||||
.buildCacheKey(dataSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void throwExceptionIfCanceled(@Nullable AtomicBoolean isCanceled)
|
private static void throwExceptionIfCanceled(@Nullable AtomicBoolean isCanceled)
|
||||||
throws InterruptedIOException {
|
throws InterruptedIOException {
|
||||||
if (isCanceled != null && isCanceled.get()) {
|
if (isCanceled != null && isCanceled.get()) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Pair;
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
|
@ -104,65 +103,6 @@ public final class CacheUtilTest {
|
||||||
Util.recursiveDelete(tempFolder);
|
Util.recursiveDelete(tempFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getCachedNoData() {
|
|
||||||
Pair<Long, Long> contentLengthAndBytesCached =
|
|
||||||
CacheUtil.getCached(
|
|
||||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
|
||||||
|
|
||||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(C.LENGTH_UNSET);
|
|
||||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getCachedDataUnknownLength() {
|
|
||||||
// Mock there is 100 bytes cached at the beginning
|
|
||||||
mockCache.spansAndGaps = new int[] {100};
|
|
||||||
Pair<Long, Long> contentLengthAndBytesCached =
|
|
||||||
CacheUtil.getCached(
|
|
||||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
|
||||||
|
|
||||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(C.LENGTH_UNSET);
|
|
||||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getCachedNoDataKnownLength() {
|
|
||||||
mockCache.contentLength = 1000;
|
|
||||||
Pair<Long, Long> contentLengthAndBytesCached =
|
|
||||||
CacheUtil.getCached(
|
|
||||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
|
||||||
|
|
||||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(1000);
|
|
||||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getCached() {
|
|
||||||
mockCache.contentLength = 1000;
|
|
||||||
mockCache.spansAndGaps = new int[] {100, 100, 200};
|
|
||||||
Pair<Long, Long> contentLengthAndBytesCached =
|
|
||||||
CacheUtil.getCached(
|
|
||||||
new DataSpec(Uri.parse("test")), mockCache, /* cacheKeyFactory= */ null);
|
|
||||||
|
|
||||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(1000);
|
|
||||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(300);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getCachedFromNonZeroPosition() {
|
|
||||||
mockCache.contentLength = 1000;
|
|
||||||
mockCache.spansAndGaps = new int[] {100, 100, 200};
|
|
||||||
Pair<Long, Long> contentLengthAndBytesCached =
|
|
||||||
CacheUtil.getCached(
|
|
||||||
new DataSpec(Uri.parse("test"), /* position= */ 100, /* length= */ C.LENGTH_UNSET),
|
|
||||||
mockCache,
|
|
||||||
/* cacheKeyFactory= */ null);
|
|
||||||
|
|
||||||
assertThat(contentLengthAndBytesCached.first).isEqualTo(900);
|
|
||||||
assertThat(contentLengthAndBytesCached.second).isEqualTo(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void cache() throws Exception {
|
public void cache() throws Exception {
|
||||||
FakeDataSet fakeDataSet = new FakeDataSet().setRandomData("test_data", 100);
|
FakeDataSet fakeDataSet = new FakeDataSet().setRandomData("test_data", 100);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue