From fcc0bd403ff2c9d0abe7f4b7503398e4e4636e06 Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 22 Jun 2018 04:03:15 -0700 Subject: [PATCH] Report uri and response headers of chunks. Both values are helpful for event reporting, but are only available while the data source is open. Similar to bytesLoaded, they need to be reported through the Chunk. Issue:#2054 Issue:#4361 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=201664907 --- .../extractor/DummyTrackOutput.java | 10 +- .../exoplayer2/extractor/TrackOutput.java | 24 +++-- .../exoplayer2/source/SampleQueue.java | 8 +- .../exoplayer2/source/chunk/Chunk.java | 35 +++++- .../source/chunk/ChunkExtractorWrapper.java | 3 +- .../source/chunk/ContainerMediaChunk.java | 20 ++-- .../exoplayer2/source/chunk/DataChunk.java | 13 +-- .../source/chunk/InitializationChunk.java | 18 ++-- .../source/chunk/SingleSampleMediaChunk.java | 20 ++-- .../exoplayer2/upstream/StatsDataSource.java | 102 ++++++++++++++++++ .../AdaptiveTrackSelectionTest.java | 5 - .../source/dash/PlayerEmsgHandler.java | 2 +- .../exoplayer2/source/hls/HlsMediaChunk.java | 20 ++-- 13 files changed, 197 insertions(+), 83 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java index c023b0de95..9eaf0f7ef7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.ParsableByteArray; @@ -50,9 +51,12 @@ public final class DummyTrackOutput implements TrackOutput { } @Override - public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, - CryptoData cryptoData) { + public void sampleMetadata( + long timeUs, + @C.BufferFlags int flags, + int size, + int offset, + @Nullable CryptoData cryptoData) { // Do nothing. } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java index 6a8cef6b64..7b832eb400 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java @@ -125,21 +125,23 @@ public interface TrackOutput { /** * Called when metadata associated with a sample has been extracted from the stream. - *

- * The corresponding sample data will have already been passed to the output via calls to - * {@link #sampleData(ExtractorInput, int, boolean)} or - * {@link #sampleData(ParsableByteArray, int)}. + * + *

The corresponding sample data will have already been passed to the output via calls to + * {@link #sampleData(ExtractorInput, int, boolean)} or {@link #sampleData(ParsableByteArray, + * int)}. * * @param timeUs The media timestamp associated with the sample, in microseconds. * @param flags Flags associated with the sample. See {@code C.BUFFER_FLAG_*}. * @param size The size of the sample data, in bytes. - * @param offset The number of bytes that have been passed to - * {@link #sampleData(ExtractorInput, int, boolean)} or - * {@link #sampleData(ParsableByteArray, int)} since the last byte belonging to the sample - * whose metadata is being passed. + * @param offset The number of bytes that have been passed to {@link #sampleData(ExtractorInput, + * int, boolean)} or {@link #sampleData(ParsableByteArray, int)} since the last byte belonging + * to the sample whose metadata is being passed. * @param encryptionData The encryption data required to decrypt the sample. May be null. */ - void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, - CryptoData encryptionData); - + void sampleMetadata( + long timeUs, + @C.BufferFlags int flags, + int size, + int offset, + @Nullable CryptoData encryptionData); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index d9090baf3b..c378a8f9a2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -568,8 +568,12 @@ public final class SampleQueue implements TrackOutput { } @Override - public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, - CryptoData cryptoData) { + public void sampleMetadata( + long timeUs, + @C.BufferFlags int flags, + int size, + int offset, + @Nullable CryptoData cryptoData) { if (pendingFormatAdjustment) { format(lastUnadjustedFormat); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java index 0453a8fa12..5c109aef8c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java @@ -15,13 +15,17 @@ */ package com.google.android.exoplayer2.source.chunk; +import android.net.Uri; import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.Loader.Loadable; +import com.google.android.exoplayer2.upstream.StatsDataSource; import com.google.android.exoplayer2.util.Assertions; +import java.util.List; +import java.util.Map; /** * An abstract base class for {@link Loadable} implementations that load chunks of data required @@ -64,7 +68,7 @@ public abstract class Chunk implements Loadable { */ public final long endTimeUs; - protected final DataSource dataSource; + protected final StatsDataSource dataSource; /** * @param dataSource The source from which the data should be loaded. @@ -85,7 +89,7 @@ public abstract class Chunk implements Loadable { @Nullable Object trackSelectionData, long startTimeUs, long endTimeUs) { - this.dataSource = Assertions.checkNotNull(dataSource); + this.dataSource = new StatsDataSource(dataSource); this.dataSpec = Assertions.checkNotNull(dataSpec); this.type = type; this.trackFormat = trackFormat; @@ -103,8 +107,31 @@ public abstract class Chunk implements Loadable { } /** - * Returns the number of bytes that have been loaded. + * Returns the number of bytes that have been loaded. Must only be called after the load + * completed, failed, or was canceled. */ - public abstract long bytesLoaded(); + public final long bytesLoaded() { + return dataSource.getBytesRead(); + } + /** + * Returns the {@link Uri} associated with the last {@link DataSource#open} call. If redirection + * occurred, this is the redirected uri. Must only be called after the load completed, failed, or + * was canceled. + * + * @see DataSource#getUri(). + */ + public final Uri getUri() { + return dataSource.getLastOpenedUri(); + } + + /** + * Returns the response headers associated with the last {@link DataSource#open} call. Must only + * be called after the load completed, failed, or was canceled. + * + * @see DataSource#getResponseHeaders(). + */ + public final Map> getResponseHeaders() { + return dataSource.getLastResponseHeaders(); + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java index f043571b69..a3abc75606 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.chunk; +import android.support.annotation.Nullable; import android.util.SparseArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; @@ -103,7 +104,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput { * @param seekTimeUs The seek position within the new chunk, or {@link C#TIME_UNSET} to output the * whole chunk. */ - public void init(TrackOutputProvider trackOutputProvider, long seekTimeUs) { + public void init(@Nullable TrackOutputProvider trackOutputProvider, long seekTimeUs) { this.trackOutputProvider = trackOutputProvider; if (!extractorInitialized) { extractor.init(this); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java index 1159f336a7..2d5ba3d2e0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java @@ -20,6 +20,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; +import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; @@ -31,13 +32,15 @@ import java.io.IOException; */ public class ContainerMediaChunk extends BaseMediaChunk { + private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder(); + private final int chunkCount; private final long sampleOffsetUs; private final ChunkExtractorWrapper extractorWrapper; - private volatile int bytesLoaded; + private long nextLoadPosition; private volatile boolean loadCanceled; - private volatile boolean loadCompleted; + private boolean loadCompleted; /** * @param dataSource The source from which the data should be loaded. @@ -94,11 +97,6 @@ public class ContainerMediaChunk extends BaseMediaChunk { return loadCompleted; } - @Override - public final long bytesLoaded() { - return bytesLoaded; - } - // Loadable implementation. @Override @@ -109,12 +107,12 @@ public class ContainerMediaChunk extends BaseMediaChunk { @SuppressWarnings("NonAtomicVolatileUpdate") @Override public final void load() throws IOException, InterruptedException { - DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); + DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition); try { // Create and open the input. ExtractorInput input = new DefaultExtractorInput(dataSource, loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec)); - if (bytesLoaded == 0) { + if (nextLoadPosition == 0) { // Configure the output and set it as the target for the extractor wrapper. BaseMediaChunkOutput output = getOutput(); output.setSampleOffsetUs(sampleOffsetUs); @@ -126,11 +124,11 @@ public class ContainerMediaChunk extends BaseMediaChunk { Extractor extractor = extractorWrapper.extractor; int result = Extractor.RESULT_CONTINUE; while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { - result = extractor.read(input, null); + result = extractor.read(input, DUMMY_POSITION_HOLDER); } Assertions.checkState(result != Extractor.RESULT_SEEK); } finally { - bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); + nextLoadPosition = input.getPosition() - dataSpec.absoluteStreamPosition; } } finally { Util.closeQuietly(dataSource); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java index 1d3bdb57da..7ea2521eb2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/DataChunk.java @@ -32,7 +32,6 @@ public abstract class DataChunk extends Chunk { private static final int READ_GRANULARITY = 16 * 1024; private byte[] data; - private int limit; private volatile boolean loadCanceled; @@ -63,11 +62,6 @@ public abstract class DataChunk extends Chunk { return data; } - @Override - public long bytesLoaded() { - return limit; - } - // Loadable implementation @Override @@ -79,10 +73,10 @@ public abstract class DataChunk extends Chunk { public final void load() throws IOException, InterruptedException { try { dataSource.open(dataSpec); - limit = 0; + int limit = 0; int bytesRead = 0; while (bytesRead != C.RESULT_END_OF_INPUT && !loadCanceled) { - maybeExpandData(); + maybeExpandData(limit); bytesRead = dataSource.read(data, limit, READ_GRANULARITY); if (bytesRead != -1) { limit += bytesRead; @@ -106,7 +100,7 @@ public abstract class DataChunk extends Chunk { */ protected abstract void consume(byte[] data, int limit) throws IOException; - private void maybeExpandData() { + private void maybeExpandData(int limit) { if (data == null) { data = new byte[READ_GRANULARITY]; } else if (data.length < limit + READ_GRANULARITY) { @@ -115,5 +109,4 @@ public abstract class DataChunk extends Chunk { data = Arrays.copyOf(data, data.length + READ_GRANULARITY); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java index 387a90297a..d5c0d6f301 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java @@ -21,6 +21,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; +import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; @@ -32,9 +33,11 @@ import java.io.IOException; */ public final class InitializationChunk extends Chunk { + private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder(); + private final ChunkExtractorWrapper extractorWrapper; - private volatile int bytesLoaded; + private long nextLoadPosition; private volatile boolean loadCanceled; /** @@ -57,11 +60,6 @@ public final class InitializationChunk extends Chunk { this.extractorWrapper = extractorWrapper; } - @Override - public long bytesLoaded() { - return bytesLoaded; - } - // Loadable implementation. @Override @@ -72,12 +70,12 @@ public final class InitializationChunk extends Chunk { @SuppressWarnings("NonAtomicVolatileUpdate") @Override public void load() throws IOException, InterruptedException { - DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); + DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition); try { // Create and open the input. ExtractorInput input = new DefaultExtractorInput(dataSource, loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec)); - if (bytesLoaded == 0) { + if (nextLoadPosition == 0) { extractorWrapper.init(/* trackOutputProvider= */ null, C.TIME_UNSET); } // Load and decode the initialization data. @@ -85,11 +83,11 @@ public final class InitializationChunk extends Chunk { Extractor extractor = extractorWrapper.extractor; int result = Extractor.RESULT_CONTINUE; while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { - result = extractor.read(input, null); + result = extractor.read(input, DUMMY_POSITION_HOLDER); } Assertions.checkState(result != Extractor.RESULT_SEEK); } finally { - bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); + nextLoadPosition = input.getPosition() - dataSpec.absoluteStreamPosition; } } finally { Util.closeQuietly(dataSource); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java index 17154ebc62..2c00c7690d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java @@ -33,8 +33,8 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { private final int trackType; private final Format sampleFormat; - private volatile int bytesLoaded; - private volatile boolean loadCompleted; + private long nextLoadPosition; + private boolean loadCompleted; /** * @param dataSource The source from which the data should be loaded. @@ -80,11 +80,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { return loadCompleted; } - @Override - public long bytesLoaded() { - return bytesLoaded; - } - // Loadable implementation. @Override @@ -95,14 +90,15 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { @SuppressWarnings("NonAtomicVolatileUpdate") @Override public void load() throws IOException, InterruptedException { - DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); + DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition); try { // Create and open the input. long length = dataSource.open(loadDataSpec); if (length != C.LENGTH_UNSET) { - length += bytesLoaded; + length += nextLoadPosition; } - ExtractorInput extractorInput = new DefaultExtractorInput(dataSource, bytesLoaded, length); + ExtractorInput extractorInput = + new DefaultExtractorInput(dataSource, nextLoadPosition, length); BaseMediaChunkOutput output = getOutput(); output.setSampleOffsetUs(0); TrackOutput trackOutput = output.track(0, trackType); @@ -110,10 +106,10 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { // Load the sample data. int result = 0; while (result != C.RESULT_END_OF_INPUT) { - bytesLoaded += result; + nextLoadPosition += result; result = trackOutput.sampleData(extractorInput, Integer.MAX_VALUE, true); } - int sampleSize = bytesLoaded; + int sampleSize = (int) nextLoadPosition; trackOutput.sampleMetadata(startTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null); } finally { Util.closeQuietly(dataSource); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java new file mode 100644 index 0000000000..71458b24a4 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.upstream; + +import android.net.Uri; +import android.support.annotation.Nullable; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.Assertions; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * {@link DataSource} wrapper which keeps track of bytes transferred, redirected uris, and response + * headers. + */ +public final class StatsDataSource implements DataSource { + + private final DataSource dataSource; + + private long bytesRead; + private Uri lastOpenedUri; + private Map> lastResponseHeaders; + + /** + * Creates the stats data source. + * + * @param dataSource The wrapped {@link DataSource}. + */ + public StatsDataSource(DataSource dataSource) { + this.dataSource = Assertions.checkNotNull(dataSource); + lastOpenedUri = Uri.EMPTY; + lastResponseHeaders = Collections.emptyMap(); + } + + /** Returns the total number of bytes that have been read from the data source. */ + public long getBytesRead() { + return bytesRead; + } + + /** + * Returns the {@link Uri} associated with the last {@link #open(DataSpec)} call. If redirection + * occurred, this is the redirected uri. + */ + public Uri getLastOpenedUri() { + return lastOpenedUri; + } + + /** Returns the response headers associated with the last {@link #open(DataSpec)} call. */ + public Map> getLastResponseHeaders() { + return lastResponseHeaders; + } + + @Override + public long open(DataSpec dataSpec) throws IOException { + // Reassign defaults in case dataSource.open throws an exception. + lastOpenedUri = dataSpec.uri; + lastResponseHeaders = Collections.emptyMap(); + long availableBytes = dataSource.open(dataSpec); + lastOpenedUri = Assertions.checkNotNull(getUri()); + lastResponseHeaders = getResponseHeaders(); + return availableBytes; + } + + @Override + public int read(byte[] buffer, int offset, int readLength) throws IOException { + int bytesRead = dataSource.read(buffer, offset, readLength); + if (bytesRead != C.RESULT_END_OF_INPUT) { + this.bytesRead += bytesRead; + } + return bytesRead; + } + + @Override + public @Nullable Uri getUri() { + return dataSource.getUri(); + } + + @Override + public Map> getResponseHeaders() { + return dataSource.getResponseHeaders(); + } + + @Override + public void close() throws IOException { + dataSource.close(); + } +} diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java index 06c34a379d..730572bbd8 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java @@ -421,10 +421,5 @@ public final class AdaptiveTrackSelectionTest { public boolean isLoadCompleted() { return true; } - - @Override - public long bytesLoaded() { - return 0; - } } } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java index 0ef6b5ff1a..a4a37cd904 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java @@ -336,7 +336,7 @@ public final class PlayerEmsgHandler implements Handler.Callback { @Override public void sampleMetadata( - long timeUs, int flags, int size, int offset, CryptoData encryptionData) { + long timeUs, int flags, int size, int offset, @Nullable CryptoData encryptionData) { sampleQueue.sampleMetadata(timeUs, flags, size, offset, encryptionData); parseAndDiscardSamples(); } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index 2805e35db7..8c151e59c1 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -80,11 +80,11 @@ import java.util.concurrent.atomic.AtomicInteger; private ParsableByteArray id3Data; private HlsSampleStreamWrapper output; private int initSegmentBytesLoaded; - private int bytesLoaded; + private int nextLoadPosition; private boolean id3TimestampPeeked; private boolean initLoadCompleted; private volatile boolean loadCanceled; - private volatile boolean loadCompleted; + private boolean loadCompleted; /** * @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor @@ -145,8 +145,7 @@ import java.util.concurrent.atomic.AtomicInteger; this.hlsUrl = hlsUrl; this.isMasterTimestampSource = isMasterTimestampSource; this.timestampAdjuster = timestampAdjuster; - // Note: this.dataSource and dataSource may be different. - this.isEncrypted = this.dataSource instanceof Aes128DataSource; + this.isEncrypted = fullSegmentEncryptionKey != null; this.hasGapTag = hasGapTag; this.extractorFactory = extractorFactory; this.muxedCaptionFormats = muxedCaptionFormats; @@ -181,11 +180,6 @@ import java.util.concurrent.atomic.AtomicInteger; return loadCompleted; } - @Override - public long bytesLoaded() { - return bytesLoaded; - } - // Loadable implementation @Override @@ -237,9 +231,9 @@ import java.util.concurrent.atomic.AtomicInteger; boolean skipLoadedBytes; if (isEncrypted) { loadDataSpec = dataSpec; - skipLoadedBytes = bytesLoaded != 0; + skipLoadedBytes = nextLoadPosition != 0; } else { - loadDataSpec = dataSpec.subrange(bytesLoaded); + loadDataSpec = dataSpec.subrange(nextLoadPosition); skipLoadedBytes = false; } if (!isMasterTimestampSource) { @@ -257,7 +251,7 @@ import java.util.concurrent.atomic.AtomicInteger; ? timestampAdjuster.adjustTsTimestamp(id3Timestamp) : startTimeUs); } if (skipLoadedBytes) { - input.skipFully(bytesLoaded); + input.skipFully(nextLoadPosition); } try { int result = Extractor.RESULT_CONTINUE; @@ -265,7 +259,7 @@ import java.util.concurrent.atomic.AtomicInteger; result = extractor.read(input, null); } } finally { - bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); + nextLoadPosition = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); } } finally { Util.closeQuietly(dataSource);