Commit fc716b57 by andrewlewis Committed by Oliver Woodman

Signal end of stream in SampleHolder flags.

Also use MediaCodec buffer flag constants instead of those on MediaExtractor.

This is in preparation for merging InputBuffer and SampleHolder.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117810136
parent 733f2ccd
...@@ -17,7 +17,6 @@ package com.google.android.exoplayer; ...@@ -17,7 +17,6 @@ package com.google.android.exoplayer;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaExtractor;
import junit.framework.TestCase; import junit.framework.TestCase;
...@@ -29,8 +28,8 @@ public class CTest extends TestCase { ...@@ -29,8 +28,8 @@ public class CTest extends TestCase {
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
public static final void testContants() { public static final void testContants() {
// Sanity check that constant values match those defined by the platform. // Sanity check that constant values match those defined by the platform.
assertEquals(MediaExtractor.SAMPLE_FLAG_SYNC, C.SAMPLE_FLAG_SYNC); assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.SAMPLE_FLAG_SYNC);
assertEquals(MediaExtractor.SAMPLE_FLAG_ENCRYPTED, C.SAMPLE_FLAG_ENCRYPTED); assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.SAMPLE_FLAG_END_OF_STREAM);
assertEquals(MediaCodec.CRYPTO_MODE_AES_CTR, C.CRYPTO_MODE_AES_CTR); assertEquals(MediaCodec.CRYPTO_MODE_AES_CTR, C.CRYPTO_MODE_AES_CTR);
} }
......
...@@ -19,7 +19,6 @@ import com.google.android.exoplayer.util.Util; ...@@ -19,7 +19,6 @@ import com.google.android.exoplayer.util.Util;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaExtractor;
/** /**
* Defines constants that are generally useful throughout the library. * Defines constants that are generally useful throughout the library.
...@@ -89,21 +88,26 @@ public final class C { ...@@ -89,21 +88,26 @@ public final class C {
? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND; ? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
/** /**
* @see MediaExtractor#SAMPLE_FLAG_SYNC * Indicates that a sample is a synchronization sample.
*/ */
@SuppressWarnings("InlinedApi") @SuppressWarnings("InlinedApi")
public static final int SAMPLE_FLAG_SYNC = MediaExtractor.SAMPLE_FLAG_SYNC; public static final int SAMPLE_FLAG_SYNC = MediaCodec.BUFFER_FLAG_KEY_FRAME;
/** /**
* @see MediaExtractor#SAMPLE_FLAG_ENCRYPTED * Flag for empty buffers that signal that the end of the stream was reached.
*/ */
@SuppressWarnings("InlinedApi") @SuppressWarnings("InlinedApi")
public static final int SAMPLE_FLAG_ENCRYPTED = MediaExtractor.SAMPLE_FLAG_ENCRYPTED; public static final int SAMPLE_FLAG_END_OF_STREAM = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
/**
* Indicates that a sample is (at least partially) encrypted.
*/
public static final int SAMPLE_FLAG_ENCRYPTED = 0x40000000;
/** /**
* Indicates that a sample should be decoded but not rendered. * Indicates that a sample should be decoded but not rendered.
*/ */
public static final int SAMPLE_FLAG_DECODE_ONLY = 0x8000000; public static final int SAMPLE_FLAG_DECODE_ONLY = 0x80000000;
/** /**
* A return value for methods where the end of an input was encountered. * A return value for methods where the end of an input was encountered.
......
...@@ -56,8 +56,6 @@ import java.util.UUID; ...@@ -56,8 +56,6 @@ import java.util.UUID;
@TargetApi(16) @TargetApi(16)
public final class FrameworkSampleSource implements SampleSource { public final class FrameworkSampleSource implements SampleSource {
private static final int ALLOWED_FLAGS_MASK = C.SAMPLE_FLAG_SYNC | C.SAMPLE_FLAG_ENCRYPTED;
private static final int TRACK_STATE_DISABLED = 0; private static final int TRACK_STATE_DISABLED = 0;
private static final int TRACK_STATE_ENABLED = 1; private static final int TRACK_STATE_ENABLED = 1;
private static final int TRACK_STATE_FORMAT_SENT = 2; private static final int TRACK_STATE_FORMAT_SENT = 2;
...@@ -196,6 +194,7 @@ public final class FrameworkSampleSource implements SampleSource { ...@@ -196,6 +194,7 @@ public final class FrameworkSampleSource implements SampleSource {
return TrackStream.FORMAT_READ; return TrackStream.FORMAT_READ;
} }
int extractorTrackIndex = extractor.getSampleTrackIndex(); int extractorTrackIndex = extractor.getSampleTrackIndex();
sampleHolder.flags = 0;
if (extractorTrackIndex == track) { if (extractorTrackIndex == track) {
if (sampleHolder.data != null) { if (sampleHolder.data != null) {
int offset = sampleHolder.data.position(); int offset = sampleHolder.data.position();
...@@ -205,15 +204,22 @@ public final class FrameworkSampleSource implements SampleSource { ...@@ -205,15 +204,22 @@ public final class FrameworkSampleSource implements SampleSource {
sampleHolder.size = 0; sampleHolder.size = 0;
} }
sampleHolder.timeUs = extractor.getSampleTime(); sampleHolder.timeUs = extractor.getSampleTime();
sampleHolder.flags = extractor.getSampleFlags() & ALLOWED_FLAGS_MASK; int flags = extractor.getSampleFlags();
if (sampleHolder.isEncrypted()) { if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
sampleHolder.flags |= C.SAMPLE_FLAG_SYNC;
}
if ((flags & MediaExtractor.SAMPLE_FLAG_ENCRYPTED) != 0) {
sampleHolder.flags |= C.SAMPLE_FLAG_ENCRYPTED;
sampleHolder.cryptoInfo.setFromExtractorV16(extractor); sampleHolder.cryptoInfo.setFromExtractorV16(extractor);
} }
pendingSeekPositionUs = C.UNKNOWN_TIME_US; pendingSeekPositionUs = C.UNKNOWN_TIME_US;
extractor.advance(); extractor.advance();
return TrackStream.SAMPLE_READ; return TrackStream.SAMPLE_READ;
} else if (extractorTrackIndex < 0) {
sampleHolder.flags |= C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM;
} else { } else {
return extractorTrackIndex < 0 ? TrackStream.END_OF_STREAM : TrackStream.NOTHING_READ; return TrackStream.NOTHING_READ;
} }
} }
......
...@@ -50,8 +50,7 @@ public final class SampleHolder { ...@@ -50,8 +50,7 @@ public final class SampleHolder {
public int size; public int size;
/** /**
* Flags that accompany the sample. A combination of {@link C#SAMPLE_FLAG_SYNC}, * Flags that accompany the sample. A combination of the {@code C.SAMPLE_FLAG_*} constants.
* {@link C#SAMPLE_FLAG_ENCRYPTED} and {@link C#SAMPLE_FLAG_DECODE_ONLY}.
*/ */
public int flags; public int flags;
......
...@@ -67,7 +67,9 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer { ...@@ -67,7 +67,9 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
* @param formatHolder A {@link FormatHolder} object to populate in the case of a new format. * @param formatHolder A {@link FormatHolder} object to populate in the case of a new format.
* @param sampleHolder A {@link SampleHolder} object to populate in the case of a new sample. * @param sampleHolder A {@link SampleHolder} object to populate in the case of a new sample.
* If the caller requires the sample data then it must ensure that {@link SampleHolder#data} * If the caller requires the sample data then it must ensure that {@link SampleHolder#data}
* references a valid output buffer. * references a valid output buffer. If the end of the stream has been reached,
* {@link TrackStream#END_OF_STREAM} will be returned and {@link C#SAMPLE_FLAG_END_OF_STREAM}
* will be set on the sample holder.
* @return The result, which can be {@link TrackStream#SAMPLE_READ}, * @return The result, which can be {@link TrackStream#SAMPLE_READ},
* {@link TrackStream#FORMAT_READ}, {@link TrackStream#NOTHING_READ} or * {@link TrackStream#FORMAT_READ}, {@link TrackStream#NOTHING_READ} or
* {@link TrackStream#END_OF_STREAM}. * {@link TrackStream#END_OF_STREAM}.
......
...@@ -162,6 +162,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load ...@@ -162,6 +162,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load
@Override @Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) { public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
if (state == STATE_END_OF_STREAM) { if (state == STATE_END_OF_STREAM) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return END_OF_STREAM; return END_OF_STREAM;
} else if (state == STATE_SEND_FORMAT) { } else if (state == STATE_SEND_FORMAT) {
formatHolder.format = format; formatHolder.format = format;
......
...@@ -77,7 +77,9 @@ public interface TrackStream { ...@@ -77,7 +77,9 @@ public interface TrackStream {
* @param formatHolder A {@link FormatHolder} to populate in the case of a new format. * @param formatHolder A {@link FormatHolder} to populate in the case of a new format.
* @param sampleHolder A {@link SampleHolder} to populate in the case of a new sample. If the * @param sampleHolder A {@link SampleHolder} to populate in the case of a new sample. If the
* caller requires the sample data then it must ensure that {@link SampleHolder#data} * caller requires the sample data then it must ensure that {@link SampleHolder#data}
* references a valid output buffer. * references a valid output buffer. If the end of the stream has been reached,
* {@link #END_OF_STREAM} will be returned and {@link C#SAMPLE_FLAG_END_OF_STREAM} will be set
* on the sample holder.
* @return The result, which can be {@link #END_OF_STREAM}, {@link #NOTHING_READ}, * @return The result, which can be {@link #END_OF_STREAM}, {@link #NOTHING_READ},
* {@link #FORMAT_READ} or {@link #SAMPLE_READ}. * {@link #FORMAT_READ} or {@link #SAMPLE_READ}.
*/ */
......
...@@ -273,6 +273,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call ...@@ -273,6 +273,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
if (!haveSamples) { if (!haveSamples) {
if (loadingFinished) { if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return END_OF_STREAM; return END_OF_STREAM;
} }
return NOTHING_READ; return NOTHING_READ;
......
...@@ -460,6 +460,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu ...@@ -460,6 +460,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
} }
if (loadingFinished) { if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM; return TrackStream.END_OF_STREAM;
} }
......
...@@ -337,6 +337,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback { ...@@ -337,6 +337,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
} }
if (loadingFinished) { if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM; return TrackStream.END_OF_STREAM;
} }
......
...@@ -20,19 +20,6 @@ package com.google.android.exoplayer.util.extensions; ...@@ -20,19 +20,6 @@ package com.google.android.exoplayer.util.extensions;
*/ */
public abstract class Buffer { public abstract class Buffer {
/**
* Flag for empty input/output buffers that signal that the end of the stream was reached.
*/
public static final int FLAG_END_OF_STREAM = 1;
/**
* Flag for non-empty input buffers which signals that the decoder must be reset before decoding.
*/
public static final int FLAG_RESET = 2;
/**
* Flag for non-empty input/output buffers that should only be decoded (not rendered).
*/
public static final int FLAG_DECODE_ONLY = 4;
private int flags; private int flags;
public void reset() { public void reset() {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer.util.extensions; package com.google.android.exoplayer.util.extensions;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import java.util.LinkedList; import java.util.LinkedList;
...@@ -219,16 +220,23 @@ public abstract class SimpleDecoder<I extends InputBuffer, O extends OutputBuffe ...@@ -219,16 +220,23 @@ public abstract class SimpleDecoder<I extends InputBuffer, O extends OutputBuffe
flushDecodedOutputBuffer = false; flushDecodedOutputBuffer = false;
} }
exception = decode(inputBuffer, outputBuffer); outputBuffer.reset();
if (exception != null) { if (inputBuffer.getFlag(C.SAMPLE_FLAG_END_OF_STREAM)) {
// Memory barrier to ensure that the decoder exception is visible from the playback thread. outputBuffer.setFlag(C.SAMPLE_FLAG_END_OF_STREAM);
synchronized (lock) {} } else {
return false; if (inputBuffer.getFlag(C.SAMPLE_FLAG_DECODE_ONLY)) {
outputBuffer.setFlag(C.SAMPLE_FLAG_DECODE_ONLY);
}
exception = decode(inputBuffer, outputBuffer);
if (exception != null) {
// Memory barrier to ensure that the decoder exception is visible from the playback thread.
synchronized (lock) {}
return false;
}
} }
boolean decodeOnly = outputBuffer.getFlag(Buffer.FLAG_DECODE_ONLY);
synchronized (lock) { synchronized (lock) {
if (flushDecodedOutputBuffer || decodeOnly) { if (flushDecodedOutputBuffer || outputBuffer.getFlag(C.SAMPLE_FLAG_DECODE_ONLY)) {
// If a flush occurred while decoding or the buffer was only for decoding (not presentation) // If a flush occurred while decoding or the buffer was only for decoding (not presentation)
// then make the output buffer available again rather than queueing it to be consumed. // then make the output buffer available again rather than queueing it to be consumed.
availableOutputBuffers[availableOutputBufferCount++] = outputBuffer; availableOutputBuffers[availableOutputBufferCount++] = outputBuffer;
...@@ -261,10 +269,11 @@ public abstract class SimpleDecoder<I extends InputBuffer, O extends OutputBuffe ...@@ -261,10 +269,11 @@ public abstract class SimpleDecoder<I extends InputBuffer, O extends OutputBuffe
* Decodes the {@code inputBuffer} and stores any decoded output in {@code outputBuffer}. * Decodes the {@code inputBuffer} and stores any decoded output in {@code outputBuffer}.
* *
* @param inputBuffer The buffer to decode. * @param inputBuffer The buffer to decode.
* @param outputBuffer The output buffer to store decoded data. If the flag * @param outputBuffer The output buffer to store decoded data. The flag
* {@link Buffer#FLAG_DECODE_ONLY} is set after this method returns, any output should not be * {@link C#SAMPLE_FLAG_DECODE_ONLY} will be set if the same flag is set on
* presented. * {@code inputBuffer}, but the decoder may set/unset the flag if required. If the flag is set
* @return A decode exception if an error occurred, or null if the decode was successful. * after this method returns, any output will not be presented.
* @return A decoder exception if an error occurred, or null if decoding was successful.
*/ */
protected abstract E decode(I inputBuffer, O outputBuffer); protected abstract E decode(I inputBuffer, O outputBuffer);
......
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