From f9d6f314e2b15e8e348fa57a64d02f5950b6159f Mon Sep 17 00:00:00 2001 From: eguven Date: Thu, 30 May 2019 14:41:03 +0100 Subject: [PATCH] Fix misreporting cached bytes when caching is paused When caching is resumed, it starts from the initial position. This makes more data to be reported as cached. Issue:#5573 PiperOrigin-RevId: 250678841 --- RELEASENOTES.md | 2 + .../exoplayer2/upstream/cache/CacheUtil.java | 44 +++++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 83a323ec626..b6cbe3d2756 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -37,6 +37,8 @@ ([#5915](https://github.com/google/ExoPlayer/issues/5915)). * Fix CacheUtil.cache() use too much data ([#5927](https://github.com/google/ExoPlayer/issues/5927)). + * Fix misreporting cached bytes when caching is paused + ([#5573](https://github.com/google/ExoPlayer/issues/5573)). * Add a playWhenReady flag to MediaSessionConnector.PlaybackPreparer methods to indicate whether a controller sent a play or only a prepare command. This allows to take advantage of decoder reuse with the MediaSessionConnector diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java index 5b066b79301..47470c5de75 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java @@ -268,6 +268,8 @@ private static long readAndDiscard( AtomicBoolean isCanceled) throws IOException, InterruptedException { long positionOffset = absoluteStreamPosition - dataSpec.absoluteStreamPosition; + long initialPositionOffset = positionOffset; + long endOffset = length != C.LENGTH_UNSET ? positionOffset + length : C.POSITION_UNSET; while (true) { if (priorityTaskManager != null) { // Wait for any other thread with higher priority to finish its job. @@ -275,45 +277,51 @@ private static long readAndDiscard( } throwExceptionIfInterruptedOrCancelled(isCanceled); try { - long resolvedLength; - try { - resolvedLength = dataSource.open(dataSpec.subrange(positionOffset, length)); - } catch (IOException exception) { - if (length == C.LENGTH_UNSET - || !isLastBlock - || !isCausedByPositionOutOfRange(exception)) { - throw exception; + long resolvedLength = C.LENGTH_UNSET; + boolean isDataSourceOpen = false; + if (endOffset != C.POSITION_UNSET) { + // If a specific length is given, first try to open the data source for that length to + // avoid more data then required to be requested. If the given length exceeds the end of + // input we will get a "position out of range" error. In that case try to open the source + // again with unset length. + try { + resolvedLength = + dataSource.open(dataSpec.subrange(positionOffset, endOffset - positionOffset)); + isDataSourceOpen = true; + } catch (IOException exception) { + if (!isLastBlock || !isCausedByPositionOutOfRange(exception)) { + throw exception; + } + Util.closeQuietly(dataSource); } - Util.closeQuietly(dataSource); - // Retry to open the data source again, setting length to C.LENGTH_UNSET to prevent - // getting an error in case the given length exceeds the end of input. + } + if (!isDataSourceOpen) { resolvedLength = dataSource.open(dataSpec.subrange(positionOffset, C.LENGTH_UNSET)); } if (isLastBlock && progressNotifier != null && resolvedLength != C.LENGTH_UNSET) { progressNotifier.onRequestLengthResolved(positionOffset + resolvedLength); } - long totalBytesRead = 0; - while (totalBytesRead != length) { + while (positionOffset != endOffset) { throwExceptionIfInterruptedOrCancelled(isCanceled); int bytesRead = dataSource.read( buffer, 0, - length != C.LENGTH_UNSET - ? (int) Math.min(buffer.length, length - totalBytesRead) + endOffset != C.POSITION_UNSET + ? (int) Math.min(buffer.length, endOffset - positionOffset) : buffer.length); if (bytesRead == C.RESULT_END_OF_INPUT) { if (progressNotifier != null) { - progressNotifier.onRequestLengthResolved(positionOffset + totalBytesRead); + progressNotifier.onRequestLengthResolved(positionOffset); } break; } - totalBytesRead += bytesRead; + positionOffset += bytesRead; if (progressNotifier != null) { progressNotifier.onBytesCached(bytesRead); } } - return totalBytesRead; + return positionOffset - initialPositionOffset; } catch (PriorityTaskManager.PriorityTooLowException exception) { // catch and try again } finally {