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;
import android.annotation.SuppressLint;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import junit.framework.TestCase;
......@@ -29,8 +28,8 @@ public class CTest extends TestCase {
@SuppressLint("InlinedApi")
public static final void testContants() {
// Sanity check that constant values match those defined by the platform.
assertEquals(MediaExtractor.SAMPLE_FLAG_SYNC, C.SAMPLE_FLAG_SYNC);
assertEquals(MediaExtractor.SAMPLE_FLAG_ENCRYPTED, C.SAMPLE_FLAG_ENCRYPTED);
assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.SAMPLE_FLAG_SYNC);
assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.SAMPLE_FLAG_END_OF_STREAM);
assertEquals(MediaCodec.CRYPTO_MODE_AES_CTR, C.CRYPTO_MODE_AES_CTR);
}
......
......@@ -19,7 +19,6 @@ import com.google.android.exoplayer.util.Util;
import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaExtractor;
/**
* Defines constants that are generally useful throughout the library.
......@@ -89,21 +88,26 @@ public final class C {
? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
/**
* @see MediaExtractor#SAMPLE_FLAG_SYNC
* Indicates that a sample is a synchronization sample.
*/
@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")
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.
*/
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.
......
......@@ -56,8 +56,6 @@ import java.util.UUID;
@TargetApi(16)
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_ENABLED = 1;
private static final int TRACK_STATE_FORMAT_SENT = 2;
......@@ -196,6 +194,7 @@ public final class FrameworkSampleSource implements SampleSource {
return TrackStream.FORMAT_READ;
}
int extractorTrackIndex = extractor.getSampleTrackIndex();
sampleHolder.flags = 0;
if (extractorTrackIndex == track) {
if (sampleHolder.data != null) {
int offset = sampleHolder.data.position();
......@@ -205,15 +204,22 @@ public final class FrameworkSampleSource implements SampleSource {
sampleHolder.size = 0;
}
sampleHolder.timeUs = extractor.getSampleTime();
sampleHolder.flags = extractor.getSampleFlags() & ALLOWED_FLAGS_MASK;
if (sampleHolder.isEncrypted()) {
int flags = extractor.getSampleFlags();
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);
}
pendingSeekPositionUs = C.UNKNOWN_TIME_US;
extractor.advance();
return TrackStream.SAMPLE_READ;
} else if (extractorTrackIndex < 0) {
sampleHolder.flags |= C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM;
} else {
return extractorTrackIndex < 0 ? TrackStream.END_OF_STREAM : TrackStream.NOTHING_READ;
return TrackStream.NOTHING_READ;
}
}
......
......@@ -50,8 +50,7 @@ public final class SampleHolder {
public int size;
/**
* Flags that accompany the sample. A combination of {@link C#SAMPLE_FLAG_SYNC},
* {@link C#SAMPLE_FLAG_ENCRYPTED} and {@link C#SAMPLE_FLAG_DECODE_ONLY}.
* Flags that accompany the sample. A combination of the {@code C.SAMPLE_FLAG_*} constants.
*/
public int flags;
......
......@@ -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 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}
* 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},
* {@link TrackStream#FORMAT_READ}, {@link TrackStream#NOTHING_READ} or
* {@link TrackStream#END_OF_STREAM}.
......
......@@ -162,6 +162,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
if (state == STATE_END_OF_STREAM) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return END_OF_STREAM;
} else if (state == STATE_SEND_FORMAT) {
formatHolder.format = format;
......
......@@ -77,7 +77,9 @@ public interface TrackStream {
* @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
* 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},
* {@link #FORMAT_READ} or {@link #SAMPLE_READ}.
*/
......
......@@ -273,6 +273,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
if (!haveSamples) {
if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return END_OF_STREAM;
}
return NOTHING_READ;
......
......@@ -460,6 +460,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
}
if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM;
}
......
......@@ -337,6 +337,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
}
if (loadingFinished) {
sampleHolder.flags = C.SAMPLE_FLAG_END_OF_STREAM;
return TrackStream.END_OF_STREAM;
}
......
......@@ -20,19 +20,6 @@ package com.google.android.exoplayer.util.extensions;
*/
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;
public void reset() {
......
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.util.extensions;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import java.util.LinkedList;
......@@ -219,16 +220,23 @@ public abstract class SimpleDecoder<I extends InputBuffer, O extends OutputBuffe
flushDecodedOutputBuffer = false;
}
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;
outputBuffer.reset();
if (inputBuffer.getFlag(C.SAMPLE_FLAG_END_OF_STREAM)) {
outputBuffer.setFlag(C.SAMPLE_FLAG_END_OF_STREAM);
} else {
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) {
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)
// then make the output buffer available again rather than queueing it to be consumed.
availableOutputBuffers[availableOutputBufferCount++] = outputBuffer;
......@@ -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}.
*
* @param inputBuffer The buffer to decode.
* @param outputBuffer The output buffer to store decoded data. If the flag
* {@link Buffer#FLAG_DECODE_ONLY} is set after this method returns, any output should not be
* presented.
* @return A decode exception if an error occurred, or null if the decode was successful.
* @param outputBuffer The output buffer to store decoded data. The flag
* {@link C#SAMPLE_FLAG_DECODE_ONLY} will be set if the same flag is set on
* {@code inputBuffer}, but the decoder may set/unset the flag if required. If the flag is set
* 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);
......
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