mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Remove DecoderInputBuffer.size
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=122146105
This commit is contained in:
parent
f9f95d638b
commit
68d39b5159
17 changed files with 106 additions and 84 deletions
|
|
@ -77,18 +77,14 @@ import java.util.List;
|
||||||
if (reset) {
|
if (reset) {
|
||||||
decoder.flush();
|
decoder.flush();
|
||||||
}
|
}
|
||||||
ByteBuffer data = inputBuffer.data;
|
decoder.setData(inputBuffer.data);
|
||||||
outputBuffer.timestampUs = inputBuffer.timeUs;
|
ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, maxOutputBufferSize);
|
||||||
data.limit(data.position());
|
int result = decoder.decodeSample(outputData);
|
||||||
data.position(data.position() - inputBuffer.size);
|
|
||||||
outputBuffer.init(maxOutputBufferSize);
|
|
||||||
decoder.setData(data);
|
|
||||||
int result = decoder.decodeSample(outputBuffer.data);
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
return new FlacDecoderException("Frame decoding failed");
|
return new FlacDecoderException("Frame decoding failed");
|
||||||
}
|
}
|
||||||
outputBuffer.data.position(0);
|
outputData.position(0);
|
||||||
outputBuffer.data.limit(result);
|
outputData.limit(result);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,34 +149,31 @@ import java.util.List;
|
||||||
opusReset(nativeDecoderContext);
|
opusReset(nativeDecoderContext);
|
||||||
// When seeking to 0, skip number of samples as specified in opus header. When seeking to
|
// When seeking to 0, skip number of samples as specified in opus header. When seeking to
|
||||||
// any other time, skip number of samples as specified by seek preroll.
|
// any other time, skip number of samples as specified by seek preroll.
|
||||||
skipSamples =
|
skipSamples = (inputBuffer.timeUs == 0) ? headerSkipSamples : headerSeekPreRollSamples;
|
||||||
(inputBuffer.timeUs == 0) ? headerSkipSamples : headerSeekPreRollSamples;
|
|
||||||
}
|
}
|
||||||
outputBuffer.timestampUs = inputBuffer.timeUs;
|
ByteBuffer inputData = inputBuffer.data;
|
||||||
inputBuffer.data.position(inputBuffer.data.position() - inputBuffer.size);
|
int inputSize = inputData.limit();
|
||||||
int requiredOutputBufferSize =
|
int outputSize = opusGetRequiredOutputBufferSize(inputData, inputSize, SAMPLE_RATE);
|
||||||
opusGetRequiredOutputBufferSize(inputBuffer.data, inputBuffer.size, SAMPLE_RATE);
|
if (outputSize < 0) {
|
||||||
if (requiredOutputBufferSize < 0) {
|
|
||||||
return new OpusDecoderException("Error when computing required output buffer size.");
|
return new OpusDecoderException("Error when computing required output buffer size.");
|
||||||
}
|
}
|
||||||
outputBuffer.init(requiredOutputBufferSize);
|
ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, outputSize);
|
||||||
int result = opusDecode(nativeDecoderContext, inputBuffer.data, inputBuffer.size,
|
int result = opusDecode(nativeDecoderContext, inputData, inputSize, outputData, outputSize);
|
||||||
outputBuffer.data, outputBuffer.data.capacity());
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
return new OpusDecoderException("Decode error: " + opusGetErrorMessage(result));
|
return new OpusDecoderException("Decode error: " + opusGetErrorMessage(result));
|
||||||
}
|
}
|
||||||
outputBuffer.data.position(0);
|
outputData.position(0);
|
||||||
outputBuffer.data.limit(result);
|
outputData.limit(result);
|
||||||
if (skipSamples > 0) {
|
if (skipSamples > 0) {
|
||||||
int bytesPerSample = channelCount * 2;
|
int bytesPerSample = channelCount * 2;
|
||||||
int skipBytes = skipSamples * bytesPerSample;
|
int skipBytes = skipSamples * bytesPerSample;
|
||||||
if (result <= skipBytes) {
|
if (result <= skipBytes) {
|
||||||
skipSamples -= result / bytesPerSample;
|
skipSamples -= result / bytesPerSample;
|
||||||
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||||
outputBuffer.data.position(result);
|
outputData.position(result);
|
||||||
} else {
|
} else {
|
||||||
skipSamples = 0;
|
skipSamples = 0;
|
||||||
outputBuffer.data.position(skipBytes);
|
outputData.position(skipBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
||||||
previousWidth = -1;
|
previousWidth = -1;
|
||||||
previousHeight = -1;
|
previousHeight = -1;
|
||||||
formatHolder = new FormatHolder();
|
formatHolder = new FormatHolder();
|
||||||
outputMode = VpxDecoder.OUTPUT_MODE_UNKNOWN;
|
outputMode = VpxDecoder.OUTPUT_MODE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -281,6 +281,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
||||||
if (inputBuffer.isEndOfStream()) {
|
if (inputBuffer.isEndOfStream()) {
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
}
|
}
|
||||||
|
inputBuffer.flip();
|
||||||
decoder.queueInputBuffer(inputBuffer);
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
inputBuffer = null;
|
inputBuffer = null;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -377,7 +378,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
||||||
}
|
}
|
||||||
this.surface = surface;
|
this.surface = surface;
|
||||||
outputBufferRenderer = null;
|
outputBufferRenderer = null;
|
||||||
outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_UNKNOWN;
|
outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE;
|
||||||
if (decoder != null) {
|
if (decoder != null) {
|
||||||
decoder.setOutputMode(outputMode);
|
decoder.setOutputMode(outputMode);
|
||||||
}
|
}
|
||||||
|
|
@ -390,8 +391,8 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
||||||
}
|
}
|
||||||
this.outputBufferRenderer = outputBufferRenderer;
|
this.outputBufferRenderer = outputBufferRenderer;
|
||||||
surface = null;
|
surface = null;
|
||||||
outputMode = (outputBufferRenderer != null)
|
outputMode = (outputBufferRenderer != null) ? VpxDecoder.OUTPUT_MODE_YUV
|
||||||
? VpxDecoder.OUTPUT_MODE_YUV : VpxDecoder.OUTPUT_MODE_UNKNOWN;
|
: VpxDecoder.OUTPUT_MODE_NONE;
|
||||||
if (decoder != null) {
|
if (decoder != null) {
|
||||||
decoder.setOutputMode(outputMode);
|
decoder.setOutputMode(outputMode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import java.nio.ByteBuffer;
|
||||||
/* package */ final class VpxDecoder extends
|
/* package */ final class VpxDecoder extends
|
||||||
SimpleDecoder<DecoderInputBuffer, VpxOutputBuffer, VpxDecoderException> {
|
SimpleDecoder<DecoderInputBuffer, VpxOutputBuffer, VpxDecoderException> {
|
||||||
|
|
||||||
public static final int OUTPUT_MODE_UNKNOWN = -1;
|
public static final int OUTPUT_MODE_NONE = -1;
|
||||||
public static final int OUTPUT_MODE_YUV = 0;
|
public static final int OUTPUT_MODE_YUV = 0;
|
||||||
public static final int OUTPUT_MODE_RGB = 1;
|
public static final int OUTPUT_MODE_RGB = 1;
|
||||||
|
|
||||||
|
|
@ -77,8 +77,8 @@ import java.nio.ByteBuffer;
|
||||||
/**
|
/**
|
||||||
* Sets the output mode for frames rendered by the decoder.
|
* Sets the output mode for frames rendered by the decoder.
|
||||||
*
|
*
|
||||||
* @param outputMode The output mode to use, which must be one of the {@code OUTPUT_MODE_*}
|
* @param outputMode The output mode. One of {@link #OUTPUT_MODE_NONE}, {@link #OUTPUT_MODE_RGB}
|
||||||
* constants in {@link VpxDecoder}.
|
* and {@link #OUTPUT_MODE_YUV}.
|
||||||
*/
|
*/
|
||||||
public void setOutputMode(int outputMode) {
|
public void setOutputMode(int outputMode) {
|
||||||
this.outputMode = outputMode;
|
this.outputMode = outputMode;
|
||||||
|
|
@ -102,12 +102,12 @@ import java.nio.ByteBuffer;
|
||||||
@Override
|
@Override
|
||||||
protected VpxDecoderException decode(DecoderInputBuffer inputBuffer, VpxOutputBuffer outputBuffer,
|
protected VpxDecoderException decode(DecoderInputBuffer inputBuffer, VpxOutputBuffer outputBuffer,
|
||||||
boolean reset) {
|
boolean reset) {
|
||||||
outputBuffer.timestampUs = inputBuffer.timeUs;
|
ByteBuffer inputData = inputBuffer.data;
|
||||||
inputBuffer.data.position(inputBuffer.data.position() - inputBuffer.size);
|
int inputSize = inputData.limit();
|
||||||
if (vpxDecode(vpxDecContext, inputBuffer.data, inputBuffer.size) != 0) {
|
if (vpxDecode(vpxDecContext, inputData, inputSize) != 0) {
|
||||||
return new VpxDecoderException("Decode error: " + vpxGetErrorMessage(vpxDecContext));
|
return new VpxDecoderException("Decode error: " + vpxGetErrorMessage(vpxDecContext));
|
||||||
}
|
}
|
||||||
outputBuffer.mode = outputMode;
|
outputBuffer.init(inputBuffer.timeUs, outputMode);
|
||||||
if (vpxGetFrame(vpxDecContext, outputBuffer) != 0) {
|
if (vpxGetFrame(vpxDecContext, outputBuffer) != 0) {
|
||||||
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import java.nio.ByteBuffer;
|
||||||
/**
|
/**
|
||||||
* Output buffer containing video frame data, populated by {@link VpxDecoder}.
|
* Output buffer containing video frame data, populated by {@link VpxDecoder}.
|
||||||
*/
|
*/
|
||||||
public final class VpxOutputBuffer extends OutputBuffer {
|
/* package */ final class VpxOutputBuffer extends OutputBuffer {
|
||||||
|
|
||||||
public static final int COLORSPACE_UNKNOWN = 0;
|
public static final int COLORSPACE_UNKNOWN = 0;
|
||||||
public static final int COLORSPACE_BT601 = 1;
|
public static final int COLORSPACE_BT601 = 1;
|
||||||
|
|
@ -44,7 +44,7 @@ public final class VpxOutputBuffer extends OutputBuffer {
|
||||||
public int[] yuvStrides;
|
public int[] yuvStrides;
|
||||||
public int colorspace;
|
public int colorspace;
|
||||||
|
|
||||||
/* package */ VpxOutputBuffer(VpxDecoder owner) {
|
public VpxOutputBuffer(VpxDecoder owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,10 +53,22 @@ public final class VpxOutputBuffer extends OutputBuffer {
|
||||||
owner.releaseOutputBuffer(this);
|
owner.releaseOutputBuffer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the buffer.
|
||||||
|
*
|
||||||
|
* @param timestampUs The presentation timestamp for the buffer, in microseconds.
|
||||||
|
* @param mode The output mode. One of {@link VpxDecoder#OUTPUT_MODE_NONE},
|
||||||
|
* {@link VpxDecoder#OUTPUT_MODE_RGB} and {@link VpxDecoder#OUTPUT_MODE_YUV}.
|
||||||
|
*/
|
||||||
|
public void init(long timestampUs, int mode) {
|
||||||
|
this.timestampUs = timestampUs;
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes the buffer based on the given dimensions. Called via JNI after decoding completes.
|
* Resizes the buffer based on the given dimensions. Called via JNI after decoding completes.
|
||||||
*/
|
*/
|
||||||
/* package */ void initForRgbFrame(int width, int height) {
|
public void initForRgbFrame(int width, int height) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.yuvPlanes = null;
|
this.yuvPlanes = null;
|
||||||
|
|
@ -68,7 +80,7 @@ public final class VpxOutputBuffer extends OutputBuffer {
|
||||||
/**
|
/**
|
||||||
* Resizes the buffer based on the given stride. Called via JNI after decoding completes.
|
* Resizes the buffer based on the given stride. Called via JNI after decoding completes.
|
||||||
*/
|
*/
|
||||||
/* package */ void initForYuvFrame(int width, int height, int yStride, int uvStride,
|
public void initForYuvFrame(int width, int height, int yStride, int uvStride,
|
||||||
int colorspace) {
|
int colorspace) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,6 @@ public class DecoderInputBuffer extends Buffer {
|
||||||
*/
|
*/
|
||||||
public ByteBuffer data;
|
public ByteBuffer data;
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of the data in bytes.
|
|
||||||
*/
|
|
||||||
public int size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time at which the sample should be presented.
|
* The time at which the sample should be presented.
|
||||||
*/
|
*/
|
||||||
|
|
@ -114,6 +109,15 @@ public class DecoderInputBuffer extends Buffer {
|
||||||
return getFlag(C.BUFFER_FLAG_ENCRYPTED);
|
return getFlag(C.BUFFER_FLAG_ENCRYPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flips {@link #data} in preparation for being queued to a decoder.
|
||||||
|
*
|
||||||
|
* @see java.nio.Buffer#flip()
|
||||||
|
*/
|
||||||
|
public final void flip() {
|
||||||
|
data.flip();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
super.clear();
|
super.clear();
|
||||||
|
|
|
||||||
|
|
@ -250,13 +250,10 @@ public final class FrameworkSampleSource implements SampleSource {
|
||||||
}
|
}
|
||||||
int extractorTrackIndex = extractor.getSampleTrackIndex();
|
int extractorTrackIndex = extractor.getSampleTrackIndex();
|
||||||
if (extractorTrackIndex == track) {
|
if (extractorTrackIndex == track) {
|
||||||
if (buffer.data != null) {
|
ByteBuffer bufferData = buffer.data;
|
||||||
int offset = buffer.data.position();
|
int offset = bufferData.position();
|
||||||
buffer.size = extractor.readSampleData(buffer.data, offset);
|
int size = extractor.readSampleData(bufferData, offset);
|
||||||
buffer.data.position(offset + buffer.size);
|
bufferData.position(offset + size);
|
||||||
} else {
|
|
||||||
buffer.size = 0;
|
|
||||||
}
|
|
||||||
buffer.timeUs = extractor.getSampleTime();
|
buffer.timeUs = extractor.getSampleTime();
|
||||||
int flags = extractor.getSampleFlags();
|
int flags = extractor.getSampleFlags();
|
||||||
if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
|
if ((flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
|
||||||
|
|
|
||||||
|
|
@ -527,6 +527,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
int adaptiveReconfigurationBytes = 0;
|
||||||
if (waitingForKeys) {
|
if (waitingForKeys) {
|
||||||
// We've already read an encrypted sample into buffer, and are waiting for keys.
|
// We've already read an encrypted sample into buffer, and are waiting for keys.
|
||||||
result = TrackStream.BUFFER_READ;
|
result = TrackStream.BUFFER_READ;
|
||||||
|
|
@ -540,6 +541,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
||||||
}
|
}
|
||||||
codecReconfigurationState = RECONFIGURATION_STATE_QUEUE_PENDING;
|
codecReconfigurationState = RECONFIGURATION_STATE_QUEUE_PENDING;
|
||||||
}
|
}
|
||||||
|
adaptiveReconfigurationBytes = buffer.data.position();
|
||||||
result = readSource(formatHolder, buffer);
|
result = readSource(formatHolder, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -598,21 +600,20 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
||||||
codecNeedsDiscardToSpsWorkaround = false;
|
codecNeedsDiscardToSpsWorkaround = false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int bufferSize = buffer.data.position();
|
|
||||||
int adaptiveReconfigurationBytes = bufferSize - buffer.size;
|
|
||||||
long presentationTimeUs = buffer.timeUs;
|
long presentationTimeUs = buffer.timeUs;
|
||||||
if (buffer.isDecodeOnly()) {
|
if (buffer.isDecodeOnly()) {
|
||||||
decodeOnlyPresentationTimestamps.add(presentationTimeUs);
|
decodeOnlyPresentationTimestamps.add(presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
onQueuedInputBuffer(presentationTimeUs, buffer.data, bufferSize, bufferEncrypted);
|
buffer.flip();
|
||||||
|
onQueueInputBuffer(buffer);
|
||||||
|
|
||||||
if (bufferEncrypted) {
|
if (bufferEncrypted) {
|
||||||
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(buffer,
|
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(buffer,
|
||||||
adaptiveReconfigurationBytes);
|
adaptiveReconfigurationBytes);
|
||||||
codec.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0);
|
codec.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0);
|
||||||
} else {
|
} else {
|
||||||
codec.queueInputBuffer(inputIndex, 0, bufferSize, presentationTimeUs, 0);
|
codec.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0);
|
||||||
}
|
}
|
||||||
inputIndex = -1;
|
inputIndex = -1;
|
||||||
codecReceivedBuffers = true;
|
codecReceivedBuffers = true;
|
||||||
|
|
@ -705,13 +706,9 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
||||||
* <p>
|
* <p>
|
||||||
* The default implementation is a no-op.
|
* The default implementation is a no-op.
|
||||||
*
|
*
|
||||||
* @param presentationTimeUs The timestamp associated with the input buffer.
|
|
||||||
* @param buffer The buffer to be queued.
|
* @param buffer The buffer to be queued.
|
||||||
* @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,
|
protected void onQueueInputBuffer(DecoderInputBuffer buffer) {
|
||||||
boolean bufferEncrypted) {
|
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,9 +203,8 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load
|
||||||
return NOTHING_READ;
|
return NOTHING_READ;
|
||||||
} else {
|
} else {
|
||||||
buffer.timeUs = 0;
|
buffer.timeUs = 0;
|
||||||
buffer.size = sampleSize;
|
|
||||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||||
buffer.ensureSpaceForWrite(buffer.size);
|
buffer.ensureSpaceForWrite(sampleSize);
|
||||||
buffer.data.put(sampleData, 0, sampleSize);
|
buffer.data.put(sampleData, 0, sampleSize);
|
||||||
streamState = STREAM_STATE_END_OF_STREAM;
|
streamState = STREAM_STATE_END_OF_STREAM;
|
||||||
return BUFFER_READ;
|
return BUFFER_READ;
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,8 @@ public interface TrackStream {
|
||||||
*
|
*
|
||||||
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
|
* @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
|
* @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
|
* end of the stream. If the end of the stream has been reached, the
|
||||||
* {@link DecoderInputBuffer#data} references a valid buffer. If the end of the stream has
|
* {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
|
||||||
* 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
|
* @return The result, which can be {@link #NOTHING_READ}, {@link #FORMAT_READ} or
|
||||||
* {@link #BUFFER_READ}.
|
* {@link #BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -217,9 +217,8 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
*
|
*
|
||||||
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
|
* @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
|
* @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
|
* end of the stream. If the end of the stream has been reached, the
|
||||||
* {@link DecoderInputBuffer#data} references a valid buffer. If the end of the stream has
|
* {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
|
||||||
* been reached, the {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
|
|
||||||
* @param loadingFinished True if an empty queue should be considered the end of the stream.
|
* @param loadingFinished True if an empty queue should be considered the end of the stream.
|
||||||
* @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
|
* @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
|
||||||
* be set if the buffer's timestamp is less than this value.
|
* be set if the buffer's timestamp is less than this value.
|
||||||
|
|
@ -247,8 +246,8 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
readEncryptionData(buffer, extrasHolder);
|
readEncryptionData(buffer, extrasHolder);
|
||||||
}
|
}
|
||||||
// Write the sample data into the holder.
|
// Write the sample data into the holder.
|
||||||
buffer.ensureSpaceForWrite(buffer.size);
|
buffer.ensureSpaceForWrite(extrasHolder.size);
|
||||||
readData(extrasHolder.offset, buffer.data, buffer.size);
|
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
|
||||||
// Advance the read head.
|
// Advance the read head.
|
||||||
dropDownstreamTo(extrasHolder.nextOffset);
|
dropDownstreamTo(extrasHolder.nextOffset);
|
||||||
return TrackStream.BUFFER_READ;
|
return TrackStream.BUFFER_READ;
|
||||||
|
|
@ -261,7 +260,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
* Reads encryption data for the current sample.
|
* Reads encryption data for the current sample.
|
||||||
* <p>
|
* <p>
|
||||||
* The encryption data is written into {@link DecoderInputBuffer#cryptoInfo}, and
|
* 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
|
* {@link BufferExtrasHolder#size} is adjusted to subtract the number of bytes that were read. The
|
||||||
* same value is added to {@link BufferExtrasHolder#offset}.
|
* same value is added to {@link BufferExtrasHolder#offset}.
|
||||||
*
|
*
|
||||||
* @param buffer The buffer into which the encryption data should be written.
|
* @param buffer The buffer into which the encryption data should be written.
|
||||||
|
|
@ -316,7 +315,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clearDataSizes[0] = 0;
|
clearDataSizes[0] = 0;
|
||||||
encryptedDataSizes[0] = buffer.size - (int) (offset - extrasHolder.offset);
|
encryptedDataSizes[0] = extrasHolder.size - (int) (offset - extrasHolder.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the cryptoInfo.
|
// Populate the cryptoInfo.
|
||||||
|
|
@ -326,7 +325,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
// Adjust the offset and size to take into account the bytes read.
|
// Adjust the offset and size to take into account the bytes read.
|
||||||
int bytesRead = (int) (offset - extrasHolder.offset);
|
int bytesRead = (int) (offset - extrasHolder.offset);
|
||||||
extrasHolder.offset += bytesRead;
|
extrasHolder.offset += bytesRead;
|
||||||
buffer.size -= bytesRead;
|
extrasHolder.size -= bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -633,10 +632,10 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
* @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
|
* @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
|
* @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
|
||||||
* end of the stream. If a sample is read then the buffer is populated with information
|
* end of the stream. If a sample is read then the buffer is populated with information
|
||||||
* about the sample, but not its data. The absolute position of the data in the rolling
|
* about the sample, but not its data. The size and absolute position of the data in the
|
||||||
* buffer is stored in {@code extrasHolder}, along with an encryption id if present and the
|
* rolling buffer is stored in {@code extrasHolder}, along with an encryption id if present
|
||||||
* absolute position of the first byte that may still be required after the current sample
|
* and the absolute position of the first byte that may still be required after the current
|
||||||
* has been read.
|
* sample has been read.
|
||||||
* @param downstreamFormat The current downstream {@link Format}. If the format of the next
|
* @param downstreamFormat The current downstream {@link Format}. If the format of the next
|
||||||
* sample is different to the current downstream format then a format will be read.
|
* sample is different to the current downstream format then a format will be read.
|
||||||
* @param extrasHolder The holder into which extra sample information should be written.
|
* @param extrasHolder The holder into which extra sample information should be written.
|
||||||
|
|
@ -659,8 +658,8 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.timeUs = timesUs[relativeReadIndex];
|
buffer.timeUs = timesUs[relativeReadIndex];
|
||||||
buffer.size = sizes[relativeReadIndex];
|
|
||||||
buffer.setFlags(flags[relativeReadIndex]);
|
buffer.setFlags(flags[relativeReadIndex]);
|
||||||
|
extrasHolder.size = sizes[relativeReadIndex];
|
||||||
extrasHolder.offset = offsets[relativeReadIndex];
|
extrasHolder.offset = offsets[relativeReadIndex];
|
||||||
extrasHolder.encryptionKeyId = encryptionKeys[relativeReadIndex];
|
extrasHolder.encryptionKeyId = encryptionKeys[relativeReadIndex];
|
||||||
|
|
||||||
|
|
@ -674,7 +673,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
|
extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
|
||||||
: extrasHolder.offset + buffer.size;
|
: extrasHolder.offset + extrasHolder.size;
|
||||||
return TrackStream.BUFFER_READ;
|
return TrackStream.BUFFER_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -830,6 +829,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
*/
|
*/
|
||||||
private static final class BufferExtrasHolder {
|
private static final class BufferExtrasHolder {
|
||||||
|
|
||||||
|
public int size;
|
||||||
public long offset;
|
public long offset;
|
||||||
public long nextOffset;
|
public long nextOffset;
|
||||||
public byte[] encryptionKeyId;
|
public byte[] encryptionKeyId;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link TrackRenderer} for metadata embedded in a media stream.
|
* A {@link TrackRenderer} for metadata embedded in a media stream.
|
||||||
|
|
@ -113,7 +114,9 @@ public final class MetadataTrackRenderer<T> extends TrackRenderer implements Cal
|
||||||
} else {
|
} else {
|
||||||
pendingMetadataTimestamp = buffer.timeUs;
|
pendingMetadataTimestamp = buffer.timeUs;
|
||||||
try {
|
try {
|
||||||
pendingMetadata = metadataParser.parse(buffer.data.array(), buffer.size);
|
buffer.flip();
|
||||||
|
ByteBuffer bufferData = buffer.data;
|
||||||
|
pendingMetadata = metadataParser.parse(bufferData.array(), bufferData.limit());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ package com.google.android.exoplayer.text;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
import com.google.android.exoplayer.util.extensions.SimpleDecoder;
|
import com.google.android.exoplayer.util.extensions.SimpleDecoder;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for subtitle parsers that use their own decode thread.
|
* Base class for subtitle parsers that use their own decode thread.
|
||||||
*/
|
*/
|
||||||
|
|
@ -54,7 +56,8 @@ public abstract class SimpleSubtitleParser extends
|
||||||
protected final ParserException decode(SubtitleInputBuffer inputBuffer,
|
protected final ParserException decode(SubtitleInputBuffer inputBuffer,
|
||||||
SubtitleOutputBuffer outputBuffer, boolean reset) {
|
SubtitleOutputBuffer outputBuffer, boolean reset) {
|
||||||
try {
|
try {
|
||||||
Subtitle subtitle = decode(inputBuffer.data.array(), inputBuffer.size);
|
ByteBuffer inputData = inputBuffer.data;
|
||||||
|
Subtitle subtitle = decode(inputData.array(), inputData.limit());
|
||||||
outputBuffer.setOutput(inputBuffer.timeUs, subtitle, inputBuffer.subsampleOffsetUs);
|
outputBuffer.setOutput(inputBuffer.timeUs, subtitle, inputBuffer.subsampleOffsetUs);
|
||||||
return null;
|
return null;
|
||||||
} catch (ParserException e) {
|
} catch (ParserException e) {
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback {
|
||||||
public int getTrackType() {
|
public int getTrackType() {
|
||||||
return C.TRACK_TYPE_TEXT;
|
return C.TRACK_TYPE_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int supportsFormat(Format format) {
|
protected int supportsFormat(Format format) {
|
||||||
return parserFactory.supportsFormat(format) ? TrackRenderer.FORMAT_HANDLED
|
return parserFactory.supportsFormat(format) ? TrackRenderer.FORMAT_HANDLED
|
||||||
|
|
@ -197,6 +197,7 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback {
|
||||||
} else {
|
} else {
|
||||||
nextInputBuffer.subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
|
nextInputBuffer.subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
|
||||||
}
|
}
|
||||||
|
nextInputBuffer.flip();
|
||||||
parser.queueInputBuffer(nextInputBuffer);
|
parser.queueInputBuffer(nextInputBuffer);
|
||||||
nextInputBuffer = null;
|
nextInputBuffer = null;
|
||||||
} else if (result == TrackStream.NOTHING_READ) {
|
} else if (result == TrackStream.NOTHING_READ) {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
|
@ -304,11 +305,13 @@ public final class Eia608Parser implements SubtitleParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decode(SubtitleInputBuffer inputBuffer) {
|
private void decode(SubtitleInputBuffer inputBuffer) {
|
||||||
if (inputBuffer.size < 10) {
|
ByteBuffer inputData = inputBuffer.data;
|
||||||
|
int inputSize = inputData.limit();
|
||||||
|
if (inputSize < 10) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
seiBuffer.reset(inputBuffer.data.array());
|
|
||||||
|
|
||||||
|
seiBuffer.reset(inputData.array(), inputSize);
|
||||||
// country_code (8) + provider_code (16) + user_identifier (32) + user_data_type_code (8) +
|
// country_code (8) + provider_code (16) + user_identifier (32) + user_data_type_code (8) +
|
||||||
// reserved (1) + process_cc_data_flag (1) + zero_bit (1)
|
// reserved (1) + process_cc_data_flag (1) + zero_bit (1)
|
||||||
seiBuffer.skipBits(67);
|
seiBuffer.skipBits(67);
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputBuffer.flip();
|
||||||
decoder.queueInputBuffer(inputBuffer);
|
decoder.queueInputBuffer(inputBuffer);
|
||||||
inputBuffer = null;
|
inputBuffer = null;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,21 @@ public class SimpleOutputBuffer extends OutputBuffer {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(int size) {
|
/**
|
||||||
|
* Initializes the buffer.
|
||||||
|
*
|
||||||
|
* @param timestampUs The presentation timestamp for the buffer, in microseconds.
|
||||||
|
* @param size An upper bound on the size of the data that will be written to the buffer.
|
||||||
|
* @return The {@link #data} buffer, for convenience.
|
||||||
|
*/
|
||||||
|
public ByteBuffer init(long timestampUs, int size) {
|
||||||
|
this.timestampUs = timestampUs;
|
||||||
if (data == null || data.capacity() < size) {
|
if (data == null || data.capacity() < size) {
|
||||||
data = ByteBuffer.allocateDirect(size);
|
data = ByteBuffer.allocateDirect(size);
|
||||||
}
|
}
|
||||||
data.position(0);
|
data.position(0);
|
||||||
data.limit(size);
|
data.limit(size);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue