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
This commit is contained in:
parent
733f2ccd1c
commit
fc716b5711
@ -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 {
|
|||||||
@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;
|
|||||||
|
|
||||||
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 {
|
|||||||
? 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;
|
|||||||
@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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
* @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
|
|||||||
@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 {
|
|||||||
* @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
|
|||||||
|
|
||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
*/
|
*/
|
||||||
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
|
|||||||
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
|
|||||||
* 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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user