Commit fcc0bd40 by tonihei Committed by Oliver Woodman

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
parent ddda4a02
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.extractor; package com.google.android.exoplayer2.extractor;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
...@@ -50,9 +51,12 @@ public final class DummyTrackOutput implements TrackOutput { ...@@ -50,9 +51,12 @@ public final class DummyTrackOutput implements TrackOutput {
} }
@Override @Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, public void sampleMetadata(
CryptoData cryptoData) { long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
// Do nothing. // Do nothing.
} }
} }
...@@ -125,21 +125,23 @@ public interface TrackOutput { ...@@ -125,21 +125,23 @@ public interface TrackOutput {
/** /**
* Called when metadata associated with a sample has been extracted from the stream. * Called when metadata associated with a sample has been extracted from the stream.
* <p> *
* The corresponding sample data will have already been passed to the output via calls to * <p>The corresponding sample data will have already been passed to the output via calls to
* {@link #sampleData(ExtractorInput, int, boolean)} or * {@link #sampleData(ExtractorInput, int, boolean)} or {@link #sampleData(ParsableByteArray,
* {@link #sampleData(ParsableByteArray, int)}. * int)}.
* *
* @param timeUs The media timestamp associated with the sample, in microseconds. * @param timeUs The media timestamp associated with the sample, in microseconds.
* @param flags Flags associated with the sample. See {@code C.BUFFER_FLAG_*}. * @param flags Flags associated with the sample. See {@code C.BUFFER_FLAG_*}.
* @param size The size of the sample data, in bytes. * @param size The size of the sample data, in bytes.
* @param offset The number of bytes that have been passed to * @param offset The number of bytes that have been passed to {@link #sampleData(ExtractorInput,
* {@link #sampleData(ExtractorInput, int, boolean)} or * int, boolean)} or {@link #sampleData(ParsableByteArray, int)} since the last byte belonging
* {@link #sampleData(ParsableByteArray, int)} since the last byte belonging to the sample * to the sample whose metadata is being passed.
* whose metadata is being passed.
* @param encryptionData The encryption data required to decrypt the sample. May be null. * @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, void sampleMetadata(
CryptoData encryptionData); long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData encryptionData);
} }
...@@ -568,8 +568,12 @@ public final class SampleQueue implements TrackOutput { ...@@ -568,8 +568,12 @@ public final class SampleQueue implements TrackOutput {
} }
@Override @Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, public void sampleMetadata(
CryptoData cryptoData) { long timeUs,
@C.BufferFlags int flags,
int size,
int offset,
@Nullable CryptoData cryptoData) {
if (pendingFormatAdjustment) { if (pendingFormatAdjustment) {
format(lastUnadjustedFormat); format(lastUnadjustedFormat);
} }
......
...@@ -15,13 +15,17 @@ ...@@ -15,13 +15,17 @@
*/ */
package com.google.android.exoplayer2.source.chunk; package com.google.android.exoplayer2.source.chunk;
import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.Loader.Loadable; import com.google.android.exoplayer2.upstream.Loader.Loadable;
import com.google.android.exoplayer2.upstream.StatsDataSource;
import com.google.android.exoplayer2.util.Assertions; 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 * An abstract base class for {@link Loadable} implementations that load chunks of data required
...@@ -64,7 +68,7 @@ public abstract class Chunk implements Loadable { ...@@ -64,7 +68,7 @@ public abstract class Chunk implements Loadable {
*/ */
public final long endTimeUs; public final long endTimeUs;
protected final DataSource dataSource; protected final StatsDataSource dataSource;
/** /**
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
...@@ -85,7 +89,7 @@ public abstract class Chunk implements Loadable { ...@@ -85,7 +89,7 @@ public abstract class Chunk implements Loadable {
@Nullable Object trackSelectionData, @Nullable Object trackSelectionData,
long startTimeUs, long startTimeUs,
long endTimeUs) { long endTimeUs) {
this.dataSource = Assertions.checkNotNull(dataSource); this.dataSource = new StatsDataSource(dataSource);
this.dataSpec = Assertions.checkNotNull(dataSpec); this.dataSpec = Assertions.checkNotNull(dataSpec);
this.type = type; this.type = type;
this.trackFormat = trackFormat; this.trackFormat = trackFormat;
...@@ -103,8 +107,31 @@ public abstract class Chunk implements Loadable { ...@@ -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<String, List<String>> getResponseHeaders() {
return dataSource.getLastResponseHeaders();
}
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source.chunk; package com.google.android.exoplayer2.source.chunk;
import android.support.annotation.Nullable;
import android.util.SparseArray; import android.util.SparseArray;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
...@@ -103,7 +104,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput { ...@@ -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 * @param seekTimeUs The seek position within the new chunk, or {@link C#TIME_UNSET} to output the
* whole chunk. * whole chunk.
*/ */
public void init(TrackOutputProvider trackOutputProvider, long seekTimeUs) { public void init(@Nullable TrackOutputProvider trackOutputProvider, long seekTimeUs) {
this.trackOutputProvider = trackOutputProvider; this.trackOutputProvider = trackOutputProvider;
if (!extractorInitialized) { if (!extractorInitialized) {
extractor.init(this); extractor.init(this);
......
...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.Format; ...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; 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.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -31,13 +32,15 @@ import java.io.IOException; ...@@ -31,13 +32,15 @@ import java.io.IOException;
*/ */
public class ContainerMediaChunk extends BaseMediaChunk { public class ContainerMediaChunk extends BaseMediaChunk {
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
private final int chunkCount; private final int chunkCount;
private final long sampleOffsetUs; private final long sampleOffsetUs;
private final ChunkExtractorWrapper extractorWrapper; private final ChunkExtractorWrapper extractorWrapper;
private volatile int bytesLoaded; private long nextLoadPosition;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
private volatile boolean loadCompleted; private boolean loadCompleted;
/** /**
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
...@@ -94,11 +97,6 @@ public class ContainerMediaChunk extends BaseMediaChunk { ...@@ -94,11 +97,6 @@ public class ContainerMediaChunk extends BaseMediaChunk {
return loadCompleted; return loadCompleted;
} }
@Override
public final long bytesLoaded() {
return bytesLoaded;
}
// Loadable implementation. // Loadable implementation.
@Override @Override
...@@ -109,12 +107,12 @@ public class ContainerMediaChunk extends BaseMediaChunk { ...@@ -109,12 +107,12 @@ public class ContainerMediaChunk extends BaseMediaChunk {
@SuppressWarnings("NonAtomicVolatileUpdate") @SuppressWarnings("NonAtomicVolatileUpdate")
@Override @Override
public final void load() throws IOException, InterruptedException { public final void load() throws IOException, InterruptedException {
DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition);
try { try {
// Create and open the input. // Create and open the input.
ExtractorInput input = new DefaultExtractorInput(dataSource, ExtractorInput input = new DefaultExtractorInput(dataSource,
loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec)); loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec));
if (bytesLoaded == 0) { if (nextLoadPosition == 0) {
// Configure the output and set it as the target for the extractor wrapper. // Configure the output and set it as the target for the extractor wrapper.
BaseMediaChunkOutput output = getOutput(); BaseMediaChunkOutput output = getOutput();
output.setSampleOffsetUs(sampleOffsetUs); output.setSampleOffsetUs(sampleOffsetUs);
...@@ -126,11 +124,11 @@ public class ContainerMediaChunk extends BaseMediaChunk { ...@@ -126,11 +124,11 @@ public class ContainerMediaChunk extends BaseMediaChunk {
Extractor extractor = extractorWrapper.extractor; Extractor extractor = extractorWrapper.extractor;
int result = Extractor.RESULT_CONTINUE; int result = Extractor.RESULT_CONTINUE;
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
result = extractor.read(input, null); result = extractor.read(input, DUMMY_POSITION_HOLDER);
} }
Assertions.checkState(result != Extractor.RESULT_SEEK); Assertions.checkState(result != Extractor.RESULT_SEEK);
} finally { } finally {
bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); nextLoadPosition = input.getPosition() - dataSpec.absoluteStreamPosition;
} }
} finally { } finally {
Util.closeQuietly(dataSource); Util.closeQuietly(dataSource);
......
...@@ -32,7 +32,6 @@ public abstract class DataChunk extends Chunk { ...@@ -32,7 +32,6 @@ public abstract class DataChunk extends Chunk {
private static final int READ_GRANULARITY = 16 * 1024; private static final int READ_GRANULARITY = 16 * 1024;
private byte[] data; private byte[] data;
private int limit;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
...@@ -63,11 +62,6 @@ public abstract class DataChunk extends Chunk { ...@@ -63,11 +62,6 @@ public abstract class DataChunk extends Chunk {
return data; return data;
} }
@Override
public long bytesLoaded() {
return limit;
}
// Loadable implementation // Loadable implementation
@Override @Override
...@@ -79,10 +73,10 @@ public abstract class DataChunk extends Chunk { ...@@ -79,10 +73,10 @@ public abstract class DataChunk extends Chunk {
public final void load() throws IOException, InterruptedException { public final void load() throws IOException, InterruptedException {
try { try {
dataSource.open(dataSpec); dataSource.open(dataSpec);
limit = 0; int limit = 0;
int bytesRead = 0; int bytesRead = 0;
while (bytesRead != C.RESULT_END_OF_INPUT && !loadCanceled) { while (bytesRead != C.RESULT_END_OF_INPUT && !loadCanceled) {
maybeExpandData(); maybeExpandData(limit);
bytesRead = dataSource.read(data, limit, READ_GRANULARITY); bytesRead = dataSource.read(data, limit, READ_GRANULARITY);
if (bytesRead != -1) { if (bytesRead != -1) {
limit += bytesRead; limit += bytesRead;
...@@ -106,7 +100,7 @@ public abstract class DataChunk extends Chunk { ...@@ -106,7 +100,7 @@ public abstract class DataChunk extends Chunk {
*/ */
protected abstract void consume(byte[] data, int limit) throws IOException; protected abstract void consume(byte[] data, int limit) throws IOException;
private void maybeExpandData() { private void maybeExpandData(int limit) {
if (data == null) { if (data == null) {
data = new byte[READ_GRANULARITY]; data = new byte[READ_GRANULARITY];
} else if (data.length < limit + READ_GRANULARITY) { } else if (data.length < limit + READ_GRANULARITY) {
...@@ -115,5 +109,4 @@ public abstract class DataChunk extends Chunk { ...@@ -115,5 +109,4 @@ public abstract class DataChunk extends Chunk {
data = Arrays.copyOf(data, data.length + READ_GRANULARITY); data = Arrays.copyOf(data, data.length + READ_GRANULARITY);
} }
} }
} }
...@@ -21,6 +21,7 @@ import com.google.android.exoplayer2.Format; ...@@ -21,6 +21,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; 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.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -32,9 +33,11 @@ import java.io.IOException; ...@@ -32,9 +33,11 @@ import java.io.IOException;
*/ */
public final class InitializationChunk extends Chunk { public final class InitializationChunk extends Chunk {
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
private final ChunkExtractorWrapper extractorWrapper; private final ChunkExtractorWrapper extractorWrapper;
private volatile int bytesLoaded; private long nextLoadPosition;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
/** /**
...@@ -57,11 +60,6 @@ public final class InitializationChunk extends Chunk { ...@@ -57,11 +60,6 @@ public final class InitializationChunk extends Chunk {
this.extractorWrapper = extractorWrapper; this.extractorWrapper = extractorWrapper;
} }
@Override
public long bytesLoaded() {
return bytesLoaded;
}
// Loadable implementation. // Loadable implementation.
@Override @Override
...@@ -72,12 +70,12 @@ public final class InitializationChunk extends Chunk { ...@@ -72,12 +70,12 @@ public final class InitializationChunk extends Chunk {
@SuppressWarnings("NonAtomicVolatileUpdate") @SuppressWarnings("NonAtomicVolatileUpdate")
@Override @Override
public void load() throws IOException, InterruptedException { public void load() throws IOException, InterruptedException {
DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition);
try { try {
// Create and open the input. // Create and open the input.
ExtractorInput input = new DefaultExtractorInput(dataSource, ExtractorInput input = new DefaultExtractorInput(dataSource,
loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec)); loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec));
if (bytesLoaded == 0) { if (nextLoadPosition == 0) {
extractorWrapper.init(/* trackOutputProvider= */ null, C.TIME_UNSET); extractorWrapper.init(/* trackOutputProvider= */ null, C.TIME_UNSET);
} }
// Load and decode the initialization data. // Load and decode the initialization data.
...@@ -85,11 +83,11 @@ public final class InitializationChunk extends Chunk { ...@@ -85,11 +83,11 @@ public final class InitializationChunk extends Chunk {
Extractor extractor = extractorWrapper.extractor; Extractor extractor = extractorWrapper.extractor;
int result = Extractor.RESULT_CONTINUE; int result = Extractor.RESULT_CONTINUE;
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) { while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
result = extractor.read(input, null); result = extractor.read(input, DUMMY_POSITION_HOLDER);
} }
Assertions.checkState(result != Extractor.RESULT_SEEK); Assertions.checkState(result != Extractor.RESULT_SEEK);
} finally { } finally {
bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); nextLoadPosition = input.getPosition() - dataSpec.absoluteStreamPosition;
} }
} finally { } finally {
Util.closeQuietly(dataSource); Util.closeQuietly(dataSource);
......
...@@ -33,8 +33,8 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { ...@@ -33,8 +33,8 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
private final int trackType; private final int trackType;
private final Format sampleFormat; private final Format sampleFormat;
private volatile int bytesLoaded; private long nextLoadPosition;
private volatile boolean loadCompleted; private boolean loadCompleted;
/** /**
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
...@@ -80,11 +80,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { ...@@ -80,11 +80,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
return loadCompleted; return loadCompleted;
} }
@Override
public long bytesLoaded() {
return bytesLoaded;
}
// Loadable implementation. // Loadable implementation.
@Override @Override
...@@ -95,14 +90,15 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { ...@@ -95,14 +90,15 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
@SuppressWarnings("NonAtomicVolatileUpdate") @SuppressWarnings("NonAtomicVolatileUpdate")
@Override @Override
public void load() throws IOException, InterruptedException { public void load() throws IOException, InterruptedException {
DataSpec loadDataSpec = dataSpec.subrange(bytesLoaded); DataSpec loadDataSpec = dataSpec.subrange(nextLoadPosition);
try { try {
// Create and open the input. // Create and open the input.
long length = dataSource.open(loadDataSpec); long length = dataSource.open(loadDataSpec);
if (length != C.LENGTH_UNSET) { 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(); BaseMediaChunkOutput output = getOutput();
output.setSampleOffsetUs(0); output.setSampleOffsetUs(0);
TrackOutput trackOutput = output.track(0, trackType); TrackOutput trackOutput = output.track(0, trackType);
...@@ -110,10 +106,10 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { ...@@ -110,10 +106,10 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
// Load the sample data. // Load the sample data.
int result = 0; int result = 0;
while (result != C.RESULT_END_OF_INPUT) { while (result != C.RESULT_END_OF_INPUT) {
bytesLoaded += result; nextLoadPosition += result;
result = trackOutput.sampleData(extractorInput, Integer.MAX_VALUE, true); 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); trackOutput.sampleMetadata(startTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
} finally { } finally {
Util.closeQuietly(dataSource); Util.closeQuietly(dataSource);
......
/*
* 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<String, List<String>> 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<String, List<String>> 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<String, List<String>> getResponseHeaders() {
return dataSource.getResponseHeaders();
}
@Override
public void close() throws IOException {
dataSource.close();
}
}
...@@ -421,10 +421,5 @@ public final class AdaptiveTrackSelectionTest { ...@@ -421,10 +421,5 @@ public final class AdaptiveTrackSelectionTest {
public boolean isLoadCompleted() { public boolean isLoadCompleted() {
return true; return true;
} }
@Override
public long bytesLoaded() {
return 0;
}
} }
} }
...@@ -336,7 +336,7 @@ public final class PlayerEmsgHandler implements Handler.Callback { ...@@ -336,7 +336,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
@Override @Override
public void sampleMetadata( 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); sampleQueue.sampleMetadata(timeUs, flags, size, offset, encryptionData);
parseAndDiscardSamples(); parseAndDiscardSamples();
} }
......
...@@ -80,11 +80,11 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -80,11 +80,11 @@ import java.util.concurrent.atomic.AtomicInteger;
private ParsableByteArray id3Data; private ParsableByteArray id3Data;
private HlsSampleStreamWrapper output; private HlsSampleStreamWrapper output;
private int initSegmentBytesLoaded; private int initSegmentBytesLoaded;
private int bytesLoaded; private int nextLoadPosition;
private boolean id3TimestampPeeked; private boolean id3TimestampPeeked;
private boolean initLoadCompleted; private boolean initLoadCompleted;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
private volatile boolean loadCompleted; private boolean loadCompleted;
/** /**
* @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor * @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor
...@@ -145,8 +145,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -145,8 +145,7 @@ import java.util.concurrent.atomic.AtomicInteger;
this.hlsUrl = hlsUrl; this.hlsUrl = hlsUrl;
this.isMasterTimestampSource = isMasterTimestampSource; this.isMasterTimestampSource = isMasterTimestampSource;
this.timestampAdjuster = timestampAdjuster; this.timestampAdjuster = timestampAdjuster;
// Note: this.dataSource and dataSource may be different. this.isEncrypted = fullSegmentEncryptionKey != null;
this.isEncrypted = this.dataSource instanceof Aes128DataSource;
this.hasGapTag = hasGapTag; this.hasGapTag = hasGapTag;
this.extractorFactory = extractorFactory; this.extractorFactory = extractorFactory;
this.muxedCaptionFormats = muxedCaptionFormats; this.muxedCaptionFormats = muxedCaptionFormats;
...@@ -181,11 +180,6 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -181,11 +180,6 @@ import java.util.concurrent.atomic.AtomicInteger;
return loadCompleted; return loadCompleted;
} }
@Override
public long bytesLoaded() {
return bytesLoaded;
}
// Loadable implementation // Loadable implementation
@Override @Override
...@@ -237,9 +231,9 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -237,9 +231,9 @@ import java.util.concurrent.atomic.AtomicInteger;
boolean skipLoadedBytes; boolean skipLoadedBytes;
if (isEncrypted) { if (isEncrypted) {
loadDataSpec = dataSpec; loadDataSpec = dataSpec;
skipLoadedBytes = bytesLoaded != 0; skipLoadedBytes = nextLoadPosition != 0;
} else { } else {
loadDataSpec = dataSpec.subrange(bytesLoaded); loadDataSpec = dataSpec.subrange(nextLoadPosition);
skipLoadedBytes = false; skipLoadedBytes = false;
} }
if (!isMasterTimestampSource) { if (!isMasterTimestampSource) {
...@@ -257,7 +251,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -257,7 +251,7 @@ import java.util.concurrent.atomic.AtomicInteger;
? timestampAdjuster.adjustTsTimestamp(id3Timestamp) : startTimeUs); ? timestampAdjuster.adjustTsTimestamp(id3Timestamp) : startTimeUs);
} }
if (skipLoadedBytes) { if (skipLoadedBytes) {
input.skipFully(bytesLoaded); input.skipFully(nextLoadPosition);
} }
try { try {
int result = Extractor.RESULT_CONTINUE; int result = Extractor.RESULT_CONTINUE;
...@@ -265,7 +259,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -265,7 +259,7 @@ import java.util.concurrent.atomic.AtomicInteger;
result = extractor.read(input, null); result = extractor.read(input, null);
} }
} finally { } finally {
bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition); nextLoadPosition = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
} }
} finally { } finally {
Util.closeQuietly(dataSource); Util.closeQuietly(dataSource);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment