Commit 5f6b1973 by Oliver Woodman

Allow direct and indirect buffer replacement.

Also tweak ManifestFetcher.
parent ae6e082d
...@@ -174,7 +174,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { ...@@ -174,7 +174,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
this.eventHandler = eventHandler; this.eventHandler = eventHandler;
this.eventListener = eventListener; this.eventListener = eventListener;
codecCounters = new CodecCounters(); codecCounters = new CodecCounters();
sampleHolder = new SampleHolder(false); sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
formatHolder = new MediaFormatHolder(); formatHolder = new MediaFormatHolder();
decodeOnlyPresentationTimestamps = new HashSet<Long>(); decodeOnlyPresentationTimestamps = new HashSet<Long>();
outputBufferInfo = new MediaCodec.BufferInfo(); outputBufferInfo = new MediaCodec.BufferInfo();
......
...@@ -23,10 +23,19 @@ import java.nio.ByteBuffer; ...@@ -23,10 +23,19 @@ import java.nio.ByteBuffer;
public final class SampleHolder { public final class SampleHolder {
/** /**
* Whether a {@link SampleSource} is permitted to replace {@link #data} if its current value is * Disallows buffer replacement.
* null or of insufficient size to hold the sample.
*/ */
public final boolean allowDataBufferReplacement; public static final int BUFFER_REPLACEMENT_MODE_DISABLED = 0;
/**
* Allows buffer replacement using {@link ByteBuffer#allocate(int)}.
*/
public static final int BUFFER_REPLACEMENT_MODE_NORMAL = 1;
/**
* Allows buffer replacement using {@link ByteBuffer#allocateDirect(int)}.
*/
public static final int BUFFER_REPLACEMENT_MODE_DIRECT = 2;
public final CryptoInfo cryptoInfo; public final CryptoInfo cryptoInfo;
...@@ -57,12 +66,34 @@ public final class SampleHolder { ...@@ -57,12 +66,34 @@ public final class SampleHolder {
*/ */
public boolean decodeOnly; public boolean decodeOnly;
private final int bufferReplacementMode;
/** /**
* @param allowDataBufferReplacement See {@link #allowDataBufferReplacement}. * @param bufferReplacementMode Determines the behavior of {@link #replaceBuffer(int)}. One of
* {@link #BUFFER_REPLACEMENT_MODE_DISABLED}, {@link #BUFFER_REPLACEMENT_MODE_NORMAL} and
* {@link #BUFFER_REPLACEMENT_MODE_DIRECT}.
*/ */
public SampleHolder(boolean allowDataBufferReplacement) { public SampleHolder(int bufferReplacementMode) {
this.cryptoInfo = new CryptoInfo(); this.cryptoInfo = new CryptoInfo();
this.allowDataBufferReplacement = allowDataBufferReplacement; this.bufferReplacementMode = bufferReplacementMode;
}
/**
* Attempts to replace {@link #data} with a {@link ByteBuffer} of the specified capacity.
*
* @param capacity The capacity of the replacement buffer, in bytes.
* @return True if the buffer was replaced. False otherwise.
*/
public boolean replaceBuffer(int capacity) {
switch (bufferReplacementMode) {
case BUFFER_REPLACEMENT_MODE_NORMAL:
data = ByteBuffer.allocate(capacity);
return true;
case BUFFER_REPLACEMENT_MODE_DIRECT:
data = ByteBuffer.allocateDirect(capacity);
return true;
}
return false;
} }
} }
...@@ -22,7 +22,6 @@ import com.google.android.exoplayer.upstream.DataSpec; ...@@ -22,7 +22,6 @@ import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.upstream.NonBlockingInputStream; import com.google.android.exoplayer.upstream.NonBlockingInputStream;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import java.nio.ByteBuffer;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -97,9 +96,8 @@ public class SingleSampleMediaChunk extends MediaChunk { ...@@ -97,9 +96,8 @@ public class SingleSampleMediaChunk extends MediaChunk {
if (headerData != null) { if (headerData != null) {
sampleSize += headerData.length; sampleSize += headerData.length;
} }
if (holder.allowDataBufferReplacement && if (holder.data == null || holder.data.capacity() < sampleSize) {
(holder.data == null || holder.data.capacity() < sampleSize)) { holder.replaceBuffer(sampleSize);
holder.data = ByteBuffer.allocate(sampleSize);
} }
int bytesRead; int bytesRead;
if (holder.data != null) { if (holder.data != null) {
......
...@@ -1069,21 +1069,20 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -1069,21 +1069,20 @@ public final class FragmentedMp4Extractor implements Extractor {
if (out == null) { if (out == null) {
return RESULT_NEED_SAMPLE_HOLDER; return RESULT_NEED_SAMPLE_HOLDER;
} }
ByteBuffer outputData = out.data;
out.timeUs = fragmentRun.getSamplePresentationTime(sampleIndex) * 1000L; out.timeUs = fragmentRun.getSamplePresentationTime(sampleIndex) * 1000L;
out.flags = 0; out.flags = 0;
if (fragmentRun.sampleIsSyncFrameTable[sampleIndex]) { if (fragmentRun.sampleIsSyncFrameTable[sampleIndex]) {
out.flags |= MediaExtractor.SAMPLE_FLAG_SYNC; out.flags |= MediaExtractor.SAMPLE_FLAG_SYNC;
lastSyncSampleIndex = sampleIndex; lastSyncSampleIndex = sampleIndex;
} }
if (out.allowDataBufferReplacement && (out.data == null || out.data.capacity() < sampleSize)) { if (out.data == null || out.data.capacity() < sampleSize) {
outputData = ByteBuffer.allocate(sampleSize); out.replaceBuffer(sampleSize);
out.data = outputData;
} }
if (fragmentRun.definesEncryptionData) { if (fragmentRun.definesEncryptionData) {
readSampleEncryptionData(fragmentRun.sampleEncryptionData, out); readSampleEncryptionData(fragmentRun.sampleEncryptionData, out);
} }
ByteBuffer outputData = out.data;
if (outputData == null) { if (outputData == null) {
inputStream.skip(sampleSize); inputStream.skip(sampleSize);
out.size = 0; out.size = 0;
......
...@@ -347,13 +347,11 @@ public final class WebmExtractor implements Extractor { ...@@ -347,13 +347,11 @@ public final class WebmExtractor implements Extractor {
throw new IllegalStateException("Lacing mode " + lacing + " not supported"); throw new IllegalStateException("Lacing mode " + lacing + " not supported");
} }
ByteBuffer outputData = sampleHolder.data; if (sampleHolder.data == null || sampleHolder.data.capacity() < sampleHolder.size) {
if (sampleHolder.allowDataBufferReplacement sampleHolder.replaceBuffer(sampleHolder.size);
&& (sampleHolder.data == null || sampleHolder.data.capacity() < sampleHolder.size)) {
outputData = ByteBuffer.allocate(sampleHolder.size);
sampleHolder.data = outputData;
} }
ByteBuffer outputData = sampleHolder.data;
if (outputData == null) { if (outputData == null) {
reader.skipBytes(inputStream, sampleHolder.size); reader.skipBytes(inputStream, sampleHolder.size);
sampleHolder.size = 0; sampleHolder.size = 0;
......
...@@ -55,7 +55,7 @@ public class SubtitleParserHelper implements Handler.Callback { ...@@ -55,7 +55,7 @@ public class SubtitleParserHelper implements Handler.Callback {
* Flushes the helper, canceling the current parsing operation, if there is one. * Flushes the helper, canceling the current parsing operation, if there is one.
*/ */
public synchronized void flush() { public synchronized void flush() {
sampleHolder = new SampleHolder(true); sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
parsing = false; parsing = false;
result = null; result = null;
error = null; error = null;
......
...@@ -24,8 +24,8 @@ import android.util.Pair; ...@@ -24,8 +24,8 @@ import android.util.Pair;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
/** /**
...@@ -282,10 +282,10 @@ public class ManifestFetcher<T> implements Loader.Callback { ...@@ -282,10 +282,10 @@ public class ManifestFetcher<T> implements Loader.Callback {
@Override @Override
public void load() throws IOException, InterruptedException { public void load() throws IOException, InterruptedException {
String inputEncoding = null; String inputEncoding;
InputStream inputStream = null; InputStream inputStream = null;
try { try {
HttpURLConnection connection = configureHttpConnection(new URL(manifestUrl)); URLConnection connection = configureConnection(new URL(manifestUrl));
inputStream = connection.getInputStream(); inputStream = connection.getInputStream();
inputEncoding = connection.getContentEncoding(); inputEncoding = connection.getContentEncoding();
result = parser.parse(inputStream, inputEncoding, contentId, result = parser.parse(inputStream, inputEncoding, contentId,
...@@ -297,8 +297,8 @@ public class ManifestFetcher<T> implements Loader.Callback { ...@@ -297,8 +297,8 @@ public class ManifestFetcher<T> implements Loader.Callback {
} }
} }
private HttpURLConnection configureHttpConnection(URL url) throws IOException { private URLConnection configureConnection(URL url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); URLConnection connection = url.openConnection();
connection.setConnectTimeout(TIMEOUT_MILLIS); connection.setConnectTimeout(TIMEOUT_MILLIS);
connection.setReadTimeout(TIMEOUT_MILLIS); connection.setReadTimeout(TIMEOUT_MILLIS);
connection.setDoOutput(false); connection.setDoOutput(false);
......
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