提交 ce9b309a 编写于 作者: A andrewlewis 提交者: Oliver Woodman

Rename SampleHolder to DecoderInputBuffer.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=118040127
上级 98fb6d15
......@@ -28,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(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.SAMPLE_FLAG_SYNC);
assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.SAMPLE_FLAG_END_OF_STREAM);
assertEquals(MediaCodec.BUFFER_FLAG_KEY_FRAME, C.BUFFER_FLAG_KEY_FRAME);
assertEquals(MediaCodec.BUFFER_FLAG_END_OF_STREAM, C.BUFFER_FLAG_END_OF_STREAM);
assertEquals(MediaCodec.CRYPTO_MODE_AES_CTR, C.CRYPTO_MODE_AES_CTR);
}
......
......@@ -137,7 +137,7 @@ public final class Mp4ExtractorTest extends TestCase {
videoTrackOutput.assertSampleCount(SAMPLE_TIMESTAMPS.length);
for (int i = 0; i < SAMPLE_TIMESTAMPS.length; i++) {
byte[] sampleData = getOutputSampleData(i, true);
int sampleFlags = SAMPLE_IS_SYNC[i] ? C.SAMPLE_FLAG_SYNC : 0;
int sampleFlags = SAMPLE_IS_SYNC[i] ? C.BUFFER_FLAG_KEY_FRAME : 0;
long sampleTimestampUs = getVideoTimestampUs(SAMPLE_TIMESTAMPS[i]);
videoTrackOutput.assertSample(i, sampleData, sampleTimestampUs, sampleFlags, null);
}
......@@ -155,7 +155,7 @@ public final class Mp4ExtractorTest extends TestCase {
videoTrackOutput.assertSampleCount(SAMPLE_TIMESTAMPS.length);
for (int i = 0; i < SAMPLE_TIMESTAMPS.length; i++) {
byte[] sampleData = getOutputSampleData(i, true);
int sampleFlags = C.SAMPLE_FLAG_SYNC;
int sampleFlags = C.BUFFER_FLAG_KEY_FRAME;
long sampleTimestampUs = getVideoTimestampUs(SAMPLE_TIMESTAMPS[i]);
videoTrackOutput.assertSample(i, sampleData, sampleTimestampUs, sampleFlags, null);
}
......@@ -182,7 +182,7 @@ public final class Mp4ExtractorTest extends TestCase {
videoTrackOutput.assertSampleCount(SAMPLE_TIMESTAMPS.length);
for (int i = 0; i < SAMPLE_TIMESTAMPS.length; i++) {
byte[] sampleData = getOutputSampleData(i, false);
int sampleFlags = SAMPLE_IS_SYNC[i] ? C.SAMPLE_FLAG_SYNC : 0;
int sampleFlags = SAMPLE_IS_SYNC[i] ? C.BUFFER_FLAG_KEY_FRAME : 0;
long sampleTimestampUs = getVideoTimestampUs(SAMPLE_TIMESTAMPS[i]);
videoTrackOutput.assertSample(i, sampleData, sampleTimestampUs, sampleFlags, null);
}
......
......@@ -94,7 +94,7 @@ public class AdtsReaderTest extends TestCase {
ADTS_CONTENT));
feed();
assertSampleCounts(0, 1);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.SAMPLE_FLAG_SYNC, null);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.BUFFER_FLAG_KEY_FRAME, null);
}
public void testNoData() throws Exception {
......@@ -120,20 +120,20 @@ public class AdtsReaderTest extends TestCase {
public void testConsumeWholeId3Packet() throws Exception {
feedLimited(ID3_DATA_1.length);
assertSampleCounts(1, 0);
id3Output.assertSample(0, ID3_DATA_1, 0, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(0, ID3_DATA_1, 0, C.BUFFER_FLAG_KEY_FRAME, null);
}
public void testMultiId3Packet() throws Exception {
feedLimited(ID3_DATA_1.length + ID3_DATA_2.length - 1);
assertSampleCounts(1, 0);
id3Output.assertSample(0, ID3_DATA_1, 0, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(0, ID3_DATA_1, 0, C.BUFFER_FLAG_KEY_FRAME, null);
}
public void testMultiId3PacketConsumed() throws Exception {
feedLimited(ID3_DATA_1.length + ID3_DATA_2.length);
assertSampleCounts(2, 0);
id3Output.assertSample(0, ID3_DATA_1, 0, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(1, ID3_DATA_2, 0, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(0, ID3_DATA_1, 0, C.BUFFER_FLAG_KEY_FRAME, null);
id3Output.assertSample(1, ID3_DATA_2, 0, C.BUFFER_FLAG_KEY_FRAME, null);
}
public void testMultiPacketConsumed() throws Exception {
......@@ -145,9 +145,9 @@ public class AdtsReaderTest extends TestCase {
int j = i * 2;
assertSampleCounts(j + 2, i + 1);
id3Output.assertSample(j, ID3_DATA_1, timeUs, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(j + 1, ID3_DATA_2, timeUs, C.SAMPLE_FLAG_SYNC, null);
adtsOutput.assertSample(i, ADTS_CONTENT, timeUs, C.SAMPLE_FLAG_SYNC, null);
id3Output.assertSample(j, ID3_DATA_1, timeUs, C.BUFFER_FLAG_KEY_FRAME, null);
id3Output.assertSample(j + 1, ID3_DATA_2, timeUs, C.BUFFER_FLAG_KEY_FRAME, null);
adtsOutput.assertSample(i, ADTS_CONTENT, timeUs, C.BUFFER_FLAG_KEY_FRAME, null);
}
}
......@@ -155,7 +155,7 @@ public class AdtsReaderTest extends TestCase {
data.setPosition(ID3_DATA_1.length + ID3_DATA_2.length);
feed();
assertSampleCounts(0, 1);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.SAMPLE_FLAG_SYNC, null);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.BUFFER_FLAG_KEY_FRAME, null);
}
private void feedLimited(int limit) {
......
......@@ -788,9 +788,9 @@ public final class WebmExtractorTest extends InstrumentationTestCase {
StreamBuilder.TEST_INITIALIZATION_VECTOR, expectedMedia);
}
int flags = 0;
flags |= keyframe ? C.SAMPLE_FLAG_SYNC : 0;
flags |= invisible ? C.SAMPLE_FLAG_DECODE_ONLY : 0;
flags |= encryptionKey != null ? C.SAMPLE_FLAG_ENCRYPTED : 0;
flags |= keyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
flags |= invisible ? C.BUFFER_FLAG_DECODE_ONLY : 0;
flags |= encryptionKey != null ? C.BUFFER_FLAG_ENCRYPTED : 0;
output.assertSample(index, expectedMedia, timeUs, flags, encryptionKey);
}
......
......@@ -88,26 +88,26 @@ public final class C {
? AudioFormat.CHANNEL_OUT_7POINT1 : AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
/**
* Indicates that a sample is a synchronization sample.
* Indicates that a buffer holds a synchronization sample.
*/
@SuppressWarnings("InlinedApi")
public static final int SAMPLE_FLAG_SYNC = MediaCodec.BUFFER_FLAG_KEY_FRAME;
public static final int BUFFER_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME;
/**
* Flag for empty buffers that signal that the end of the stream was reached.
*/
@SuppressWarnings("InlinedApi")
public static final int SAMPLE_FLAG_END_OF_STREAM = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
public static final int BUFFER_FLAG_END_OF_STREAM = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
/**
* Indicates that a sample is (at least partially) encrypted.
* Indicates that a buffer is (at least partially) encrypted.
*/
public static final int SAMPLE_FLAG_ENCRYPTED = 0x40000000;
public static final int BUFFER_FLAG_ENCRYPTED = 0x40000000;
/**
* Indicates that a sample should be decoded but not rendered.
* Indicates that a buffer should be decoded but not rendered.
*/
public static final int SAMPLE_FLAG_DECODE_ONLY = 0x80000000;
public static final int BUFFER_FLAG_DECODE_ONLY = 0x80000000;
/**
* A return value for methods where the end of an input was encountered.
......
......@@ -20,9 +20,9 @@ import com.google.android.exoplayer.util.Buffer;
import java.nio.ByteBuffer;
/**
* Holds sample data and corresponding metadata.
* Holds input for a decoder and corresponding metadata.
*/
public class SampleHolder extends Buffer {
public class DecoderInputBuffer extends Buffer {
/**
* Disallows buffer replacement.
......@@ -40,17 +40,17 @@ public class SampleHolder extends Buffer {
public static final int BUFFER_REPLACEMENT_MODE_DIRECT = 2;
/**
* {@link CryptoInfo} for encrypted samples.
* {@link CryptoInfo} for encrypted data.
*/
public final CryptoInfo cryptoInfo;
/**
* A buffer holding the sample data, or {@code null} if no sample data has been set.
* The buffer's data, or {@code null} if no data has been set.
*/
public ByteBuffer data;
/**
* The size of the sample in bytes.
* The size of the data in bytes.
*/
public int size;
......@@ -66,7 +66,7 @@ public class SampleHolder extends Buffer {
* of {@link #BUFFER_REPLACEMENT_MODE_DISABLED}, {@link #BUFFER_REPLACEMENT_MODE_NORMAL} and
* {@link #BUFFER_REPLACEMENT_MODE_DIRECT}.
*/
public SampleHolder(int bufferReplacementMode) {
public DecoderInputBuffer(int bufferReplacementMode) {
this.cryptoInfo = new CryptoInfo();
this.bufferReplacementMode = bufferReplacementMode;
}
......@@ -85,7 +85,7 @@ public class SampleHolder extends Buffer {
*/
public void ensureSpaceForWrite(int length) throws IllegalStateException {
if (data == null) {
data = createReplacementBuffer(length);
data = createReplacementByteBuffer(length);
return;
}
// Check whether the current buffer is sufficient.
......@@ -96,7 +96,7 @@ public class SampleHolder extends Buffer {
return;
}
// Instantiate a new buffer if possible.
ByteBuffer newData = createReplacementBuffer(requiredCapacity);
ByteBuffer newData = createReplacementByteBuffer(requiredCapacity);
// Copy data up to the current position from the old buffer to the new one.
if (position > 0) {
data.position(0);
......@@ -108,10 +108,10 @@ public class SampleHolder extends Buffer {
}
/**
* Returns whether the sample has the {@link C#SAMPLE_FLAG_ENCRYPTED} flag set.
* Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set.
*/
public final boolean isEncrypted() {
return getFlag(C.SAMPLE_FLAG_ENCRYPTED);
return getFlag(C.BUFFER_FLAG_ENCRYPTED);
}
@Override
......@@ -122,7 +122,7 @@ public class SampleHolder extends Buffer {
}
}
private ByteBuffer createReplacementBuffer(int requiredCapacity) {
private ByteBuffer createReplacementByteBuffer(int requiredCapacity) {
if (bufferReplacementMode == BUFFER_REPLACEMENT_MODE_NORMAL) {
return ByteBuffer.allocate(requiredCapacity);
} else if (bufferReplacementMode == BUFFER_REPLACEMENT_MODE_DIRECT) {
......
......@@ -212,7 +212,7 @@ public final class FrameworkSampleSource implements SampleSource {
return TrackStream.NO_RESET;
}
/* package */ int readData(int track, FormatHolder formatHolder, SampleHolder sampleHolder) {
/* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer) {
Assertions.checkState(trackStates[track] != TRACK_STATE_DISABLED);
if (pendingResets[track]) {
return TrackStream.NOTHING_READ;
......@@ -225,28 +225,28 @@ public final class FrameworkSampleSource implements SampleSource {
}
int extractorTrackIndex = extractor.getSampleTrackIndex();
if (extractorTrackIndex == track) {
if (sampleHolder.data != null) {
int offset = sampleHolder.data.position();
sampleHolder.size = extractor.readSampleData(sampleHolder.data, offset);
sampleHolder.data.position(offset + sampleHolder.size);
if (buffer.data != null) {
int offset = buffer.data.position();
buffer.size = extractor.readSampleData(buffer.data, offset);
buffer.data.position(offset + buffer.size);
} else {
sampleHolder.size = 0;
buffer.size = 0;
}
sampleHolder.timeUs = extractor.getSampleTime();
buffer.timeUs = extractor.getSampleTime();
int flags = extractor.getSampleFlags();
if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
sampleHolder.addFlag(C.SAMPLE_FLAG_SYNC);
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
}
if ((flags & MediaExtractor.SAMPLE_FLAG_ENCRYPTED) != 0) {
sampleHolder.addFlag(C.SAMPLE_FLAG_ENCRYPTED);
sampleHolder.cryptoInfo.setFromExtractorV16(extractor);
buffer.addFlag(C.BUFFER_FLAG_ENCRYPTED);
buffer.cryptoInfo.setFromExtractorV16(extractor);
}
pendingSeekPositionUs = C.UNKNOWN_TIME_US;
extractor.advance();
return TrackStream.SAMPLE_READ;
return TrackStream.BUFFER_READ;
} else if (extractorTrackIndex < 0) {
sampleHolder.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return TrackStream.END_OF_STREAM;
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return TrackStream.BUFFER_READ;
} else {
return TrackStream.NOTHING_READ;
}
......@@ -392,8 +392,8 @@ public final class FrameworkSampleSource implements SampleSource {
}
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
return FrameworkSampleSource.this.readData(track, formatHolder, sampleHolder);
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
return FrameworkSampleSource.this.readData(track, formatHolder, buffer);
}
}
......
......@@ -199,7 +199,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
private final MediaCodecSelector mediaCodecSelector;
private final DrmSessionManager drmSessionManager;
private final boolean playClearSamplesWithoutKeys;
private final SampleHolder sampleHolder;
private final DecoderInputBuffer buffer;
private final FormatHolder formatHolder;
private final List<Long> decodeOnlyPresentationTimestamps;
private final MediaCodec.BufferInfo outputBufferInfo;
......@@ -255,7 +255,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
this.eventHandler = eventHandler;
this.eventListener = eventListener;
codecCounters = new CodecCounters();
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
formatHolder = new FormatHolder();
decodeOnlyPresentationTimestamps = new ArrayList<>();
outputBufferInfo = new MediaCodec.BufferInfo();
......@@ -554,8 +554,8 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
if (inputIndex < 0) {
return false;
}
sampleHolder.data = inputBuffers[inputIndex];
sampleHolder.clear();
buffer.data = inputBuffers[inputIndex];
buffer.clear();
}
if (codecReinitializationState == REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM) {
......@@ -574,19 +574,19 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
int result;
if (waitingForKeys) {
// We've already read an encrypted sample into sampleHolder, and are waiting for keys.
result = TrackStream.SAMPLE_READ;
// We've already read an encrypted sample into buffer, and are waiting for keys.
result = TrackStream.BUFFER_READ;
} else {
// For adaptive reconfiguration OMX decoders expect all reconfiguration data to be supplied
// at the start of the buffer that also contains the first frame in the new format.
if (codecReconfigurationState == RECONFIGURATION_STATE_WRITE_PENDING) {
for (int i = 0; i < format.initializationData.size(); i++) {
byte[] data = format.initializationData.get(i);
sampleHolder.data.put(data);
buffer.data.put(data);
}
codecReconfigurationState = RECONFIGURATION_STATE_QUEUE_PENDING;
}
result = readSource(formatHolder, sampleHolder);
result = readSource(formatHolder, buffer);
if (firstFeed && sourceState == SOURCE_STATE_READY && result == TrackStream.NOTHING_READ) {
sourceState = SOURCE_STATE_READY_READ_MAY_FAIL;
}
......@@ -599,18 +599,20 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
// We received two formats in a row. Clear the current buffer of any reconfiguration data
// associated with the first format.
sampleHolder.clear();
buffer.clear();
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
}
onInputFormatChanged(formatHolder);
return true;
}
if (result == TrackStream.END_OF_STREAM) {
// We've read a buffer.
if (buffer.isEndOfStream()) {
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
// We received a new format immediately before the end of the stream. We need to clear
// the corresponding reconfiguration data from the current buffer, but re-write it into
// a subsequent buffer if there are any (e.g. if the user seeks backwards).
sampleHolder.clear();
buffer.clear();
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
}
inputStreamEnded = true;
......@@ -632,30 +634,30 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
}
return false;
}
boolean sampleEncrypted = sampleHolder.isEncrypted();
waitingForKeys = shouldWaitForKeys(sampleEncrypted);
boolean bufferEncrypted = buffer.isEncrypted();
waitingForKeys = shouldWaitForKeys(bufferEncrypted);
if (waitingForKeys) {
return false;
}
if (codecNeedsDiscardToSpsWorkaround && !sampleEncrypted) {
NalUnitUtil.discardToSps(sampleHolder.data);
if (sampleHolder.data.position() == 0) {
if (codecNeedsDiscardToSpsWorkaround && !bufferEncrypted) {
NalUnitUtil.discardToSps(buffer.data);
if (buffer.data.position() == 0) {
return true;
}
codecNeedsDiscardToSpsWorkaround = false;
}
try {
int bufferSize = sampleHolder.data.position();
int adaptiveReconfigurationBytes = bufferSize - sampleHolder.size;
long presentationTimeUs = sampleHolder.timeUs;
if (sampleHolder.isDecodeOnly()) {
int bufferSize = buffer.data.position();
int adaptiveReconfigurationBytes = bufferSize - buffer.size;
long presentationTimeUs = buffer.timeUs;
if (buffer.isDecodeOnly()) {
decodeOnlyPresentationTimestamps.add(presentationTimeUs);
}
onQueuedInputBuffer(presentationTimeUs, sampleHolder.data, bufferSize, sampleEncrypted);
onQueuedInputBuffer(presentationTimeUs, buffer.data, bufferSize, bufferEncrypted);
if (sampleEncrypted) {
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(sampleHolder,
if (bufferEncrypted) {
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(buffer,
adaptiveReconfigurationBytes);
codec.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0);
} else {
......@@ -672,9 +674,9 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
return true;
}
private static MediaCodec.CryptoInfo getFrameworkCryptoInfo(SampleHolder sampleHolder,
private static MediaCodec.CryptoInfo getFrameworkCryptoInfo(DecoderInputBuffer buffer,
int adaptiveReconfigurationBytes) {
MediaCodec.CryptoInfo cryptoInfo = sampleHolder.cryptoInfo.getFrameworkCryptoInfoV16();
MediaCodec.CryptoInfo cryptoInfo = buffer.cryptoInfo.getFrameworkCryptoInfoV16();
if (adaptiveReconfigurationBytes == 0) {
return cryptoInfo;
}
......@@ -688,7 +690,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
return cryptoInfo;
}
private boolean shouldWaitForKeys(boolean sampleEncrypted) throws ExoPlaybackException {
private boolean shouldWaitForKeys(boolean bufferEncrypted) throws ExoPlaybackException {
if (!openedDrmSession) {
return false;
}
......@@ -697,7 +699,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
throw ExoPlaybackException.createForRenderer(drmSessionManager.getError(), getIndex());
}
if (drmManagerState != DrmSessionManager.STATE_OPENED_WITH_KEYS &&
(sampleEncrypted || !playClearSamplesWithoutKeys)) {
(bufferEncrypted || !playClearSamplesWithoutKeys)) {
return true;
}
return false;
......@@ -758,11 +760,11 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
*
* @param presentationTimeUs The timestamp associated with the input buffer.
* @param buffer The buffer to be queued.
* @param bufferSize the size of the sample data stored in the buffer.
* @param sampleEncrypted Whether the sample data is encrypted.
* @param bufferSize The size of the sample data stored in the buffer.
* @param bufferEncrypted Whether the buffer is encrypted.
*/
protected void onQueuedInputBuffer(
long presentationTimeUs, ByteBuffer buffer, int bufferSize, boolean sampleEncrypted) {
protected void onQueuedInputBuffer(long presentationTimeUs, ByteBuffer buffer, int bufferSize,
boolean bufferEncrypted) {
// Do nothing.
}
......
......@@ -64,18 +64,10 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
/**
* Reads from the enabled upstream source.
*
* @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. 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}.
* @see TrackStream#readData(FormatHolder, DecoderInputBuffer)
*/
protected final int readSource(FormatHolder formatHolder, SampleHolder sampleHolder) {
return trackStream.readData(formatHolder, sampleHolder);
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer) {
return trackStream.readData(formatHolder, buffer);
}
// Abstract methods.
......
......@@ -186,10 +186,10 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load
}
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (streamState == STREAM_STATE_END_OF_STREAM) {
sampleHolder.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return END_OF_STREAM;
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return BUFFER_READ;
} else if (streamState == STREAM_STATE_SEND_FORMAT) {
formatHolder.format = format;
streamState = STREAM_STATE_SEND_SAMPLE;
......@@ -200,13 +200,13 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load
if (!loadingFinished) {
return NOTHING_READ;
} else {
sampleHolder.timeUs = 0;
sampleHolder.size = sampleSize;
sampleHolder.addFlag(C.SAMPLE_FLAG_SYNC);
sampleHolder.ensureSpaceForWrite(sampleHolder.size);
sampleHolder.data.put(sampleData, 0, sampleSize);
buffer.timeUs = 0;
buffer.size = sampleSize;
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
buffer.ensureSpaceForWrite(buffer.size);
buffer.data.put(sampleData, 0, sampleSize);
streamState = STREAM_STATE_END_OF_STREAM;
return SAMPLE_READ;
return BUFFER_READ;
}
}
......
......@@ -22,22 +22,18 @@ import java.io.IOException;
*/
public interface TrackStream {
/**
* The end of stream has been reached.
*/
int END_OF_STREAM = -1;
/**
* Nothing was read.
*/
int NOTHING_READ = -2;
int NOTHING_READ = -1;
/**
* A sample was read.
* The buffer was populated.
*/
int SAMPLE_READ = -3;
int BUFFER_READ = -2;
/**
* A format was read.
*/
int FORMAT_READ = -4;
int FORMAT_READ = -3;
/**
* Returned from {@link #readReset()} to indicate no reset is required.
*/
......@@ -46,8 +42,8 @@ public interface TrackStream {
/**
* Returns whether data is available to be read.
* <p>
* Note: If the stream has ended then {@link #END_OF_STREAM} can always be read from
* {@link #readData(FormatHolder, SampleHolder)}. Hence an ended stream is always ready.
* Note: If the stream has ended then a buffer with the end of stream flag can always be read from
* {@link #readData(FormatHolder, DecoderInputBuffer)}. Hence an ended stream is always ready.
*
* @return True if data is available to be read. False otherwise.
*/
......@@ -69,20 +65,19 @@ public interface TrackStream {
long readReset();
/**
* Attempts to read the next format or sample.
* Attempts to read from the stream.
* <p>
* This method will always return {@link #NOTHING_READ} in the case that there's a pending
* discontinuity to be read from {@link #readReset} for the specified track.
*
* @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. 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}.
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
* @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
* end of the stream. If the caller requires the sample data then it must ensure that
* {@link DecoderInputBuffer#data} references a valid buffer. If the end of the stream has
* been reached, the {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* @return The result, which can be {@link #NOTHING_READ}, {@link #FORMAT_READ} or
* {@link #BUFFER_READ}.
*/
int readData(FormatHolder formatHolder, SampleHolder sampleHolder);
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer);
}
......@@ -16,10 +16,10 @@
package com.google.android.exoplayer.chunk;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.LoadControl;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackGroup;
import com.google.android.exoplayer.TrackGroupArray;
......@@ -246,7 +246,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
}
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (pendingReset || isPendingReset()) {
return NOTHING_READ;
}
......@@ -277,18 +277,18 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
if (!haveSamples) {
if (loadingFinished) {
sampleHolder.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return END_OF_STREAM;
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return BUFFER_READ;
}
return NOTHING_READ;
}
if (sampleQueue.getSample(sampleHolder)) {
if (sampleHolder.timeUs < lastSeekPositionUs) {
sampleHolder.addFlag(C.SAMPLE_FLAG_DECODE_ONLY);
if (sampleQueue.getSample(buffer)) {
if (buffer.timeUs < lastSeekPositionUs) {
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
onSampleRead(currentChunk, sampleHolder);
return SAMPLE_READ;
onSampleRead(currentChunk, buffer);
return BUFFER_READ;
}
return NOTHING_READ;
......@@ -395,9 +395,9 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
* the sample is returned.
*
* @param mediaChunk The chunk from which the sample was obtained.
* @param sampleHolder Holds the read sample.
* @param buffer Holds the read sample.
*/
protected void onSampleRead(MediaChunk mediaChunk, SampleHolder sampleHolder) {
protected void onSampleRead(MediaChunk mediaChunk, DecoderInputBuffer buffer) {
// Do nothing.
}
......
......@@ -104,7 +104,7 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
result = getOutput().sampleData(extractorInput, Integer.MAX_VALUE, true);
}
int sampleSize = bytesLoaded;
getOutput().sampleMetadata(startTimeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
getOutput().sampleMetadata(startTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
} finally {
dataSource.close();
}
......
......@@ -15,8 +15,8 @@
*/
package com.google.android.exoplayer.extractor;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.util.ParsableByteArray;
......@@ -29,7 +29,7 @@ import java.io.IOException;
public class DefaultTrackOutput implements TrackOutput {
private final RollingSampleBuffer rollingBuffer;
private final SampleHolder sampleInfoHolder;
private final DecoderInputBuffer sampleBuffer;
// Accessed only by the consuming thread.
private boolean needKeyframe;
......@@ -45,7 +45,7 @@ public class DefaultTrackOutput implements TrackOutput {
*/
public DefaultTrackOutput(Allocator allocator) {
rollingBuffer = new RollingSampleBuffer(allocator);
sampleInfoHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
sampleBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
needKeyframe = true;
lastReadTimeUs = Long.MIN_VALUE;
spliceOutTimeUs = Long.MIN_VALUE;
......@@ -79,7 +79,7 @@ public class DefaultTrackOutput implements TrackOutput {
*/
public void discardUpstreamSamples(int discardFromIndex) {
rollingBuffer.discardUpstreamSamples(discardFromIndex);
largestParsedTimestampUs = rollingBuffer.peekSample(sampleInfoHolder) ? sampleInfoHolder.timeUs
largestParsedTimestampUs = rollingBuffer.peekSample(sampleBuffer) ? sampleBuffer.timeUs
: Long.MIN_VALUE;
}
......@@ -122,23 +122,23 @@ public class DefaultTrackOutput implements TrackOutput {
}
/**
* Removes the next sample from the head of the queue, writing it into the provided holder.
* Removes the next sample from the head of the queue, writing it into the provided buffer.
* <p>
* The first sample returned is guaranteed to be a keyframe, since any non-keyframe samples
* queued prior to the first keyframe are discarded.
*
* @param holder A {@link SampleHolder} into which the sample should be read.
* @param buffer A {@link DecoderInputBuffer} into which the sample should be read.
* @return True if a sample was read. False otherwise.
*/
public boolean getSample(SampleHolder holder) {
public boolean getSample(DecoderInputBuffer buffer) {
boolean foundEligibleSample = advanceToEligibleSample();
if (!foundEligibleSample) {
return false;
}
// Write the sample into the holder.
rollingBuffer.readSample(holder);
// Write the sample into the buffer.
rollingBuffer.readSample(buffer);
needKeyframe = false;
lastReadTimeUs = holder.timeUs;
lastReadTimeUs = buffer.timeUs;
return true;
}
......@@ -148,7 +148,7 @@ public class DefaultTrackOutput implements TrackOutput {
* @param timeUs The time up to which samples should be discarded, in microseconds.
*/
public void discardUntil(long timeUs) {
while (rollingBuffer.peekSample(sampleInfoHolder) && sampleInfoHolder.timeUs < timeUs) {
while (rollingBuffer.peekSample(sampleBuffer) && sampleBuffer.timeUs < timeUs) {
rollingBuffer.skipSample();
// We're discarding one or more samples. A subsequent read will need to start at a keyframe.
needKeyframe = true;
......@@ -178,22 +178,22 @@ public class DefaultTrackOutput implements TrackOutput {
return true;
}
long firstPossibleSpliceTime;
if (rollingBuffer.peekSample(sampleInfoHolder)) {
firstPossibleSpliceTime = sampleInfoHolder.timeUs;
if (rollingBuffer.peekSample(sampleBuffer)) {
firstPossibleSpliceTime = sampleBuffer.timeUs;
} else {
firstPossibleSpliceTime = lastReadTimeUs + 1;
}
RollingSampleBuffer nextRollingBuffer = nextQueue.rollingBuffer;
while (nextRollingBuffer.peekSample(sampleInfoHolder)
&& (sampleInfoHolder.timeUs < firstPossibleSpliceTime || !sampleInfoHolder.isSyncFrame())) {
while (nextRollingBuffer.peekSample(sampleBuffer)
&& (sampleBuffer.timeUs < firstPossibleSpliceTime || !sampleBuffer.isKeyFrame())) {
// Discard samples from the next queue for as long as they are before the earliest possible
// splice time, or not keyframes.
nextRollingBuffer.skipSample();
}
if (nextRollingBuffer.peekSample(sampleInfoHolder)) {
if (nextRollingBuffer.peekSample(sampleBuffer)) {
// We've found a keyframe in the next queue that can serve as the splice point. Set the
// splice point now.
spliceOutTimeUs = sampleInfoHolder.timeUs;
spliceOutTimeUs = sampleBuffer.timeUs;
return true;
}
return false;
......@@ -206,17 +206,17 @@ public class DefaultTrackOutput implements TrackOutput {
* buffer has been emptied.
*/
private boolean advanceToEligibleSample() {
boolean haveNext = rollingBuffer.peekSample(sampleInfoHolder);
boolean haveNext = rollingBuffer.peekSample(sampleBuffer);
if (needKeyframe) {
while (haveNext && !sampleInfoHolder.isSyncFrame()) {
while (haveNext && !sampleBuffer.isKeyFrame()) {
rollingBuffer.skipSample();
haveNext = rollingBuffer.peekSample(sampleInfoHolder);
haveNext = rollingBuffer.peekSample(sampleBuffer);
}
}
if (!haveNext) {
return false;
}
if (spliceOutTimeUs != Long.MIN_VALUE && sampleInfoHolder.timeUs >= spliceOutTimeUs) {
if (spliceOutTimeUs != Long.MIN_VALUE && sampleBuffer.timeUs >= spliceOutTimeUs) {
return false;
}
return true;
......
......@@ -16,9 +16,9 @@
package com.google.android.exoplayer.extractor;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackGroup;
import com.google.android.exoplayer.TrackGroupArray;
......@@ -445,7 +445,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
return TrackStream.NO_RESET;
}
/* package */ int readData(int track, FormatHolder formatHolder, SampleHolder sampleHolder) {
/* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (pendingResets[track] || isPendingReset()) {
return TrackStream.NOTHING_READ;
}
......@@ -458,22 +458,22 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
return TrackStream.FORMAT_READ;
}
if (sampleQueue.getSample(sampleHolder)) {
if (sampleHolder.timeUs < lastSeekPositionUs) {
sampleHolder.addFlag(C.SAMPLE_FLAG_DECODE_ONLY);
if (sampleQueue.getSample(buffer)) {
if (buffer.timeUs < lastSeekPositionUs) {
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
if (havePendingNextSampleUs) {
// Set the offset to make the timestamp of this sample equal to pendingNextSampleUs.
sampleTimeOffsetUs = pendingNextSampleUs - sampleHolder.timeUs;
sampleTimeOffsetUs = pendingNextSampleUs - buffer.timeUs;
havePendingNextSampleUs = false;
}
sampleHolder.timeUs += sampleTimeOffsetUs;
return TrackStream.SAMPLE_READ;
buffer.timeUs += sampleTimeOffsetUs;
return TrackStream.BUFFER_READ;
}
if (loadingFinished) {
sampleHolder.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return TrackStream.END_OF_STREAM;
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return TrackStream.BUFFER_READ;
}
return TrackStream.NOTHING_READ;
......@@ -764,8 +764,8 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
}
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
return ExtractorSampleSource.this.readData(track, formatHolder, sampleHolder);
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
return ExtractorSampleSource.this.readData(track, formatHolder, buffer);
}
}
......
......@@ -16,7 +16,7 @@
package com.google.android.exoplayer.extractor;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.upstream.Allocation;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DataSource;
......@@ -40,7 +40,7 @@ import java.util.concurrent.LinkedBlockingDeque;
private final InfoQueue infoQueue;
private final LinkedBlockingDeque<Allocation> dataQueue;
private final SampleExtrasHolder extrasHolder;
private final BufferExtrasHolder extrasHolder;
private final ParsableByteArray scratch;
// Accessed only by the consuming thread.
......@@ -59,7 +59,7 @@ import java.util.concurrent.LinkedBlockingDeque;
allocationLength = allocator.getIndividualAllocationLength();
infoQueue = new InfoQueue();
dataQueue = new LinkedBlockingDeque<>();
extrasHolder = new SampleExtrasHolder();
extrasHolder = new BufferExtrasHolder();
scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE);
lastAllocationOffset = allocationLength;
}
......@@ -133,15 +133,16 @@ import java.util.concurrent.LinkedBlockingDeque;
}
/**
* Fills {@code holder} with information about the current sample, but does not write its data.
* Fills {@code buffer} with information about the current sample, but does not write its data.
* <p>
* Populates {@link SampleHolder#size}, {@link SampleHolder#timeUs} and the sample flags.
* Populates {@link DecoderInputBuffer#size}, {@link DecoderInputBuffer#timeUs} and the buffer
* flags.
*
* @param holder The holder into which the current sample information should be written.
* @return True if the holder was filled. False if there is no current sample.
* @param buffer The buffer into which the current sample information should be written.
* @return True if the buffer was filled. False if there is no current sample.
*/
public boolean peekSample(SampleHolder holder) {
return infoQueue.peekSample(holder, extrasHolder);
public boolean peekSample(DecoderInputBuffer buffer) {
return infoQueue.peekSample(buffer, extrasHolder);
}
/**
......@@ -170,23 +171,23 @@ import java.util.concurrent.LinkedBlockingDeque;
/**
* Reads the current sample, advancing the read index to the next sample.
*
* @param sampleHolder The holder into which the current sample should be written.
* @param buffer The buffer into which the current sample should be written.
* @return True if a sample was read. False if there is no current sample.
*/
public boolean readSample(SampleHolder sampleHolder) {
// Write the sample information into the holder and extrasHolder.
boolean haveSample = infoQueue.peekSample(sampleHolder, extrasHolder);
public boolean readSample(DecoderInputBuffer buffer) {
// Write the sample information into the buffer and extrasHolder.
boolean haveSample = infoQueue.peekSample(buffer, extrasHolder);
if (!haveSample) {
return false;
}
// Read encryption data if the sample is encrypted.
if (sampleHolder.isEncrypted()) {
readEncryptionData(sampleHolder, extrasHolder);
if (buffer.isEncrypted()) {
readEncryptionData(buffer, extrasHolder);
}
// Write the sample data into the holder.
sampleHolder.ensureSpaceForWrite(sampleHolder.size);
readData(extrasHolder.offset, sampleHolder.data, sampleHolder.size);
buffer.ensureSpaceForWrite(buffer.size);
readData(extrasHolder.offset, buffer.data, buffer.size);
// Advance the read head.
long nextOffset = infoQueue.moveToNextSample();
dropDownstreamTo(nextOffset);
......@@ -196,14 +197,14 @@ import java.util.concurrent.LinkedBlockingDeque;
/**
* Reads encryption data for the current sample.
* <p>
* The encryption data is written into {@code sampleHolder.cryptoInfo}, and
* {@code sampleHolder.size} is adjusted to subtract the number of bytes that were read. The
* same value is added to {@code extrasHolder.offset}.
* The encryption data is written into {@link DecoderInputBuffer#cryptoInfo}, and
* {@link DecoderInputBuffer#size} is adjusted to subtract the number of bytes that were read. The
* same value is added to {@link BufferExtrasHolder#offset}.
*
* @param sampleHolder The holder into which the encryption data should be written.
* @param buffer The buffer into which the encryption data should be written.
* @param extrasHolder The extras holder whose offset should be read and subsequently adjusted.
*/
private void readEncryptionData(SampleHolder sampleHolder, SampleExtrasHolder extrasHolder) {
private void readEncryptionData(DecoderInputBuffer buffer, BufferExtrasHolder extrasHolder) {
long offset = extrasHolder.offset;
// Read the signal byte.
......@@ -214,10 +215,10 @@ import java.util.concurrent.LinkedBlockingDeque;
int ivSize = signalByte & 0x7F;
// Read the initialization vector.
if (sampleHolder.cryptoInfo.iv == null) {
sampleHolder.cryptoInfo.iv = new byte[16];
if (buffer.cryptoInfo.iv == null) {
buffer.cryptoInfo.iv = new byte[16];
}
readData(offset, sampleHolder.cryptoInfo.iv, ivSize);
readData(offset, buffer.cryptoInfo.iv, ivSize);
offset += ivSize;
// Read the subsample count, if present.
......@@ -232,11 +233,11 @@ import java.util.concurrent.LinkedBlockingDeque;
}
// Write the clear and encrypted subsample sizes.
int[] clearDataSizes = sampleHolder.cryptoInfo.numBytesOfClearData;
int[] clearDataSizes = buffer.cryptoInfo.numBytesOfClearData;
if (clearDataSizes == null || clearDataSizes.length < subsampleCount) {
clearDataSizes = new int[subsampleCount];
}
int[] encryptedDataSizes = sampleHolder.cryptoInfo.numBytesOfEncryptedData;
int[] encryptedDataSizes = buffer.cryptoInfo.numBytesOfEncryptedData;
if (encryptedDataSizes == null || encryptedDataSizes.length < subsampleCount) {
encryptedDataSizes = new int[subsampleCount];
}
......@@ -252,17 +253,17 @@ import java.util.concurrent.LinkedBlockingDeque;
}
} else {
clearDataSizes[0] = 0;
encryptedDataSizes[0] = sampleHolder.size - (int) (offset - extrasHolder.offset);
encryptedDataSizes[0] = buffer.size - (int) (offset - extrasHolder.offset);
}
// Populate the cryptoInfo.
sampleHolder.cryptoInfo.set(subsampleCount, clearDataSizes, encryptedDataSizes,
extrasHolder.encryptionKeyId, sampleHolder.cryptoInfo.iv, C.CRYPTO_MODE_AES_CTR);
buffer.cryptoInfo.set(subsampleCount, clearDataSizes, encryptedDataSizes,
extrasHolder.encryptionKeyId, buffer.cryptoInfo.iv, C.CRYPTO_MODE_AES_CTR);
// Adjust the offset and size to take into account the bytes read.
int bytesRead = (int) (offset - extrasHolder.offset);
extrasHolder.offset += bytesRead;
sampleHolder.size -= bytesRead;
buffer.size -= bytesRead;
}
/**
......@@ -418,7 +419,7 @@ import java.util.concurrent.LinkedBlockingDeque;
* Indicates the end point for the current sample, making it available for consumption.
*
* @param sampleTimeUs The sample timestamp.
* @param flags Flags that accompany the sample. See {@code C.SAMPLE_FLAG_*}.
* @param flags Flags that accompany the sample. See {@code C.BUFFER_FLAG_*}.
* @param position The position of the sample data in the rolling buffer.
* @param size The size of the sample, in bytes.
* @param encryptionKey The encryption key associated with the sample, or null.
......@@ -523,24 +524,25 @@ import java.util.concurrent.LinkedBlockingDeque;
}
/**
* Fills {@code holder} with information about the current sample, but does not write its data.
* The first entry in {@code offsetHolder} is filled with the absolute position of the sample's
* data in the rolling buffer.
* <p>
* Populates {@link SampleHolder#size}, {@link SampleHolder#timeUs}, the sample flags and
* Fills {@code buffer} with information about the current sample, but does not write its data.
* The absolute position of the sample's data in the rolling buffer is stored in
* {@code extrasHolder}.
* <p>
* Populates {@link DecoderInputBuffer#size}, {@link DecoderInputBuffer#timeUs}, the buffer
* flags and {@code extrasHolder}.
*
* @param holder The holder into which the current sample information should be written.
* @param buffer The buffer into which the current sample information should be written.
* @param extrasHolder The holder into which extra sample information should be written.
* @return True if the holders were filled. False if there is no current sample.
* @return True if the buffer and extras were filled. False if there is no current sample.
*/
public synchronized boolean peekSample(SampleHolder holder, SampleExtrasHolder extrasHolder) {
public synchronized boolean peekSample(DecoderInputBuffer buffer,
BufferExtrasHolder extrasHolder) {
if (queueSize == 0) {
return false;
}
holder.timeUs = timesUs[relativeReadIndex];
holder.size = sizes[relativeReadIndex];
holder.setFlags(flags[relativeReadIndex]);
buffer.timeUs = timesUs[relativeReadIndex];
buffer.size = sizes[relativeReadIndex];
buffer.setFlags(flags[relativeReadIndex]);
extrasHolder.offset = offsets[relativeReadIndex];
extrasHolder.encryptionKeyId = encryptionKeys[relativeReadIndex];
return true;
......@@ -590,7 +592,7 @@ import java.util.concurrent.LinkedBlockingDeque;
if (timesUs[searchIndex] > timeUs) {
// We've gone too far.
break;
} else if ((flags[searchIndex] & C.SAMPLE_FLAG_SYNC) != 0) {
} else if ((flags[searchIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
// We've found a keyframe, and we're still before the seek position.
sampleCountToKeyframe = sampleCount;
}
......@@ -660,9 +662,9 @@ import java.util.concurrent.LinkedBlockingDeque;
}
/**
* Holds additional sample information not held by {@link SampleHolder}.
* Holds additional buffer information not held by {@link DecoderInputBuffer}.
*/
private static final class SampleExtrasHolder {
private static final class BufferExtrasHolder {
public long offset;
public byte[] encryptionKeyId;
......
......@@ -65,7 +65,7 @@ public interface TrackOutput {
* {@link #sampleData(ParsableByteArray, int)}.
*
* @param timeUs The media timestamp associated with the sample, in microseconds.
* @param flags Flags associated with the sample. See {@code C.SAMPLE_FLAG_*}.
* @param flags Flags associated with the sample. See {@code C.BUFFER_FLAG_*}.
* @param size The size of the sample data, in bytes.
* @param offset The number of bytes that have been passed to
* {@link #sampleData(ExtractorInput, int, boolean)} or
......
......@@ -95,7 +95,7 @@ import java.util.Collections;
// Sample audio AAC frames
int bytesToWrite = data.bytesLeft();
output.sampleData(data, bytesToWrite);
output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, bytesToWrite, 0, null);
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, bytesToWrite, 0, null);
}
}
......
......@@ -129,7 +129,7 @@ import java.util.List;
output.sampleData(data, bytesToWrite);
bytesWritten += bytesToWrite;
}
output.sampleMetadata(timeUs, frameType == VIDEO_FRAME_KEYFRAME ? C.SAMPLE_FLAG_SYNC : 0,
output.sampleMetadata(timeUs, frameType == VIDEO_FRAME_KEYFRAME ? C.BUFFER_FLAG_KEY_FRAME : 0,
bytesWritten, 0, null);
}
}
......
......@@ -151,7 +151,8 @@ public final class Mp3Extractor implements Extractor {
return RESULT_CONTINUE;
}
long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
trackOutput.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, synchronizedHeader.frameSize, 0, null);
trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
null);
samplesRead += synchronizedHeader.samplesPerFrame;
sampleBytesRemaining = 0;
return RESULT_CONTINUE;
......
......@@ -196,9 +196,9 @@ import java.util.List;
timestamps[i] = timestampTimeUnits + timestampOffset;
// All samples are synchronization samples if the stss is not present.
flags[i] = stss == null ? C.SAMPLE_FLAG_SYNC : 0;
flags[i] = stss == null ? C.BUFFER_FLAG_KEY_FRAME : 0;
if (i == nextSynchronizationSampleIndex) {
flags[i] = C.SAMPLE_FLAG_SYNC;
flags[i] = C.BUFFER_FLAG_KEY_FRAME;
remainingSynchronizationSamples--;
if (remainingSynchronizationSamples > 0) {
nextSynchronizationSampleIndex = stss.readUnsignedIntToInt() - 1;
......@@ -330,7 +330,7 @@ import java.util.List;
boolean hasSyncSample = false;
for (int i = 0; i < editedFlags.length && !hasSyncSample; i++) {
hasSyncSample |= (editedFlags[i] & C.SAMPLE_FLAG_SYNC) != 0;
hasSyncSample |= (editedFlags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0;
}
if (!hasSyncSample) {
throw new ParserException("The edited sample sequence does not contain a sync sample.");
......
......@@ -874,8 +874,8 @@ public final class FragmentedMp4Extractor implements Extractor {
}
long sampleTimeUs = fragment.getSamplePresentationTime(sampleIndex) * 1000L;
int sampleFlags = (fragment.definesEncryptionData ? C.SAMPLE_FLAG_ENCRYPTED : 0)
| (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.SAMPLE_FLAG_SYNC : 0);
int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0)
| (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0);
int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex;
byte[] encryptionKey = fragment.definesEncryptionData
? track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId : null;
......
......@@ -79,7 +79,7 @@ import com.google.android.exoplayer.util.Util;
// Frames are not reordered past synchronization samples so this works in practice.
int startIndex = Util.binarySearchFloor(timestampsUs, timeUs, true, false);
for (int i = startIndex; i >= 0; i--) {
if ((flags[i] & C.SAMPLE_FLAG_SYNC) != 0) {
if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
return i;
}
}
......@@ -96,7 +96,7 @@ import com.google.android.exoplayer.util.Util;
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
for (int i = startIndex; i < timestampsUs.length; i++) {
if ((flags[i] & C.SAMPLE_FLAG_SYNC) != 0) {
if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
return i;
}
}
......
......@@ -164,7 +164,7 @@ public final class OggVorbisExtractor implements Extractor, SeekMap {
// Calculate time and send audio data to codec.
long timeUs = elapsedSamples * C.MICROS_PER_SECOND / vorbisSetup.idHeader.sampleRate;
trackOutput.sampleData(scratch, scratch.limit());
trackOutput.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, scratch.limit(), 0, null);
trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, scratch.limit(), 0, null);
targetGranule = -1;
}
// Update state in members for next iteration.
......
......@@ -103,7 +103,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
output.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
state = STATE_FINDING_SYNC;
}
......
......@@ -302,7 +302,7 @@ import java.util.Collections;
currentOutput.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
currentOutput.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
currentOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += currentSampleDuration;
setFindingSampleState();
}
......
......@@ -100,7 +100,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
output.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
state = STATE_FINDING_SYNC;
}
......
......@@ -131,7 +131,7 @@ import java.util.Collections;
if (hasOutputFormat && (startCodeValue == START_GROUP || startCodeValue == START_PICTURE)) {
int bytesWrittenPastStartCode = limit - startCodeOffset;
if (foundFirstFrameInGroup) {
int flags = isKeyframe ? C.SAMPLE_FLAG_SYNC : 0;
int flags = isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (totalBytesWritten - framePosition) - bytesWrittenPastStartCode;
output.sampleMetadata(frameTimeUs, flags, size, bytesWrittenPastStartCode, null);
isKeyframe = false;
......
......@@ -431,7 +431,7 @@ import java.util.List;
}
private void outputSample(int offset) {
int flags = sampleIsKeyframe ? C.SAMPLE_FLAG_SYNC : 0;
int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (nalUnitStartPosition - samplePosition);
output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
......
......@@ -453,7 +453,7 @@ import java.util.Collections;
}
private void outputSample(int offset) {
int flags = sampleIsKeyframe ? C.SAMPLE_FLAG_SYNC : 0;
int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (nalUnitStartPosition - samplePosition);
output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
......
......@@ -87,7 +87,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
if (!writingSample || sampleSize == 0 || sampleBytesRead != sampleSize) {
return;
}
output.sampleMetadata(sampleTimeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
writingSample = false;
}
......
......@@ -194,7 +194,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
return;
}
output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, frameSize, 0, null);
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, frameSize, 0, null);
timeUs += frameDurationUs;
frameBytesRead = 0;
state = STATE_FINDING_HEADER;
......
......@@ -55,7 +55,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
// Process the payload.
if (Eia608Parser.isSeiMessageEia608(payloadType, payloadSize, seiBuffer)) {
output.sampleData(seiBuffer, payloadSize);
output.sampleMetadata(pesTimeUs, C.SAMPLE_FLAG_SYNC, payloadSize, 0, null);
output.sampleMetadata(pesTimeUs, C.BUFFER_FLAG_KEY_FRAME, payloadSize, 0, null);
} else {
seiBuffer.skipBytes(payloadSize);
}
......
......@@ -83,7 +83,7 @@ public final class WavExtractor implements Extractor, SeekMap {
}
trackOutput.sampleMetadata(
wavHeader.getTimeUs(inputPosition), C.SAMPLE_FLAG_SYNC, bytesRead, 0, null);
wavHeader.getTimeUs(inputPosition), C.BUFFER_FLAG_KEY_FRAME, bytesRead, 0, null);
return RESULT_CONTINUE;
}
......
......@@ -449,7 +449,7 @@ public final class WebmExtractor implements Extractor {
}
// If the ReferenceBlock element was not found for this sample, then it is a keyframe.
if (!sampleSeenReferenceBlock) {
blockFlags |= C.SAMPLE_FLAG_SYNC;
blockFlags |= C.BUFFER_FLAG_KEY_FRAME;
}
commitSampleToOutput(tracks.get(blockTrackNumber), blockTimeUs);
blockState = BLOCK_STATE_START;
......@@ -766,8 +766,8 @@ public final class WebmExtractor implements Extractor {
boolean isInvisible = (scratch.data[2] & 0x08) == 0x08;
boolean isKeyframe = track.type == TRACK_TYPE_AUDIO
|| (id == ID_SIMPLE_BLOCK && (scratch.data[2] & 0x80) == 0x80);
blockFlags = (isKeyframe ? C.SAMPLE_FLAG_SYNC : 0)
| (isInvisible ? C.SAMPLE_FLAG_DECODE_ONLY : 0);
blockFlags = (isKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0)
| (isInvisible ? C.BUFFER_FLAG_DECODE_ONLY : 0);
blockState = BLOCK_STATE_DATA;
blockLacingSampleIndex = 0;
}
......@@ -850,7 +850,7 @@ public final class WebmExtractor implements Extractor {
if (track.hasContentEncryption) {
// If the sample is encrypted, read its encryption signal byte and set the IV size.
// Clear the encrypted flag.
blockFlags &= ~C.SAMPLE_FLAG_ENCRYPTED;
blockFlags &= ~C.BUFFER_FLAG_ENCRYPTED;
input.readFully(scratch.data, 0, 1);
sampleBytesRead++;
if ((scratch.data[0] & 0x80) == 0x80) {
......@@ -861,7 +861,7 @@ public final class WebmExtractor implements Extractor {
scratch.setPosition(0);
output.sampleData(scratch, 1);
sampleBytesWritten++;
blockFlags |= C.SAMPLE_FLAG_ENCRYPTED;
blockFlags |= C.BUFFER_FLAG_ENCRYPTED;
}
} else if (track.sampleStrippedBytes != null) {
// If the sample has header stripping, prepare to read/output the stripped bytes first.
......
......@@ -15,8 +15,8 @@
*/
package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.drm.DrmInitData;
import com.google.android.exoplayer.extractor.DefaultTrackOutput;
import com.google.android.exoplayer.extractor.Extractor;
......@@ -182,12 +182,12 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
* This method must only be called after the extractor has been prepared.
*
* @param track The track from which to read.
* @param holder A {@link SampleHolder} into which the sample should be read.
* @param buffer A {@link DecoderInputBuffer} to populate with a sample.
* @return True if a sample was read. False otherwise.
*/
public boolean getSample(int track, SampleHolder holder) {
public boolean getSample(int track, DecoderInputBuffer buffer) {
Assertions.checkState(isPrepared());
return sampleQueues.valueAt(track).getSample(holder);
return sampleQueues.valueAt(track).getSample(buffer);
}
/**
......@@ -204,13 +204,13 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
}
/**
* Whether samples are available for reading from {@link #getSample(int, SampleHolder)} for the
* specified track.
* Whether samples are available for reading from {@link #getSample(int, DecoderInputBuffer)} for
* the specified track.
* <p>
* This method must only be called after the extractor has been prepared.
*
* @return True if samples are available for reading from {@link #getSample(int, SampleHolder)}
* for the specified track. False otherwise.
* @return True if samples are available for reading from
* {@link #getSample(int, DecoderInputBuffer)} for the specified track. False otherwise.
*/
public boolean hasSamples(int track) {
Assertions.checkState(isPrepared());
......
......@@ -16,10 +16,10 @@
package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.LoadControl;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackGroup;
import com.google.android.exoplayer.TrackGroupArray;
......@@ -293,7 +293,7 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
return TrackStream.NO_RESET;
}
/* package */ int readData(int group, FormatHolder formatHolder, SampleHolder sampleHolder) {
/* package */ int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (pendingResets[group] || isPendingReset()) {
return TrackStream.NOTHING_READ;
}
......@@ -332,16 +332,16 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
return TrackStream.FORMAT_READ;
}
if (extractor.getSample(group, sampleHolder)) {
if (sampleHolder.timeUs < lastSeekPositionUs) {
sampleHolder.addFlag(C.SAMPLE_FLAG_DECODE_ONLY);
if (extractor.getSample(group, buffer)) {
if (buffer.timeUs < lastSeekPositionUs) {
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
return TrackStream.SAMPLE_READ;
return TrackStream.BUFFER_READ;
}
if (loadingFinished) {
sampleHolder.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return TrackStream.END_OF_STREAM;
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return TrackStream.BUFFER_READ;
}
return TrackStream.NOTHING_READ;
......@@ -836,8 +836,8 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback {
}
@Override
public int readData(FormatHolder formatHolder, SampleHolder sampleHolder) {
return HlsSampleSource.this.readData(group, formatHolder, sampleHolder);
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
return HlsSampleSource.this.readData(group, formatHolder, buffer);
}
}
......
......@@ -156,7 +156,7 @@ import java.util.regex.Pattern;
// Output the sample.
sampleDataWrapper.reset(sampleData, sampleSize);
trackOutput.sampleData(sampleDataWrapper, sampleSize);
trackOutput.sampleMetadata(sampleTimeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null);
trackOutput.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
private TrackOutput buildTrackOutput(long subsampleOffsetUs) {
......
......@@ -15,10 +15,10 @@
*/
package com.google.android.exoplayer.metadata;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSourceTrackRenderer;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.TrackStream;
......@@ -60,7 +60,7 @@ public final class MetadataTrackRenderer<T> extends SampleSourceTrackRenderer im
private final MetadataRenderer<T> metadataRenderer;
private final Handler metadataHandler;
private final FormatHolder formatHolder;
private final SampleHolder sampleHolder;
private final DecoderInputBuffer buffer;
private boolean inputStreamEnded;
private long pendingMetadataTimestamp;
......@@ -82,7 +82,7 @@ public final class MetadataTrackRenderer<T> extends SampleSourceTrackRenderer im
this.metadataHandler = metadataRendererLooper == null ? null
: new Handler(metadataRendererLooper, this);
formatHolder = new FormatHolder();
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
}
@Override
......@@ -101,17 +101,19 @@ public final class MetadataTrackRenderer<T> extends SampleSourceTrackRenderer im
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
throws ExoPlaybackException {
if (!inputStreamEnded && pendingMetadata == null) {
sampleHolder.clear();
int result = readSource(formatHolder, sampleHolder);
if (result == TrackStream.SAMPLE_READ) {
pendingMetadataTimestamp = sampleHolder.timeUs;
try {
pendingMetadata = metadataParser.parse(sampleHolder.data.array(), sampleHolder.size);
} catch (IOException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
buffer.clear();
int result = readSource(formatHolder, buffer);
if (result == TrackStream.BUFFER_READ) {
if (buffer.isEndOfStream()) {
inputStreamEnded = true;
} else {
pendingMetadataTimestamp = buffer.timeUs;
try {
pendingMetadata = metadataParser.parse(buffer.data.array(), buffer.size);
} catch (IOException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
}
}
} else if (result == TrackStream.END_OF_STREAM) {
inputStreamEnded = true;
}
}
......
......@@ -15,17 +15,17 @@
*/
package com.google.android.exoplayer.text;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.DecoderInputBuffer;
/**
* An input buffer for {@link SubtitleParser}.
*/
/* package */ final class SubtitleInputBuffer extends SampleHolder {
/* package */ final class SubtitleInputBuffer extends DecoderInputBuffer {
public long subsampleOffsetUs;
public SubtitleInputBuffer() {
super(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
super(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
}
}
......@@ -176,11 +176,14 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
}
// Try and read the next subtitle from the source.
int result = readSource(formatHolder, nextInputBuffer);
if (result == TrackStream.SAMPLE_READ) {
nextInputBuffer.subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
parser.queueInputBuffer(nextInputBuffer);
} else if (result == TrackStream.END_OF_STREAM) {
inputStreamEnded = true;
if (result == TrackStream.BUFFER_READ) {
if (nextInputBuffer.isEndOfStream()) {
inputStreamEnded = true;
// TODO: Queue the end of stream buffer.
} else {
nextInputBuffer.subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
parser.queueInputBuffer(nextInputBuffer);
}
}
}
} catch (ParserException e) {
......
......@@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer.text.eia608;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParsableBitArray;
import com.google.android.exoplayer.util.ParsableByteArray;
......@@ -116,14 +116,14 @@ public final class Eia608Parser {
return mimeType.equals(MimeTypes.APPLICATION_EIA608);
}
/* package */ ClosedCaptionList parse(SampleHolder sampleHolder) {
if (sampleHolder.size < 10) {
/* package */ ClosedCaptionList parse(DecoderInputBuffer buffer) {
if (buffer.size < 10) {
return null;
}
captions.clear();
stringBuilder.setLength(0);
seiBuffer.reset(sampleHolder.data.array());
seiBuffer.reset(buffer.data.array());
// country_code (8) + provider_code (16) + user_identifier (32) + user_data_type_code (8) +
// reserved (1) + process_cc_data_flag (1) + zero_bit (1)
......@@ -200,7 +200,7 @@ public final class Eia608Parser {
ClosedCaption[] captionArray = new ClosedCaption[captions.size()];
captions.toArray(captionArray);
return new ClosedCaptionList(sampleHolder.timeUs, sampleHolder.isDecodeOnly(), captionArray);
return new ClosedCaptionList(buffer.timeUs, buffer.isDecodeOnly(), captionArray);
}
private static char getChar(byte ccData) {
......
......@@ -16,10 +16,10 @@
package com.google.android.exoplayer.text.eia608;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.Format;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSourceTrackRenderer;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.TrackStream;
......@@ -51,13 +51,13 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
// The default number of rows to display in roll-up captions mode.
private static final int DEFAULT_CAPTIONS_ROW_COUNT = 4;
// The maximum duration that captions are parsed ahead of the current position.
private static final int MAX_SAMPLE_READAHEAD_US = 5000000;
private static final int MAX_BUFFER_READAHEAD_US = 5000000;
private final Eia608Parser eia608Parser;
private final TextRenderer textRenderer;
private final Handler textRendererHandler;
private final FormatHolder formatHolder;
private final SampleHolder sampleHolder;
private final DecoderInputBuffer buffer;
private final StringBuilder captionStringBuilder;
private final TreeSet<ClosedCaptionList> pendingCaptionLists;
......@@ -81,7 +81,7 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
textRendererHandler = textRendererLooper == null ? null : new Handler(textRendererLooper, this);
eia608Parser = new Eia608Parser();
formatHolder = new FormatHolder();
sampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
captionStringBuilder = new StringBuilder();
pendingCaptionLists = new TreeSet<>();
}
......@@ -97,7 +97,7 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
inputStreamEnded = false;
repeatableControl = null;
pendingCaptionLists.clear();
clearPendingSample();
clearPendingBuffer();
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
setCaptionMode(CC_MODE_UNKNOWN);
invokeRenderer(null);
......@@ -106,17 +106,20 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
@Override
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
throws ExoPlaybackException {
if (isSamplePending()) {
maybeParsePendingSample(positionUs);
if (isBufferPending()) {
maybeParsePendingBuffer(positionUs);
}
int result = inputStreamEnded ? TrackStream.END_OF_STREAM : TrackStream.SAMPLE_READ;
while (!isSamplePending() && result == TrackStream.SAMPLE_READ) {
result = readSource(formatHolder, sampleHolder);
if (result == TrackStream.SAMPLE_READ) {
maybeParsePendingSample(positionUs);
} else if (result == TrackStream.END_OF_STREAM) {
inputStreamEnded = true;
while (!isBufferPending() && !inputStreamEnded) {
int result = readSource(formatHolder, buffer);
if (result == TrackStream.BUFFER_READ) {
if (buffer.isEndOfStream()) {
inputStreamEnded = true;
} else {
maybeParsePendingBuffer(positionUs);
}
} else if (result == TrackStream.NOTHING_READ) {
break;
}
}
......@@ -177,13 +180,13 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
}
}
private void maybeParsePendingSample(long positionUs) {
if (sampleHolder.timeUs > positionUs + MAX_SAMPLE_READAHEAD_US) {
// We're too early to parse the sample.
private void maybeParsePendingBuffer(long positionUs) {
if (buffer.timeUs > positionUs + MAX_BUFFER_READAHEAD_US) {
// We're too early to parse the buffer.
return;
}
ClosedCaptionList holder = eia608Parser.parse(sampleHolder);
clearPendingSample();
ClosedCaptionList holder = eia608Parser.parse(buffer);
clearPendingBuffer();
if (holder != null) {
pendingCaptionLists.add(holder);
}
......@@ -338,13 +341,13 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
return captionStringBuilder.substring(0, endIndex - startIndex);
}
private void clearPendingSample() {
sampleHolder.clear();
sampleHolder.timeUs = C.UNKNOWN_TIME_US;
private void clearPendingBuffer() {
buffer.clear();
buffer.timeUs = C.UNKNOWN_TIME_US;
}
private boolean isSamplePending() {
return sampleHolder.timeUs != C.UNKNOWN_TIME_US;
private boolean isBufferPending() {
return buffer.timeUs != C.UNKNOWN_TIME_US;
}
}
......@@ -32,30 +32,30 @@ public abstract class Buffer {
}
/**
* Returns whether the {@link C#SAMPLE_FLAG_DECODE_ONLY} flag is set.
* Returns whether the {@link C#BUFFER_FLAG_DECODE_ONLY} flag is set.
*/
public final boolean isDecodeOnly() {
return getFlag(C.SAMPLE_FLAG_DECODE_ONLY);
return getFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
/**
* Returns whether the {@link C#SAMPLE_FLAG_END_OF_STREAM} flag is set.
* Returns whether the {@link C#BUFFER_FLAG_END_OF_STREAM} flag is set.
*/
public final boolean isEndOfStream() {
return getFlag(C.SAMPLE_FLAG_END_OF_STREAM);
return getFlag(C.BUFFER_FLAG_END_OF_STREAM);
}
/**
* Returns whether the sample has the {@link C#SAMPLE_FLAG_SYNC} flag set.
* Returns whether the {@link C#BUFFER_FLAG_KEY_FRAME} flag is set.
*/
public final boolean isSyncFrame() {
return getFlag(C.SAMPLE_FLAG_SYNC);
public final boolean isKeyFrame() {
return getFlag(C.BUFFER_FLAG_KEY_FRAME);
}
/**
* Replaces this buffer's flags with {@code flags}.
*
* @param flags The flags to set, which should be a combination of the {@code C.SAMPLE_FLAG_*}
* @param flags The flags to set, which should be a combination of the {@code C.BUFFER_FLAG_*}
* constants.
*/
public final void setFlags(int flags) {
......@@ -66,7 +66,7 @@ public abstract class Buffer {
* Adds the {@code flag} to this buffer's flags.
*
* @param flag The flag to add to this buffer's flags, which should be one of the
* {@code C.SAMPLE_FLAG_*} constants.
* {@code C.BUFFER_FLAG_*} constants.
*/
public final void addFlag(int flag) {
flags |= flag;
......
......@@ -16,7 +16,7 @@
package com.google.android.exoplayer.util.extensions;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.DecoderInputBuffer;
import com.google.android.exoplayer.util.Assertions;
import java.util.LinkedList;
......@@ -24,7 +24,7 @@ import java.util.LinkedList;
/**
* Base class for {@link Decoder}s that use their own decode thread.
*/
public abstract class SimpleDecoder<I extends SampleHolder, O extends OutputBuffer,
public abstract class SimpleDecoder<I extends DecoderInputBuffer, O extends OutputBuffer,
E extends Exception> extends Thread implements Decoder<I, O, E> {
/**
......@@ -218,10 +218,10 @@ public abstract class SimpleDecoder<I extends SampleHolder, O extends OutputBuff
}
if (inputBuffer.isEndOfStream()) {
outputBuffer.addFlag(C.SAMPLE_FLAG_END_OF_STREAM);
outputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
} else {
if (inputBuffer.isDecodeOnly()) {
outputBuffer.addFlag(C.SAMPLE_FLAG_DECODE_ONLY);
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
exception = decode(inputBuffer, outputBuffer);
if (exception != null) {
......@@ -276,7 +276,7 @@ public abstract class SimpleDecoder<I extends SampleHolder, O extends OutputBuff
*
* @param inputBuffer The buffer to decode.
* @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
* {@link C#BUFFER_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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册